diff --git a/Fableon.xcodeproj/project.pbxproj b/Fableon.xcodeproj/project.pbxproj index 1d33a06..375dbed 100644 --- a/Fableon.xcodeproj/project.pbxproj +++ b/Fableon.xcodeproj/project.pbxproj @@ -16,6 +16,23 @@ F342969A2EA0F8E700A58F99 /* FAGenresListViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = F34296992EA0F8E700A58F99 /* FAGenresListViewController.swift */; }; F342969F2EA0FA2200A58F99 /* FAGenresListCell.xib in Resources */ = {isa = PBXBuildFile; fileRef = F342969E2EA0FA2200A58F99 /* FAGenresListCell.xib */; }; F34296A02EA0FA2200A58F99 /* FAGenresListCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = F342969D2EA0FA2200A58F99 /* FAGenresListCell.swift */; }; + F34296A82EA5D2C600A58F99 /* FACategoryModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = F34296A72EA5D2C600A58F99 /* FACategoryModel.swift */; }; + F34296AA2EA5DF1600A58F99 /* FAPopularListViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = F34296A92EA5DF1600A58F99 /* FAPopularListViewController.swift */; }; + F34296AC2EA5E11A00A58F99 /* FANewListViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = F34296AB2EA5E11A00A58F99 /* FANewListViewController.swift */; }; + F34296AE2EA5E4CE00A58F99 /* FAPopularModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = F34296AD2EA5E4CE00A58F99 /* FAPopularModel.swift */; }; + F34296B22EA604D400A58F99 /* FARankingListViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = F34296B12EA604D400A58F99 /* FARankingListViewController.swift */; }; + F34296B42EA605E800A58F99 /* FARankingListHeaderView.swift in Sources */ = {isa = PBXBuildFile; fileRef = F34296B32EA605E800A58F99 /* FARankingListHeaderView.swift */; }; + F34296B62EA60C8E00A58F99 /* FAGradientView.swift in Sources */ = {isa = PBXBuildFile; fileRef = F34296B52EA60C8E00A58F99 /* FAGradientView.swift */; }; + F34296B92EA61C9100A58F99 /* FARankingListCell.xib in Resources */ = {isa = PBXBuildFile; fileRef = F34296B82EA61C9100A58F99 /* FARankingListCell.xib */; }; + F34296BA2EA61C9100A58F99 /* FARankingListCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = F34296B72EA61C9100A58F99 /* FARankingListCell.swift */; }; + F34296BC2EA62C1A00A58F99 /* FAVideoLockView.swift in Sources */ = {isa = PBXBuildFile; fileRef = F34296BB2EA62C1A00A58F99 /* FAVideoLockView.swift */; }; + F34296BE2EA765CA00A58F99 /* FAGradientButton.swift in Sources */ = {isa = PBXBuildFile; fileRef = F34296BD2EA765CA00A58F99 /* FAGradientButton.swift */; }; + F34296C02EA7742900A58F99 /* FAVideoUnlockResult.swift in Sources */ = {isa = PBXBuildFile; fileRef = F34296BF2EA7742900A58F99 /* FAVideoUnlockResult.swift */; }; + F34296D52EA8B70100A58F99 /* FAMeCoinsView.swift in Sources */ = {isa = PBXBuildFile; fileRef = F34296D42EA8B70100A58F99 /* FAMeCoinsView.swift */; }; + F34296D92EA8BD0B00A58F99 /* FAMeTableViewHeaderView.swift in Sources */ = {isa = PBXBuildFile; fileRef = F34296D82EA8BD0B00A58F99 /* FAMeTableViewHeaderView.swift */; }; + F34296DB2EA8CA2B00A58F99 /* Date+FAAdd.swift in Sources */ = {isa = PBXBuildFile; fileRef = F34296DA2EA8CA2400A58F99 /* Date+FAAdd.swift */; }; + F34296DF2EA8D04800A58F99 /* FAStoreViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = F34296DE2EA8D04800A58F99 /* FAStoreViewController.swift */; }; + F34296E12EA8D85D00A58F99 /* FABaseWebViewController+Script.swift in Sources */ = {isa = PBXBuildFile; fileRef = F34296E02EA8D85400A58F99 /* FABaseWebViewController+Script.swift */; }; F37103312E978F8C00E7F171 /* FACollectViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = F37103302E978F8C00E7F171 /* FACollectViewController.swift */; }; F37103352E97929F00E7F171 /* FACollectCell.xib in Resources */ = {isa = PBXBuildFile; fileRef = F37103342E97929F00E7F171 /* FACollectCell.xib */; }; F37103362E97929F00E7F171 /* FACollectCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = F37103332E97929F00E7F171 /* FACollectCell.swift */; }; @@ -127,6 +144,23 @@ F3DCC08B2E8BB16F00D58007 /* FARecommendViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = F3DCC08A2E8BB16F00D58007 /* FARecommendViewController.swift */; }; F3DCC08E2E8BB1F100D58007 /* FARecommendViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = F3DCC08D2E8BB1F100D58007 /* FARecommendViewModel.swift */; }; F3DCC0912E8BBB7600D58007 /* FARecommendPlayerCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = F3DCC0902E8BBB7600D58007 /* FARecommendPlayerCell.swift */; }; + F3EE96562EA8DFBD00A9306D /* FAWebMessageModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = F3EE96552EA8DFBD00A9306D /* FAWebMessageModel.swift */; }; + F3EE96582EA8E1A000A9306D /* FAWalletViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = F3EE96572EA8E1A000A9306D /* FAWalletViewController.swift */; }; + F3EE96602EA8E39200A9306D /* FAWalletCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = F3EE965E2EA8E39200A9306D /* FAWalletCell.swift */; }; + F3EE96612EA8E39200A9306D /* FAWalletCell.xib in Resources */ = {isa = PBXBuildFile; fileRef = F3EE965F2EA8E39200A9306D /* FAWalletCell.xib */; }; + F3EE96632EA8E61200A9306D /* FAWalletHeaderView.swift in Sources */ = {isa = PBXBuildFile; fileRef = F3EE96622EA8E61200A9306D /* FAWalletHeaderView.swift */; }; + F3EE96652EA9C63D00A9306D /* FAConsumptionRecordsViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = F3EE96642EA9C63D00A9306D /* FAConsumptionRecordsViewController.swift */; }; + F3EE966A2EA9C72600A9306D /* FAConsumptionRecordsCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = F3EE96682EA9C72600A9306D /* FAConsumptionRecordsCell.swift */; }; + F3EE966B2EA9C72600A9306D /* FAConsumptionRecordsCell.xib in Resources */ = {isa = PBXBuildFile; fileRef = F3EE96692EA9C72600A9306D /* FAConsumptionRecordsCell.xib */; }; + F3EE966D2EA9D29600A9306D /* FAOrderRecordsViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = F3EE966C2EA9D29600A9306D /* FAOrderRecordsViewController.swift */; }; + F3EE966F2EA9F94E00A9306D /* FACoinRecordViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = F3EE966E2EA9F94E00A9306D /* FACoinRecordViewController.swift */; }; + F3EE96712EA9F96E00A9306D /* FAVipRecordViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = F3EE96702EA9F96D00A9306D /* FAVipRecordViewController.swift */; }; + F3EE96742EA9FA5D00A9306D /* FAOrderRecordCell.xib in Resources */ = {isa = PBXBuildFile; fileRef = F3EE96732EA9FA5C00A9306D /* FAOrderRecordCell.xib */; }; + F3EE96752EA9FA5D00A9306D /* FAOrderRecordCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = F3EE96722EA9FA5C00A9306D /* FAOrderRecordCell.swift */; }; + F3EE96772EA9FD5F00A9306D /* FARewardCoinsViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = F3EE96762EA9FD5F00A9306D /* FARewardCoinsViewController.swift */; }; + F3EE967A2EA9FE0800A9306D /* FARewardCoinsCell.xib in Resources */ = {isa = PBXBuildFile; fileRef = F3EE96792EA9FE0800A9306D /* FARewardCoinsCell.xib */; }; + F3EE967B2EA9FE0800A9306D /* FARewardCoinsCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = F3EE96782EA9FE0800A9306D /* FARewardCoinsCell.swift */; }; + F3EE967D2EAA07F200A9306D /* FAMeListViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = F3EE967C2EAA07F200A9306D /* FAMeListViewController.swift */; }; /* End PBXBuildFile section */ /* Begin PBXFileReference section */ @@ -141,6 +175,23 @@ F34296992EA0F8E700A58F99 /* FAGenresListViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FAGenresListViewController.swift; sourceTree = ""; }; F342969D2EA0FA2200A58F99 /* FAGenresListCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FAGenresListCell.swift; sourceTree = ""; }; F342969E2EA0FA2200A58F99 /* FAGenresListCell.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; path = FAGenresListCell.xib; sourceTree = ""; }; + F34296A72EA5D2C600A58F99 /* FACategoryModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FACategoryModel.swift; sourceTree = ""; }; + F34296A92EA5DF1600A58F99 /* FAPopularListViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FAPopularListViewController.swift; sourceTree = ""; }; + F34296AB2EA5E11A00A58F99 /* FANewListViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FANewListViewController.swift; sourceTree = ""; }; + F34296AD2EA5E4CE00A58F99 /* FAPopularModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FAPopularModel.swift; sourceTree = ""; }; + F34296B12EA604D400A58F99 /* FARankingListViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FARankingListViewController.swift; sourceTree = ""; }; + F34296B32EA605E800A58F99 /* FARankingListHeaderView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FARankingListHeaderView.swift; sourceTree = ""; }; + F34296B52EA60C8E00A58F99 /* FAGradientView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FAGradientView.swift; sourceTree = ""; }; + F34296B72EA61C9100A58F99 /* FARankingListCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FARankingListCell.swift; sourceTree = ""; }; + F34296B82EA61C9100A58F99 /* FARankingListCell.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; path = FARankingListCell.xib; sourceTree = ""; }; + F34296BB2EA62C1A00A58F99 /* FAVideoLockView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FAVideoLockView.swift; sourceTree = ""; }; + F34296BD2EA765CA00A58F99 /* FAGradientButton.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FAGradientButton.swift; sourceTree = ""; }; + F34296BF2EA7742900A58F99 /* FAVideoUnlockResult.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FAVideoUnlockResult.swift; sourceTree = ""; }; + F34296D42EA8B70100A58F99 /* FAMeCoinsView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FAMeCoinsView.swift; sourceTree = ""; }; + F34296D82EA8BD0B00A58F99 /* FAMeTableViewHeaderView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FAMeTableViewHeaderView.swift; sourceTree = ""; }; + F34296DA2EA8CA2400A58F99 /* Date+FAAdd.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Date+FAAdd.swift"; sourceTree = ""; }; + F34296DE2EA8D04800A58F99 /* FAStoreViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FAStoreViewController.swift; sourceTree = ""; }; + F34296E02EA8D85400A58F99 /* FABaseWebViewController+Script.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "FABaseWebViewController+Script.swift"; sourceTree = ""; }; F37103302E978F8C00E7F171 /* FACollectViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FACollectViewController.swift; sourceTree = ""; }; F37103332E97929F00E7F171 /* FACollectCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FACollectCell.swift; sourceTree = ""; }; F37103342E97929F00E7F171 /* FACollectCell.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; path = FACollectCell.xib; sourceTree = ""; }; @@ -255,6 +306,23 @@ F3DCC08A2E8BB16F00D58007 /* FARecommendViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FARecommendViewController.swift; sourceTree = ""; }; F3DCC08D2E8BB1F100D58007 /* FARecommendViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FARecommendViewModel.swift; sourceTree = ""; }; F3DCC0902E8BBB7600D58007 /* FARecommendPlayerCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FARecommendPlayerCell.swift; sourceTree = ""; }; + F3EE96552EA8DFBD00A9306D /* FAWebMessageModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FAWebMessageModel.swift; sourceTree = ""; }; + F3EE96572EA8E1A000A9306D /* FAWalletViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FAWalletViewController.swift; sourceTree = ""; }; + F3EE965E2EA8E39200A9306D /* FAWalletCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FAWalletCell.swift; sourceTree = ""; }; + F3EE965F2EA8E39200A9306D /* FAWalletCell.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; path = FAWalletCell.xib; sourceTree = ""; }; + F3EE96622EA8E61200A9306D /* FAWalletHeaderView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FAWalletHeaderView.swift; sourceTree = ""; }; + F3EE96642EA9C63D00A9306D /* FAConsumptionRecordsViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FAConsumptionRecordsViewController.swift; sourceTree = ""; }; + F3EE96682EA9C72600A9306D /* FAConsumptionRecordsCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FAConsumptionRecordsCell.swift; sourceTree = ""; }; + F3EE96692EA9C72600A9306D /* FAConsumptionRecordsCell.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; path = FAConsumptionRecordsCell.xib; sourceTree = ""; }; + F3EE966C2EA9D29600A9306D /* FAOrderRecordsViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FAOrderRecordsViewController.swift; sourceTree = ""; }; + F3EE966E2EA9F94E00A9306D /* FACoinRecordViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FACoinRecordViewController.swift; sourceTree = ""; }; + F3EE96702EA9F96D00A9306D /* FAVipRecordViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FAVipRecordViewController.swift; sourceTree = ""; }; + F3EE96722EA9FA5C00A9306D /* FAOrderRecordCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FAOrderRecordCell.swift; sourceTree = ""; }; + F3EE96732EA9FA5C00A9306D /* FAOrderRecordCell.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; path = FAOrderRecordCell.xib; sourceTree = ""; }; + F3EE96762EA9FD5F00A9306D /* FARewardCoinsViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FARewardCoinsViewController.swift; sourceTree = ""; }; + F3EE96782EA9FE0800A9306D /* FARewardCoinsCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FARewardCoinsCell.swift; sourceTree = ""; }; + F3EE96792EA9FE0800A9306D /* FARewardCoinsCell.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; path = FARewardCoinsCell.xib; sourceTree = ""; }; + F3EE967C2EAA07F200A9306D /* FAMeListViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FAMeListViewController.swift; sourceTree = ""; }; /* End PBXFileReference section */ /* Begin PBXFrameworksBuildPhase section */ @@ -286,6 +354,29 @@ path = Pods; sourceTree = ""; }; + F34296DC2EA8D02500A58F99 /* Store */ = { + isa = PBXGroup; + children = ( + F34296DD2EA8D03200A58F99 /* C */, + F3EE965D2EA8E35A00A9306D /* V */, + ); + path = Store; + sourceTree = ""; + }; + F34296DD2EA8D03200A58F99 /* C */ = { + isa = PBXGroup; + children = ( + F34296DE2EA8D04800A58F99 /* FAStoreViewController.swift */, + F3EE96572EA8E1A000A9306D /* FAWalletViewController.swift */, + F3EE96642EA9C63D00A9306D /* FAConsumptionRecordsViewController.swift */, + F3EE966C2EA9D29600A9306D /* FAOrderRecordsViewController.swift */, + F3EE966E2EA9F94E00A9306D /* FACoinRecordViewController.swift */, + F3EE96702EA9F96D00A9306D /* FAVipRecordViewController.swift */, + F3EE96762EA9FD5F00A9306D /* FARewardCoinsViewController.swift */, + ); + path = C; + sourceTree = ""; + }; F371032E2E978F4D00E7F171 /* MyShort */ = { isa = PBXGroup; children = ( @@ -337,6 +428,8 @@ F371037D2EA082C700E7F171 /* FAWebView.swift */, F371037F2EA0839500E7F171 /* FABaseWebViewController.swift */, F37103812EA0868100E7F171 /* FAAppWebViewController.swift */, + F34296E02EA8D85400A58F99 /* FABaseWebViewController+Script.swift */, + F3EE96552EA8DFBD00A9306D /* FAWebMessageModel.swift */, ); path = WebView; sourceTree = ""; @@ -428,6 +521,7 @@ F37103482E9DD97200E7F171 /* UIScrollView+FARefresh.swift */, F371036A2E9E52FE00E7F171 /* UIStackView+FAAdd.swift */, F37103832EA0873400E7F171 /* Dictionary+FAAdd.swift */, + F34296DA2EA8CA2400A58F99 /* Date+FAAdd.swift */, ); path = Extension; sourceTree = ""; @@ -456,6 +550,7 @@ F3A792C92E77F70C0097E0BC /* FAShortDetailModel.swift */, F3A792CA2E77F70C0097E0BC /* FAShortPlayModel.swift */, F3A792CB2E77F70C0097E0BC /* FAVideoInfoModel.swift */, + F34296BF2EA7742900A58F99 /* FAVideoUnlockResult.swift */, ); path = M; sourceTree = ""; @@ -478,6 +573,7 @@ F3DCC0462E8A65B000D58007 /* FAEpSelectorCell.swift */, F3DCC0472E8A65B000D58007 /* FAEpSelectorCell.xib */, F3DCC04A2E8A6EAE00D58007 /* FAEpMenuView.swift */, + F34296BB2EA62C1A00A58F99 /* FAVideoLockView.swift */, ); path = V; sourceTree = ""; @@ -544,6 +640,8 @@ children = ( F3A792E72E77F8580097E0BC /* FAHomeModuleItem.swift */, F3A793112E78F8970097E0BC /* FAHomeItem.swift */, + F34296A72EA5D2C600A58F99 /* FACategoryModel.swift */, + F34296AD2EA5E4CE00A58F99 /* FAPopularModel.swift */, ); path = M; sourceTree = ""; @@ -575,6 +673,9 @@ F34296962EA0EAAA00A58F99 /* FAGenresCell.xib */, F342969D2EA0FA2200A58F99 /* FAGenresListCell.swift */, F342969E2EA0FA2200A58F99 /* FAGenresListCell.xib */, + F34296B32EA605E800A58F99 /* FARankingListHeaderView.swift */, + F34296B72EA61C9100A58F99 /* FARankingListCell.swift */, + F34296B82EA61C9100A58F99 /* FARankingListCell.xib */, ); path = V; sourceTree = ""; @@ -586,6 +687,9 @@ F371034C2E9DF9FB00E7F171 /* FASearchViewController.swift */, F34296932EA0E8CB00A58F99 /* FAGenresViewController.swift */, F34296992EA0F8E700A58F99 /* FAGenresListViewController.swift */, + F34296A92EA5DF1600A58F99 /* FAPopularListViewController.swift */, + F34296AB2EA5E11A00A58F99 /* FANewListViewController.swift */, + F34296B12EA604D400A58F99 /* FARankingListViewController.swift */, ); path = C; sourceTree = ""; @@ -636,6 +740,8 @@ F3A793172E790D440097E0BC /* FAImageView.swift */, F3A798BD2E82ACD10097E0BC /* FAPanModalContentView.swift */, F3DCC04C2E8A6F0D00D58007 /* FAScrollView.swift */, + F34296B52EA60C8E00A58F99 /* FAGradientView.swift */, + F34296BD2EA765CA00A58F99 /* FAGradientButton.swift */, ); path = View; sourceTree = ""; @@ -670,6 +776,7 @@ F3C9AE582E77DD8C00E25109 /* Class */ = { isa = PBXGroup; children = ( + F34296DC2EA8D02500A58F99 /* Store */, F3A792E02E77F8040097E0BC /* Home */, F3DCC0532E8A8EB200D58007 /* Me */, F3A792D52E77F70C0097E0BC /* Player */, @@ -721,6 +828,7 @@ isa = PBXGroup; children = ( F3DCC0562E8A8EE800D58007 /* FAMeViewController.swift */, + F3EE967C2EAA07F200A9306D /* FAMeListViewController.swift */, F37103722E9F9E0D00E7F171 /* FAAboutViewController.swift */, F371037A2EA0820C00E7F171 /* FASettingViewController.swift */, F37103852EA087FB00E7F171 /* FAFeedbackViewController.swift */, @@ -732,6 +840,8 @@ isa = PBXGroup; children = ( F3DCC0592E8A931900D58007 /* FAMeHeaderView.swift */, + F34296D42EA8B70100A58F99 /* FAMeCoinsView.swift */, + F34296D82EA8BD0B00A58F99 /* FAMeTableViewHeaderView.swift */, F3DCC0612E8A9E7600D58007 /* FAMeCell.swift */, F3DCC0622E8A9E7600D58007 /* FAMeCell.xib */, F37103742E9FA15B00E7F171 /* FAAboutCell.swift */, @@ -784,6 +894,22 @@ path = V; sourceTree = ""; }; + F3EE965D2EA8E35A00A9306D /* V */ = { + isa = PBXGroup; + children = ( + F3EE965E2EA8E39200A9306D /* FAWalletCell.swift */, + F3EE965F2EA8E39200A9306D /* FAWalletCell.xib */, + F3EE96622EA8E61200A9306D /* FAWalletHeaderView.swift */, + F3EE96682EA9C72600A9306D /* FAConsumptionRecordsCell.swift */, + F3EE96692EA9C72600A9306D /* FAConsumptionRecordsCell.xib */, + F3EE96722EA9FA5C00A9306D /* FAOrderRecordCell.swift */, + F3EE96732EA9FA5C00A9306D /* FAOrderRecordCell.xib */, + F3EE96782EA9FE0800A9306D /* FARewardCoinsCell.swift */, + F3EE96792EA9FE0800A9306D /* FARewardCoinsCell.xib */, + ); + path = V; + sourceTree = ""; + }; /* End PBXGroup section */ /* Begin PBXNativeTarget section */ @@ -847,19 +973,24 @@ buildActionMask = 2147483647; files = ( F34296982EA0EAAA00A58F99 /* FAGenresCell.xib in Resources */, + F3EE966B2EA9C72600A9306D /* FAConsumptionRecordsCell.xib in Resources */, F3A798B72E828C180097E0BC /* Localizable.strings in Resources */, F37103572E9E1FA500E7F171 /* FASearchRecordCell.xib in Resources */, + F34296B92EA61C9100A58F99 /* FARankingListCell.xib in Resources */, F342969F2EA0FA2200A58F99 /* FAGenresListCell.xib in Resources */, F39E663A2E77BAD0008AAAFA /* Assets.xcassets in Resources */, + F3EE96612EA8E39200A9306D /* FAWalletCell.xib in Resources */, F37103772E9FA15B00E7F171 /* FAAboutCell.xib in Resources */, F371035E2E9E2E7400E7F171 /* FASearchRecommendCell.xib in Resources */, F37103462E9CF9EE00E7F171 /* FAHistoryCell.xib in Resources */, F3A793292E795B4C0097E0BC /* FAHomeSectionTitleView.xib in Resources */, F3A793232E7944FF0097E0BC /* FAHomeRecommendedCell.xib in Resources */, F37103662E9E3ABC00E7F171 /* FASearchResultCell.xib in Resources */, + F3EE967A2EA9FE0800A9306D /* FARewardCoinsCell.xib in Resources */, F3DCC0482E8A65B000D58007 /* FAEpSelectorCell.xib in Resources */, F39E663C2E77BAD0008AAAFA /* LaunchScreen.storyboard in Resources */, F3DCC0642E8A9E7600D58007 /* FAMeCell.xib in Resources */, + F3EE96742EA9FA5D00A9306D /* FAOrderRecordCell.xib in Resources */, F37103352E97929F00E7F171 /* FACollectCell.xib in Resources */, ); runOnlyForDeploymentPostprocessing = 0; @@ -924,13 +1055,20 @@ F38C25FD2E86A290008C22C3 /* FADefine.swift in Sources */, F3A793182E790D440097E0BC /* FAImageView.swift in Sources */, F3DCC05A2E8A931900D58007 /* FAMeHeaderView.swift in Sources */, + F34296AC2EA5E11A00A58F99 /* FANewListViewController.swift in Sources */, F3A792B62E77E0CC0097E0BC /* FANetworkManager.swift in Sources */, + F3EE966A2EA9C72600A9306D /* FAConsumptionRecordsCell.swift in Sources */, F3A792C62E77E93E0097E0BC /* FANavigationController.swift in Sources */, + F3EE966D2EA9D29600A9306D /* FAOrderRecordsViewController.swift in Sources */, + F34296BE2EA765CA00A58F99 /* FAGradientButton.swift in Sources */, + F34296A82EA5D2C600A58F99 /* FACategoryModel.swift in Sources */, F37103692E9E44A000E7F171 /* FASearchViewModel.swift in Sources */, F3A793122E78F8970097E0BC /* FAHomeItem.swift in Sources */, F3A798BE2E82ACD10097E0BC /* FAPanModalContentView.swift in Sources */, F3A792F22E77F8A80097E0BC /* FAHomeMustSeeView.swift in Sources */, F3A793242E7944FF0097E0BC /* FAHomeRecommendedCell.swift in Sources */, + F34296B22EA604D400A58F99 /* FARankingListViewController.swift in Sources */, + F34296B42EA605E800A58F99 /* FARankingListHeaderView.swift in Sources */, F3A792F42E77F8A80097E0BC /* FAHomeMustSeeContentView.swift in Sources */, F3DCC05E2E8A9C5800D58007 /* FATableViewCell.swift in Sources */, F371037E2EA082CD00E7F171 /* FAWebView.swift in Sources */, @@ -938,16 +1076,19 @@ F37103612E9E379E00E7F171 /* FASearchResultView.swift in Sources */, F3A792F52E77F8A80097E0BC /* FAHomeRecommendedItemView.swift in Sources */, F34296972EA0EAAA00A58F99 /* FAGenresCell.swift in Sources */, + F34296D92EA8BD0B00A58F99 /* FAMeTableViewHeaderView.swift in Sources */, F37103842EA0873B00E7F171 /* Dictionary+FAAdd.swift in Sources */, F3A792F72E77F8A80097E0BC /* FAHomeNewView.swift in Sources */, F3A792F82E77F8A80097E0BC /* FAHomeMustSeeShortView.swift in Sources */, F3A793042E77FB110097E0BC /* FAHomeViewController.swift in Sources */, + F34296DF2EA8D04800A58F99 /* FAStoreViewController.swift in Sources */, F371034F2E9DFB2000E7F171 /* FASearchInputView.swift in Sources */, F37103562E9E1FA500E7F171 /* FASearchRecordCell.swift in Sources */, F37103792E9FA91C00E7F171 /* FAAboutHeaderView.swift in Sources */, F3A792B12E77DFEE0097E0BC /* FALogin.swift in Sources */, F3DCC0502E8A861300D58007 /* FAHUD.swift in Sources */, F3DCC04D2E8A6F0D00D58007 /* FAScrollView.swift in Sources */, + F3EE967D2EAA07F200A9306D /* FAMeListViewController.swift in Sources */, F3DCC0572E8A8EE800D58007 /* FAMeViewController.swift in Sources */, F3A792E82E77F8590097E0BC /* FAHomeModuleItem.swift in Sources */, F3DCC0452E89530200D58007 /* CGMutablePath+FARoundedCorner.swift in Sources */, @@ -962,12 +1103,14 @@ F3C9AE5B2E77DDE100E25109 /* FAKeychainHelper.swift in Sources */, F371034D2E9DF9FB00E7F171 /* FASearchViewController.swift in Sources */, F3A792B82E77E0EF0097E0BC /* FACryptorService.swift in Sources */, + F3EE967B2EA9FE0800A9306D /* FARewardCoinsCell.swift in Sources */, F3A7932C2E796EF80097E0BC /* FAPlayerDetailControlView.swift in Sources */, F3A798BC2E82AB6F0097E0BC /* FAEpSelectorView.swift in Sources */, F37103512E9E1D7800E7F171 /* FASearchHomeView.swift in Sources */, F34296942EA0E8CB00A58F99 /* FAGenresViewController.swift in Sources */, F3A792AF2E77DFB90097E0BC /* FATokenModel.swift in Sources */, F38C25FA2E86A217008C22C3 /* UIView+FAAdd.swift in Sources */, + F3EE96652EA9C63D00A9306D /* FAConsumptionRecordsViewController.swift in Sources */, F342969A2EA0F8E700A58F99 /* FAGenresListViewController.swift in Sources */, F3A7931A2E7911420097E0BC /* FAPagerViewTransformer.swift in Sources */, F3DCC0672E8AA14A00D58007 /* FAMeItemModel.swift in Sources */, @@ -978,26 +1121,38 @@ F37103762E9FA15B00E7F171 /* FAAboutCell.swift in Sources */, F37103412E97C20C00E7F171 /* UINavigationBar+FAAdd.swift in Sources */, F3A792D82E77F70C0097E0BC /* FAShortDetailViewModel.swift in Sources */, + F3EE96562EA8DFBD00A9306D /* FAWebMessageModel.swift in Sources */, F37103802EA0839500E7F171 /* FABaseWebViewController.swift in Sources */, F3A793002E77FA0C0097E0BC /* SwiftUIExtension.swift in Sources */, F3A792D92E77F70C0097E0BC /* FAShortDetailModel.swift in Sources */, + F34296C02EA7742900A58F99 /* FAVideoUnlockResult.swift in Sources */, F3A792DA2E77F70C0097E0BC /* FAPlayerDetailCell.swift in Sources */, F3A792DB2E77F70C0097E0BC /* FAVideoInfoModel.swift in Sources */, F3A7930C2E7813FE0097E0BC /* FACollectionView.swift in Sources */, F37103822EA0868100E7F171 /* FAAppWebViewController.swift in Sources */, F37103712E9F964000E7F171 /* FALocalized.swift in Sources */, + F34296DB2EA8CA2B00A58F99 /* Date+FAAdd.swift in Sources */, + F3EE966F2EA9F94E00A9306D /* FACoinRecordViewController.swift in Sources */, + F3EE96632EA8E61200A9306D /* FAWalletHeaderView.swift in Sources */, + F34296E12EA8D85D00A58F99 /* FABaseWebViewController+Script.swift in Sources */, F3A792DC2E77F70C0097E0BC /* FAPlayerDetailViewController.swift in Sources */, F38C25FF2E86B663008C22C3 /* AppDelegate+FAConfig.swift in Sources */, F37103592E9E281C00E7F171 /* FASearchRecommendView.swift in Sources */, + F34296D52EA8B70100A58F99 /* FAMeCoinsView.swift in Sources */, F34296A02EA0FA2200A58F99 /* FAGenresListCell.swift in Sources */, F3A792BF2E77E4B80097E0BC /* FATool.swift in Sources */, F371033F2E97BDF800E7F171 /* FAHistoryViewController.swift in Sources */, + F3EE96752EA9FA5D00A9306D /* FAOrderRecordCell.swift in Sources */, + F34296BA2EA61C9100A58F99 /* FARankingListCell.swift in Sources */, F3DCC08B2E8BB16F00D58007 /* FARecommendViewController.swift in Sources */, F3DCC0492E8A65B000D58007 /* FAEpSelectorCell.swift in Sources */, F3A793162E790CC90097E0BC /* FAHomeBannerCell.swift in Sources */, + F3EE96602EA8E39200A9306D /* FAWalletCell.swift in Sources */, + F3EE96772EA9FD5F00A9306D /* FARewardCoinsViewController.swift in Sources */, F3DCC04B2E8A6EAE00D58007 /* FAEpMenuView.swift in Sources */, F3DCC0632E8A9E7600D58007 /* FAMeCell.swift in Sources */, F3A793142E78FC4C0097E0BC /* FAHomeBannerContentCell.swift in Sources */, + F3EE96712EA9F96E00A9306D /* FAVipRecordViewController.swift in Sources */, F39E66372E77BAD0008AAAFA /* AppDelegate.swift in Sources */, F3DCC08E2E8BB1F100D58007 /* FARecommendViewModel.swift in Sources */, F371036B2E9E530400E7F171 /* UIStackView+FAAdd.swift in Sources */, @@ -1005,13 +1160,16 @@ F3A792BC2E77E2EE0097E0BC /* String+FAAdd.swift in Sources */, F3A792AD2E77DF830097E0BC /* FAUserInfo.swift in Sources */, F3A792DF2E77F7EA0097E0BC /* FAAPI.swift in Sources */, + F34296AA2EA5DF1600A58F99 /* FAPopularListViewController.swift in Sources */, F3A7932A2E795B4C0097E0BC /* FAHomeSectionTitleView.swift in Sources */, F3DCC05C2E8A9C1B00D58007 /* FATableView.swift in Sources */, F37103492E9DD98600E7F171 /* UIScrollView+FARefresh.swift in Sources */, F3A7931E2E793D000097E0BC /* FAHomeNewContentCell.swift in Sources */, + F34296BC2EA62C1A00A58F99 /* FAVideoLockView.swift in Sources */, F39E66382E77BAD0008AAAFA /* SceneDelegate.swift in Sources */, F371036E2E9E6E7800E7F171 /* FAEmpty.swift in Sources */, F37103362E97929F00E7F171 /* FACollectCell.swift in Sources */, + F3EE96582EA8E1A000A9306D /* FAWalletViewController.swift in Sources */, F3A793532E7BA54A0097E0BC /* FAPlayerEpUIButton.swift in Sources */, F3A792EA2E77F8820097E0BC /* FAHomeViewModel.swift in Sources */, F3A792C82E77EED10097E0BC /* Font+FAAdd.swift in Sources */, @@ -1020,6 +1178,8 @@ F3A798B92E828F5E0097E0BC /* FAPlayerProgressView.swift in Sources */, F371035F2E9E2E7400E7F171 /* FASearchRecommendCell.swift in Sources */, F3A793092E7812F60097E0BC /* FAWaterfallFlowLayout.swift in Sources */, + F34296AE2EA5E4CE00A58F99 /* FAPopularModel.swift in Sources */, + F34296B62EA60C8E00A58F99 /* FAGradientView.swift in Sources */, F37103732E9F9E0D00E7F171 /* FAAboutViewController.swift in Sources */, ); runOnlyForDeploymentPostprocessing = 0; @@ -1060,6 +1220,8 @@ GENERATE_INFOPLIST_FILE = YES; INFOPLIST_FILE = Fableon/Source/Info.plist; INFOPLIST_KEY_CFBundleDisplayName = Fableon; + INFOPLIST_KEY_NSCameraUsageDescription = "The APP needs to access your album to provide screenshots for feedback."; + INFOPLIST_KEY_NSPhotoLibraryUsageDescription = "The APP needs to access your album to provide screenshots for feedback."; INFOPLIST_KEY_UIApplicationSupportsIndirectInputEvents = YES; INFOPLIST_KEY_UILaunchStoryboardName = LaunchScreen; INFOPLIST_KEY_UIMainStoryboardFile = ""; @@ -1096,6 +1258,8 @@ GENERATE_INFOPLIST_FILE = YES; INFOPLIST_FILE = Fableon/Source/Info.plist; INFOPLIST_KEY_CFBundleDisplayName = Fableon; + INFOPLIST_KEY_NSCameraUsageDescription = "The APP needs to access your album to provide screenshots for feedback."; + INFOPLIST_KEY_NSPhotoLibraryUsageDescription = "The APP needs to access your album to provide screenshots for feedback."; INFOPLIST_KEY_UIApplicationSupportsIndirectInputEvents = YES; INFOPLIST_KEY_UILaunchStoryboardName = LaunchScreen; INFOPLIST_KEY_UIMainStoryboardFile = ""; diff --git a/Fableon/Base/Controller/FAViewController.swift b/Fableon/Base/Controller/FAViewController.swift index 144f65f..d1e5fb8 100644 --- a/Fableon/Base/Controller/FAViewController.swift +++ b/Fableon/Base/Controller/FAViewController.swift @@ -6,8 +6,9 @@ // import UIKit +import JXSegmentedView -class FAViewController: UIViewController { +class FAViewController: UIViewController, JXSegmentedListContainerViewListDelegate { lazy var bgView: UIView = { let view = UIImageView(image: UIImage(named: "背景")) @@ -45,8 +46,13 @@ class FAViewController: UIViewController { return .lightContent } + + func listView() -> UIView { + return self.view + } } + extension UIViewController { func configNavigationBack(_ imageName: String = "Frame 3011") { let image = UIImage(named: imageName) diff --git a/Fableon/Base/Extension/Date+FAAdd.swift b/Fableon/Base/Extension/Date+FAAdd.swift new file mode 100644 index 0000000..74d4c53 --- /dev/null +++ b/Fableon/Base/Extension/Date+FAAdd.swift @@ -0,0 +1,31 @@ +// +// Date+FAAdd.swift +// Fableon +// +// Created by 长沙鸿瑶 on 2025/10/22. +// + +import Foundation + +extension Date { + + ///相差天数 + func fa_differenceDay(_ date: Date) -> Int { + let dateComponents = Calendar.current.dateComponents([.day], from: self, to: date) + return dateComponents.day ?? 0 + } + + func fa_formatString(_ dateFormat: String) -> String { + let formatter = DateFormatter() + formatter.dateFormat = dateFormat + return formatter.string(from: self) + } + + ///是否是今天 + var br_isToday: Bool { + get { + return Calendar.current.isDateInToday(self) + } + } + +} diff --git a/Fableon/Base/Extension/UIScreen+FAAdd.swift b/Fableon/Base/Extension/UIScreen+FAAdd.swift index 758882b..1aa7f3d 100644 --- a/Fableon/Base/Extension/UIScreen+FAAdd.swift +++ b/Fableon/Base/Extension/UIScreen+FAAdd.swift @@ -37,4 +37,13 @@ extension UIScreen { static var tabBarHeight: CGFloat { return safeBottom + 49 } + + ///屏幕宽比 + static var widthRatio: CGFloat { + return UIScreen.width / 375 + } + + static func getRatioWidth(size: CGFloat) -> CGFloat { + return self.widthRatio * size + } } diff --git a/Fableon/Base/Request/FAAPI/FAAPI.swift b/Fableon/Base/Request/FAAPI/FAAPI.swift index d5b34cf..3a301b5 100644 --- a/Fableon/Base/Request/FAAPI/FAAPI.swift +++ b/Fableon/Base/Request/FAAPI/FAAPI.swift @@ -168,6 +168,87 @@ struct FAAPI { completer?(response.data?.list) } } + + static func requestGenresData(completer: ((_ list: [FACategoryModel]?) -> Void)?) { + + let parameters = [ + "short_play_num" : 5, + ] + + FANetworkManager.manager.request(FABaseURL + "/categoryListAppendShortPlay", + method: .get, + parameters: parameters, + isToast: true) { (response: FANetworkManager.Response>) in + completer?(response.data?.list) + } + } + + static func requestCategoryVideoList(id: String, page: Int, completer: ((_ listModel: FANetworkManager.List?) -> Void)?) { + + let parameters: [String : Any] = [ + "category_id" : id, + "current_page" : page, + "page_size" : 20 + ] + + FANetworkManager.manager.request(FABaseURL + "/videoList", + method: .get, + parameters: parameters, + isToast: true) { (response: FANetworkManager.Response>) in + completer?(response.data) + } + } + + static func requestPopularVideoList( completer: ((_ list: [FAShortPlayModel]?) -> Void)?) { + + FANetworkManager.manager.request(FABaseURL + "/homeTop", + method: .post, + parameters: nil, + isToast: true) { (response: FANetworkManager.Response) in + completer?(response.data?.hotData) + } + } + + static func requestNewVideoList( completer: ((_ list: [FAShortPlayModel]?) -> Void)?) { + + FANetworkManager.manager.request(FABaseURL + "/newShortPlayNoPaginate", + method: .post, + parameters: nil, + isToast: true) { (response: FANetworkManager.Response>) in + completer?(response.data?.list) + } + } + + static func requestRankingVideoList( completer: ((_ list: [FAShortPlayModel]?) -> Void)?) { + + let parameters = [ + "type" : "most_trending" + ] + + FANetworkManager.manager.request(FABaseURL + "/homeRanking", + method: .post, + parameters: parameters, + isToast: true) { (response: FANetworkManager.Response>) in + completer?(response.data?.list) + } + } + + ///金币解锁视频 + static func requestCoinUnlockVideo(shortPlayId: String, videoId: String, completer: ((_ model: FAVideoUnlockResult?) -> Void)?) { + + let parameters = [ + "short_play_id" : shortPlayId, + "video_id" : videoId, + ] + + FANetworkManager.manager.request(FABaseURL + "/buy_video", + method: .post, + parameters: parameters, + isLoding: true, + isToast: true) { (response: FANetworkManager.Response) in + completer?(response.data) + } + } } diff --git a/Fableon/Base/View/FAGradientButton.swift b/Fableon/Base/View/FAGradientButton.swift new file mode 100644 index 0000000..f752a12 --- /dev/null +++ b/Fableon/Base/View/FAGradientButton.swift @@ -0,0 +1,44 @@ +// +// FAGradientButton.swift +// Fableon +// +// Created by 长沙鸿瑶 on 2025/10/21. +// + +import UIKit + +class FAGradientButton: UIButton { + + override class var layerClass: AnyClass { + return CAGradientLayer.self + } + + var fa_gradientLayer: CAGradientLayer { + return self.layer as! CAGradientLayer + } + + var fa_colors: [CGColor]? { + didSet { + fa_gradientLayer.colors = fa_colors + } + } + + var fa_startPoint: CGPoint = .zero { + didSet { + fa_gradientLayer.startPoint = fa_startPoint + } + } + + var fa_endPoint: CGPoint = .zero { + didSet { + fa_gradientLayer.endPoint = fa_endPoint + } + } + + var fa_locations: [NSNumber] = [] { + didSet { + fa_gradientLayer.locations = fa_locations + } + } + +} diff --git a/Fableon/Base/View/FAGradientView.swift b/Fableon/Base/View/FAGradientView.swift new file mode 100644 index 0000000..f5c4c98 --- /dev/null +++ b/Fableon/Base/View/FAGradientView.swift @@ -0,0 +1,44 @@ +// +// FAGradientView.swift +// Fableon +// +// Created by 长沙鸿瑶 on 2025/10/20. +// + +import UIKit + +class FAGradientView: UIView { + + override class var layerClass: AnyClass { + return CAGradientLayer.self + } + + var fa_gradientLayer: CAGradientLayer { + return self.layer as! CAGradientLayer + } + + var fa_colors: [CGColor]? { + didSet { + fa_gradientLayer.colors = fa_colors + } + } + + var fa_startPoint: CGPoint = .zero { + didSet { + fa_gradientLayer.startPoint = fa_startPoint + } + } + + var fa_endPoint: CGPoint = .zero { + didSet { + fa_gradientLayer.endPoint = fa_endPoint + } + } + + var fa_locations: [NSNumber] = [] { + didSet { + fa_gradientLayer.locations = fa_locations + } + } + +} diff --git a/Fableon/Base/View/FAScrollView.swift b/Fableon/Base/View/FAScrollView.swift index dc41a6e..4b206a1 100644 --- a/Fableon/Base/View/FAScrollView.swift +++ b/Fableon/Base/View/FAScrollView.swift @@ -7,7 +7,10 @@ import UIKit -class FAScrollView: UIScrollView { +class FAScrollView: UIScrollView, UIGestureRecognizerDelegate { + + ///允许同时识别滑动手势 + var allowSimultaneousRecognition = false override init(frame: CGRect) { super.init(frame: frame) @@ -17,5 +20,10 @@ class FAScrollView: UIScrollView { required init?(coder: NSCoder) { fatalError("init(coder:) has not been implemented") } + + + func gestureRecognizer(_ gestureRecognizer: UIGestureRecognizer, shouldRecognizeSimultaneouslyWith otherGestureRecognizer: UIGestureRecognizer) -> Bool { + return allowSimultaneousRecognition + } } diff --git a/Fableon/Base/WebView/FAAppWebViewController.swift b/Fableon/Base/WebView/FAAppWebViewController.swift index 53698bb..c6c78f5 100644 --- a/Fableon/Base/WebView/FAAppWebViewController.swift +++ b/Fableon/Base/WebView/FAAppWebViewController.swift @@ -18,8 +18,16 @@ class FAAppWebViewController: FABaseWebViewController { override func viewDidLoad() { super.viewDidLoad() - - // Do any additional setup after loading the view. + self.autoTitle = false + + if webUrl == kFAFeedBackListWebUrl { + self.title = "Feedback History".localized + } else if webUrl == kFAFeedBackHomeWebUrl { + self.title = "Feedback".localized + } else if webUrl == kFAFeedBackDetailWebUrl { + self.title = "Feedback Details".localized + } + } override func fa_webViewDidFinishLoad(_ webView: FAWebView) { diff --git a/Fableon/Base/WebView/FABaseWebViewController+Script.swift b/Fableon/Base/WebView/FABaseWebViewController+Script.swift new file mode 100644 index 0000000..7ada9df --- /dev/null +++ b/Fableon/Base/WebView/FABaseWebViewController+Script.swift @@ -0,0 +1,104 @@ +// +// FABaseWebViewController+Script.swift +// Fableon +// +// Created by 长沙鸿瑶 on 2025/10/22. +// + +import UIKit +import WebKit +import ZLPhotoBrowser +import SmartCodable + +///APP交互 +let kFAWebMessageAPP = "js2app" +///打开反馈列表 +let kFAWebMessageOpenFeedbackList = "openFeedbackList" +///打开反馈详情 +let kFAWebMessageOpenFeedbackDetail = "openFeedbackDetail" +///打开相册 +let kFAWebMessageOpenPhotoPicker = "openPhotoPicker" + +extension FABaseWebViewController { + + func fa_webViewUserContentController(didReceive message: WKScriptMessage) { + let name = message.name + let body = message.body + + switch name { + case kFAWebMessageOpenFeedbackList: + let vc = FAAppWebViewController() + vc.webUrl = kFAFeedBackListWebUrl + self.navigationController?.pushViewController(vc, animated: true) + + case kFAWebMessageOpenFeedbackDetail: + guard let body = body as? [String : Any] else { return } + guard let id = body["id"] as? Int else { return } + + let vc = FAAppWebViewController() + vc.id = "\(id)" + vc.webUrl = kFAFeedBackDetailWebUrl + self.navigationController?.pushViewController(vc, animated: true) + + case kFAWebMessageOpenPhotoPicker: + openPhotoPicker() + + case kFAWebMessageAPP: + guard let body = message.body as? [String : Any] else { return } + guard let model = FAWebMessageModel.deserialize(from: body) else { return } + let type = model.type + let data = model.data + + if type == "login" { +// VPLoginManager.manager.openLogin() + + } else if type == "open_notify" { +// openNotify() + + } else if type == "watch_video" { + let vc = FAPlayerDetailViewController() + vc.shortPlayId = data?.short_play_id + vc.activityId = data?.activity_id + self.navigationController?.pushViewController(vc, animated: true) + } else { + + guard let urlStr = data?.link else { return } + guard let url = URL(string: urlStr) else { return } + if UIApplication.shared.canOpenURL(url) { + UIApplication.shared.open(url) + } + } + + + default: + break + } + + } + + + ///打开相册 + private func openPhotoPicker() { + + ZLPhotoConfiguration.default().allowSelectOriginal = false + ZLPhotoConfiguration.default().maxSelectCount = 1 + ZLPhotoConfiguration.default().allowEditImage = false + ZLPhotoConfiguration.default().allowSelectVideo = false + ZLPhotoConfiguration.default().allowSelectGif = false + ZLPhotoConfiguration.default().allowTakePhotoInLibrary = false + + let picker = ZLPhotoPicker() + picker.selectImageBlock = { [weak self] (results, _) in + guard let self = self else { return } + guard let image = results.first?.image else { return } + guard let imageData = image.jpegData(compressionQuality: 0.8) else { return } + let imageDataStr = imageData.base64EncodedString(options: .endLineWithCarriageReturn) + + let js = "uploadConvertImage('\(imageDataStr)')" + self.webView.evaluateJavaScript(js) + } + + picker.showPhotoLibrary(sender: self) + } + +} diff --git a/Fableon/Base/WebView/FABaseWebViewController.swift b/Fableon/Base/WebView/FABaseWebViewController.swift index ec5a3b7..c55161e 100644 --- a/Fableon/Base/WebView/FABaseWebViewController.swift +++ b/Fableon/Base/WebView/FABaseWebViewController.swift @@ -107,6 +107,6 @@ extension FABaseWebViewController: FAWebViewDelegate { } func fa_userContentController(_ userContentController: WKUserContentController, didReceive message: WKScriptMessage) { - + self.fa_webViewUserContentController(didReceive: message) } } diff --git a/Fableon/Base/WebView/FAWebMessageModel.swift b/Fableon/Base/WebView/FAWebMessageModel.swift new file mode 100644 index 0000000..0ef29e9 --- /dev/null +++ b/Fableon/Base/WebView/FAWebMessageModel.swift @@ -0,0 +1,24 @@ +// +// FAWebMessageModel.swift +// Fableon +// +// Created by 长沙鸿瑶 on 2025/10/22. +// + +import UIKit +import SmartCodable + +struct FAWebMessageModel: SmartCodable { + var type: String? + + var data: FAWebMessageData? + +} + +struct FAWebMessageData: SmartCodable { + + var activity_id: String? + var short_play_id: String? + var link: String? + +} diff --git a/Fableon/Base/WebView/FAWebView.swift b/Fableon/Base/WebView/FAWebView.swift index b60acde..a1f78a7 100644 --- a/Fableon/Base/WebView/FAWebView.swift +++ b/Fableon/Base/WebView/FAWebView.swift @@ -34,6 +34,10 @@ class FAWebView: WKWebView { weak var delegate: FAWebViewDelegate? private(set) var scriptMessageHandlerArray: [String] = [ + kFAWebMessageAPP, + kFAWebMessageOpenFeedbackList, + kFAWebMessageOpenFeedbackDetail, + kFAWebMessageOpenPhotoPicker, ] diff --git a/Fableon/Class/Home/C/FAGenresListViewController.swift b/Fableon/Class/Home/C/FAGenresListViewController.swift index b8e9f1d..5a7624e 100644 --- a/Fableon/Class/Home/C/FAGenresListViewController.swift +++ b/Fableon/Class/Home/C/FAGenresListViewController.swift @@ -9,6 +9,10 @@ import UIKit class FAGenresListViewController: FAViewController { + var model: FACategoryModel? + + private var dataArr: [FAShortPlayModel] = [] + private var page = 1 private lazy var collectionViewLayout: UICollectionViewFlowLayout = { let width = floor((UIScreen.width - 32 - 16) / 3) @@ -28,13 +32,22 @@ class FAGenresListViewController: FAViewController { collectionView.dataSource = self collectionView.contentInset = .init(top: 20, left: 0, bottom: UIScreen.safeBottom + 10, right: 0) collectionView.register(UINib(nibName: "FAGenresListCell", bundle: nil), forCellWithReuseIdentifier: "cell") + collectionView.fa_addRefreshHeader(insetTop: collectionView.contentInset.top) { [weak self] in + self?.handleHeaderRefresh(nil) + } + collectionView.fa_addRefreshFooter(insetBottom: 0) { [weak self] in + self?.handleFooterRefresh(nil) + } return collectionView }() override func viewDidLoad() { super.viewDidLoad() + self.title = model?.category_name fa_setupLayout() + + requestDataArr(page: 1, completer: nil) } override func viewWillAppear(_ animated: Bool) { @@ -43,7 +56,17 @@ class FAGenresListViewController: FAViewController { fa_setNavigationStyle() } + override func handleHeaderRefresh(_ completer: (() -> Void)?) { + requestDataArr(page: 1) { [weak self] in + self?.collectionView.fa_endHeaderRefreshing() + } + } + override func handleFooterRefresh(_ completer: (() -> Void)?) { + requestDataArr(page: page + 1) { [weak self] in + self?.collectionView.fa_endFooterRefreshing() + } + } } @@ -64,11 +87,43 @@ extension FAGenresListViewController { extension FAGenresListViewController: UICollectionViewDelegate, UICollectionViewDataSource { func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int { - return 10 + return dataArr.count } func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell { let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "cell", for: indexPath) as! FAGenresListCell + cell.model = dataArr[indexPath.row] return cell } + + func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) { + let model = dataArr[indexPath.row] + let vc = FAPlayerDetailViewController() + vc.shortPlayId = model.short_play_id + self.navigationController?.pushViewController(vc, animated: true) + } +} + +extension FAGenresListViewController { + + private func requestDataArr(page: Int, completer: (() -> Void)?) { + guard let id = self.model?.id else { return } + + FAAPI.requestCategoryVideoList(id: id, page: page) { [weak self] listModel in + guard let self = self else { return } + if let list = listModel?.list { + if page == 1 { + self.dataArr.removeAll() + } + + self.dataArr += list + self.collectionView.reloadData() + + self.page = page + } + completer?() + self.collectionView.fa_updateNoMoreDataState(listModel?.hasNextPage) + } + } + } diff --git a/Fableon/Class/Home/C/FAGenresViewController.swift b/Fableon/Class/Home/C/FAGenresViewController.swift index 1c9e3fb..d86a836 100644 --- a/Fableon/Class/Home/C/FAGenresViewController.swift +++ b/Fableon/Class/Home/C/FAGenresViewController.swift @@ -18,6 +18,8 @@ class FAGenresViewController: FAViewController { .FCB_072_0_5 ] + private lazy var dataArr: [FACategoryModel] = [] + private lazy var collectionViewLayout: UICollectionViewFlowLayout = { let layout = UICollectionViewFlowLayout() layout.minimumLineSpacing = 10 @@ -39,6 +41,8 @@ class FAGenresViewController: FAViewController { self.title = "Genres".localized fa_setupLayout() + + requestDataArr() } override func viewWillAppear(_ animated: Bool) { @@ -68,16 +72,33 @@ extension FAGenresViewController: UICollectionViewDelegate, UICollectionViewData func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell { let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "cell", for: indexPath) as! FAGenresCell cell.bgView.backgroundColor = bgColorArr[indexPath.row % 5] + cell.model = self.dataArr[indexPath.row] return cell } func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int { - return 10 + return self.dataArr.count } func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) { let vc = FAGenresListViewController() + vc.model = dataArr[indexPath.row] self.navigationController?.pushViewController(vc, animated: true) } } + +extension FAGenresViewController { + + private func requestDataArr() { + + FAAPI.requestGenresData { [weak self] list in + guard let self = self else { return } + guard let list = list else { return } + + self.dataArr = list + self.collectionView.reloadData() + } + } + +} diff --git a/Fableon/Class/Home/C/FANewListViewController.swift b/Fableon/Class/Home/C/FANewListViewController.swift new file mode 100644 index 0000000..128f1e2 --- /dev/null +++ b/Fableon/Class/Home/C/FANewListViewController.swift @@ -0,0 +1,119 @@ +// +// FANewListViewController.swift +// Fableon +// +// Created by 长沙鸿瑶 on 2025/10/20. +// + +import UIKit + +class FANewListViewController: FAViewController { + + private var dataArr: [FAShortPlayModel] = [] +// private var page = 1 + + private lazy var collectionViewLayout: UICollectionViewFlowLayout = { + let width = floor((UIScreen.width - 32 - 16) / 3) + let height = 145 / 109 * width + 41 + + let layout = UICollectionViewFlowLayout() + layout.minimumLineSpacing = 12 + layout.minimumInteritemSpacing = 8 + layout.itemSize = .init(width: width, height: height) + layout.sectionInset = .init(top: 0, left: 16, bottom: 0, right: 16) + return layout + }() + + private lazy var collectionView: FACollectionView = { + let collectionView = FACollectionView(frame: .zero, collectionViewLayout: collectionViewLayout) + collectionView.delegate = self + collectionView.dataSource = self + collectionView.contentInset = .init(top: 20, left: 0, bottom: UIScreen.safeBottom + 10, right: 0) + collectionView.register(UINib(nibName: "FAGenresListCell", bundle: nil), forCellWithReuseIdentifier: "cell") + collectionView.fa_addRefreshHeader(insetTop: collectionView.contentInset.top) { [weak self] in + self?.handleHeaderRefresh(nil) + } +// collectionView.fa_addRefreshFooter(insetBottom: 0) { [weak self] in +// self?.handleFooterRefresh(nil) +// } + return collectionView + }() + + override func viewDidLoad() { + super.viewDidLoad() + self.title = "New".localized + + fa_setupLayout() + + requestDataArr(page: 1, completer: nil) + } + + override func viewWillAppear(_ animated: Bool) { + super.viewWillAppear(animated) + self.navigationController?.setNavigationBarHidden(false, animated: true) + fa_setNavigationStyle() + } + + override func handleHeaderRefresh(_ completer: (() -> Void)?) { + requestDataArr(page: 1) { [weak self] in + self?.collectionView.fa_endHeaderRefreshing() + } + } + +// override func handleFooterRefresh(_ completer: (() -> Void)?) { +// requestDataArr(page: page + 1) { [weak self] in +// self?.collectionView.fa_endFooterRefreshing() +// } +// } +} + +extension FANewListViewController { + + private func fa_setupLayout() { + view.addSubview(collectionView) + + collectionView.snp.makeConstraints { make in + make.left.right.bottom.equalToSuperview() + make.top.equalToSuperview().offset(UIScreen.navBarHeight) + } + } + +} + +//MARK: UICollectionViewDelegate UICollectionViewDataSource +extension FANewListViewController: UICollectionViewDelegate, UICollectionViewDataSource { + + func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int { + return dataArr.count + } + + func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell { + let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "cell", for: indexPath) as! FAGenresListCell + cell.model = dataArr[indexPath.row] + return cell + } + + func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) { + let model = dataArr[indexPath.row] + let vc = FAPlayerDetailViewController() + vc.shortPlayId = model.short_play_id + self.navigationController?.pushViewController(vc, animated: true) + } +} + +extension FANewListViewController { + + private func requestDataArr(page: Int, completer: (() -> Void)?) { + + FAAPI.requestNewVideoList { [weak self] list in + guard let self = self else { return } + if let list = list { + self.dataArr = list + self.collectionView.reloadData() + + } + completer?() + } + } + +} diff --git a/Fableon/Class/Home/C/FAPopularListViewController.swift b/Fableon/Class/Home/C/FAPopularListViewController.swift new file mode 100644 index 0000000..6e08801 --- /dev/null +++ b/Fableon/Class/Home/C/FAPopularListViewController.swift @@ -0,0 +1,121 @@ +// +// FAPopularListViewController.swift +// Fableon +// +// Created by 长沙鸿瑶 on 2025/10/20. +// + +import UIKit + +class FAPopularListViewController: FAViewController { + + private var dataArr: [FAShortPlayModel] = [] +// private var page = 1 + + private lazy var collectionViewLayout: UICollectionViewFlowLayout = { + let width = floor((UIScreen.width - 32 - 16) / 3) + let height = 145 / 109 * width + 41 + + let layout = UICollectionViewFlowLayout() + layout.minimumLineSpacing = 12 + layout.minimumInteritemSpacing = 8 + layout.itemSize = .init(width: width, height: height) + layout.sectionInset = .init(top: 0, left: 16, bottom: 0, right: 16) + return layout + }() + + private lazy var collectionView: FACollectionView = { + let collectionView = FACollectionView(frame: .zero, collectionViewLayout: collectionViewLayout) + collectionView.delegate = self + collectionView.dataSource = self + collectionView.contentInset = .init(top: 20, left: 0, bottom: UIScreen.safeBottom + 10, right: 0) + collectionView.register(UINib(nibName: "FAGenresListCell", bundle: nil), forCellWithReuseIdentifier: "cell") + collectionView.fa_addRefreshHeader(insetTop: collectionView.contentInset.top) { [weak self] in + self?.handleHeaderRefresh(nil) + } +// collectionView.fa_addRefreshFooter(insetBottom: 0) { [weak self] in +// self?.handleFooterRefresh(nil) +// } + return collectionView + }() + + override func viewDidLoad() { + super.viewDidLoad() + self.title = "Popular".localized + + fa_setupLayout() + + requestDataArr(page: 1, completer: nil) + } + + override func viewWillAppear(_ animated: Bool) { + super.viewWillAppear(animated) + self.navigationController?.setNavigationBarHidden(false, animated: true) + fa_setNavigationStyle() + } + + override func handleHeaderRefresh(_ completer: (() -> Void)?) { + requestDataArr(page: 1) { [weak self] in + self?.collectionView.fa_endHeaderRefreshing() + } + } + +// override func handleFooterRefresh(_ completer: (() -> Void)?) { +// requestDataArr(page: page + 1) { [weak self] in +// self?.collectionView.fa_endFooterRefreshing() +// } +// } + +} + +extension FAPopularListViewController { + + private func fa_setupLayout() { + view.addSubview(collectionView) + + collectionView.snp.makeConstraints { make in + make.left.right.bottom.equalToSuperview() + make.top.equalToSuperview().offset(UIScreen.navBarHeight) + } + } + +} + +//MARK: UICollectionViewDelegate UICollectionViewDataSource +extension FAPopularListViewController: UICollectionViewDelegate, UICollectionViewDataSource { + + func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int { + return dataArr.count + } + + func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell { + let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "cell", for: indexPath) as! FAGenresListCell + cell.model = dataArr[indexPath.row] + return cell + } + + func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) { + let model = dataArr[indexPath.row] + let vc = FAPlayerDetailViewController() + vc.shortPlayId = model.short_play_id + self.navigationController?.pushViewController(vc, animated: true) + } +} + +extension FAPopularListViewController { + + private func requestDataArr(page: Int, completer: (() -> Void)?) { + + FAAPI.requestPopularVideoList { [weak self] list in + guard let self = self else { return } + if let list = list { + + self.dataArr = list + self.collectionView.reloadData() + } + completer?() + } + } + +} + diff --git a/Fableon/Class/Home/C/FARankingListViewController.swift b/Fableon/Class/Home/C/FARankingListViewController.swift new file mode 100644 index 0000000..e48f558 --- /dev/null +++ b/Fableon/Class/Home/C/FARankingListViewController.swift @@ -0,0 +1,128 @@ +// +// FARankingListViewController.swift +// Fableon +// +// Created by 长沙鸿瑶 on 2025/10/20. +// + +import UIKit + +class FARankingListViewController: FAViewController { + + private lazy var dataArr: [FAShortPlayModel] = [] + + private lazy var headerView: FARankingListHeaderView = { + let view = FARankingListHeaderView() + return view + }() + + private lazy var contentView: UIView = { + let view = UIView() + view.fa_setRoundedCorner(topLeft: 27, topRight: 27, bottomLeft: 0, bottomRight: 0) + view.backgroundColor = ._5_CA_8_FF_0_2 + return view + }() + + private lazy var collectionViewLayout: UICollectionViewFlowLayout = { + let layout = UICollectionViewFlowLayout() + layout.itemSize = .init(width: UIScreen.width - 32, height: 70) + layout.minimumLineSpacing = 15 + return layout + }() + + private lazy var collectionView: FACollectionView = { + let collectionView = FACollectionView(frame: .zero, collectionViewLayout: collectionViewLayout) + collectionView.delegate = self + collectionView.dataSource = self + collectionView.showsVerticalScrollIndicator = false + collectionView.showsHorizontalScrollIndicator = false + collectionView.contentInset = .init(top: 15, left: 0, bottom: UIScreen.safeBottom + 10, right: 0) + collectionView.register(UINib(nibName: "FARankingListCell", bundle: nil), forCellWithReuseIdentifier: "cell") + return collectionView + }() + + override func viewDidLoad() { + super.viewDidLoad() + self.title = "Rankings".localized + + fa_setupLayout() + + requestDataArr(completer: nil) + } + + override func viewWillAppear(_ animated: Bool) { + super.viewWillAppear(animated) + self.navigationController?.setNavigationBarHidden(false, animated: true) + fa_setNavigationStyle() + } + +} + +extension FARankingListViewController { + + private func fa_setupLayout() { + view.addSubview(headerView) + view.addSubview(contentView) + contentView.addSubview(collectionView) + + headerView.snp.makeConstraints { make in + make.left.right.equalToSuperview() + make.top.equalToSuperview().offset(UIScreen.navBarHeight) + } + + contentView.snp.makeConstraints { make in + make.left.equalToSuperview().offset(16) + make.centerX.equalToSuperview() + make.top.equalTo(headerView.snp.bottom) + make.bottom.equalToSuperview() + } + + collectionView.snp.makeConstraints { make in + make.edges.equalToSuperview() + } + } + +} + +//MARK: UICollectionViewDelegate UICollectionViewDataSource +extension FARankingListViewController: UICollectionViewDelegate, UICollectionViewDataSource { + + func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell { + let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "cell", for: indexPath) as! FARankingListCell + cell.model = dataArr[indexPath.row + 3] + cell.number = indexPath.row + 4 + return cell + } + + func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int { + let count = self.dataArr.count - 3 + if count < 0 { + return 0 + } + return count + } + + func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) { + let model = dataArr[indexPath.row + 3] + let vc = FAPlayerDetailViewController() + vc.shortPlayId = model.short_play_id + self.navigationController?.pushViewController(vc, animated: true) + } +} + +extension FARankingListViewController { + + private func requestDataArr(completer: (() -> Void)?) { + + FAAPI.requestRankingVideoList { [weak self] list in + guard let self = self else { return } + if let list = list { + self.dataArr = list + self.headerView.dataArr = list + self.collectionView.reloadData() + + } + completer?() + } + } +} diff --git a/Fableon/Class/Home/M/FACategoryModel.swift b/Fableon/Class/Home/M/FACategoryModel.swift new file mode 100644 index 0000000..eaf67a3 --- /dev/null +++ b/Fableon/Class/Home/M/FACategoryModel.swift @@ -0,0 +1,16 @@ +// +// FACategoryModel.swift +// Fableon +// +// Created by 长沙鸿瑶 on 2025/10/20. +// + +import UIKit +import SmartCodable + +struct FACategoryModel: SmartCodable { + + var id: String? + var category_name: String? + var short_play_list: [FAShortPlayModel]? +} diff --git a/Fableon/Class/Home/M/FAPopularModel.swift b/Fableon/Class/Home/M/FAPopularModel.swift new file mode 100644 index 0000000..ad62f9b --- /dev/null +++ b/Fableon/Class/Home/M/FAPopularModel.swift @@ -0,0 +1,15 @@ +// +// FAPopularModel.swift +// Fableon +// +// Created by 长沙鸿瑶 on 2025/10/20. +// + +import UIKit +import SmartCodable + +struct FAPopularModel: SmartCodable { + + var hotData: [FAShortPlayModel]? + +} diff --git a/Fableon/Class/Home/UI/FAHomeMustSeeContentView.swift b/Fableon/Class/Home/UI/FAHomeMustSeeContentView.swift index 6b36348..59cee9d 100644 --- a/Fableon/Class/Home/UI/FAHomeMustSeeContentView.swift +++ b/Fableon/Class/Home/UI/FAHomeMustSeeContentView.swift @@ -25,12 +25,12 @@ struct FAHomeMustSeeContentView: View { .padding(.leading, 10) .padding(.top, 12) Spacer() -// Image("Frame 3013") -// .padding(.top, 14) -// .padding(.trailing, 10) -// .onTapGesture { -// self.viewModel.pushMustSee(moduleKey) -// } + Image("Frame 3013") + .padding(.top, 14) + .padding(.trailing, 10) + .onTapGesture { + self.viewModel.pushMustSee(moduleKey) + } } VStack(spacing: 11) { diff --git a/Fableon/Class/Home/UI/FAHomeMustSeeShortView.swift b/Fableon/Class/Home/UI/FAHomeMustSeeShortView.swift index d9fd114..627817d 100644 --- a/Fableon/Class/Home/UI/FAHomeMustSeeShortView.swift +++ b/Fableon/Class/Home/UI/FAHomeMustSeeShortView.swift @@ -31,9 +31,9 @@ struct FAHomeMustSeeShortView: View { KFImage(URL(string: model.image_url ?? "")) .resizable() .scaledToFill() + .frame(width: 76, height: 102) .cornerRadius(5) .clipped() - .frame(width: 76, height: 102) .padding(.leading, 9) VStack(alignment: .leading) { diff --git a/Fableon/Class/Home/V/FAGenresCell.swift b/Fableon/Class/Home/V/FAGenresCell.swift index bba7246..17c4368 100644 --- a/Fableon/Class/Home/V/FAGenresCell.swift +++ b/Fableon/Class/Home/V/FAGenresCell.swift @@ -9,6 +9,23 @@ import UIKit class FAGenresCell: UICollectionViewCell { + var model: FACategoryModel? { + didSet { + var list = model?.short_play_list + let firstModel = list?.removeFirst() + + hotCountLabel.text = "\(firstModel?.watch_total ?? 0)" + nameLabel.text = model?.category_name + coverImageView.fa_setImage(firstModel?.image_url) + + + list?.enumerated().forEach { + let i = $0 + let imageView = smallImageViewArr[i] + imageView.fa_setImage($1.image_url) + } + } + } @IBOutlet weak var bgView: UIView! @@ -18,7 +35,7 @@ class FAGenresCell: UICollectionViewCell { @IBOutlet weak var hotCountLabel: UILabel! - private lazy var smallImageViewArr: [UIView] = [] + private lazy var smallImageViewArr: [UIImageView] = [] override func awakeFromNib() { super.awakeFromNib() diff --git a/Fableon/Class/Home/V/FAGenresCell.xib b/Fableon/Class/Home/V/FAGenresCell.xib index 0601e39..8e5fa7e 100644 --- a/Fableon/Class/Home/V/FAGenresCell.xib +++ b/Fableon/Class/Home/V/FAGenresCell.xib @@ -45,6 +45,7 @@ + diff --git a/Fableon/Class/Home/V/FAGenresListCell.swift b/Fableon/Class/Home/V/FAGenresListCell.swift index 0910ac2..d7d4ed6 100644 --- a/Fableon/Class/Home/V/FAGenresListCell.swift +++ b/Fableon/Class/Home/V/FAGenresListCell.swift @@ -8,7 +8,18 @@ import UIKit class FAGenresListCell: UICollectionViewCell { - + + var model: FAShortPlayModel? { + didSet { + coverImageView.fa_setImage(model?.image_url) + nameLabel.text = model?.name + } + } + + @IBOutlet weak var coverImageView: FAImageView! + + @IBOutlet weak var nameLabel: UILabel! + override func awakeFromNib() { super.awakeFromNib() // Initialization code diff --git a/Fableon/Class/Home/V/FAGenresListCell.xib b/Fableon/Class/Home/V/FAGenresListCell.xib index 35b4127..1f0e95d 100644 --- a/Fableon/Class/Home/V/FAGenresListCell.xib +++ b/Fableon/Class/Home/V/FAGenresListCell.xib @@ -45,6 +45,10 @@ + + + + diff --git a/Fableon/Class/Home/V/FARankingListCell.swift b/Fableon/Class/Home/V/FARankingListCell.swift new file mode 100644 index 0000000..5843061 --- /dev/null +++ b/Fableon/Class/Home/V/FARankingListCell.swift @@ -0,0 +1,42 @@ +// +// FARankingListCell.swift +// Fableon +// +// Created by 长沙鸿瑶 on 2025/10/20. +// + +import UIKit + +class FARankingListCell: UICollectionViewCell { + + var model: FAShortPlayModel? { + didSet { + coverImageView.fa_setImage(model?.image_url) + nameLabel.text = model?.name + epLabel.text = "Ep.##".localizedReplace(text: "\(model?.episode_total ?? 0)") + countLabel.text = "\(model?.watch_total ?? 0)" + } + } + + var number: Int = 0 { + didSet { + numberLabel.text = "\(number)" + } + } + + @IBOutlet weak var numberLabel: UILabel! + + @IBOutlet weak var coverImageView: FAImageView! + + @IBOutlet weak var nameLabel: UILabel! + + @IBOutlet weak var epLabel: UILabel! + + @IBOutlet weak var countLabel: UILabel! + + override func awakeFromNib() { + super.awakeFromNib() + // Initialization code + } + +} diff --git a/Fableon/Class/Home/V/FARankingListCell.xib b/Fableon/Class/Home/V/FARankingListCell.xib new file mode 100644 index 0000000..041de41 --- /dev/null +++ b/Fableon/Class/Home/V/FARankingListCell.xib @@ -0,0 +1,119 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Fableon/Class/Home/V/FARankingListHeaderView.swift b/Fableon/Class/Home/V/FARankingListHeaderView.swift new file mode 100644 index 0000000..33e363e --- /dev/null +++ b/Fableon/Class/Home/V/FARankingListHeaderView.swift @@ -0,0 +1,212 @@ +// +// FARankingListHeaderView.swift +// Fableon +// +// Created by 长沙鸿瑶 on 2025/10/20. +// + +import UIKit + +class FARankingListHeaderView: UIView { + + override var intrinsicContentSize: CGSize { + return .init(width: UIScreen.width, height: 150 + coverSize) + } + + var dataArr: [FAShortPlayModel] = [] { + didSet { + oneView.isHidden = true + twoView.isHidden = true + threeView.isHidden = true + if dataArr.count > 0 { + oneView.isHidden = false + oneView.model = dataArr[0] + } + if dataArr.count > 1 { + twoView.isHidden = false + twoView.model = dataArr[1] + } + if dataArr.count > 2 { + threeView.isHidden = false + threeView.model = dataArr[2] + } + } + } + + private lazy var margin = UIScreen.getRatioWidth(size: 43) + private lazy var spacing = 10.0 + private lazy var itemWidth = floor((UIScreen.width - margin * 2 - spacing * 2) / 3) + private lazy var coverSize = itemWidth - UIScreen.getRatioWidth(size: 36) + + + + private lazy var oneView: FARankingListHeaderItemView = { + let view = FARankingListHeaderItemView() + view.isHidden = true + view.coverSize = coverSize + view.numberImageView.image = UIImage(named: "皇冠1") + return view + }() + + private lazy var twoView: FARankingListHeaderItemView = { + let view = FARankingListHeaderItemView() + view.isHidden = true + view.coverSize = coverSize + view.numberImageView.image = UIImage(named: "皇冠2") + return view + }() + + private lazy var threeView: FARankingListHeaderItemView = { + let view = FARankingListHeaderItemView() + view.isHidden = true + view.coverSize = coverSize + view.numberImageView.image = UIImage(named: "皇冠3") + return view + }() + + override init(frame: CGRect) { + super.init(frame: frame) + + + addSubview(oneView) + addSubview(twoView) + addSubview(threeView) + + oneView.snp.makeConstraints { make in + make.centerX.equalToSuperview() + make.width.equalTo(itemWidth) + make.top.equalToSuperview().offset(32) + make.bottom.equalToSuperview().offset(-10) + } + + twoView.snp.makeConstraints { make in + make.right.equalTo(oneView.snp.left).offset(-10) + make.top.equalTo(oneView).offset(25) + make.width.equalTo(oneView) + make.bottom.equalToSuperview().offset(-10) + } + + threeView.snp.makeConstraints { make in + make.left.equalTo(oneView.snp.right).offset(10) + make.top.equalTo(twoView).offset(5) + make.width.equalTo(oneView) + make.bottom.equalToSuperview().offset(-10) + } + + } + + required init?(coder: NSCoder) { + fatalError("init(coder:) has not been implemented") + } + +} + + +class FARankingListHeaderItemView: UIView { + +// override var intrinsicContentSize: CGSize { +// return .init(width: 97, height: 140 + coverSize) +// } + + var model: FAShortPlayModel? { + didSet { + coverImageView.fa_setImage(model?.image_url) + nameLabel.text = model?.name + + } + } + + var coverSize: CGFloat = 60 { + didSet { + self.invalidateIntrinsicContentSize() + + coverImageView.snp.updateConstraints { make in + make.width.height.equalTo(coverSize) + } + + coverImageView.layer.cornerRadius = coverSize / 2 + + } + } + + private lazy var bgView: UIView = { + let view = FAGradientView() + view.fa_locations = [0, 1] + view.fa_colors = [UIColor._1680_FB.cgColor, UIColor._79_A_7_DB.withAlphaComponent(0).cgColor] + view.fa_startPoint = .init(x: 0.5, y: 0) + view.fa_endPoint = .init(x: 0.5, y: 1) + return view + }() + + private lazy var coverImageView: FAImageView = { + let imageView = FAImageView() + imageView.layer.borderWidth = 2 + imageView.layer.borderColor = UIColor.FFFFFF.cgColor + return imageView + }() + + private(set) lazy var numberImageView: UIImageView = { + let imageView = UIImageView() + return imageView + }() + + private lazy var nameLabel: UILabel = { + let label = UILabel() + label.textAlignment = .center + label.textColor = .FFFFFF + label.font = .font(ofSize: 14, weight: .bold) + label.numberOfLines = 2 + return label + }() + + override init(frame: CGRect) { + super.init(frame: frame) + addSubview(bgView) + addSubview(coverImageView) + addSubview(numberImageView) + addSubview(nameLabel) + + bgView.snp.makeConstraints { make in + make.edges.equalToSuperview() + } + + coverImageView.snp.makeConstraints { make in + make.centerX.equalToSuperview() + make.top.equalToSuperview().offset(20) + make.width.height.equalTo(60) + } + + numberImageView.snp.makeConstraints { make in + make.left.equalToSuperview().offset(-5) + make.top.equalToSuperview().offset(-8) + } + + nameLabel.snp.makeConstraints { make in + make.centerX.equalToSuperview() + make.right.lessThanOrEqualToSuperview().offset(-9) + make.top.equalTo(coverImageView.snp.bottom).offset(10) + } + + + let tap = UITapGestureRecognizer(target: self, action: #selector(handleTap)) + addGestureRecognizer(tap) + } + @objc private func handleTap() { + let vc = FAPlayerDetailViewController() + vc.shortPlayId = self.model?.short_play_id + self.viewController?.navigationController?.pushViewController(vc, animated: true) + } + + override func layoutSubviews() { + super.layoutSubviews() + + bgView.fa_setRoundedCorner(topLeft: self.width / 2, topRight: self.width / 2, bottomLeft: 0, bottomRight: 0) + + + } + + required init?(coder: NSCoder) { + fatalError("init(coder:) has not been implemented") + } + +} diff --git a/Fableon/Class/Home/VM/FAHomeViewModel.swift b/Fableon/Class/Home/VM/FAHomeViewModel.swift index c60b19e..3641698 100644 --- a/Fableon/Class/Home/VM/FAHomeViewModel.swift +++ b/Fableon/Class/Home/VM/FAHomeViewModel.swift @@ -126,9 +126,27 @@ extension FAHomeViewModel { } func pushMustSee(_ key: FAHomeModuleItem.ModuleKey?) { - debugLog("\(key?.rawValue)") + var vc: FAViewController? - let vc = FAGenresViewController() - FATool.topViewController?.navigationController?.pushViewController(vc, animated: true) + switch key { + case .v3_recommand: + vc = FAPopularListViewController() + + case .cagetory_recommand: + vc = FAGenresViewController() + + case .new_recommand: + vc = FANewListViewController() + + case .week_ranking: + vc = FARankingListViewController() + + default: + break + } + + if let vc = vc { + FATool.topViewController?.navigationController?.pushViewController(vc, animated: true) + } } } diff --git a/Fableon/Class/Me/C/FAFeedbackViewController.swift b/Fableon/Class/Me/C/FAFeedbackViewController.swift index e6534f3..0589cd7 100644 --- a/Fableon/Class/Me/C/FAFeedbackViewController.swift +++ b/Fableon/Class/Me/C/FAFeedbackViewController.swift @@ -13,18 +13,17 @@ class FAFeedbackViewController: FAAppWebViewController { self.webUrl = kFAFeedBackHomeWebUrl super.viewDidLoad() - + self.navigationItem.rightBarButtonItem = UIBarButtonItem(image: UIImage(named: "Frame 2085663258"), style: .plain, target: self, action: #selector(handleRightBarButton)) } - /* - // MARK: - Navigation - - // In a storyboard-based application, you will often want to do a little preparation before navigation - override func prepare(for segue: UIStoryboardSegue, sender: Any?) { - // Get the new view controller using segue.destination. - // Pass the selected object to the new view controller. + @objc private func handleRightBarButton() { + + let vc = FAAppWebViewController() + vc.webUrl = kFAFeedBackListWebUrl + + self.navigationController?.pushViewController(vc, animated: true) + } - */ } diff --git a/Fableon/Class/Me/C/FAMeListViewController.swift b/Fableon/Class/Me/C/FAMeListViewController.swift new file mode 100644 index 0000000..2f956bf --- /dev/null +++ b/Fableon/Class/Me/C/FAMeListViewController.swift @@ -0,0 +1,154 @@ +// +// FAMeListViewController.swift +// Fableon +// +// Created by 长沙鸿瑶 on 2025/10/23. +// + +import UIKit +import JXPagingView + +class FAMeListViewController: FAViewController, JXPagingViewListViewDelegate { + + var scrollCallback: ((_ : UIScrollView) -> Void)? + + private lazy var dataArr: [FAMeItemModel] = { + let arr = [ + FAMeItemModel(type: .feedback, name: "Feedback".localized, icon: UIImage(named: "icon_feedback")), + FAMeItemModel(type: .about, name: "About".localized, icon: UIImage(named: "icon_about")), +// FAMeItemModel(type: .setting, name: "Setting".localized, icon: UIImage(named: "icon_setting")) + + FAMeItemModel(type: .privacyPolicy, name: "Privacy Policy".localized, icon: UIImage(named: "icon_privacy")), + FAMeItemModel(type: .userAgreement, name: "User Agreement".localized, icon: UIImage(named: "icon_user")), + FAMeItemModel(type: .visitWebsite, name: "Visit Website".localized, icon: UIImage(named: "icon_visit")), + ] + return arr + }() + + + + private lazy var tableViewHeaderView: FAMeTableViewHeaderView = { + let view = FAMeTableViewHeaderView(frame: .init(x: 0, y: 0, width: UIScreen.width, height: 124)) + view.userInfo = FALogin.manager.userInfo + return view + }() + + private lazy var contentView: UIView = { + let view = UIView() + view.backgroundColor = ._4_D_4_A_4_A.withAlphaComponent(0.5) + view.fa_setRoundedCorner(topLeft: 28, topRight: 0, bottomLeft: 0, bottomRight: 0) + return view + }() + + private lazy var tableView: FATableView = { + let tableView = FATableView(frame: .zero, style: .plain) + tableView.delegate = self + tableView.dataSource = self + tableView.rowHeight = 56 + tableView.separatorInset = .init(top: 0, left: 32, bottom: 0, right: 32) + tableView.register(UINib(nibName: "FAMeCell", bundle: nil), forCellReuseIdentifier: "cell") +// tableView.addObserver(self, forKeyPath: "contentSize", context: nil) + return tableView + }() + + deinit { + NotificationCenter.default.removeObserver(self) + } + + override func viewDidLoad() { + super.viewDidLoad() + + NotificationCenter.default.addObserver(self, selector: #selector(userInfoUpdateNotification), name: FALogin.userInfoUpdateNotification, object: nil) + + self.bgView.isHidden = true + + fa_setupLayout() + } + + + @objc private func userInfoUpdateNotification() { + tableViewHeaderView.userInfo = FALogin.manager.userInfo + } + + func listScrollView() -> UIScrollView { + return self.tableView + } + + func listViewDidScrollCallback(callback: @escaping (UIScrollView) -> ()) { + self.scrollCallback = callback + } +} + +extension FAMeListViewController { + + private func fa_setupLayout() { + tableView.tableHeaderView = self.tableViewHeaderView + + view.addSubview(contentView) + contentView.addSubview(tableView) + + + contentView.snp.makeConstraints { make in + make.left.right.top.bottom.equalToSuperview() + } + + tableView.snp.makeConstraints { make in + make.left.right.bottom.equalToSuperview() + make.top.equalToSuperview().offset(19) + } + } +} + +//MARK: UITableViewDelegate, UITableViewDataSource +extension FAMeListViewController: UITableViewDelegate, UITableViewDataSource { + + func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { + let cell = tableView.dequeueReusableCell(withIdentifier: "cell", for: indexPath) as! FAMeCell + cell.item = dataArr[indexPath.row] + return cell + } + + func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { + return dataArr.count + } + + func scrollViewDidScroll(_ scrollView: UIScrollView) { + self.scrollCallback?(scrollView) + } + + func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) { + let item = dataArr[indexPath.row] + switch item.type { + case .about: + let vc = FAAboutViewController() + self.navigationController?.pushViewController(vc, animated: true) + + case .setting: + let vc = FASettingViewController() + self.navigationController?.pushViewController(vc, animated: true) + + case .feedback: + let vc = FAFeedbackViewController() + self.navigationController?.pushViewController(vc, animated: true) + + case .privacyPolicy: + let vc = FABaseWebViewController() + vc.webUrl = FAWebBaseURL + "/private" + self.navigationController?.pushViewController(vc, animated: true) + + case .userAgreement: + let vc = FABaseWebViewController() + vc.webUrl = FAWebBaseURL + "/user_policy" + self.navigationController?.pushViewController(vc, animated: true) + + case .visitWebsite: + if let url = URL(string: FAWebBaseURL) { + UIApplication.shared.open(url) + } + + default: + break + } + } +} + diff --git a/Fableon/Class/Me/C/FAMeViewController.swift b/Fableon/Class/Me/C/FAMeViewController.swift index 2f21b59..85269e9 100644 --- a/Fableon/Class/Me/C/FAMeViewController.swift +++ b/Fableon/Class/Me/C/FAMeViewController.swift @@ -7,53 +7,36 @@ import UIKit import YYText +import JXSegmentedView +import JXPagingView class FAMeViewController: FAViewController { - - private lazy var dataArr: [FAMeItemModel] = { - let arr = [ -// FAMeItemModel(type: .feedback, name: "Feedback".localized, icon: UIImage(named: "icon_feedback")), - FAMeItemModel(type: .about, name: "About".localized, icon: UIImage(named: "icon_about")), -// FAMeItemModel(type: .setting, name: "Setting".localized, icon: UIImage(named: "icon_setting")) - - FAMeItemModel(type: .privacyPolicy, name: "Privacy Policy".localized, icon: UIImage(named: "icon_privacy")), - FAMeItemModel(type: .userAgreement, name: "User Agreement".localized, icon: UIImage(named: "icon_user")), - FAMeItemModel(type: .visitWebsite, name: "Visit Website".localized, icon: UIImage(named: "icon_visit")), - ] - return arr - }() - - - private lazy var scrollView: FAScrollView = { - let scrollView = FAScrollView() - return scrollView - }() - private lazy var headerView: FAMeHeaderView = { let view = FAMeHeaderView() view.userInfo = FALogin.manager.userInfo return view }() - private lazy var contentView: UIView = { - let view = UIView() - view.backgroundColor = ._4_D_4_A_4_A.withAlphaComponent(0.5) - view.fa_setRoundedCorner(topLeft: 30, topRight: 30, bottomLeft: 0, bottomRight: 0) + private lazy var listView: FAMeListViewController = FAMeListViewController() + + private lazy var segmentedView: JXSegmentedView = { + let view = JXSegmentedView() return view }() - private lazy var tableView: FATableView = { - let tableView = FATableView(frame: .zero, style: .plain) - tableView.delegate = self - tableView.dataSource = self - tableView.rowHeight = 56 - tableView.separatorInset = .init(top: 0, left: 32, bottom: 0, right: 32) - tableView.register(UINib(nibName: "FAMeCell", bundle: nil), forCellReuseIdentifier: "cell") - tableView.addObserver(self, forKeyPath: "contentSize", context: nil) - return tableView + private lazy var pagingView: JXPagingView = { + let view = JXPagingView(delegate: self) + view.mainTableView.backgroundColor = .clear + view.listContainerView.backgroundColor = .clear + view.listContainerView.listCellBackgroundColor = .clear + view.mainTableView.fa_addRefreshHeader(insetTop: 0) { [weak self] in + self?.handleHeaderRefresh(nil) + } + return view }() + deinit { NotificationCenter.default.removeObserver(self) } @@ -62,6 +45,8 @@ class FAMeViewController: FAViewController { super.viewDidLoad() NotificationCenter.default.addObserver(self, selector: #selector(userInfoUpdateNotification), name: FALogin.userInfoUpdateNotification, object: nil) + + fa_setupLayout() } @@ -75,13 +60,12 @@ class FAMeViewController: FAViewController { FALogin.manager.requestUserInfo(completer: nil) } - override func observeValue(forKeyPath keyPath: String?, of object: Any?, change: [NSKeyValueChangeKey : Any]?, context: UnsafeMutableRawPointer?) { - if keyPath == "contentSize" { - self.updateLayout() + override func handleHeaderRefresh(_ completer: (() -> Void)?) { + FALogin.manager.requestUserInfo { [weak self] in + self?.pagingView.mainTableView.fa_endHeaderRefreshing() } } - @objc private func userInfoUpdateNotification() { headerView.userInfo = FALogin.manager.userInfo } @@ -91,98 +75,43 @@ class FAMeViewController: FAViewController { extension FAMeViewController { private func fa_setupLayout() { - view.addSubview(scrollView) - scrollView.addSubview(headerView) - scrollView.addSubview(contentView) - contentView.addSubview(tableView) + view.addSubview(pagingView) - scrollView.snp.makeConstraints { make in + pagingView.snp.makeConstraints { make in make.left.right.bottom.equalToSuperview() make.top.equalToSuperview().offset(UIScreen.safeTop) } - - headerView.snp.makeConstraints { make in - make.left.centerX.equalToSuperview() - make.top.equalToSuperview().offset(40) - } - - contentView.snp.makeConstraints { make in - make.left.centerX.equalToSuperview() - make.top.equalTo(headerView.snp.bottom).offset(24) - make.bottom.equalToSuperview() - make.height.equalTo(UIScreen.height - UIScreen.tabBarHeight - UIScreen.safeTop) - } - - tableView.snp.makeConstraints { make in - make.left.right.bottom.equalToSuperview() - make.top.equalToSuperview().offset(19) - } } - private func updateLayout() { - let maxHeight = UIScreen.height - UIScreen.tabBarHeight - UIScreen.safeTop - let minHeight = UIScreen.height - UIScreen.tabBarHeight - UIScreen.safeTop - self.headerView.height - 40 - 24 - var height = self.tableView.contentSize.height - if height > maxHeight { - height = maxHeight - } - if height < minHeight { - height = minHeight - } - - contentView.snp.updateConstraints { make in - make.height.equalTo(height) - } - } } -//MARK: UITableViewDelegate, UITableViewDataSource -extension FAMeViewController: UITableViewDelegate, UITableViewDataSource { + +//MARK: JXPagingViewDelegate +extension FAMeViewController: JXPagingViewDelegate { - - func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { - let cell = tableView.dequeueReusableCell(withIdentifier: "cell", for: indexPath) as! FAMeCell - cell.item = dataArr[indexPath.row] - return cell + func pagingView(_ pagingView: JXPagingView, initListAtIndex index: Int) -> any JXPagingViewListViewDelegate { + return listView } - func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { - return dataArr.count + func tableHeaderViewHeight(in pagingView: JXPagingView) -> Int { + return Int(ceill(headerView.contentHeight)) } - func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) { - let item = dataArr[indexPath.row] - switch item.type { - case .about: - let vc = FAAboutViewController() - self.navigationController?.pushViewController(vc, animated: true) - - case .setting: - let vc = FASettingViewController() - self.navigationController?.pushViewController(vc, animated: true) - - case .feedback: - let vc = FAFeedbackViewController() - self.navigationController?.pushViewController(vc, animated: true) - - case .privacyPolicy: - let vc = FABaseWebViewController() - vc.webUrl = FAWebBaseURL + "/private" - self.navigationController?.pushViewController(vc, animated: true) - - case .userAgreement: - let vc = FABaseWebViewController() - vc.webUrl = FAWebBaseURL + "/user_policy" - self.navigationController?.pushViewController(vc, animated: true) - - case .visitWebsite: - if let url = URL(string: FAWebBaseURL) { - UIApplication.shared.open(url) - } - - default: - break - } + func tableHeaderView(in pagingView: JXPagingView) -> UIView { + return headerView + } + + func heightForPinSectionHeader(in pagingView: JXPagingView) -> Int { + return 0 + } + + func viewForPinSectionHeader(in pagingView: JXPagingView) -> UIView { + return UIView() + } + + func numberOfLists(in pagingView: JXPagingView) -> Int { + return 1 } } + diff --git a/Fableon/Class/Me/M/FAMeItemModel.swift b/Fableon/Class/Me/M/FAMeItemModel.swift index 81aa17b..260310a 100644 --- a/Fableon/Class/Me/M/FAMeItemModel.swift +++ b/Fableon/Class/Me/M/FAMeItemModel.swift @@ -16,6 +16,12 @@ struct FAMeItemModel { case privacyPolicy case userAgreement case visitWebsite + ///消费记录 + case consumptionRecords + ///购买记录 + case purchaseRecords + ///金币奖励 + case rewardCoins } diff --git a/Fableon/Class/Me/V/FAMeCoinsView.swift b/Fableon/Class/Me/V/FAMeCoinsView.swift new file mode 100644 index 0000000..9bf556c --- /dev/null +++ b/Fableon/Class/Me/V/FAMeCoinsView.swift @@ -0,0 +1,83 @@ +// +// FAMeCoinsView.swift +// Fableon +// +// Created by 长沙鸿瑶 on 2025/10/22. +// + +import UIKit + +class FAMeCoinsView: UIControl { + + var title: String? { + didSet { + titleLabel.text = title + } + } + + var count: Int = 0 { + didSet { + coinLabel.text = "\(count)" + } + } + + private lazy var coinImageView: UIImageView = { + let imageView = UIImageView(image: UIImage(named: "coins_icon_01")) + imageView.setContentHuggingPriority(.required, for: .horizontal) + imageView.setContentCompressionResistancePriority(.required, for: .horizontal) + return imageView + }() + + private lazy var titleLabel: UILabel = { + let label = UILabel() + label.font = .font(ofSize: 10, weight: .bold) + label.textColor = .F_7_F_497 + return label + }() + + private lazy var coinLabel: UILabel = { + let label = UILabel() + label.font = .font(ofSize: 14, weight: .bold) + label.textColor = .FFFFFF + return label + }() + + override init(frame: CGRect) { + super.init(frame: frame) + + fa_setupLayout() + } + + required init?(coder: NSCoder) { + fatalError("init(coder:) has not been implemented") + } + +} + +extension FAMeCoinsView { + + private func fa_setupLayout() { + addSubview(coinImageView) + addSubview(titleLabel) + addSubview(coinLabel) + + coinImageView.snp.makeConstraints { make in + make.left.equalToSuperview() + make.centerY.equalToSuperview() + make.top.equalToSuperview() + } + + titleLabel.snp.makeConstraints { make in + make.top.equalToSuperview().offset(-2) + make.left.equalTo(coinImageView.snp.right).offset(10) + make.right.lessThanOrEqualToSuperview() + } + + coinLabel.snp.makeConstraints { make in + make.left.equalTo(titleLabel) + make.right.lessThanOrEqualToSuperview() + make.bottom.equalToSuperview().offset(0) + } + } + +} diff --git a/Fableon/Class/Me/V/FAMeHeaderView.swift b/Fableon/Class/Me/V/FAMeHeaderView.swift index 4514e01..604c596 100644 --- a/Fableon/Class/Me/V/FAMeHeaderView.swift +++ b/Fableon/Class/Me/V/FAMeHeaderView.swift @@ -9,6 +9,8 @@ import UIKit class FAMeHeaderView: UIView { + var contentHeight: CGFloat = 40 + 66 + 40 + 28 + 24 + var userInfo: FAUserInfo? { didSet { avatarImageView.fa_setImage(userInfo?.avator) @@ -16,6 +18,10 @@ class FAMeHeaderView: UIView { userNameLabel.text = userInfo?.getNickName() idLabel.text = "ID:\(userInfo?.customer_id ?? "")" + + coinsView.count = userInfo?.coin_left_total ?? 0 + + bonusCoinsView.count = userInfo?.send_coin_left_total ?? 0 } } @@ -39,6 +45,31 @@ class FAMeHeaderView: UIView { return label }() + private lazy var coinsView: FAMeCoinsView = { + let view = FAMeCoinsView() + view.title = "Coins".localized + view.count = 0 + view.addAction(UIAction(handler: { [weak self] _ in + guard let self = self else { return } + let vc = FAWalletViewController() + self.viewController?.navigationController?.pushViewController(vc, animated: true) + }), for: .touchUpInside) + return view + }() + + private lazy var bonusCoinsView: FAMeCoinsView = { + let view = FAMeCoinsView() + view.title = "Bonus" + view.count = 0 + view.addAction(UIAction(handler: { [weak self] _ in + guard let self = self else { return } + let vc = FAWalletViewController() + self.viewController?.navigationController?.pushViewController(vc, animated: true) + }), for: .touchUpInside) + return view + }() + + override init(frame: CGRect) { super.init(frame: frame) fa_setupLayout() @@ -55,12 +86,13 @@ extension FAMeHeaderView { addSubview(avatarImageView) addSubview(userNameLabel) addSubview(idLabel) + addSubview(coinsView) + addSubview(bonusCoinsView) avatarImageView.snp.makeConstraints { make in make.left.equalToSuperview().offset(16) - make.top.equalToSuperview() + make.top.equalToSuperview().offset(40) make.width.height.equalTo(66) - make.bottom.equalToSuperview() } userNameLabel.snp.makeConstraints { make in @@ -73,6 +105,16 @@ extension FAMeHeaderView { make.left.equalTo(userNameLabel) make.top.equalTo(userNameLabel.snp.bottom).offset(2) } + + coinsView.snp.makeConstraints { make in + make.left.equalToSuperview().offset(16) + make.top.equalTo(avatarImageView.snp.bottom).offset(40) + } + + bonusCoinsView.snp.makeConstraints { make in + make.top.equalTo(coinsView) + make.left.equalTo(coinsView.snp.right).offset(40) + } } } diff --git a/Fableon/Class/Me/V/FAMeTableViewHeaderView.swift b/Fableon/Class/Me/V/FAMeTableViewHeaderView.swift new file mode 100644 index 0000000..78711bd --- /dev/null +++ b/Fableon/Class/Me/V/FAMeTableViewHeaderView.swift @@ -0,0 +1,165 @@ +// +// FAMeTableViewHeaderView.swift +// Fableon +// +// Created by 长沙鸿瑶 on 2025/10/22. +// + +import UIKit + +class FAMeTableViewHeaderView: UIView { + + var userInfo: FAUserInfo? { + didSet { + if userInfo?.is_vip == true { + subscribeView.isHidden = true + expirationView.isHidden = false + vipImageView.image = UIImage(named: "vip_image_02") + titleLabel.text = "Activated".localized + subtitleLabel.text = "vip_tip_01".localized + } else { + subscribeView.isHidden = false + expirationView.isHidden = true + vipImageView.image = UIImage(named: "vip_image_01") + titleLabel.text = "Not Activated".localized + subtitleLabel.text = "vip_tip_02".localized + } + + + expirationView.setNeedsUpdateConfiguration() + } + } + + private lazy var contentView: FAGradientView = { + let view = FAGradientView() + view.fa_colors = [UIColor.C_3_FAFF.cgColor, UIColor._7_FDBF_5.cgColor, UIColor._105_C_91.cgColor] + view.fa_locations = [0, 0.5, 1] + view.fa_startPoint = .init(x: 0, y: 0.5) + view.fa_endPoint = .init(x: 1, y: 0.5) + view.fa_setRoundedCorner(topLeft: 28, topRight: 6, bottomLeft: 6, bottomRight: 6) + return view + }() + + private lazy var vipImageView: UIImageView = { + let imageView = UIImageView(image: UIImage(named: "vip_image_01")) + return imageView + }() + + private lazy var titleLabel: UILabel = { + let label = UILabel() + label.font = .font(ofSize: 18, weight: .bold) + label.textColor = ._3_A_271_E + return label + }() + + private lazy var subtitleLabel: UILabel = { + let label = UILabel() + label.font = .font(ofSize: 12, weight: .regular) + label.textColor = ._000000.withAlphaComponent(0.5) + return label + }() + + private lazy var subscribeView: UIButton = { + var config = UIButton.Configuration.plain() + config.attributedTitle = AttributedString("Subscribe".localized, attributes: AttributeContainer([ + .font : UIFont.font(ofSize: 14, weight: .bold), + .foregroundColor : UIColor._333333 + ])) + + let button = FAGradientButton(configuration: config) + button.isUserInteractionEnabled = false + button.layer.cornerRadius = 18 + button.layer.masksToBounds = true + button.fa_colors = [UIColor.BEDFFF.cgColor, UIColor._52_A_2_F_1.cgColor] + button.fa_locations = [0, 1] + button.fa_startPoint = .init(x: 0, y: 0.5) + button.fa_endPoint = .init(x: 1, y: 0.5) + return button + }() + + private lazy var expirationView: UIButton = { + var config = UIButton.Configuration.plain() + config.contentInsets = .zero + config.image = UIImage(named: "Frame 3021") + config.imagePadding = 4 + + let button = UIButton(configuration: config) + button.isUserInteractionEnabled = false + button.configurationUpdateHandler = { [weak self] button in + guard let self = self else { return } + + let date = Date(timeIntervalSince1970: userInfo?.vip_end_time ?? 0) + let text = "vip_expires_date".localizedReplace(text: date.fa_formatString("yyyy-MM-dd")) + button.configuration?.attributedTitle = AttributedString(text, attributes: AttributeContainer([ + .font : UIFont.font(ofSize: 12, weight: .medium), + .foregroundColor : UIColor._3_A_271_E + ])) + } + return button + }() + + override init(frame: CGRect) { + super.init(frame: frame) + + let tap = UITapGestureRecognizer { [weak self] _ in + guard let self = self else { return } + let vc = FAStoreViewController() + self.viewController?.navigationController?.pushViewController(vc, animated: true) + } + contentView.addGestureRecognizer(tap) + + fa_setupLayout() + } + + required init?(coder: NSCoder) { + fatalError("init(coder:) has not been implemented") + } + +} + +extension FAMeTableViewHeaderView { + + private func fa_setupLayout() { + addSubview(contentView) + contentView.addSubview(vipImageView) + contentView.addSubview(titleLabel) + contentView.addSubview(subtitleLabel) + contentView.addSubview(subscribeView) + contentView.addSubview(expirationView) + + contentView.snp.makeConstraints { make in + make.left.equalToSuperview().offset(16) + make.centerX.equalToSuperview() + make.top.bottom.equalToSuperview() + } + + vipImageView.snp.makeConstraints { make in + make.centerY.equalToSuperview() + make.right.equalToSuperview().offset(-4) + } + + titleLabel.snp.makeConstraints { make in + make.left.equalToSuperview().offset(16) + make.top.equalToSuperview().offset(16) + } + + subtitleLabel.snp.makeConstraints { make in + make.left.equalToSuperview().offset(16) + make.top.equalTo(titleLabel.snp.bottom).offset(3) + } + + subscribeView.snp.makeConstraints { make in + make.left.equalToSuperview().offset(16) + make.bottom.equalToSuperview().offset(-16) + make.height.equalTo(36) + make.width.equalTo(130) + } + + expirationView.snp.makeConstraints { make in + make.left.equalToSuperview().offset(16) + make.bottom.equalToSuperview().offset(-16) + } + + } + +} diff --git a/Fableon/Class/Player/M/FAVideoUnlockResult.swift b/Fableon/Class/Player/M/FAVideoUnlockResult.swift new file mode 100644 index 0000000..21d4e6b --- /dev/null +++ b/Fableon/Class/Player/M/FAVideoUnlockResult.swift @@ -0,0 +1,26 @@ +// +// FAVideoUnlockResult.swift +// Fableon +// +// Created by 长沙鸿瑶 on 2025/10/21. +// + +import UIKit +import SmartCodable + +struct FAVideoUnlockResult: SmartCodable { + + enum Status: String, SmartCaseDefaultable { + ///前面还有没购买的剧 + case jump = "jump" + ///没找到视频 + case noPlay = "no_play" + ///金币不足跳充值 + case notEnough = "not_enough" + ///购买成功 + case success = "success" + } + + var status: Status? + +} diff --git a/Fableon/Class/Player/V/FAEpSelectorCell.swift b/Fableon/Class/Player/V/FAEpSelectorCell.swift index 63fd8fa..bcdc4ad 100644 --- a/Fableon/Class/Player/V/FAEpSelectorCell.swift +++ b/Fableon/Class/Player/V/FAEpSelectorCell.swift @@ -12,6 +12,8 @@ class FAEpSelectorCell: UICollectionViewCell { var model: FAVideoInfoModel? { didSet { numberLabel.text = model?.episode + + lockImageView.isHidden = !(model?.is_lock ?? true) } } @@ -31,6 +33,9 @@ class FAEpSelectorCell: UICollectionViewCell { @IBOutlet weak var numberLabel: UILabel! + @IBOutlet weak var lockImageView: UIImageView! + + override func awakeFromNib() { super.awakeFromNib() self.layer.masksToBounds = false diff --git a/Fableon/Class/Player/V/FAEpSelectorCell.xib b/Fableon/Class/Player/V/FAEpSelectorCell.xib index 67bc00c..3281f19 100644 --- a/Fableon/Class/Player/V/FAEpSelectorCell.xib +++ b/Fableon/Class/Player/V/FAEpSelectorCell.xib @@ -23,18 +23,27 @@ + + + + + + + + + diff --git a/Fableon/Class/Player/V/FAPlayerDetailCell.swift b/Fableon/Class/Player/V/FAPlayerDetailCell.swift index ae930bd..4538d57 100644 --- a/Fableon/Class/Player/V/FAPlayerDetailCell.swift +++ b/Fableon/Class/Player/V/FAPlayerDetailCell.swift @@ -14,11 +14,17 @@ class FAPlayerDetailCell: JXPlayerListCell { return FAPlayerDetailControlView.self } + var fa_viewModel: FAShortDetailViewModel { + return self.viewModel as! FAShortDetailViewModel + } override var model: Any? { didSet { let model = self.model as? FAVideoInfoModel self.player.setPlayUrl(url: model?.video_url ?? "") + + self.lockView.isHidden = !(model?.is_lock ?? true) + lockView.videoInfo = model } } @@ -29,9 +35,26 @@ class FAPlayerDetailCell: JXPlayerListCell { } } + var hasLastEpisodeUnlocked: Bool = false { + didSet { + self.lockView.hasLastEpisodeUnlocked = hasLastEpisodeUnlocked + } + } + + + + private lazy var lockView: FAVideoLockView = { + let view = FAVideoLockView() + view.clickUnlockButton = { [weak self] in + self?.fa_viewModel.handleUnlockVideo() + } + return view + }() + override init(frame: CGRect) { super.init(frame: frame) + fa_setupLayout() } @MainActor required init?(coder: NSCoder) { @@ -41,6 +64,18 @@ class FAPlayerDetailCell: JXPlayerListCell { } +extension FAPlayerDetailCell { + + private func fa_setupLayout() { + addSubview(lockView) + + lockView.snp.makeConstraints { make in + make.edges.equalToSuperview() + } + } + +} + extension FAPlayerDetailCell { override func jx_playerReadyToPlay(_ player: JXPlayer) { diff --git a/Fableon/Class/Player/V/FAPlayerDetailControlView.swift b/Fableon/Class/Player/V/FAPlayerDetailControlView.swift index 21bf133..9b1a59e 100644 --- a/Fableon/Class/Player/V/FAPlayerDetailControlView.swift +++ b/Fableon/Class/Player/V/FAPlayerDetailControlView.swift @@ -24,7 +24,7 @@ class FAPlayerDetailControlView: JXPlayerListControlView { override var model: Any? { didSet { -// let model = self.model as? FAVideoInfoModel + let model = self.model as? FAVideoInfoModel updateEp() } @@ -133,6 +133,8 @@ class FAPlayerDetailControlView: JXPlayerListControlView { return button }() + + deinit { NotificationCenter.default.removeObserver(self) } @@ -230,6 +232,8 @@ extension FAPlayerDetailControlView { make.height.equalTo(44) } + + } } diff --git a/Fableon/Class/Player/V/FAVideoLockView.swift b/Fableon/Class/Player/V/FAVideoLockView.swift new file mode 100644 index 0000000..d0eefee --- /dev/null +++ b/Fableon/Class/Player/V/FAVideoLockView.swift @@ -0,0 +1,80 @@ +// +// FAVideoLockView.swift +// Fableon +// +// Created by 长沙鸿瑶 on 2025/10/20. +// + +import UIKit + +class FAVideoLockView: UIView { + + var clickUnlockButton: (() -> Void)? + + var videoInfo: FAVideoInfoModel? { + didSet { + unlockButton.setNeedsUpdateConfiguration() + } + } + + var hasLastEpisodeUnlocked = false { + didSet { + unlockButton.setNeedsUpdateConfiguration() + } + } + + private lazy var unlockButton: UIButton = { + var config = UIButton.Configuration.plain() + config.image = UIImage(named: "lock_icon_02") + config.imagePadding = 6 + + let button = FAGradientButton(configuration: config, primaryAction: UIAction(handler: { [weak self] _ in + guard let self = self else { return } + self.clickUnlockButton?() + })) + button.configurationUpdateHandler = { [weak self] button in + guard let self = self else { return } + let attributeContainer = AttributeContainer([ + .font : UIFont.font(ofSize: 14, weight: .medium), + .foregroundColor : UIColor._000000 + ]) + if hasLastEpisodeUnlocked { + button.configuration?.attributedTitle = .init("video_lock_tip_text".localized, attributes: attributeContainer) + } else { + button.configuration?.attributedTitle = .init("Unlocking costs ## coins".localizedReplace(text: "\(videoInfo?.coins ?? 0)"), attributes: attributeContainer) + } + } + button.layer.cornerRadius = 26 + button.layer.masksToBounds = true + button.fa_colors = [UIColor.BEDFFF.cgColor, UIColor._52_A_2_F_1.cgColor] + button.fa_locations = [0, 1] + button.fa_startPoint = .init(x: 0, y: 0.5) + button.fa_endPoint = .init(x: 1, y: 0.5) + return button + }() + + override init(frame: CGRect) { + super.init(frame: frame) + backgroundColor = ._000000.withAlphaComponent(0.6) + fa_setupLayout() + } + + required init?(coder: NSCoder) { + fatalError("init(coder:) has not been implemented") + } + +} + +extension FAVideoLockView { + + private func fa_setupLayout() { + addSubview(unlockButton) + + unlockButton.snp.makeConstraints { make in + make.center.equalToSuperview() + make.left.equalToSuperview().offset(44) + make.height.equalTo(52) + } + } + +} diff --git a/Fableon/Class/Player/VC/FAPlayerDetailViewController.swift b/Fableon/Class/Player/VC/FAPlayerDetailViewController.swift index 7a1d05f..f8ab0d1 100644 --- a/Fableon/Class/Player/VC/FAPlayerDetailViewController.swift +++ b/Fableon/Class/Player/VC/FAPlayerDetailViewController.swift @@ -13,6 +13,7 @@ import FDFullscreenPopGesture class FAPlayerDetailViewController: JXPlayerListViewController { var shortPlayId: String? + var activityId: String? override var ViewModelClass: JXPlayerListViewModel.Type { return FAShortDetailViewModel.self @@ -77,10 +78,16 @@ class FAPlayerDetailViewController: JXPlayerListViewController { } override func play() { - super.play() - let videoInfo = self.viewModel.currentCell?.model as? FAVideoInfoModel - FAAPI.requestCreatePlayHistory(videoId: videoInfo?.short_play_video_id, shortPlayId: videoInfo?.short_play_id) + + if videoInfo?.is_lock != true { + super.play() + FAAPI.requestCreatePlayHistory(videoId: videoInfo?.short_play_video_id, shortPlayId: videoInfo?.short_play_id) + return + } + self.pause() + + } } @@ -110,6 +117,13 @@ extension FAPlayerDetailViewController: JXPlayerListViewControllerDelegate, JXPl let cell = self.dequeueReusableCell(withReuseIdentifier: "FAPlayerDetailCell", for: indexPath) as! FAPlayerDetailCell cell.model = self.fa_viewModel.dataArr[indexPath.section].episodeList?[indexPath.row] cell.shortModel = self.fa_viewModel.dataArr[indexPath.section].shortPlayInfo + + let upRow = indexPath.row - 1 + if upRow >= 0, let videoInfo = self.fa_viewModel.dataArr[indexPath.section].episodeList?[upRow], videoInfo.is_lock == true { + cell.hasLastEpisodeUnlocked = true + } else { + cell.hasLastEpisodeUnlocked = false + } return cell } diff --git a/Fableon/Class/Player/VM/FAShortDetailViewModel.swift b/Fableon/Class/Player/VM/FAShortDetailViewModel.swift index f297f69..5766c34 100644 --- a/Fableon/Class/Player/VM/FAShortDetailViewModel.swift +++ b/Fableon/Class/Player/VM/FAShortDetailViewModel.swift @@ -110,5 +110,61 @@ extension FAShortDetailViewModel { self.popView = view } + func handleUnlockVideo() { + unlockVideo { [weak self] finish in + if finish { + self?.playerListVC?.reloadData { + self?.playerListVC?.play() + } + } + } + } + + ///打开充值页面 + func openRechargeView() { + guard let videoInfo = self.currentCell?.model as? FAVideoInfoModel else { return } + guard self.popView == nil else { return } + + + + + } + +} + +extension FAShortDetailViewModel { + + private func unlockVideo(completer: ((_ finish: Bool) -> Void)?) { + guard let videoInfo = self.currentCell?.model as? FAVideoInfoModel else { return } + guard let shortPlayId = videoInfo.short_play_id else { return } + guard let videoId = videoInfo.short_play_video_id else { return } + + FAAPI.requestCoinUnlockVideo(shortPlayId: shortPlayId, videoId: videoId) { [weak self] model in + guard let self = self else { return } + guard let model = model else { + completer?(false) + return + } + + switch model.status { + case .jump: + FAToast.show(text: "buy_fail_toast_02".localized) + case .noPlay: + FAToast.show(text: "buy_fail_toast_01".localized) + case .notEnough: + self.openRechargeView() + default: break + } + + if model.status == .success { + FALogin.manager.requestUserInfo { + videoInfo.is_lock = false + completer?(true) + } + } else { + completer?(false) + } + } + } } diff --git a/Fableon/Class/Store/C/FACoinRecordViewController.swift b/Fableon/Class/Store/C/FACoinRecordViewController.swift new file mode 100644 index 0000000..ca8b2af --- /dev/null +++ b/Fableon/Class/Store/C/FACoinRecordViewController.swift @@ -0,0 +1,52 @@ +// +// FACoinRecordViewController.swift +// Fableon +// +// Created by 长沙鸿瑶 on 2025/10/23. +// + +import UIKit + +class FACoinRecordViewController: FAViewController { + + + private lazy var tableView: FATableView = { + let tableView = FATableView(frame: .zero, style: .plain) + tableView.delegate = self + tableView.dataSource = self + tableView.rowHeight = 72 + tableView.separatorColor = .FFFFFF.withAlphaComponent(0.1) + 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") + return tableView + }() + + override func viewDidLoad() { + super.viewDidLoad() + bgView.isHidden = true + + view.addSubview(tableView) + + tableView.snp.makeConstraints { make in + make.left.right.bottom.equalToSuperview() + make.top.equalToSuperview() + } + } + + +} + +//MARK: UITableViewDelegate UITableViewDataSource +extension FACoinRecordViewController: UITableViewDelegate, UITableViewDataSource { + + func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { + let cell = tableView.dequeueReusableCell(withIdentifier: "cell", for: indexPath) as! FAOrderRecordCell + return cell + } + + func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { + return 20 + } + +} diff --git a/Fableon/Class/Store/C/FAConsumptionRecordsViewController.swift b/Fableon/Class/Store/C/FAConsumptionRecordsViewController.swift new file mode 100644 index 0000000..bff7493 --- /dev/null +++ b/Fableon/Class/Store/C/FAConsumptionRecordsViewController.swift @@ -0,0 +1,66 @@ +// +// FAConsumptionRecordsViewController.swift +// Fableon +// +// Created by 长沙鸿瑶 on 2025/10/23. +// + +import UIKit + +class FAConsumptionRecordsViewController: FAViewController { + + + private lazy var tableView: FATableView = { + let tableView = FATableView(frame: .zero, style: .plain) + tableView.delegate = self + tableView.dataSource = self + tableView.rowHeight = 71 + tableView.separatorColor = .FFFFFF.withAlphaComponent(0.1) + 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") + return tableView + }() + + override func viewDidLoad() { + super.viewDidLoad() + self.title = "Consumption Records".localized + + fa_setupLayout() + } + + + override func viewWillAppear(_ animated: Bool) { + super.viewWillAppear(animated) + self.navigationController?.setNavigationBarHidden(false, animated: true) + fa_setNavigationStyle() + } + +} + +extension FAConsumptionRecordsViewController { + + private func fa_setupLayout() { + view.addSubview(tableView) + + tableView.snp.makeConstraints { make in + make.left.right.bottom.equalToSuperview() + make.top.equalToSuperview().offset(UIScreen.navBarHeight) + } + } + +} + + +//MARK: UITableViewDelegate UITableViewDataSource +extension FAConsumptionRecordsViewController: UITableViewDelegate, UITableViewDataSource { + + func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { + let cell = tableView.dequeueReusableCell(withIdentifier: "cell", for: indexPath) as! FAConsumptionRecordsCell + return cell + } + + func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { + return 20 + } +} diff --git a/Fableon/Class/Store/C/FAOrderRecordsViewController.swift b/Fableon/Class/Store/C/FAOrderRecordsViewController.swift new file mode 100644 index 0000000..7a2bac1 --- /dev/null +++ b/Fableon/Class/Store/C/FAOrderRecordsViewController.swift @@ -0,0 +1,112 @@ +// +// FAOrderRecordsViewController.swift +// Fableon +// +// Created by 长沙鸿瑶 on 2025/10/23. +// + +import UIKit +import JXSegmentedView + +class FAOrderRecordsViewController: FAViewController { + + private lazy var titles = ["Coin Record".localized, "VIP Record".localized] + private lazy var viewControllers = [FACoinRecordViewController(), FAVipRecordViewController()] + + private lazy var segmentedDataSource: JXSegmentedTitleDataSource = { + let dataSource = JXSegmentedTitleDataSource() + dataSource.itemWidth = (UIScreen.width - 32 - 24) / CGFloat(titles.count) + dataSource.titles = titles + dataSource.isTitleMaskEnabled = true + dataSource.titleNormalColor = .FFFFFF.withAlphaComponent(0.5) + dataSource.titleSelectedColor = ._333333 + dataSource.titleNormalFont = .font(ofSize: 14, weight: .bold) + dataSource.titleSelectedFont = .font(ofSize: 14, weight: .bold) + dataSource.itemSpacing = 0 + return dataSource + }() + + private lazy var segmentedIndicator: JXSegmentedIndicatorBackgroundView = { + let indicator = JXSegmentedIndicatorBackgroundView() + indicator.indicatorHeight = 36 + indicator.indicatorWidthIncrement = 0 + indicator.indicatorColor = ._74_BBFF + return indicator + }() + + private lazy var segmentedView: JXSegmentedView = { + let view = JXSegmentedView() + view.backgroundColor = .FFFFFF.withAlphaComponent(0.15) + view.layer.cornerRadius = 24 + view.layer.masksToBounds = true + view.dataSource = segmentedDataSource + view.delegate = self + view.indicators = [segmentedIndicator] + view.listContainer = listContainerView + return view + }() + + private lazy var listContainerView: JXSegmentedListContainerView = { + let view = JXSegmentedListContainerView(dataSource: self) + return view + }() + + + + + override func viewDidLoad() { + super.viewDidLoad() + self.title = "Order Records".localized + + fa_setupLayout() + } + + override func viewWillAppear(_ animated: Bool) { + super.viewWillAppear(animated) + self.navigationController?.setNavigationBarHidden(false, animated: true) + fa_setNavigationStyle() + } + + +} + +extension FAOrderRecordsViewController { + + private func fa_setupLayout() { + view.addSubview(segmentedView) + view.addSubview(listContainerView) + + segmentedView.snp.makeConstraints { make in + make.left.equalToSuperview().offset(16) + make.centerX.equalToSuperview() + make.top.equalToSuperview().offset(20 + UIScreen.navBarHeight) + make.height.equalTo(48) + } + + listContainerView.snp.makeConstraints { make in + make.left.right.bottom.equalToSuperview() + make.top.equalTo(segmentedView.snp.bottom) + } + } + + +} + +//MARK: JXSegmentedViewDelegate +extension FAOrderRecordsViewController: JXSegmentedViewDelegate { + func segmentedView(_ segmentedView: JXSegmentedView, didSelectedItemAt index: Int) { + + } +} + +//MARK: JXSegmentedViewDelegate +extension FAOrderRecordsViewController: JXSegmentedListContainerViewDataSource { + func listContainerView(_ listContainerView: JXSegmentedListContainerView, initListAt index: Int) -> any JXSegmentedListContainerViewListDelegate { + return viewControllers[index] + } + + func numberOfLists(in listContainerView: JXSegmentedListContainerView) -> Int { + return self.titles.count + } + +} diff --git a/Fableon/Class/Store/C/FARewardCoinsViewController.swift b/Fableon/Class/Store/C/FARewardCoinsViewController.swift new file mode 100644 index 0000000..6cd6063 --- /dev/null +++ b/Fableon/Class/Store/C/FARewardCoinsViewController.swift @@ -0,0 +1,55 @@ +// +// FARewardCoinsViewController.swift +// Fableon +// +// Created by 长沙鸿瑶 on 2025/10/23. +// + +import UIKit + +class FARewardCoinsViewController: FAViewController { + + private lazy var tableView: FATableView = { + let tableView = FATableView(frame: .zero, style: .plain) + tableView.delegate = self + tableView.dataSource = self + tableView.rowHeight = 87 + tableView.separatorColor = .FFFFFF.withAlphaComponent(0.1) + 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") + return tableView + }() + + override func viewDidLoad() { + super.viewDidLoad() + self.title = "Reward coins" + + view.addSubview(tableView) + + tableView.snp.makeConstraints { make in + make.left.right.bottom.equalToSuperview() + make.top.equalToSuperview().offset(UIScreen.navBarHeight + 10) + } + } + + + override func viewWillAppear(_ animated: Bool) { + super.viewWillAppear(animated) + self.navigationController?.setNavigationBarHidden(false, animated: true) + fa_setNavigationStyle() + } + +} + +//MARK: UITableViewDelegate UITableViewDataSource +extension FARewardCoinsViewController: UITableViewDelegate, UITableViewDataSource { + func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { + let cell = tableView.dequeueReusableCell(withIdentifier: "cell", for: indexPath) as! FARewardCoinsCell + return cell + } + + func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { + return 20 + } +} diff --git a/Fableon/Class/Store/C/FAStoreViewController.swift b/Fableon/Class/Store/C/FAStoreViewController.swift new file mode 100644 index 0000000..f266285 --- /dev/null +++ b/Fableon/Class/Store/C/FAStoreViewController.swift @@ -0,0 +1,58 @@ +// +// FAStoreViewController.swift +// Fableon +// +// Created by 长沙鸿瑶 on 2025/10/22. +// + +import UIKit + +class FAStoreViewController: FAViewController { + + private lazy var scrollView: FAScrollView = { + let scrollView = FAScrollView() + return scrollView + }() + + 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 + }() + + override func viewDidLoad() { + super.viewDidLoad() + self.title = "Store".localized + + fa_setupLayout() + } + + override func viewWillAppear(_ animated: Bool) { + super.viewWillAppear(animated) + self.navigationController?.setNavigationBarHidden(false, animated: true) + fa_setNavigationStyle() + } + + +} + +extension FAStoreViewController { + + private func fa_setupLayout() { + view.addSubview(scrollView) + scrollView.addSubview(titleLabel) + + scrollView.snp.makeConstraints { make in + make.left.right.bottom.equalToSuperview() + make.top.equalToSuperview().offset(UIScreen.navBarHeight) + } + + titleLabel.snp.makeConstraints { make in + make.top.equalToSuperview().offset(0) + make.centerX.equalToSuperview() + } + } + +} diff --git a/Fableon/Class/Store/C/FAVipRecordViewController.swift b/Fableon/Class/Store/C/FAVipRecordViewController.swift new file mode 100644 index 0000000..e0302ed --- /dev/null +++ b/Fableon/Class/Store/C/FAVipRecordViewController.swift @@ -0,0 +1,53 @@ +// +// FAVipRecordViewController.swift +// Fableon +// +// Created by 长沙鸿瑶 on 2025/10/23. +// + +import UIKit + +class FAVipRecordViewController: FAViewController { + + private lazy var tableView: FATableView = { + let tableView = FATableView(frame: .zero, style: .plain) + tableView.delegate = self + tableView.dataSource = self + tableView.rowHeight = 72 + tableView.separatorColor = .FFFFFF.withAlphaComponent(0.1) + 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") + return tableView + }() + + override func viewDidLoad() { + super.viewDidLoad() + bgView.isHidden = true + + view.addSubview(tableView) + + tableView.snp.makeConstraints { make in + make.left.right.bottom.equalToSuperview() + make.top.equalToSuperview() + } + } + + + +} + +//MARK: UITableViewDelegate UITableViewDataSource +extension FAVipRecordViewController: UITableViewDelegate, UITableViewDataSource { + + func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { + let cell = tableView.dequeueReusableCell(withIdentifier: "cell", for: indexPath) as! FAOrderRecordCell + cell.iconImageView.isHidden = true + return cell + } + + func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { + return 20 + } + +} diff --git a/Fableon/Class/Store/C/FAWalletViewController.swift b/Fableon/Class/Store/C/FAWalletViewController.swift new file mode 100644 index 0000000..d0514f9 --- /dev/null +++ b/Fableon/Class/Store/C/FAWalletViewController.swift @@ -0,0 +1,115 @@ +// +// FAWalletViewController.swift +// Fableon +// +// Created by 长沙鸿瑶 on 2025/10/22. +// + +import UIKit + +class FAWalletViewController: FAViewController { + + private lazy var dataArr: [FAMeItemModel] = [ + FAMeItemModel(type: .consumptionRecords, name: "Consumption Records".localized), + FAMeItemModel(type: .purchaseRecords, name: "Purchase Records".localized), + FAMeItemModel(type: .rewardCoins, name: "Reward Coins".localized), + ] + + private lazy var tableView: FATableView = { + let tableView = FATableView(frame: .zero, style: .plain) + tableView.delegate = self + tableView.dataSource = self + tableView.rowHeight = 46 + tableView.separatorColor = .FFFFFF.withAlphaComponent(0.1) + tableView.separatorInset = .init(top: 0, left: 32, bottom: 0, right: 32) + tableView.register(UINib(nibName: "FAWalletCell", bundle: nil), forCellReuseIdentifier: "cell") + return tableView + }() + + private lazy var headerView: FAWalletHeaderView = { + let view = FAWalletHeaderView(frame: .init(x: 0, y: 0, width: UIScreen.width, height: 190)) + view.userInfo = FALogin.manager.userInfo + return view + }() + + deinit { + NotificationCenter.default.removeObserver(self) + } + + override func viewDidLoad() { + super.viewDidLoad() + self.title = "My Wallet".localized + NotificationCenter.default.addObserver(self, selector: #selector(userInfoUpdateNotification), name: FALogin.userInfoUpdateNotification, object: nil) + + fa_setupLayout() + } + + + override func viewWillAppear(_ animated: Bool) { + super.viewWillAppear(animated) + self.navigationController?.setNavigationBarHidden(false, animated: true) + fa_setNavigationStyle() + } + + @objc private func userInfoUpdateNotification() { + headerView.userInfo = FALogin.manager.userInfo + } +} + +extension FAWalletViewController { + + private func fa_setupLayout() { + tableView.tableHeaderView = self.headerView + + view.addSubview(tableView) + + tableView.snp.makeConstraints { make in + make.left.right.bottom.equalToSuperview() + make.top.equalToSuperview().offset(UIScreen.navBarHeight) + } + } + +} + +//MARK: UITableViewDelegate UITableViewDataSource +extension FAWalletViewController: UITableViewDelegate, UITableViewDataSource { + + func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { + let cell = tableView.dequeueReusableCell(withIdentifier: "cell", for: indexPath) as! FAWalletCell + cell.item = dataArr[indexPath.row] + return cell + } + + func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { + return dataArr.count + } + + func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) { + let item = dataArr[indexPath.row] + + var vc: FAViewController? + + switch item.type { + case .consumptionRecords: + vc = FAConsumptionRecordsViewController() + + case .purchaseRecords: + vc = FAOrderRecordsViewController() + + case .rewardCoins: + vc = FARewardCoinsViewController() + + default: + break + } + + if let vc = vc { + self.navigationController?.pushViewController(vc, animated: true) + } + + + } + + + +} diff --git a/Fableon/Class/Store/V/FAConsumptionRecordsCell.swift b/Fableon/Class/Store/V/FAConsumptionRecordsCell.swift new file mode 100644 index 0000000..071ec3e --- /dev/null +++ b/Fableon/Class/Store/V/FAConsumptionRecordsCell.swift @@ -0,0 +1,37 @@ +// +// FAConsumptionRecordsCell.swift +// Fableon +// +// Created by 长沙鸿瑶 on 2025/10/23. +// + +import UIKit + +class FAConsumptionRecordsCell: FATableViewCell { + + + @IBOutlet weak var titleLabel: UILabel! + + @IBOutlet weak var subtitleLabel: UILabel! + + @IBOutlet weak var dateLabel: UILabel! + + @IBOutlet weak var coinsLabel: UILabel! + + + override func awakeFromNib() { + super.awakeFromNib() + + 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" + } + + override func setSelected(_ selected: Bool, animated: Bool) { + super.setSelected(selected, animated: animated) + + // Configure the view for the selected state + } + +} diff --git a/Fableon/Class/Store/V/FAConsumptionRecordsCell.xib b/Fableon/Class/Store/V/FAConsumptionRecordsCell.xib new file mode 100644 index 0000000..34f879b --- /dev/null +++ b/Fableon/Class/Store/V/FAConsumptionRecordsCell.xib @@ -0,0 +1,80 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Fableon/Class/Store/V/FAOrderRecordCell.swift b/Fableon/Class/Store/V/FAOrderRecordCell.swift new file mode 100644 index 0000000..3b11218 --- /dev/null +++ b/Fableon/Class/Store/V/FAOrderRecordCell.swift @@ -0,0 +1,33 @@ +// +// FAOrderRecordCell.swift +// Fableon +// +// Created by 长沙鸿瑶 on 2025/10/23. +// + +import UIKit + +class FAOrderRecordCell: FATableViewCell { + + + @IBOutlet weak var titleLabel: UILabel! + + @IBOutlet weak var dateLabel: UILabel! + + @IBOutlet weak var countLabel: UILabel! + + @IBOutlet weak var iconImageView: UIImageView! + + + override func awakeFromNib() { + super.awakeFromNib() + // Initialization code + } + + override func setSelected(_ selected: Bool, animated: Bool) { + super.setSelected(selected, animated: animated) + + // Configure the view for the selected state + } + +} diff --git a/Fableon/Class/Store/V/FAOrderRecordCell.xib b/Fableon/Class/Store/V/FAOrderRecordCell.xib new file mode 100644 index 0000000..48dc8a9 --- /dev/null +++ b/Fableon/Class/Store/V/FAOrderRecordCell.xib @@ -0,0 +1,76 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Fableon/Class/Store/V/FARewardCoinsCell.swift b/Fableon/Class/Store/V/FARewardCoinsCell.swift new file mode 100644 index 0000000..39f2bb1 --- /dev/null +++ b/Fableon/Class/Store/V/FARewardCoinsCell.swift @@ -0,0 +1,43 @@ +// +// FARewardCoinsCell.swift +// Fableon +// +// Created by 长沙鸿瑶 on 2025/10/23. +// + +import UIKit + +class FARewardCoinsCell: FATableViewCell { + + + @IBOutlet weak var dateLabel: UILabel! + + @IBOutlet weak var nameLabel: UILabel! + + @IBOutlet weak var expiresIconImageView: UIImageView! + + @IBOutlet weak var expiresLabel: UILabel! + + @IBOutlet weak var expiredLabel: UILabel! + + @IBOutlet weak var countLabel: UILabel! + + @IBOutlet weak var remainingLabel: UILabel! + + + + override func awakeFromNib() { + super.awakeFromNib() + expiredLabel.text = "Expired".localized + + expiredLabel.isHidden = true + + } + + override func setSelected(_ selected: Bool, animated: Bool) { + super.setSelected(selected, animated: animated) + + // Configure the view for the selected state + } + +} diff --git a/Fableon/Class/Store/V/FARewardCoinsCell.xib b/Fableon/Class/Store/V/FARewardCoinsCell.xib new file mode 100644 index 0000000..87e8738 --- /dev/null +++ b/Fableon/Class/Store/V/FARewardCoinsCell.xib @@ -0,0 +1,106 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Fableon/Class/Store/V/FAWalletCell.swift b/Fableon/Class/Store/V/FAWalletCell.swift new file mode 100644 index 0000000..3a63e69 --- /dev/null +++ b/Fableon/Class/Store/V/FAWalletCell.swift @@ -0,0 +1,33 @@ +// +// FAWalletCell.swift +// Fableon +// +// Created by 长沙鸿瑶 on 2025/10/22. +// + +import UIKit + +class FAWalletCell: FATableViewCell { + + var item: FAMeItemModel? { + didSet { + titleLabel.text = item?.name + } + } + + + @IBOutlet weak var titleLabel: UILabel! + + + override func awakeFromNib() { + super.awakeFromNib() + // Initialization code + } + + override func setSelected(_ selected: Bool, animated: Bool) { + super.setSelected(selected, animated: animated) + + // Configure the view for the selected state + } + +} diff --git a/Fableon/Class/Store/V/FAWalletCell.xib b/Fableon/Class/Store/V/FAWalletCell.xib new file mode 100644 index 0000000..da778a3 --- /dev/null +++ b/Fableon/Class/Store/V/FAWalletCell.xib @@ -0,0 +1,52 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Fableon/Class/Store/V/FAWalletHeaderView.swift b/Fableon/Class/Store/V/FAWalletHeaderView.swift new file mode 100644 index 0000000..f36d299 --- /dev/null +++ b/Fableon/Class/Store/V/FAWalletHeaderView.swift @@ -0,0 +1,158 @@ +// +// FAWalletHeaderView.swift +// Fableon +// +// Created by 长沙鸿瑶 on 2025/10/22. +// + +import UIKit + +class FAWalletHeaderView: UIView { + + var userInfo: FAUserInfo? { + didSet { + coinsView.setNeedsUpdateConfiguration() + bonusView.setNeedsUpdateConfiguration() + } + } + + private lazy var contentView: UIView = { + let view = UIView() + view.backgroundColor = ._5_CA_8_FF_0_2 + view.layer.cornerRadius = 12 + view.layer.masksToBounds = true + return view + }() + + private lazy var storeButton: UIButton = { + let button = FAGradientButton(type: .custom, primaryAction: UIAction(handler: { [weak self] _ in + guard let self = self else { return } + let vc = FAStoreViewController() + self.viewController?.navigationController?.pushViewController(vc, animated: true) + })) + button.layer.cornerRadius = 24 + button.layer.masksToBounds = true + button.fa_colors = [UIColor.BEDFFF.cgColor, UIColor._52_A_2_F_1.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("Store".localized, for: .normal) + button.setTitleColor(._000000, for: .normal) + button.titleLabel?.font = .font(ofSize: 18, weight: .bold) + return button + }() + + private lazy var lineView: UIView = { + let view = UIView() + view.backgroundColor = .FFFFFF.withAlphaComponent(0.1) + return view + }() + + private lazy var coinsView: UIButton = { + var config = UIButton.Configuration.plain() + config.image = UIImage(named: "coins_icon_02") + config.imagePadding = 11 + config.attributedTitle = AttributedString("Coins".localized, attributes: AttributeContainer([ + .font : UIFont.font(ofSize: 10, weight: .bold), + .foregroundColor : UIColor.F_7_F_497 + ])) + + let button = UIButton(configuration: config) + button.isUserInteractionEnabled = false + button.configurationUpdateHandler = { [weak self] button in + guard let self = self else { return } + + button.configuration?.attributedSubtitle = AttributedString("\(self.userInfo?.coin_left_total ?? 0)", attributes: AttributeContainer([ + .font : UIFont.font(ofSize: 14, weight: .bold), + .foregroundColor : UIColor.FFFFFF + ])) + } + + return button + }() + + private lazy var bonusView: UIButton = { + var config = UIButton.Configuration.plain() + config.image = UIImage(named: "coins_icon_02") + config.imagePadding = 11 + config.imagePlacement = .trailing + config.titleAlignment = .leading + config.attributedTitle = AttributedString("Bonus".localized, attributes: AttributeContainer([ + .font : UIFont.font(ofSize: 10, weight: .bold), + .foregroundColor : UIColor.F_7_F_497 + ])) + + let button = UIButton(configuration: config) + button.isUserInteractionEnabled = false + button.configurationUpdateHandler = { [weak self] button in + guard let self = self else { return } + + button.configuration?.attributedSubtitle = AttributedString("\(self.userInfo?.send_coin_left_total ?? 0)", attributes: AttributeContainer([ + .font : UIFont.font(ofSize: 14, weight: .bold), + .foregroundColor : UIColor.FFFFFF + ])) + } + + return button + }() + + + + + + override init(frame: CGRect) { + super.init(frame: frame) + + fa_setupLayout() + } + + required init?(coder: NSCoder) { + fatalError("init(coder:) has not been implemented") + } + +} + +extension FAWalletHeaderView { + + private func fa_setupLayout() { + addSubview(contentView) + contentView.addSubview(storeButton) + contentView.addSubview(lineView) + contentView.addSubview(coinsView) + contentView.addSubview(bonusView) + + contentView.snp.makeConstraints { make in + make.left.equalToSuperview().offset(16) + make.centerX.equalToSuperview() + make.top.equalToSuperview().offset(25) + make.height.equalTo(150) + } + + storeButton.snp.makeConstraints { make in + make.left.equalToSuperview().offset(16) + make.centerX.equalToSuperview() + make.bottom.equalToSuperview().offset(-14) + make.height.equalTo(48) + } + + lineView.snp.makeConstraints { make in + make.centerX.equalToSuperview() + make.top.equalToSuperview().offset(33) + make.width.equalTo(1) + make.height.equalTo(30) + } + + coinsView.snp.makeConstraints { make in + make.left.equalToSuperview() + make.right.equalTo(lineView.snp.left) + make.centerY.equalTo(lineView) + } + + bonusView.snp.makeConstraints { make in + make.left.equalTo(lineView.snp.right) + make.right.equalToSuperview() + make.centerY.equalTo(lineView) + } + } + +} diff --git a/Fableon/Libs/FALogin/FAUserInfo.swift b/Fableon/Libs/FALogin/FAUserInfo.swift index 74cea37..e9d7601 100644 --- a/Fableon/Libs/FALogin/FAUserInfo.swift +++ b/Fableon/Libs/FALogin/FAUserInfo.swift @@ -15,6 +15,10 @@ class FAUserInfo: NSObject, SmartCodable, NSSecureCoding { var is_tourist: Bool? var family_name: String? var avator: String? + var coin_left_total: Int? + var send_coin_left_total: Int? + var is_vip: Bool? + var vip_end_time: TimeInterval? func getNickName() -> String { if let name = family_name, !name.isEmpty { @@ -24,6 +28,10 @@ class FAUserInfo: NSObject, SmartCodable, NSSecureCoding { } } + var totalCoins: Int { + return (coin_left_total ?? 0) + (send_coin_left_total ?? 0) + } + required override init() { } static var supportsSecureCoding: Bool { @@ -36,6 +44,10 @@ class FAUserInfo: NSObject, SmartCodable, NSSecureCoding { coder.encode(is_tourist, forKey: "is_tourist") coder.encode(avator, forKey: "avator") coder.encode(family_name, forKey: "family_name") + coder.encode(coin_left_total, forKey: "coin_left_total") + coder.encode(send_coin_left_total, forKey: "send_coin_left_total") + coder.encode(is_vip, forKey: "is_vip") + coder.encode(vip_end_time, forKey: "vip_end_time") } required init?(coder: NSCoder) { @@ -45,5 +57,9 @@ class FAUserInfo: NSObject, SmartCodable, NSSecureCoding { is_tourist = coder.decodeObject(of: NSNumber.self, forKey: "is_tourist")?.boolValue avator = coder.decodeObject(of: NSString.self, forKey: "avator") as? String family_name = coder.decodeObject(of: NSString.self, forKey: "family_name") as? String + coin_left_total = coder.decodeObject(of: NSNumber.self, forKey: "coin_left_total")?.intValue + send_coin_left_total = coder.decodeObject(of: NSNumber.self, forKey: "send_coin_left_total")?.intValue + is_vip = coder.decodeObject(of: NSNumber.self, forKey: "is_vip")?.boolValue + vip_end_time = coder.decodeObject(of: NSNumber.self, forKey: "vip_end_time")?.doubleValue } } diff --git a/Fableon/Source/Assets.xcassets/color/#105C91.colorset/Contents.json b/Fableon/Source/Assets.xcassets/color/#105C91.colorset/Contents.json new file mode 100644 index 0000000..480524d --- /dev/null +++ b/Fableon/Source/Assets.xcassets/color/#105C91.colorset/Contents.json @@ -0,0 +1,20 @@ +{ + "colors" : [ + { + "color" : { + "color-space" : "srgb", + "components" : { + "alpha" : "1.000", + "blue" : "0x91", + "green" : "0x5C", + "red" : "0x10" + } + }, + "idiom" : "universal" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/Fableon/Source/Assets.xcassets/color/#1680FB.colorset/Contents.json b/Fableon/Source/Assets.xcassets/color/#1680FB.colorset/Contents.json new file mode 100644 index 0000000..520243f --- /dev/null +++ b/Fableon/Source/Assets.xcassets/color/#1680FB.colorset/Contents.json @@ -0,0 +1,20 @@ +{ + "colors" : [ + { + "color" : { + "color-space" : "srgb", + "components" : { + "alpha" : "1.000", + "blue" : "0xFB", + "green" : "0x80", + "red" : "0x16" + } + }, + "idiom" : "universal" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/Fableon/Source/Assets.xcassets/color/#3A271E.colorset/Contents.json b/Fableon/Source/Assets.xcassets/color/#3A271E.colorset/Contents.json new file mode 100644 index 0000000..28f7057 --- /dev/null +++ b/Fableon/Source/Assets.xcassets/color/#3A271E.colorset/Contents.json @@ -0,0 +1,20 @@ +{ + "colors" : [ + { + "color" : { + "color-space" : "srgb", + "components" : { + "alpha" : "1.000", + "blue" : "0x1E", + "green" : "0x27", + "red" : "0x3A" + } + }, + "idiom" : "universal" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/Fableon/Source/Assets.xcassets/color/#74BBFF.colorset/Contents.json b/Fableon/Source/Assets.xcassets/color/#74BBFF.colorset/Contents.json new file mode 100644 index 0000000..c74c7bd --- /dev/null +++ b/Fableon/Source/Assets.xcassets/color/#74BBFF.colorset/Contents.json @@ -0,0 +1,20 @@ +{ + "colors" : [ + { + "color" : { + "color-space" : "srgb", + "components" : { + "alpha" : "1.000", + "blue" : "0xFF", + "green" : "0xBB", + "red" : "0x74" + } + }, + "idiom" : "universal" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/Fableon/Source/Assets.xcassets/color/#79A7DB.colorset/Contents.json b/Fableon/Source/Assets.xcassets/color/#79A7DB.colorset/Contents.json new file mode 100644 index 0000000..ed77228 --- /dev/null +++ b/Fableon/Source/Assets.xcassets/color/#79A7DB.colorset/Contents.json @@ -0,0 +1,20 @@ +{ + "colors" : [ + { + "color" : { + "color-space" : "srgb", + "components" : { + "alpha" : "1.000", + "blue" : "0xDB", + "green" : "0xA7", + "red" : "0x79" + } + }, + "idiom" : "universal" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/Fableon/Source/Assets.xcassets/color/#7FDBF5.colorset/Contents.json b/Fableon/Source/Assets.xcassets/color/#7FDBF5.colorset/Contents.json new file mode 100644 index 0000000..f9ff760 --- /dev/null +++ b/Fableon/Source/Assets.xcassets/color/#7FDBF5.colorset/Contents.json @@ -0,0 +1,20 @@ +{ + "colors" : [ + { + "color" : { + "color-space" : "srgb", + "components" : { + "alpha" : "1.000", + "blue" : "0xF5", + "green" : "0xDB", + "red" : "0x7F" + } + }, + "idiom" : "universal" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/Fableon/Source/Assets.xcassets/color/#C3FAFF.colorset/Contents.json b/Fableon/Source/Assets.xcassets/color/#C3FAFF.colorset/Contents.json new file mode 100644 index 0000000..f96f0a8 --- /dev/null +++ b/Fableon/Source/Assets.xcassets/color/#C3FAFF.colorset/Contents.json @@ -0,0 +1,20 @@ +{ + "colors" : [ + { + "color" : { + "color-space" : "srgb", + "components" : { + "alpha" : "1.000", + "blue" : "0xFF", + "green" : "0xFA", + "red" : "0xC3" + } + }, + "idiom" : "universal" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/Fableon/Source/Assets.xcassets/color/#F7F497.colorset/Contents.json b/Fableon/Source/Assets.xcassets/color/#F7F497.colorset/Contents.json new file mode 100644 index 0000000..0446adf --- /dev/null +++ b/Fableon/Source/Assets.xcassets/color/#F7F497.colorset/Contents.json @@ -0,0 +1,20 @@ +{ + "colors" : [ + { + "color" : { + "color-space" : "srgb", + "components" : { + "alpha" : "1.000", + "blue" : "0x97", + "green" : "0xF4", + "red" : "0xF7" + } + }, + "idiom" : "universal" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/Fableon/Source/Assets.xcassets/color/#FFFFFF_0.8.colorset/Contents.json b/Fableon/Source/Assets.xcassets/color/#FFFFFF_0.8.colorset/Contents.json new file mode 100644 index 0000000..ead18a8 --- /dev/null +++ b/Fableon/Source/Assets.xcassets/color/#FFFFFF_0.8.colorset/Contents.json @@ -0,0 +1,20 @@ +{ + "colors" : [ + { + "color" : { + "color-space" : "srgb", + "components" : { + "alpha" : "0.800", + "blue" : "0xFF", + "green" : "0xFF", + "red" : "0xFF" + } + }, + "idiom" : "universal" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/Fableon/Source/Assets.xcassets/image/Frame 2085663258.imageset/Contents.json b/Fableon/Source/Assets.xcassets/image/Frame 2085663258.imageset/Contents.json new file mode 100644 index 0000000..1a2967a --- /dev/null +++ b/Fableon/Source/Assets.xcassets/image/Frame 2085663258.imageset/Contents.json @@ -0,0 +1,25 @@ +{ + "images" : [ + { + "idiom" : "universal", + "scale" : "1x" + }, + { + "filename" : "Frame 2085663258@2x.png", + "idiom" : "universal", + "scale" : "2x" + }, + { + "filename" : "Frame 2085663258@3x.png", + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + }, + "properties" : { + "template-rendering-intent" : "original" + } +} diff --git a/Fableon/Source/Assets.xcassets/image/Frame 2085663258.imageset/Frame 2085663258@2x.png b/Fableon/Source/Assets.xcassets/image/Frame 2085663258.imageset/Frame 2085663258@2x.png new file mode 100644 index 0000000..b92fdb4 Binary files /dev/null and b/Fableon/Source/Assets.xcassets/image/Frame 2085663258.imageset/Frame 2085663258@2x.png differ diff --git a/Fableon/Source/Assets.xcassets/image/Frame 2085663258.imageset/Frame 2085663258@3x.png b/Fableon/Source/Assets.xcassets/image/Frame 2085663258.imageset/Frame 2085663258@3x.png new file mode 100644 index 0000000..c978b09 Binary files /dev/null and b/Fableon/Source/Assets.xcassets/image/Frame 2085663258.imageset/Frame 2085663258@3x.png differ diff --git a/Fableon/Source/Assets.xcassets/image/Frame 3021.imageset/Contents.json b/Fableon/Source/Assets.xcassets/image/Frame 3021.imageset/Contents.json new file mode 100644 index 0000000..8f5ca8e --- /dev/null +++ b/Fableon/Source/Assets.xcassets/image/Frame 3021.imageset/Contents.json @@ -0,0 +1,22 @@ +{ + "images" : [ + { + "idiom" : "universal", + "scale" : "1x" + }, + { + "filename" : "Frame 3021@2x.png", + "idiom" : "universal", + "scale" : "2x" + }, + { + "filename" : "Frame 3021@3x.png", + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/Fableon/Source/Assets.xcassets/image/Frame 3021.imageset/Frame 3021@2x.png b/Fableon/Source/Assets.xcassets/image/Frame 3021.imageset/Frame 3021@2x.png new file mode 100644 index 0000000..8b93ec8 Binary files /dev/null and b/Fableon/Source/Assets.xcassets/image/Frame 3021.imageset/Frame 3021@2x.png differ diff --git a/Fableon/Source/Assets.xcassets/image/Frame 3021.imageset/Frame 3021@3x.png b/Fableon/Source/Assets.xcassets/image/Frame 3021.imageset/Frame 3021@3x.png new file mode 100644 index 0000000..e551a42 Binary files /dev/null and b/Fableon/Source/Assets.xcassets/image/Frame 3021.imageset/Frame 3021@3x.png differ diff --git a/Fableon/Source/Assets.xcassets/image/coins_icon_01.imageset/Contents.json b/Fableon/Source/Assets.xcassets/image/coins_icon_01.imageset/Contents.json new file mode 100644 index 0000000..6974814 --- /dev/null +++ b/Fableon/Source/Assets.xcassets/image/coins_icon_01.imageset/Contents.json @@ -0,0 +1,22 @@ +{ + "images" : [ + { + "idiom" : "universal", + "scale" : "1x" + }, + { + "filename" : "金币@2x.png", + "idiom" : "universal", + "scale" : "2x" + }, + { + "filename" : "金币@3x.png", + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/Fableon/Source/Assets.xcassets/image/coins_icon_01.imageset/金币@2x.png b/Fableon/Source/Assets.xcassets/image/coins_icon_01.imageset/金币@2x.png new file mode 100644 index 0000000..b958cd9 Binary files /dev/null and b/Fableon/Source/Assets.xcassets/image/coins_icon_01.imageset/金币@2x.png differ diff --git a/Fableon/Source/Assets.xcassets/image/coins_icon_01.imageset/金币@3x.png b/Fableon/Source/Assets.xcassets/image/coins_icon_01.imageset/金币@3x.png new file mode 100644 index 0000000..46a4bc8 Binary files /dev/null and b/Fableon/Source/Assets.xcassets/image/coins_icon_01.imageset/金币@3x.png differ diff --git a/Fableon/Source/Assets.xcassets/image/coins_icon_02.imageset/Contents.json b/Fableon/Source/Assets.xcassets/image/coins_icon_02.imageset/Contents.json new file mode 100644 index 0000000..6974814 --- /dev/null +++ b/Fableon/Source/Assets.xcassets/image/coins_icon_02.imageset/Contents.json @@ -0,0 +1,22 @@ +{ + "images" : [ + { + "idiom" : "universal", + "scale" : "1x" + }, + { + "filename" : "金币@2x.png", + "idiom" : "universal", + "scale" : "2x" + }, + { + "filename" : "金币@3x.png", + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/Fableon/Source/Assets.xcassets/image/coins_icon_02.imageset/金币@2x.png b/Fableon/Source/Assets.xcassets/image/coins_icon_02.imageset/金币@2x.png new file mode 100644 index 0000000..b958cd9 Binary files /dev/null and b/Fableon/Source/Assets.xcassets/image/coins_icon_02.imageset/金币@2x.png differ diff --git a/Fableon/Source/Assets.xcassets/image/coins_icon_02.imageset/金币@3x.png b/Fableon/Source/Assets.xcassets/image/coins_icon_02.imageset/金币@3x.png new file mode 100644 index 0000000..46a4bc8 Binary files /dev/null and b/Fableon/Source/Assets.xcassets/image/coins_icon_02.imageset/金币@3x.png differ diff --git a/Fableon/Source/Assets.xcassets/image/coins_icon_03.imageset/Contents.json b/Fableon/Source/Assets.xcassets/image/coins_icon_03.imageset/Contents.json new file mode 100644 index 0000000..6974814 --- /dev/null +++ b/Fableon/Source/Assets.xcassets/image/coins_icon_03.imageset/Contents.json @@ -0,0 +1,22 @@ +{ + "images" : [ + { + "idiom" : "universal", + "scale" : "1x" + }, + { + "filename" : "金币@2x.png", + "idiom" : "universal", + "scale" : "2x" + }, + { + "filename" : "金币@3x.png", + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/Fableon/Source/Assets.xcassets/image/coins_icon_03.imageset/金币@2x.png b/Fableon/Source/Assets.xcassets/image/coins_icon_03.imageset/金币@2x.png new file mode 100644 index 0000000..7443843 Binary files /dev/null and b/Fableon/Source/Assets.xcassets/image/coins_icon_03.imageset/金币@2x.png differ diff --git a/Fableon/Source/Assets.xcassets/image/coins_icon_03.imageset/金币@3x.png b/Fableon/Source/Assets.xcassets/image/coins_icon_03.imageset/金币@3x.png new file mode 100644 index 0000000..d940759 Binary files /dev/null and b/Fableon/Source/Assets.xcassets/image/coins_icon_03.imageset/金币@3x.png differ diff --git a/Fableon/Source/Assets.xcassets/image/lock_icon_01.imageset/Contents.json b/Fableon/Source/Assets.xcassets/image/lock_icon_01.imageset/Contents.json new file mode 100644 index 0000000..5c4d3b1 --- /dev/null +++ b/Fableon/Source/Assets.xcassets/image/lock_icon_01.imageset/Contents.json @@ -0,0 +1,22 @@ +{ + "images" : [ + { + "idiom" : "universal", + "scale" : "1x" + }, + { + "filename" : "Frame@2x.png", + "idiom" : "universal", + "scale" : "2x" + }, + { + "filename" : "Frame@3x.png", + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/Fableon/Source/Assets.xcassets/image/lock_icon_01.imageset/Frame@2x.png b/Fableon/Source/Assets.xcassets/image/lock_icon_01.imageset/Frame@2x.png new file mode 100644 index 0000000..3cc8c40 Binary files /dev/null and b/Fableon/Source/Assets.xcassets/image/lock_icon_01.imageset/Frame@2x.png differ diff --git a/Fableon/Source/Assets.xcassets/image/lock_icon_01.imageset/Frame@3x.png b/Fableon/Source/Assets.xcassets/image/lock_icon_01.imageset/Frame@3x.png new file mode 100644 index 0000000..563ce90 Binary files /dev/null and b/Fableon/Source/Assets.xcassets/image/lock_icon_01.imageset/Frame@3x.png differ diff --git a/Fableon/Source/Assets.xcassets/image/lock_icon_02.imageset/Contents.json b/Fableon/Source/Assets.xcassets/image/lock_icon_02.imageset/Contents.json new file mode 100644 index 0000000..975dc3f --- /dev/null +++ b/Fableon/Source/Assets.xcassets/image/lock_icon_02.imageset/Contents.json @@ -0,0 +1,22 @@ +{ + "images" : [ + { + "idiom" : "universal", + "scale" : "1x" + }, + { + "filename" : "Frame 2958@2x.png", + "idiom" : "universal", + "scale" : "2x" + }, + { + "filename" : "Frame 2958@3x.png", + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/Fableon/Source/Assets.xcassets/image/lock_icon_02.imageset/Frame 2958@2x.png b/Fableon/Source/Assets.xcassets/image/lock_icon_02.imageset/Frame 2958@2x.png new file mode 100644 index 0000000..623e85c Binary files /dev/null and b/Fableon/Source/Assets.xcassets/image/lock_icon_02.imageset/Frame 2958@2x.png differ diff --git a/Fableon/Source/Assets.xcassets/image/lock_icon_02.imageset/Frame 2958@3x.png b/Fableon/Source/Assets.xcassets/image/lock_icon_02.imageset/Frame 2958@3x.png new file mode 100644 index 0000000..a78d506 Binary files /dev/null and b/Fableon/Source/Assets.xcassets/image/lock_icon_02.imageset/Frame 2958@3x.png differ diff --git a/Fableon/Source/Assets.xcassets/image/time icon.imageset/Contents.json b/Fableon/Source/Assets.xcassets/image/time icon.imageset/Contents.json new file mode 100644 index 0000000..6efec3a --- /dev/null +++ b/Fableon/Source/Assets.xcassets/image/time icon.imageset/Contents.json @@ -0,0 +1,22 @@ +{ + "images" : [ + { + "idiom" : "universal", + "scale" : "1x" + }, + { + "filename" : "time icon@2x.png", + "idiom" : "universal", + "scale" : "2x" + }, + { + "filename" : "time icon@3x.png", + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/Fableon/Source/Assets.xcassets/image/time icon.imageset/time icon@2x.png b/Fableon/Source/Assets.xcassets/image/time icon.imageset/time icon@2x.png new file mode 100644 index 0000000..db82f2d Binary files /dev/null and b/Fableon/Source/Assets.xcassets/image/time icon.imageset/time icon@2x.png differ diff --git a/Fableon/Source/Assets.xcassets/image/time icon.imageset/time icon@3x.png b/Fableon/Source/Assets.xcassets/image/time icon.imageset/time icon@3x.png new file mode 100644 index 0000000..e255409 Binary files /dev/null and b/Fableon/Source/Assets.xcassets/image/time icon.imageset/time icon@3x.png differ diff --git a/Fableon/Source/Assets.xcassets/image/vip_image_01.imageset/Contents.json b/Fableon/Source/Assets.xcassets/image/vip_image_01.imageset/Contents.json new file mode 100644 index 0000000..5c4d3b1 --- /dev/null +++ b/Fableon/Source/Assets.xcassets/image/vip_image_01.imageset/Contents.json @@ -0,0 +1,22 @@ +{ + "images" : [ + { + "idiom" : "universal", + "scale" : "1x" + }, + { + "filename" : "Frame@2x.png", + "idiom" : "universal", + "scale" : "2x" + }, + { + "filename" : "Frame@3x.png", + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/Fableon/Source/Assets.xcassets/image/vip_image_01.imageset/Frame@2x.png b/Fableon/Source/Assets.xcassets/image/vip_image_01.imageset/Frame@2x.png new file mode 100644 index 0000000..20aff5e Binary files /dev/null and b/Fableon/Source/Assets.xcassets/image/vip_image_01.imageset/Frame@2x.png differ diff --git a/Fableon/Source/Assets.xcassets/image/vip_image_01.imageset/Frame@3x.png b/Fableon/Source/Assets.xcassets/image/vip_image_01.imageset/Frame@3x.png new file mode 100644 index 0000000..beeb476 Binary files /dev/null and b/Fableon/Source/Assets.xcassets/image/vip_image_01.imageset/Frame@3x.png differ diff --git a/Fableon/Source/Assets.xcassets/image/vip_image_02.imageset/Contents.json b/Fableon/Source/Assets.xcassets/image/vip_image_02.imageset/Contents.json new file mode 100644 index 0000000..5c4d3b1 --- /dev/null +++ b/Fableon/Source/Assets.xcassets/image/vip_image_02.imageset/Contents.json @@ -0,0 +1,22 @@ +{ + "images" : [ + { + "idiom" : "universal", + "scale" : "1x" + }, + { + "filename" : "Frame@2x.png", + "idiom" : "universal", + "scale" : "2x" + }, + { + "filename" : "Frame@3x.png", + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/Fableon/Source/Assets.xcassets/image/vip_image_02.imageset/Frame@2x.png b/Fableon/Source/Assets.xcassets/image/vip_image_02.imageset/Frame@2x.png new file mode 100644 index 0000000..e224a65 Binary files /dev/null and b/Fableon/Source/Assets.xcassets/image/vip_image_02.imageset/Frame@2x.png differ diff --git a/Fableon/Source/Assets.xcassets/image/vip_image_02.imageset/Frame@3x.png b/Fableon/Source/Assets.xcassets/image/vip_image_02.imageset/Frame@3x.png new file mode 100644 index 0000000..23b34ff Binary files /dev/null and b/Fableon/Source/Assets.xcassets/image/vip_image_02.imageset/Frame@3x.png differ diff --git a/Fableon/Source/Assets.xcassets/image/皇冠1.imageset/Contents.json b/Fableon/Source/Assets.xcassets/image/皇冠1.imageset/Contents.json new file mode 100644 index 0000000..674f5de --- /dev/null +++ b/Fableon/Source/Assets.xcassets/image/皇冠1.imageset/Contents.json @@ -0,0 +1,22 @@ +{ + "images" : [ + { + "idiom" : "universal", + "scale" : "1x" + }, + { + "filename" : "皇冠1@2x.png", + "idiom" : "universal", + "scale" : "2x" + }, + { + "filename" : "皇冠1@3x.png", + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/Fableon/Source/Assets.xcassets/image/皇冠1.imageset/皇冠1@2x.png b/Fableon/Source/Assets.xcassets/image/皇冠1.imageset/皇冠1@2x.png new file mode 100644 index 0000000..a244c92 Binary files /dev/null and b/Fableon/Source/Assets.xcassets/image/皇冠1.imageset/皇冠1@2x.png differ diff --git a/Fableon/Source/Assets.xcassets/image/皇冠1.imageset/皇冠1@3x.png b/Fableon/Source/Assets.xcassets/image/皇冠1.imageset/皇冠1@3x.png new file mode 100644 index 0000000..03a7c99 Binary files /dev/null and b/Fableon/Source/Assets.xcassets/image/皇冠1.imageset/皇冠1@3x.png differ diff --git a/Fableon/Source/Assets.xcassets/image/皇冠2.imageset/Contents.json b/Fableon/Source/Assets.xcassets/image/皇冠2.imageset/Contents.json new file mode 100644 index 0000000..fdd1e55 --- /dev/null +++ b/Fableon/Source/Assets.xcassets/image/皇冠2.imageset/Contents.json @@ -0,0 +1,22 @@ +{ + "images" : [ + { + "idiom" : "universal", + "scale" : "1x" + }, + { + "filename" : "皇冠2@2x.png", + "idiom" : "universal", + "scale" : "2x" + }, + { + "filename" : "皇冠2@3x.png", + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/Fableon/Source/Assets.xcassets/image/皇冠2.imageset/皇冠2@2x.png b/Fableon/Source/Assets.xcassets/image/皇冠2.imageset/皇冠2@2x.png new file mode 100644 index 0000000..4e79224 Binary files /dev/null and b/Fableon/Source/Assets.xcassets/image/皇冠2.imageset/皇冠2@2x.png differ diff --git a/Fableon/Source/Assets.xcassets/image/皇冠2.imageset/皇冠2@3x.png b/Fableon/Source/Assets.xcassets/image/皇冠2.imageset/皇冠2@3x.png new file mode 100644 index 0000000..519523d Binary files /dev/null and b/Fableon/Source/Assets.xcassets/image/皇冠2.imageset/皇冠2@3x.png differ diff --git a/Fableon/Source/Assets.xcassets/image/皇冠3.imageset/Contents.json b/Fableon/Source/Assets.xcassets/image/皇冠3.imageset/Contents.json new file mode 100644 index 0000000..e9d2fc2 --- /dev/null +++ b/Fableon/Source/Assets.xcassets/image/皇冠3.imageset/Contents.json @@ -0,0 +1,22 @@ +{ + "images" : [ + { + "idiom" : "universal", + "scale" : "1x" + }, + { + "filename" : "皇冠3@2x.png", + "idiom" : "universal", + "scale" : "2x" + }, + { + "filename" : "皇冠3@3x.png", + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/Fableon/Source/Assets.xcassets/image/皇冠3.imageset/皇冠3@2x.png b/Fableon/Source/Assets.xcassets/image/皇冠3.imageset/皇冠3@2x.png new file mode 100644 index 0000000..e5f7bee Binary files /dev/null and b/Fableon/Source/Assets.xcassets/image/皇冠3.imageset/皇冠3@2x.png differ diff --git a/Fableon/Source/Assets.xcassets/image/皇冠3.imageset/皇冠3@3x.png b/Fableon/Source/Assets.xcassets/image/皇冠3.imageset/皇冠3@3x.png new file mode 100644 index 0000000..731862c Binary files /dev/null and b/Fableon/Source/Assets.xcassets/image/皇冠3.imageset/皇冠3@3x.png differ diff --git a/Fableon/Source/en.lproj/Localizable.strings b/Fableon/Source/en.lproj/Localizable.strings index e5ca0d2..3373d5e 100644 --- a/Fableon/Source/en.lproj/Localizable.strings +++ b/Fableon/Source/en.lproj/Localizable.strings @@ -1,15 +1,12 @@ "Ep.##" = "Ep.##"; -"network_error_01" = "The service is abnormal. Check the network."; "Error" = "Error"; "Feedback" = "Feedback"; "Collect" = "Collect"; "History" = "History"; "Search" = "Search"; "Historical search" = "Historical search"; -"empty_title_01" = "No search results"; -"empty_title_02" = "There is no data for the moment."; "About" = "About"; "Privacy Policy" = "Privacy Policy"; "User Agreement" = "User Agreement"; @@ -18,3 +15,39 @@ "Settings" = "Settings"; "Last Watch:Ep.##" = "Last Watch:Ep.##"; "Genres" = "Genres"; +"Popular" = "Popular"; +"New" = "New"; +"Coins" = "Coins"; +"Bonus" = "Bonus"; +"Unlocking costs ## coins" = "Unlocking costs ## coins"; +"video_lock_tip_text" = "Pre.locked"; +"Activated" = "Activated"; +"Not Activated" = "Not Activated"; +"Subscribe" = "Subscribe"; +"vip_expires_date" = "Expiration Time:##"; +"Store" = "Store"; +"Feedback History" = "Feedback History"; +"Feedback Details" = "Feedback Details"; +"My Wallet" = "My Wallet"; +"Consumption Records" = "Consumption Records"; +"Purchase Records" = "Purchase Records"; +"Reward Coins" = "Reward Coins"; +"Order Records" = "Order Records"; +"Coin Record" = "Coin Record"; +"VIP Record" = "VIP Record"; +"Expired" = "Expired"; + +"store_title_1" = "VIP Auto renew,cancel anytime"; + +"network_error_01" = "The service is abnormal. Check the network."; + +"buy_fail_toast_01" = "Purchase failed, please try again later!"; +"buy_fail_toast_02" = "The prequel to this series is not unlocked. Please unlock the prequel before unlocking this series"; + +"vip_tip_01" = "Unlimited access to all series"; +"vip_tip_02" = "All Dramas Free with VIP"; + +"empty_title_01" = "No search results"; +"empty_title_02" = "There is no data for the moment."; + + diff --git a/Podfile b/Podfile index eac23ec..c252699 100644 --- a/Podfile +++ b/Podfile @@ -32,6 +32,9 @@ target 'Fableon' do pod 'LYEmptyView' pod 'collection-view-layouts/TagsLayout' pod 'FDFullscreenPopGesture' + pod 'ZLPhotoBrowser' + pod 'JXPagingView/Paging' + pod 'JXSegmentedView' # swiftUI # pod 'SwiftUIPager' diff --git a/Podfile.lock b/Podfile.lock index 77d369f..406bc23 100644 --- a/Podfile.lock +++ b/Podfile.lock @@ -44,9 +44,11 @@ PODS: - IQKeyboardCore - IQTextView (1.0.5): - IQKeyboardToolbar/Placeholderable + - JXPagingView/Paging (2.1.3) - JXPlayer (0.1.5): - SJMediaCacheServer - SJVideoPlayer + - JXSegmentedView (1.4.1) - Kingfisher (8.5.0) - LYEmptyView (1.3.1) - Masonry (1.1.0) @@ -128,6 +130,9 @@ PODS: - YYCategories/no-arc (1.0.4) - YYModel (1.0.4) - YYText (1.0.7) + - ZLPhotoBrowser (4.7.3): + - ZLPhotoBrowser/Core (= 4.7.3) + - ZLPhotoBrowser/Core (4.7.3) DEPENDENCIES: - Alamofire @@ -136,7 +141,9 @@ DEPENDENCIES: - FSPagerView - HWPanModal - IQKeyboardManagerSwift + - JXPagingView/Paging - JXPlayer (~> 0.1.5) + - JXSegmentedView - Kingfisher - LYEmptyView - MJRefresh @@ -146,9 +153,14 @@ DEPENDENCIES: - Toast - YYCategories - YYText + - ZLPhotoBrowser SPEC REPOS: https://mirrors.tuna.tsinghua.edu.cn/git/CocoaPods/Specs.git: + - JXPagingView + - JXSegmentedView + - ZLPhotoBrowser + trunk: - Alamofire - collection-view-layouts - FDFullscreenPopGesture @@ -193,7 +205,9 @@ SPEC CHECKSUMS: IQKeyboardToolbarManager: c8a575e8b5fffe5873d0e75312244498a0759473 IQTextInputViewNotification: 3b9fb27a16e7ee8958cc9092cfb07a1a9e1fd559 IQTextView: ae13b4922f22e6f027f62c557d9f4f236b19d5c7 + JXPagingView: afdd2e9af09c90160dd232b970d603cc6e7ddd0e JXPlayer: 0e0cd9a2ee406ebb3051d00c760cd5fc599bf09b + JXSegmentedView: cd73555ce2134d1656db2cb383ba9c2f36fb5078 Kingfisher: ff0d31a1f07bdff6a1ebb3ba08b8e6e567b6500c LYEmptyView: b6d418cfa38b78df0cf243f9a9c25ccbdc399922 Masonry: 678fab65091a9290e40e2832a55e7ab731aad201 @@ -209,7 +223,9 @@ SPEC CHECKSUMS: YYCategories: 6bcd4314c6661a561410dce4a793379ebd306abd YYModel: 2a7fdd96aaa4b86a824e26d0c517de8928c04b30 YYText: 5c461d709e24d55a182d1441c41dc639a18a4849 + ZLPhotoBrowser: d5928f08485c90a0b349a3a1e804e82c83ccf193 PODFILE CHECKSUM: 67e3a33ffd850bc173185fa60cd225726eaf969c +PODFILE CHECKSUM: 631a8194b3b1b6d74b60a8ba767e3a1c6a63989b COCOAPODS: 1.16.2