Compare commits
2 Commits
54742c4a67
...
8bbb3d10ad
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
8bbb3d10ad | ||
|
|
e0163dabe3 |
@ -17,6 +17,29 @@
|
||||
031FDEBA2EB0B82600F4CAC7 /* FACoinPackConfirmItem2View.swift in Sources */ = {isa = PBXBuildFile; fileRef = 031FDEB92EB0B82600F4CAC7 /* FACoinPackConfirmItem2View.swift */; };
|
||||
031FDEBC2EB0C97A00F4CAC7 /* FAOldVideoRechargeView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 031FDEBB2EB0C97A00F4CAC7 /* FAOldVideoRechargeView.swift */; };
|
||||
031FDEBE2EB0C99900F4CAC7 /* FANewVideoRechargeView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 031FDEBD2EB0C99900F4CAC7 /* FANewVideoRechargeView.swift */; };
|
||||
031FDEC02EB1C08900F4CAC7 /* FAMeCoinsPackButton.swift in Sources */ = {isa = PBXBuildFile; fileRef = 031FDEBF2EB1C08900F4CAC7 /* FAMeCoinsPackButton.swift */; };
|
||||
031FDEC22EB1E19D00F4CAC7 /* FACoinPackViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 031FDEC12EB1E19D00F4CAC7 /* FACoinPackViewController.swift */; };
|
||||
031FDEC42EB1E45300F4CAC7 /* FACoinPackHeaderView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 031FDEC32EB1E45300F4CAC7 /* FACoinPackHeaderView.swift */; };
|
||||
031FDEC62EB1E4E600F4CAC7 /* FACoinPackTitleView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 031FDEC52EB1E4E600F4CAC7 /* FACoinPackTitleView.swift */; };
|
||||
031FDEC82EB1F89F00F4CAC7 /* FACoinsPackModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 031FDEC72EB1F89F00F4CAC7 /* FACoinsPackModel.swift */; };
|
||||
031FDECA2EB1F8F200F4CAC7 /* FACoinsPackReceiveModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 031FDEC92EB1F8F200F4CAC7 /* FACoinsPackReceiveModel.swift */; };
|
||||
031FDECC2EB1FDF500F4CAC7 /* FACoinsPackClaimListView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 031FDECB2EB1FDF500F4CAC7 /* FACoinsPackClaimListView.swift */; };
|
||||
031FDECE2EB2006000F4CAC7 /* FACoinsPackClaimListCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 031FDECD2EB2006000F4CAC7 /* FACoinsPackClaimListCell.swift */; };
|
||||
031FDED02EB2167200F4CAC7 /* FACoinsPackBuyView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 031FDECF2EB2167200F4CAC7 /* FACoinsPackBuyView.swift */; };
|
||||
031FDED22EB2F69200F4CAC7 /* FALoginView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 031FDED12EB2F69200F4CAC7 /* FALoginView.swift */; };
|
||||
031FDED42EB2FF4000F4CAC7 /* FALogin+Apple.swift in Sources */ = {isa = PBXBuildFile; fileRef = 031FDED32EB2FF3A00F4CAC7 /* FALogin+Apple.swift */; };
|
||||
031FDED62EB300F400F4CAC7 /* FAThirdSignModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 031FDED52EB300F400F4CAC7 /* FAThirdSignModel.swift */; };
|
||||
031FDED92EB30D6E00F4CAC7 /* FASettingCell.xib in Resources */ = {isa = PBXBuildFile; fileRef = 031FDED82EB30D6E00F4CAC7 /* FASettingCell.xib */; };
|
||||
031FDEDA2EB30D6E00F4CAC7 /* FASettingCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 031FDED72EB30D6E00F4CAC7 /* FASettingCell.swift */; };
|
||||
031FDEDC2EB3141E00F4CAC7 /* FASettingFooterView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 031FDEDB2EB3141E00F4CAC7 /* FASettingFooterView.swift */; };
|
||||
031FDEDF2EB3423000F4CAC7 /* FacebookLogin in Frameworks */ = {isa = PBXBuildFile; productRef = 031FDEDE2EB3423000F4CAC7 /* FacebookLogin */; };
|
||||
031FDEE12EB344AB00F4CAC7 /* FALogin+Facebook.swift in Sources */ = {isa = PBXBuildFile; fileRef = 031FDEE02EB344A200F4CAC7 /* FALogin+Facebook.swift */; };
|
||||
031FDEE42EB348AA00F4CAC7 /* FABaseAlert.swift in Sources */ = {isa = PBXBuildFile; fileRef = 031FDEE32EB348AA00F4CAC7 /* FABaseAlert.swift */; };
|
||||
031FDEE62EB34FBC00F4CAC7 /* FARemoveCollectAlert.swift in Sources */ = {isa = PBXBuildFile; fileRef = 031FDEE52EB34FBC00F4CAC7 /* FARemoveCollectAlert.swift */; };
|
||||
031FDEE82EB358AE00F4CAC7 /* FAHomeCoinsPackButton.swift in Sources */ = {isa = PBXBuildFile; fileRef = 031FDEE72EB358AE00F4CAC7 /* FAHomeCoinsPackButton.swift */; };
|
||||
031FDEEA2EB35D2600F4CAC7 /* FACoinPackCanReceiveModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 031FDEE92EB35D2600F4CAC7 /* FACoinPackCanReceiveModel.swift */; };
|
||||
031FDEEC2EB35DF600F4CAC7 /* FACoinsPackAlert.swift in Sources */ = {isa = PBXBuildFile; fileRef = 031FDEEB2EB35DF600F4CAC7 /* FACoinsPackAlert.swift */; };
|
||||
031FDEEE2EB3682000F4CAC7 /* FAVipRetainAlert.swift in Sources */ = {isa = PBXBuildFile; fileRef = 031FDEED2EB3682000F4CAC7 /* FAVipRetainAlert.swift */; };
|
||||
039CE6042EAA2621007B5EED /* AppDelegate+FAAdjust.swift in Sources */ = {isa = PBXBuildFile; fileRef = 039CE6032EAA2612007B5EED /* AppDelegate+FAAdjust.swift */; };
|
||||
039CE6092EAA2F71007B5EED /* FAAdjustStateManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = 039CE6082EAA2F62007B5EED /* FAAdjustStateManager.swift */; };
|
||||
039CE60B2EAA31CB007B5EED /* FAStatAPI.swift in Sources */ = {isa = PBXBuildFile; fileRef = 039CE60A2EAA31CB007B5EED /* FAStatAPI.swift */; };
|
||||
@ -189,6 +212,11 @@
|
||||
03E23AB72EAA1A7F004A8CEC /* FALocalized.swift in Sources */ = {isa = PBXBuildFile; fileRef = 03E23A9C2EAA1A7F004A8CEC /* FALocalized.swift */; };
|
||||
03E23AB82EAA1A7F004A8CEC /* FAWaterfallFlowLayout.swift in Sources */ = {isa = PBXBuildFile; fileRef = 03E23AAA2EAA1A7F004A8CEC /* FAWaterfallFlowLayout.swift */; };
|
||||
03E23ABA2EAA1D85004A8CEC /* MNNItemController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 03E23AB92EAA1D85004A8CEC /* MNNItemController.swift */; };
|
||||
03E9A7362EB44F26000D1067 /* FirebaseMessaging in Frameworks */ = {isa = PBXBuildFile; productRef = 03E9A7352EB44F26000D1067 /* FirebaseMessaging */; };
|
||||
03E9A7382EB44F26000D1067 /* FirebasePerformance in Frameworks */ = {isa = PBXBuildFile; productRef = 03E9A7372EB44F26000D1067 /* FirebasePerformance */; };
|
||||
03E9A73A2EB45154000D1067 /* AppDelegate+FAApns.swift in Sources */ = {isa = PBXBuildFile; fileRef = 03E9A7392EB45149000D1067 /* AppDelegate+FAApns.swift */; };
|
||||
03E9A73C2EB45507000D1067 /* GoogleService-Info.plist in Resources */ = {isa = PBXBuildFile; fileRef = 03E9A73B2EB45507000D1067 /* GoogleService-Info.plist */; };
|
||||
03E9A73E2EB460F2000D1067 /* FAApnsAlert.swift in Sources */ = {isa = PBXBuildFile; fileRef = 03E9A73D2EB460F2000D1067 /* FAApnsAlert.swift */; };
|
||||
B86XD3O90WO2R4725L084287 /* Pods_Fableon.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = C4THBP0A1283PFXW440071Q5 /* Pods_Fableon.framework */; };
|
||||
F3019606DA7P36H41G408X13 /* ZStreamCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = F38E33739F391364D0151P7Z /* ZStreamCell.swift */; };
|
||||
F30470W590T8274E1642349G /* CControlCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = F32MR5F8X6Q3HSZ560BD0159 /* CControlCell.swift */; };
|
||||
@ -306,6 +334,28 @@
|
||||
031FDEB92EB0B82600F4CAC7 /* FACoinPackConfirmItem2View.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FACoinPackConfirmItem2View.swift; sourceTree = "<group>"; };
|
||||
031FDEBB2EB0C97A00F4CAC7 /* FAOldVideoRechargeView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FAOldVideoRechargeView.swift; sourceTree = "<group>"; };
|
||||
031FDEBD2EB0C99900F4CAC7 /* FANewVideoRechargeView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FANewVideoRechargeView.swift; sourceTree = "<group>"; };
|
||||
031FDEBF2EB1C08900F4CAC7 /* FAMeCoinsPackButton.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FAMeCoinsPackButton.swift; sourceTree = "<group>"; };
|
||||
031FDEC12EB1E19D00F4CAC7 /* FACoinPackViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FACoinPackViewController.swift; sourceTree = "<group>"; };
|
||||
031FDEC32EB1E45300F4CAC7 /* FACoinPackHeaderView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FACoinPackHeaderView.swift; sourceTree = "<group>"; };
|
||||
031FDEC52EB1E4E600F4CAC7 /* FACoinPackTitleView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FACoinPackTitleView.swift; sourceTree = "<group>"; };
|
||||
031FDEC72EB1F89F00F4CAC7 /* FACoinsPackModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FACoinsPackModel.swift; sourceTree = "<group>"; };
|
||||
031FDEC92EB1F8F200F4CAC7 /* FACoinsPackReceiveModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FACoinsPackReceiveModel.swift; sourceTree = "<group>"; };
|
||||
031FDECB2EB1FDF500F4CAC7 /* FACoinsPackClaimListView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FACoinsPackClaimListView.swift; sourceTree = "<group>"; };
|
||||
031FDECD2EB2006000F4CAC7 /* FACoinsPackClaimListCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FACoinsPackClaimListCell.swift; sourceTree = "<group>"; };
|
||||
031FDECF2EB2167200F4CAC7 /* FACoinsPackBuyView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FACoinsPackBuyView.swift; sourceTree = "<group>"; };
|
||||
031FDED12EB2F69200F4CAC7 /* FALoginView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FALoginView.swift; sourceTree = "<group>"; };
|
||||
031FDED32EB2FF3A00F4CAC7 /* FALogin+Apple.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "FALogin+Apple.swift"; sourceTree = "<group>"; };
|
||||
031FDED52EB300F400F4CAC7 /* FAThirdSignModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FAThirdSignModel.swift; sourceTree = "<group>"; };
|
||||
031FDED72EB30D6E00F4CAC7 /* FASettingCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FASettingCell.swift; sourceTree = "<group>"; };
|
||||
031FDED82EB30D6E00F4CAC7 /* FASettingCell.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; path = FASettingCell.xib; sourceTree = "<group>"; };
|
||||
031FDEDB2EB3141E00F4CAC7 /* FASettingFooterView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FASettingFooterView.swift; sourceTree = "<group>"; };
|
||||
031FDEE02EB344A200F4CAC7 /* FALogin+Facebook.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "FALogin+Facebook.swift"; sourceTree = "<group>"; };
|
||||
031FDEE32EB348AA00F4CAC7 /* FABaseAlert.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FABaseAlert.swift; sourceTree = "<group>"; };
|
||||
031FDEE52EB34FBC00F4CAC7 /* FARemoveCollectAlert.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FARemoveCollectAlert.swift; sourceTree = "<group>"; };
|
||||
031FDEE72EB358AE00F4CAC7 /* FAHomeCoinsPackButton.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FAHomeCoinsPackButton.swift; sourceTree = "<group>"; };
|
||||
031FDEE92EB35D2600F4CAC7 /* FACoinPackCanReceiveModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FACoinPackCanReceiveModel.swift; sourceTree = "<group>"; };
|
||||
031FDEEB2EB35DF600F4CAC7 /* FACoinsPackAlert.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FACoinsPackAlert.swift; sourceTree = "<group>"; };
|
||||
031FDEED2EB3682000F4CAC7 /* FAVipRetainAlert.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FAVipRetainAlert.swift; sourceTree = "<group>"; };
|
||||
039CE6032EAA2612007B5EED /* AppDelegate+FAAdjust.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "AppDelegate+FAAdjust.swift"; sourceTree = "<group>"; };
|
||||
039CE6082EAA2F62007B5EED /* FAAdjustStateManager.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FAAdjustStateManager.swift; sourceTree = "<group>"; };
|
||||
039CE60A2EAA31CB007B5EED /* FAStatAPI.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FAStatAPI.swift; sourceTree = "<group>"; };
|
||||
@ -479,6 +529,9 @@
|
||||
03E23AA82EAA1A7F004A8CEC /* FAToast.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FAToast.swift; sourceTree = "<group>"; };
|
||||
03E23AAA2EAA1A7F004A8CEC /* FAWaterfallFlowLayout.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FAWaterfallFlowLayout.swift; sourceTree = "<group>"; };
|
||||
03E23AB92EAA1D85004A8CEC /* MNNItemController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MNNItemController.swift; sourceTree = "<group>"; };
|
||||
03E9A7392EB45149000D1067 /* AppDelegate+FAApns.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "AppDelegate+FAApns.swift"; sourceTree = "<group>"; };
|
||||
03E9A73B2EB45507000D1067 /* GoogleService-Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = "GoogleService-Info.plist"; sourceTree = "<group>"; };
|
||||
03E9A73D2EB460F2000D1067 /* FAApnsAlert.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FAApnsAlert.swift; sourceTree = "<group>"; };
|
||||
19196I43BR665O55RD205171 /* Pods-Fableon.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Fableon.debug.xcconfig"; path = "Target Support Files/Pods-Fableon/Pods-Fableon.debug.xcconfig"; sourceTree = "<group>"; };
|
||||
C4THBP0A1283PFXW440071Q5 /* Pods_Fableon.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_Fableon.framework; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
DCD59738B6J31K33W4Z524S0 /* Pods-Fableon.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Fableon.release.xcconfig"; path = "Target Support Files/Pods-Fableon/Pods-Fableon.release.xcconfig"; sourceTree = "<group>"; };
|
||||
@ -594,6 +647,9 @@
|
||||
isa = PBXFrameworksBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
03E9A7362EB44F26000D1067 /* FirebaseMessaging in Frameworks */,
|
||||
031FDEDF2EB3423000F4CAC7 /* FacebookLogin in Frameworks */,
|
||||
03E9A7382EB44F26000D1067 /* FirebasePerformance in Frameworks */,
|
||||
B86XD3O90WO2R4725L084287 /* Pods_Fableon.framework in Frameworks */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
@ -601,6 +657,18 @@
|
||||
/* End PBXFrameworksBuildPhase section */
|
||||
|
||||
/* Begin PBXGroup section */
|
||||
031FDEE22EB3487700F4CAC7 /* Alert */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
031FDEE32EB348AA00F4CAC7 /* FABaseAlert.swift */,
|
||||
031FDEE52EB34FBC00F4CAC7 /* FARemoveCollectAlert.swift */,
|
||||
031FDEEB2EB35DF600F4CAC7 /* FACoinsPackAlert.swift */,
|
||||
031FDEED2EB3682000F4CAC7 /* FAVipRetainAlert.swift */,
|
||||
03E9A73D2EB460F2000D1067 /* FAApnsAlert.swift */,
|
||||
);
|
||||
path = Alert;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
039CE6072EAA2F37007B5EED /* AdjustStateManager */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
@ -645,6 +713,9 @@
|
||||
031FDEAD2EB093B100F4CAC7 /* FABuyRecordsModel.swift */,
|
||||
031FDEAF2EB09AB300F4CAC7 /* FARechargeRecordModel.swift */,
|
||||
031FDEB12EB0A5AF00F4CAC7 /* FASendCoinRecordModel.swift */,
|
||||
031FDEC72EB1F89F00F4CAC7 /* FACoinsPackModel.swift */,
|
||||
031FDEC92EB1F8F200F4CAC7 /* FACoinsPackReceiveModel.swift */,
|
||||
031FDEE92EB35D2600F4CAC7 /* FACoinPackCanReceiveModel.swift */,
|
||||
);
|
||||
path = M;
|
||||
sourceTree = "<group>";
|
||||
@ -849,6 +920,7 @@
|
||||
03E239DF2EAA1A4E004A8CEC /* FASearchResultCell.swift */,
|
||||
03E239E02EAA1A4E004A8CEC /* FASearchResultCell.xib */,
|
||||
03E239E12EAA1A4E004A8CEC /* FASearchResultView.swift */,
|
||||
031FDEE72EB358AE00F4CAC7 /* FAHomeCoinsPackButton.swift */,
|
||||
);
|
||||
path = V;
|
||||
sourceTree = "<group>";
|
||||
@ -882,6 +954,7 @@
|
||||
03E239E92EAA1A4E004A8CEC /* FAMeListViewController.swift */,
|
||||
03E239EA2EAA1A4E004A8CEC /* FAMeViewController.swift */,
|
||||
03E239EB2EAA1A4E004A8CEC /* FASettingViewController.swift */,
|
||||
031FDEC12EB1E19D00F4CAC7 /* FACoinPackViewController.swift */,
|
||||
);
|
||||
path = C;
|
||||
sourceTree = "<group>";
|
||||
@ -905,6 +978,16 @@
|
||||
03E239F42EAA1A4E004A8CEC /* FAMeCoinsView.swift */,
|
||||
03E239F52EAA1A4E004A8CEC /* FAMeHeaderView.swift */,
|
||||
03E239F62EAA1A4E004A8CEC /* FAMeTableViewHeaderView.swift */,
|
||||
031FDEBF2EB1C08900F4CAC7 /* FAMeCoinsPackButton.swift */,
|
||||
031FDEC52EB1E4E600F4CAC7 /* FACoinPackTitleView.swift */,
|
||||
031FDEC32EB1E45300F4CAC7 /* FACoinPackHeaderView.swift */,
|
||||
031FDECB2EB1FDF500F4CAC7 /* FACoinsPackClaimListView.swift */,
|
||||
031FDECD2EB2006000F4CAC7 /* FACoinsPackClaimListCell.swift */,
|
||||
031FDECF2EB2167200F4CAC7 /* FACoinsPackBuyView.swift */,
|
||||
031FDED12EB2F69200F4CAC7 /* FALoginView.swift */,
|
||||
031FDED72EB30D6E00F4CAC7 /* FASettingCell.swift */,
|
||||
031FDED82EB30D6E00F4CAC7 /* FASettingCell.xib */,
|
||||
031FDEDB2EB3141E00F4CAC7 /* FASettingFooterView.swift */,
|
||||
);
|
||||
path = V;
|
||||
sourceTree = "<group>";
|
||||
@ -1101,6 +1184,7 @@
|
||||
03E23A962EAA1A65004A8CEC /* Libs */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
031FDEE22EB3487700F4CAC7 /* Alert */,
|
||||
039CE6122EAB0DE1007B5EED /* FAIap */,
|
||||
039CE60F2EAB0D2D007B5EED /* JXIAPManager */,
|
||||
039CE6072EAA2F37007B5EED /* AdjustStateManager */,
|
||||
@ -1145,8 +1229,11 @@
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
03E23A9E2EAA1A7F004A8CEC /* FALogin.swift */,
|
||||
031FDED32EB2FF3A00F4CAC7 /* FALogin+Apple.swift */,
|
||||
031FDEE02EB344A200F4CAC7 /* FALogin+Facebook.swift */,
|
||||
03E23A9F2EAA1A7F004A8CEC /* FATokenModel.swift */,
|
||||
03E23AA02EAA1A7F004A8CEC /* FAUserInfo.swift */,
|
||||
031FDED52EB300F400F4CAC7 /* FAThirdSignModel.swift */,
|
||||
);
|
||||
path = FALogin;
|
||||
sourceTree = "<group>";
|
||||
@ -1555,6 +1642,7 @@
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
F32J2363K02108Z62849Y019 /* Assets.xcassets */,
|
||||
03E9A73B2EB45507000D1067 /* GoogleService-Info.plist */,
|
||||
F3718184F516RJ76435E1IQ3 /* Info.plist */,
|
||||
F3S22333V8I503E2Z4YYN165 /* LaunchScreen.storyboard */,
|
||||
F3A0557617AU32W3L218F159 /* Localizable.strings */,
|
||||
@ -1600,9 +1688,10 @@
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
03E239602EAA1945004A8CEC /* AppDelegate.swift */,
|
||||
03E239622EAA1945004A8CEC /* SceneDelegate.swift */,
|
||||
03E239612EAA1945004A8CEC /* AppDelegate+FAConfig.swift */,
|
||||
039CE6032EAA2612007B5EED /* AppDelegate+FAAdjust.swift */,
|
||||
03E239622EAA1945004A8CEC /* SceneDelegate.swift */,
|
||||
03E9A7392EB45149000D1067 /* AppDelegate+FAApns.swift */,
|
||||
);
|
||||
path = App;
|
||||
sourceTree = "<group>";
|
||||
@ -1713,6 +1802,10 @@
|
||||
);
|
||||
mainGroup = F31ABI705806054356280I22;
|
||||
minimizedProjectReferenceProxies = 1;
|
||||
packageReferences = (
|
||||
031FDEDD2EB3423000F4CAC7 /* XCRemoteSwiftPackageReference "facebook-ios-sdk" */,
|
||||
03E9A7342EB44F26000D1067 /* XCRemoteSwiftPackageReference "firebase-ios-sdk" */,
|
||||
);
|
||||
preferredProjectObjectVersion = 77;
|
||||
productRefGroup = F3B536I6734E05L319J6654P /* Products */;
|
||||
projectDirPath = "";
|
||||
@ -1744,6 +1837,7 @@
|
||||
03E23A862EAA1A4E004A8CEC /* FAHistoryCell.xib in Resources */,
|
||||
03E23A872EAA1A4E004A8CEC /* FAHomeRecommendedCell.xib in Resources */,
|
||||
03E23A882EAA1A4E004A8CEC /* FAMeCell.xib in Resources */,
|
||||
031FDED92EB30D6E00F4CAC7 /* FASettingCell.xib in Resources */,
|
||||
03E23A892EAA1A4E004A8CEC /* FASearchResultCell.xib in Resources */,
|
||||
03E23A8A2EAA1A4E004A8CEC /* FASearchRecommendCell.xib in Resources */,
|
||||
03E23A8B2EAA1A4E004A8CEC /* FAHomeSectionTitleView.xib in Resources */,
|
||||
@ -1756,6 +1850,7 @@
|
||||
03E23A922EAA1A4E004A8CEC /* FAConsumptionRecordsCell.xib in Resources */,
|
||||
03E23A932EAA1A4E004A8CEC /* FASearchRecordCell.xib in Resources */,
|
||||
03E23A942EAA1A4E004A8CEC /* FARankingListCell.xib in Resources */,
|
||||
03E9A73C2EB45507000D1067 /* GoogleService-Info.plist in Resources */,
|
||||
03E23A952EAA1A4E004A8CEC /* FAAboutCell.xib in Resources */,
|
||||
F3R81ZR0ZIP4Q85CX4Z5J3I4 /* LaunchScreen.storyboard in Resources */,
|
||||
F362972840Y56X1RPFI92W64 /* XKRefreshCell.xib in Resources */,
|
||||
@ -1838,12 +1933,14 @@
|
||||
F336143N569M8JG811WM9549 /* XHEedbackDetailView.swift in Sources */,
|
||||
F3F0952W592747Y1H6263E06 /* UCVBbfdebaffdFlowCell.swift in Sources */,
|
||||
F3SUP8DL68BIIEF1B8Z6U863 /* CFQConfigView.swift in Sources */,
|
||||
031FDEE12EB344AB00F4CAC7 /* FALogin+Facebook.swift in Sources */,
|
||||
F30E153206675C3SJ3974VL1 /* OJQUnechoSectionView.swift in Sources */,
|
||||
F381909BQ5JWXYI119A49469 /* DREychainCell.swift in Sources */,
|
||||
F39R66F983517825QO331145 /* QCenterEfineView.swift in Sources */,
|
||||
F3II3AF834346F516W51V693 /* GAMainRecommendedView.swift in Sources */,
|
||||
031FDEAE2EB093B100F4CAC7 /* FABuyRecordsModel.swift in Sources */,
|
||||
F377Y22Z3J44H22J23963544 /* CDNewsController.swift in Sources */,
|
||||
031FDEC22EB1E19D00F4CAC7 /* FACoinPackViewController.swift in Sources */,
|
||||
F358686093028548K00WQIO1 /* NGleeVionView.swift in Sources */,
|
||||
F3019606DA7P36H41G408X13 /* ZStreamCell.swift in Sources */,
|
||||
F392T441X031FH7N0HA03SZ7 /* WPSectionView.swift in Sources */,
|
||||
@ -1865,6 +1962,7 @@
|
||||
F3P4D170962A2JAF14W0520R /* ADCheckMageView.swift in Sources */,
|
||||
031FDEBA2EB0B82600F4CAC7 /* FACoinPackConfirmItem2View.swift in Sources */,
|
||||
F3206101P0DVK224N85S1W62 /* XIPathEviceController.swift in Sources */,
|
||||
031FDEC82EB1F89F00F4CAC7 /* FACoinsPackModel.swift in Sources */,
|
||||
F31N0S2575E3YC5AOG80WE90 /* TYElyon.swift in Sources */,
|
||||
F3JX29E3JQ40V23245TS8Z36 /* YRegisterController.swift in Sources */,
|
||||
F381171472542RD403O12925 /* QZOast.swift in Sources */,
|
||||
@ -1882,6 +1980,7 @@
|
||||
03E23AAC2EAA1A7F004A8CEC /* FALogin.swift in Sources */,
|
||||
03E23AAD2EAA1A7F004A8CEC /* FAKeychainHelper.swift in Sources */,
|
||||
03E23AAE2EAA1A7F004A8CEC /* FATool.swift in Sources */,
|
||||
031FDECC2EB1FDF500F4CAC7 /* FACoinsPackClaimListView.swift in Sources */,
|
||||
039CE6262EAB2A72007B5EED /* FAPayAlertModel.swift in Sources */,
|
||||
03E23AAF2EAA1A7F004A8CEC /* FSPagerSwiftUIView.swift in Sources */,
|
||||
03E23AB02EAA1A7F004A8CEC /* FADeviceIDManager.swift in Sources */,
|
||||
@ -1896,6 +1995,7 @@
|
||||
03E23AB72EAA1A7F004A8CEC /* FALocalized.swift in Sources */,
|
||||
039CE6222EAB1340007B5EED /* FAUserDefaultsKey.swift in Sources */,
|
||||
03E23AB82EAA1A7F004A8CEC /* FAWaterfallFlowLayout.swift in Sources */,
|
||||
031FDEC62EB1E4E600F4CAC7 /* FACoinPackTitleView.swift in Sources */,
|
||||
F3K238643L913I6RK4G7S006 /* CSceneRegister.swift in Sources */,
|
||||
F3ZT3I4VAGB5405FWL36UW12 /* ZFGEtworkCell.swift in Sources */,
|
||||
F35O71332554S53191121042 /* UOModalCell.swift in Sources */,
|
||||
@ -1908,6 +2008,7 @@
|
||||
03E23A352EAA1A4E004A8CEC /* FARecommendPlayerControlView.swift in Sources */,
|
||||
03E23A362EAA1A4E004A8CEC /* FAHomeMustSeeView.swift in Sources */,
|
||||
03E23A372EAA1A4E004A8CEC /* FAHomeItem.swift in Sources */,
|
||||
03E9A73E2EB460F2000D1067 /* FAApnsAlert.swift in Sources */,
|
||||
03E23A382EAA1A4E004A8CEC /* FACategoryModel.swift in Sources */,
|
||||
03E23A392EAA1A4E004A8CEC /* FANewListViewController.swift in Sources */,
|
||||
03E23A3A2EAA1A4E004A8CEC /* FAHomeRecommendedCell.swift in Sources */,
|
||||
@ -1928,12 +2029,14 @@
|
||||
03E23A492EAA1A4E004A8CEC /* FAVideoInfoModel.swift in Sources */,
|
||||
039CE6202EAB114B007B5EED /* FAPayDateModel.swift in Sources */,
|
||||
03E23A4A2EAA1A4E004A8CEC /* FAConsumptionRecordsViewController.swift in Sources */,
|
||||
031FDED02EB2167200F4CAC7 /* FACoinsPackBuyView.swift in Sources */,
|
||||
03E23A4B2EAA1A4E004A8CEC /* FAMeCoinsView.swift in Sources */,
|
||||
03E23A4C2EAA1A4E004A8CEC /* FAHomeViewModel.swift in Sources */,
|
||||
03E23A4D2EAA1A4E004A8CEC /* FAGenresViewController.swift in Sources */,
|
||||
03E23A4E2EAA1A4E004A8CEC /* FAHomeBannerContentCell.swift in Sources */,
|
||||
03E23A4F2EAA1A4E004A8CEC /* FAEpSelectorView.swift in Sources */,
|
||||
03E23A502EAA1A4E004A8CEC /* FAMeHeaderView.swift in Sources */,
|
||||
031FDEC02EB1C08900F4CAC7 /* FAMeCoinsPackButton.swift in Sources */,
|
||||
03E23A512EAA1A4E004A8CEC /* FAConsumptionRecordsCell.swift in Sources */,
|
||||
03E23A522EAA1A4E004A8CEC /* FARankingListHeaderView.swift in Sources */,
|
||||
03E23A532EAA1A4E004A8CEC /* FAVideoLockView.swift in Sources */,
|
||||
@ -1941,20 +2044,25 @@
|
||||
03E23A552EAA1A4E004A8CEC /* FAPopularListViewController.swift in Sources */,
|
||||
039CE6042EAA2621007B5EED /* AppDelegate+FAAdjust.swift in Sources */,
|
||||
03E23A562EAA1A4E004A8CEC /* FAPlayerEpUIButton.swift in Sources */,
|
||||
031FDEE42EB348AA00F4CAC7 /* FABaseAlert.swift in Sources */,
|
||||
03E23A572EAA1A4E004A8CEC /* FAHistoryCell.swift in Sources */,
|
||||
03E23A582EAA1A4E004A8CEC /* FASearchViewController.swift in Sources */,
|
||||
03E23A592EAA1A4E004A8CEC /* FAWalletCell.swift in Sources */,
|
||||
03E23A5A2EAA1A4E004A8CEC /* FASearchInputView.swift in Sources */,
|
||||
031FDEE82EB358AE00F4CAC7 /* FAHomeCoinsPackButton.swift in Sources */,
|
||||
03E23A5B2EAA1A4E004A8CEC /* FAAboutCell.swift in Sources */,
|
||||
03E23A5C2EAA1A4E004A8CEC /* FAGenresListViewController.swift in Sources */,
|
||||
03E23A5D2EAA1A4E004A8CEC /* FARecommendViewModel.swift in Sources */,
|
||||
03E23A5E2EAA1A4E004A8CEC /* FAHomeMustSeeContentView.swift in Sources */,
|
||||
03E23A5F2EAA1A4E004A8CEC /* FAEpSelectorCell.swift in Sources */,
|
||||
031FDEEC2EB35DF600F4CAC7 /* FACoinsPackAlert.swift in Sources */,
|
||||
03E23A602EAA1A4E004A8CEC /* FASearchResultView.swift in Sources */,
|
||||
03E23A612EAA1A4E004A8CEC /* FAHomeMustSeeContentCell.swift in Sources */,
|
||||
03E23A622EAA1A4E004A8CEC /* FAShortDetailModel.swift in Sources */,
|
||||
03E23A632EAA1A4E004A8CEC /* FASearchResultCell.swift in Sources */,
|
||||
03E23A642EAA1A4E004A8CEC /* FAMeTableViewHeaderView.swift in Sources */,
|
||||
031FDEE62EB34FBC00F4CAC7 /* FARemoveCollectAlert.swift in Sources */,
|
||||
031FDECE2EB2006000F4CAC7 /* FACoinsPackClaimListCell.swift in Sources */,
|
||||
03E23A652EAA1A4E004A8CEC /* FARewardCoinsViewController.swift in Sources */,
|
||||
03E23A662EAA1A4E004A8CEC /* FAStoreViewController.swift in Sources */,
|
||||
03E23A672EAA1A4E004A8CEC /* FAMeListViewController.swift in Sources */,
|
||||
@ -1964,7 +2072,9 @@
|
||||
03E23A6B2EAA1A4E004A8CEC /* FARecommendPlayerCell.swift in Sources */,
|
||||
03E23A6C2EAA1A4E004A8CEC /* FAHomeNewView.swift in Sources */,
|
||||
03E23A6D2EAA1A4E004A8CEC /* FARankingListViewController.swift in Sources */,
|
||||
031FDEEA2EB35D2600F4CAC7 /* FACoinPackCanReceiveModel.swift in Sources */,
|
||||
03E23A6E2EAA1A4E004A8CEC /* FARankingListCell.swift in Sources */,
|
||||
031FDED22EB2F69200F4CAC7 /* FALoginView.swift in Sources */,
|
||||
03E23A6F2EAA1A4E004A8CEC /* FAHomeBannerCell.swift in Sources */,
|
||||
03E23A702EAA1A4E004A8CEC /* FAGenresCell.swift in Sources */,
|
||||
03E23A712EAA1A4E004A8CEC /* FAHomeSectionTitleView.swift in Sources */,
|
||||
@ -1981,12 +2091,14 @@
|
||||
03E23A7A2EAA1A4E004A8CEC /* FASearchRecordView.swift in Sources */,
|
||||
03E23A7B2EAA1A4E004A8CEC /* FACollectViewController.swift in Sources */,
|
||||
03E23A7C2EAA1A4E004A8CEC /* FAMeCell.swift in Sources */,
|
||||
03E9A73A2EB45154000D1067 /* AppDelegate+FAApns.swift in Sources */,
|
||||
03E23A7D2EAA1A4E004A8CEC /* FAWalletHeaderView.swift in Sources */,
|
||||
03E23A7E2EAA1A4E004A8CEC /* FAPlayerProgressView.swift in Sources */,
|
||||
031FDEB82EB0B80400F4CAC7 /* FACoinPackConfirmItem1View.swift in Sources */,
|
||||
03E23A7F2EAA1A4E004A8CEC /* FAMeItemModel.swift in Sources */,
|
||||
03E23A802EAA1A4E004A8CEC /* FAGenresListCell.swift in Sources */,
|
||||
03E23A812EAA1A4E004A8CEC /* FACollectCell.swift in Sources */,
|
||||
031FDED62EB300F400F4CAC7 /* FAThirdSignModel.swift in Sources */,
|
||||
03E23A822EAA1A4E004A8CEC /* FASearchRecommendView.swift in Sources */,
|
||||
03E23A832EAA1A4E004A8CEC /* FAHomeMustSeeShortView.swift in Sources */,
|
||||
039CE60B2EAA31CB007B5EED /* FAStatAPI.swift in Sources */,
|
||||
@ -2014,11 +2126,14 @@
|
||||
F3M8439X72Q55JY9G8U502D9 /* DXYFire.swift in Sources */,
|
||||
03E239912EAA1A29004A8CEC /* Dictionary+FAAdd.swift in Sources */,
|
||||
03E239922EAA1A29004A8CEC /* FAImageView.swift in Sources */,
|
||||
031FDEDC2EB3141E00F4CAC7 /* FASettingFooterView.swift in Sources */,
|
||||
031FDEBE2EB0C99900F4CAC7 /* FANewVideoRechargeView.swift in Sources */,
|
||||
03E239932EAA1A29004A8CEC /* Date+FAAdd.swift in Sources */,
|
||||
031FDEDA2EB30D6E00F4CAC7 /* FASettingCell.swift in Sources */,
|
||||
03E239942EAA1A29004A8CEC /* UserDefaults+FAAdd.swift in Sources */,
|
||||
039CE6322EAB796F007B5EED /* FALabel.swift in Sources */,
|
||||
03E239952EAA1A29004A8CEC /* Font+FAAdd.swift in Sources */,
|
||||
031FDEEE2EB3682000F4CAC7 /* FAVipRetainAlert.swift in Sources */,
|
||||
03E239962EAA1A29004A8CEC /* FACryptorService.swift in Sources */,
|
||||
03E239972EAA1A29004A8CEC /* FANetworkManager.swift in Sources */,
|
||||
03E239982EAA1A29004A8CEC /* UIScrollView+FARefresh.swift in Sources */,
|
||||
@ -2035,6 +2150,7 @@
|
||||
03E239A22EAA1A29004A8CEC /* FATabBarController.swift in Sources */,
|
||||
03E239A32EAA1A29004A8CEC /* UIStackView+FAAdd.swift in Sources */,
|
||||
03E239A42EAA1A29004A8CEC /* UIScreen+FAAdd.swift in Sources */,
|
||||
031FDED42EB2FF4000F4CAC7 /* FALogin+Apple.swift in Sources */,
|
||||
039CE6182EAB0E7E007B5EED /* FAStoreAPI.swift in Sources */,
|
||||
03E239A52EAA1A29004A8CEC /* FACollectionView.swift in Sources */,
|
||||
03E239A62EAA1A29004A8CEC /* UIView+FAAdd.swift in Sources */,
|
||||
@ -2046,9 +2162,11 @@
|
||||
03E239AB2EAA1A29004A8CEC /* FATableViewCell.swift in Sources */,
|
||||
03E239AC2EAA1A29004A8CEC /* FABaseWebViewController+Script.swift in Sources */,
|
||||
03E239AD2EAA1A29004A8CEC /* FAAppWebViewController.swift in Sources */,
|
||||
031FDEC42EB1E45300F4CAC7 /* FACoinPackHeaderView.swift in Sources */,
|
||||
03E239AE2EAA1A29004A8CEC /* SwiftUIExtension.swift in Sources */,
|
||||
039CE60E2EAA32A8007B5EED /* FAOpenAppModel.swift in Sources */,
|
||||
03E239AF2EAA1A29004A8CEC /* FAAPI.swift in Sources */,
|
||||
031FDECA2EB1F8F200F4CAC7 /* FACoinsPackReceiveModel.swift in Sources */,
|
||||
03E239B02EAA1A29004A8CEC /* FAWebView.swift in Sources */,
|
||||
039CE61C2EAB0F29007B5EED /* FAIapOrderModel.swift in Sources */,
|
||||
03E239B12EAA1A29004A8CEC /* FANetworkMonitor.swift in Sources */,
|
||||
@ -2233,6 +2351,7 @@
|
||||
INFOPLIST_KEY_ITSAppUsesNonExemptEncryption = NO;
|
||||
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_NSUserTrackingUsageDescription = "We will use your advertising identifier (IDFA) to provide a personalized advertising experience.";
|
||||
INFOPLIST_KEY_UIApplicationSupportsIndirectInputEvents = YES;
|
||||
INFOPLIST_KEY_UILaunchStoryboardName = LaunchScreen;
|
||||
INFOPLIST_KEY_UIMainStoryboardFile = "";
|
||||
@ -2273,6 +2392,7 @@
|
||||
INFOPLIST_KEY_ITSAppUsesNonExemptEncryption = NO;
|
||||
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_NSUserTrackingUsageDescription = "We will use your advertising identifier (IDFA) to provide a personalized advertising experience.";
|
||||
INFOPLIST_KEY_UIApplicationSupportsIndirectInputEvents = YES;
|
||||
INFOPLIST_KEY_UILaunchStoryboardName = LaunchScreen;
|
||||
INFOPLIST_KEY_UIMainStoryboardFile = "";
|
||||
@ -2317,6 +2437,43 @@
|
||||
defaultConfigurationName = Release;
|
||||
};
|
||||
/* End XCConfigurationList section */
|
||||
|
||||
/* Begin XCRemoteSwiftPackageReference section */
|
||||
031FDEDD2EB3423000F4CAC7 /* XCRemoteSwiftPackageReference "facebook-ios-sdk" */ = {
|
||||
isa = XCRemoteSwiftPackageReference;
|
||||
repositoryURL = "https://github.com/facebook/facebook-ios-sdk";
|
||||
requirement = {
|
||||
kind = upToNextMajorVersion;
|
||||
minimumVersion = 14.1.0;
|
||||
};
|
||||
};
|
||||
03E9A7342EB44F26000D1067 /* XCRemoteSwiftPackageReference "firebase-ios-sdk" */ = {
|
||||
isa = XCRemoteSwiftPackageReference;
|
||||
repositoryURL = "https://github.com/firebase/firebase-ios-sdk";
|
||||
requirement = {
|
||||
kind = upToNextMajorVersion;
|
||||
minimumVersion = 12.5.0;
|
||||
};
|
||||
};
|
||||
/* End XCRemoteSwiftPackageReference section */
|
||||
|
||||
/* Begin XCSwiftPackageProductDependency section */
|
||||
031FDEDE2EB3423000F4CAC7 /* FacebookLogin */ = {
|
||||
isa = XCSwiftPackageProductDependency;
|
||||
package = 031FDEDD2EB3423000F4CAC7 /* XCRemoteSwiftPackageReference "facebook-ios-sdk" */;
|
||||
productName = FacebookLogin;
|
||||
};
|
||||
03E9A7352EB44F26000D1067 /* FirebaseMessaging */ = {
|
||||
isa = XCSwiftPackageProductDependency;
|
||||
package = 03E9A7342EB44F26000D1067 /* XCRemoteSwiftPackageReference "firebase-ios-sdk" */;
|
||||
productName = FirebaseMessaging;
|
||||
};
|
||||
03E9A7372EB44F26000D1067 /* FirebasePerformance */ = {
|
||||
isa = XCSwiftPackageProductDependency;
|
||||
package = 03E9A7342EB44F26000D1067 /* XCRemoteSwiftPackageReference "firebase-ios-sdk" */;
|
||||
productName = FirebasePerformance;
|
||||
};
|
||||
/* End XCSwiftPackageProductDependency section */
|
||||
};
|
||||
rootObject = F3LK276P33H73Y39H9X6VTDI /* Project object */;
|
||||
}
|
||||
|
||||
@ -133,7 +133,7 @@ extension SceneDelegate {
|
||||
var result = false
|
||||
|
||||
#if canImport(FacebookCore)
|
||||
let result = ApplicationDelegate.shared.application(UIApplication.shared, continue: userActivity)
|
||||
result = ApplicationDelegate.shared.application(UIApplication.shared, continue: userActivity)
|
||||
#endif
|
||||
|
||||
if !result {
|
||||
|
||||
123
Fableon/App/AppDelegate+FAApns.swift
Normal file
@ -0,0 +1,123 @@
|
||||
//
|
||||
// AppDelegate+FAApns.swift
|
||||
// Fableon
|
||||
//
|
||||
// Created by 湖北秦九 on 2025/10/31.
|
||||
//
|
||||
import UIKit
|
||||
import FirebaseMessaging
|
||||
import SmartCodable
|
||||
import FirebaseCore
|
||||
|
||||
extension SceneDelegate {
|
||||
|
||||
func requestFirebase() {
|
||||
FirebaseApp.configure()
|
||||
Messaging.messaging().delegate = self
|
||||
}
|
||||
|
||||
func requestApns() {
|
||||
let center = UNUserNotificationCenter.current()
|
||||
center.delegate = self
|
||||
|
||||
center.requestAuthorization(options: [.badge, .sound, .alert]) { grant, error in
|
||||
if !grant {
|
||||
DispatchQueue.main.asyncAfter(deadline: .now() + 0.5) {
|
||||
self.showApnsAlert()
|
||||
}
|
||||
}
|
||||
FAAdjustStateManager.manager.apnsAuthorizationFinish = true
|
||||
|
||||
FATool.sceneDelegate?.retryHandleOpenAppMessage()
|
||||
|
||||
|
||||
FATool.requestIDFAAuthorization(nil)
|
||||
FAStatAPI.uploadApnsAuthorizationStatus()
|
||||
}
|
||||
UIApplication.shared.registerForRemoteNotifications()
|
||||
}
|
||||
|
||||
|
||||
|
||||
func setBadgeCount(_ count: Int) {
|
||||
if #available(iOS 16.0, *) {
|
||||
UNUserNotificationCenter.current().setBadgeCount(count)
|
||||
} else {
|
||||
UIApplication.shared.applicationIconBadgeNumber = count
|
||||
}
|
||||
}
|
||||
|
||||
private func showApnsAlert() {
|
||||
guard let date = UserDefaults.standard.object(forKey: kFAApnsAlertDefaultsKey) as? Date else {
|
||||
UserDefaults.standard.set(Date(), forKey: kFAApnsAlertDefaultsKey)
|
||||
return
|
||||
}
|
||||
#if !DEBUG
|
||||
if date.fa_isToday { return }
|
||||
UserDefaults.standard.set(Date(), forKey: kFAApnsAlertDefaultsKey)
|
||||
#endif
|
||||
|
||||
let view = FAApnsAlert()
|
||||
view.show()
|
||||
}
|
||||
}
|
||||
|
||||
extension AppDelegate {
|
||||
func application(_ application: UIApplication, didRegisterForRemoteNotificationsWithDeviceToken deviceToken: Data) {
|
||||
Messaging.messaging().apnsToken = deviceToken
|
||||
}
|
||||
|
||||
func application(_ application: UIApplication, didFailToRegisterForRemoteNotificationsWithError error: any Error) {
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
//MARK: -------------- UNUserNotificationCenterDelegate --------------
|
||||
extension SceneDelegate: UNUserNotificationCenterDelegate {
|
||||
|
||||
|
||||
///APP处于前台是接收通知消息
|
||||
func userNotificationCenter(_ center: UNUserNotificationCenter, willPresent notification: UNNotification, withCompletionHandler completionHandler: @escaping (UNNotificationPresentationOptions) -> Void) {
|
||||
completionHandler([.badge, .banner])
|
||||
}
|
||||
|
||||
///点击通知消息进入app
|
||||
func userNotificationCenter(_ center: UNUserNotificationCenter, didReceive response: UNNotificationResponse, withCompletionHandler completionHandler: @escaping () -> Void) {
|
||||
setBadgeCount(0)
|
||||
|
||||
guard let userInfo: [String : Any] = response.notification.request.content.userInfo as? [String : Any] else {
|
||||
completionHandler()
|
||||
return
|
||||
}
|
||||
|
||||
guard let model = FAOpenAppModel.deserialize(from: userInfo) else {
|
||||
completionHandler()
|
||||
return
|
||||
}
|
||||
FAStatAPI.requestStatApnsClick(id: model.message_id ?? "", title: response.notification.request.content.title)
|
||||
|
||||
if model.path == .videoDetail, let shortPlayId = model.short_play_id {
|
||||
let vc = FAPlayerDetailViewController()
|
||||
vc.shortPlayId = shortPlayId
|
||||
FATool.topViewController?.navigationController?.pushViewController(vc, animated: true)
|
||||
|
||||
} else if model.path == .feedback {
|
||||
let vc = FAAppWebViewController()
|
||||
vc.webUrl = kFAFeedBackListWebUrl
|
||||
FATool.topViewController?.navigationController?.pushViewController(vc, animated: true)
|
||||
}
|
||||
|
||||
completionHandler()
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
//MARK: MessagingDelegate
|
||||
extension SceneDelegate: MessagingDelegate {
|
||||
func messaging(_ messaging: Messaging, didReceiveRegistrationToken fcmToken: String?) {
|
||||
if let token = fcmToken {
|
||||
FAStatAPI.requestUploadApnsDeviceToken(token: token)
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -9,6 +9,7 @@ import UIKit
|
||||
import MJRefresh
|
||||
import IQKeyboardManagerSwift
|
||||
import IQKeyboardToolbarManager
|
||||
import FacebookCore
|
||||
|
||||
|
||||
extension AppDelegate {
|
||||
@ -30,6 +31,11 @@ extension AppDelegate {
|
||||
UINavigationBar.appearance().standardAppearance = appearance
|
||||
|
||||
registerAdjust()
|
||||
|
||||
}
|
||||
|
||||
func fa_registThirdparty(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) {
|
||||
ApplicationDelegate.shared.application(application, didFinishLaunchingWithOptions: launchOptions)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@ -6,6 +6,7 @@
|
||||
//
|
||||
|
||||
import UIKit
|
||||
import FacebookCore
|
||||
|
||||
@main
|
||||
class AppDelegate: UIResponder, UIApplicationDelegate {
|
||||
@ -14,6 +15,8 @@ class AppDelegate: UIResponder, UIApplicationDelegate {
|
||||
|
||||
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
|
||||
FANetworkMonitor.manager.startMonitoring()
|
||||
fa_registThirdparty(application, didFinishLaunchingWithOptions: launchOptions)
|
||||
|
||||
self.fa_config()
|
||||
|
||||
NotificationCenter.default.addObserver(self, selector: #selector(networkStatusDidChangeNotification), name: FANetworkMonitor.networkStatusDidChangeNotification, object: nil)
|
||||
|
||||
@ -6,40 +6,54 @@
|
||||
//
|
||||
|
||||
import UIKit
|
||||
import YYText
|
||||
|
||||
class SceneDelegate: UIResponder, UIWindowSceneDelegate {
|
||||
|
||||
var window: UIWindow?
|
||||
|
||||
private var onLineTimer: Timer?
|
||||
|
||||
func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) {
|
||||
guard let windowScene = (scene as? UIWindowScene) else { return }
|
||||
NotificationCenter.default.addObserver(self, selector: #selector(networkStatusDidChangeNotification), name: FANetworkMonitor.networkStatusDidChangeNotification, object: nil)
|
||||
FATool.sceneDelegate = self
|
||||
FATool.windowScene = windowScene
|
||||
|
||||
window = UIWindow(windowScene: windowScene)
|
||||
window?.rootViewController = FATabBarController()
|
||||
window?.makeKeyAndVisible()
|
||||
FAAdjustStateManager.manager.isOpenApp = true
|
||||
|
||||
onLineTimer = Timer.scheduledTimer(timeInterval: 60 * 10, target: YYTextWeakProxy(target: self), selector: #selector(handleOnLine), userInfo: nil, repeats: true)
|
||||
|
||||
|
||||
if let webpageURL = connectionOptions.userActivities.first?.webpageURL {
|
||||
self.handleOpenAppMessage(webpageURL: webpageURL)
|
||||
} else if let url = connectionOptions.urlContexts.first?.url {
|
||||
self.handleOpenAppMessage(webpageURL: url)
|
||||
}
|
||||
|
||||
requestFirebase()
|
||||
requestApns()
|
||||
}
|
||||
|
||||
func sceneDidDisconnect(_ scene: UIScene) {
|
||||
// Called as the scene is being released by the system.
|
||||
// This occurs shortly after the scene enters the background, or when its session is discarded.
|
||||
// Release any resources associated with this scene that can be re-created the next time the scene connects.
|
||||
// The scene may re-connect later, as its session was not necessarily discarded (see `application:didDiscardSceneSessions` instead).
|
||||
|
||||
}
|
||||
|
||||
func sceneDidBecomeActive(_ scene: UIScene) {
|
||||
// Called when the scene has moved from an inactive state to an active state.
|
||||
// Use this method to restart any tasks that were paused (or not yet started) when the scene was inactive.
|
||||
self.handleOnLine()
|
||||
FAStatAPI.requestEnterApp()
|
||||
self.setBadgeCount(0)
|
||||
}
|
||||
|
||||
func sceneWillResignActive(_ scene: UIScene) {
|
||||
// Called when the scene will move from an active state to an inactive state.
|
||||
// This may occur due to temporary interruptions (ex. an incoming phone call).
|
||||
FAStatAPI.requestLeaveApp()
|
||||
}
|
||||
|
||||
func sceneWillEnterForeground(_ scene: UIScene) {
|
||||
FAStatAPI.uploadApnsAuthorizationStatus()
|
||||
DispatchQueue.main.asyncAfter(deadline: .now() + 0.5) {
|
||||
self.handleOpenAppMessage(webpageURL: nil)
|
||||
}
|
||||
@ -52,3 +66,14 @@ class SceneDelegate: UIResponder, UIWindowSceneDelegate {
|
||||
|
||||
}
|
||||
|
||||
extension SceneDelegate {
|
||||
|
||||
@objc private func handleOnLine() {
|
||||
FAStatAPI.requestStatOnLine()
|
||||
}
|
||||
|
||||
@objc private func networkStatusDidChangeNotification() {
|
||||
FATool.requestIDFAAuthorization(nil)
|
||||
self.retryHandleOpenAppMessage()
|
||||
}
|
||||
}
|
||||
|
||||
@ -2,10 +2,16 @@
|
||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||
<plist version="1.0">
|
||||
<dict>
|
||||
<key>com.apple.developer.applesignin</key>
|
||||
<array>
|
||||
<string>Default</string>
|
||||
</array>
|
||||
<key>com.apple.developer.associated-domains</key>
|
||||
<array>
|
||||
<string>applinks:fableon.go.link</string>
|
||||
<string>applinks:kuzt.adj.st</string>
|
||||
</array>
|
||||
<key>keychain-access-groups</key>
|
||||
<array/>
|
||||
</dict>
|
||||
</plist>
|
||||
|
||||
@ -7,3 +7,5 @@
|
||||
|
||||
|
||||
let kFAWaitRestoreIAPDefaultsKey = "kFAWaitRestoreIAPDefaultsKey"
|
||||
|
||||
let kFAApnsAlertDefaultsKey = "kFAApnsAlertDefaultsKey"
|
||||
|
||||
@ -22,7 +22,7 @@ extension Date {
|
||||
}
|
||||
|
||||
///是否是今天
|
||||
var br_isToday: Bool {
|
||||
var fa_isToday: Bool {
|
||||
get {
|
||||
return Calendar.current.isDateInToday(self)
|
||||
}
|
||||
|
||||
@ -6,6 +6,7 @@
|
||||
//
|
||||
|
||||
import UIKit
|
||||
import SmartCodable
|
||||
|
||||
extension FAAPI {
|
||||
///更新短剧关注状态 [ "state" : isCollect, "id" : shortPlayId,]
|
||||
@ -249,6 +250,34 @@ struct FAAPI {
|
||||
completer?(response.data)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
//MARK: 用户登录
|
||||
extension FAAPI {
|
||||
///第三方用户登录
|
||||
static func requestSignThirdLogin(model: FAThirdSignModel, completer: ((_ token: FATokenModel?) -> Void)?) {
|
||||
FANetworkManager.manager.request(FABaseURL + "/customer/login",
|
||||
method: .post,
|
||||
parameters: model.toDictionary(),
|
||||
isLoding: false,
|
||||
isToast: true) { (response: FANetworkManager.Response<FATokenModel>) in
|
||||
completer?(response.data)
|
||||
}
|
||||
}
|
||||
|
||||
static func requestLogout(completer: ((_ token: FATokenModel?) -> Void)?) {
|
||||
|
||||
FANetworkManager.manager.request(FABaseURL + "/customer/signout",
|
||||
method: .post,
|
||||
parameters: nil,
|
||||
isLoding: true,
|
||||
isToast: true) { (response: FANetworkManager.Response<FATokenModel>) in
|
||||
completer?(response.data)
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
@ -84,4 +84,97 @@ class FAStatAPI: NSObject {
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
///进入APP
|
||||
static func requestEnterApp() {
|
||||
|
||||
FANetworkManager.manager.request(FABaseURL + "/customer/enterTheApp",
|
||||
method: .post,
|
||||
parameters: nil,
|
||||
isLoding: false,
|
||||
isToast: false,
|
||||
) { (response: FANetworkManager.Response<String>) in
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
///离开APP
|
||||
static func requestLeaveApp() {
|
||||
|
||||
FANetworkManager.manager.request(FABaseURL + "/customer/leaveApp",
|
||||
method: .post,
|
||||
parameters: nil,
|
||||
isLoding: false,
|
||||
isToast: false,
|
||||
) { (response: FANetworkManager.Response<String>) in
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
static func requestStatOnLine() {
|
||||
FANetworkManager.manager.request(FABaseURL + "/customer/onLine",
|
||||
method: .post,
|
||||
parameters: nil,
|
||||
isLoding: false,
|
||||
isToast: false,
|
||||
) { (response: FANetworkManager.Response<String>) in
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
static func requestUploadApnsAuthorizationStatus(_ status: Bool) {
|
||||
let parameters = [
|
||||
"is_open_notice" : status ? 1 : 0
|
||||
]
|
||||
FANetworkManager.manager.request(FABaseURL + "/customer/uploadNoticeStatus",
|
||||
method: .post,
|
||||
parameters: parameters,
|
||||
isLoding: false,
|
||||
isToast: false,
|
||||
) { (response: FANetworkManager.Response<String>) in
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
static func requestStatApnsClick(id: String, title: String) {
|
||||
let parameters = [
|
||||
"message_id" : id,
|
||||
"title" : title
|
||||
]
|
||||
FANetworkManager.manager.request(FABaseURL + "/message/sendReport",
|
||||
method: .post,
|
||||
parameters: parameters,
|
||||
isLoding: false,
|
||||
isToast: false,
|
||||
) { (response: FANetworkManager.Response<String>) in
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
static func requestUploadApnsDeviceToken(token: String) {
|
||||
let parameters = [
|
||||
"fcm_token": token
|
||||
]
|
||||
FANetworkManager.manager.request(FABaseURL + "/customer/firebaseToken",
|
||||
method: .post,
|
||||
parameters: parameters,
|
||||
isLoding: false,
|
||||
isToast: false,
|
||||
) { (response: FANetworkManager.Response<String>) in
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
extension FAStatAPI {
|
||||
///更新通知状态
|
||||
static func uploadApnsAuthorizationStatus() {
|
||||
UNUserNotificationCenter.current().getNotificationSettings { settings in
|
||||
if settings.authorizationStatus == .authorized {
|
||||
requestUploadApnsAuthorizationStatus(true)
|
||||
} else if settings.authorizationStatus == .denied {
|
||||
requestUploadApnsAuthorizationStatus(false)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -131,4 +131,70 @@ class FAStoreAPI: NSObject {
|
||||
completer?(response.data)
|
||||
}
|
||||
}
|
||||
|
||||
///金币包数据
|
||||
static func requestCoinsPackData(completer: ((_ model: FACoinsPackModel?) -> Void)?) {
|
||||
|
||||
FANetworkManager.manager.request(FABaseURL + "/getReceiveDayCoinInfo",
|
||||
method: .get,
|
||||
parameters: nil,
|
||||
isLoding: false,
|
||||
isToast: true,
|
||||
) { (response: FANetworkManager.Response<FACoinsPackModel>) in
|
||||
completer?(response.data)
|
||||
}
|
||||
}
|
||||
|
||||
///领取金币包金币
|
||||
static func requestReceiveCoinsPackCoins(id: String?, completer: ((_ finish: Bool) -> Void)?) {
|
||||
|
||||
var parameters: [String : Any]? = nil
|
||||
if let id = id {
|
||||
parameters = [
|
||||
"id" : id
|
||||
]
|
||||
}
|
||||
|
||||
FANetworkManager.manager.request(FABaseURL + "/receiveDayCoin",
|
||||
method: .post,
|
||||
parameters: parameters,
|
||||
isLoding: true,
|
||||
isToast: true,
|
||||
) { (response: FANetworkManager.Response<FACoinsPackModel>) in
|
||||
if response.isSuccess {
|
||||
completer?(true)
|
||||
} else {
|
||||
completer?(false)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
///获取金币包可领取信息
|
||||
static func requestCoinBagCanReceiveInfo(completer: ((_ model: FACoinPackCanReceiveModel?) -> Void)?) {
|
||||
FANetworkManager.manager.request(FABaseURL + "/getReceiveDayCoin",
|
||||
method: .get,
|
||||
parameters: nil,
|
||||
isLoding: false,
|
||||
isToast: true,
|
||||
) { (response: FANetworkManager.Response<FACoinPackCanReceiveModel>) in
|
||||
completer?(response.data)
|
||||
}
|
||||
}
|
||||
|
||||
///挽留支付项
|
||||
static func requestVipRetainPayInfo(completer: ((_ model: FAPayAlertModel?) -> Void)?) {
|
||||
|
||||
FANetworkManager.manager.request(FABaseURL + "/getRetainVipPaySetting",
|
||||
method: .get,
|
||||
parameters: nil,
|
||||
isLoding: true,
|
||||
isToast: true,
|
||||
) { (response: FANetworkManager.Response<FAPayAlertModel>) in
|
||||
if let _ = response.data?.info {
|
||||
completer?(response.data)
|
||||
} else {
|
||||
completer?(nil)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -16,3 +16,6 @@ let kFAFeedBackHomeWebUrl = FACampaignWebURL + "/pages/leave/index"
|
||||
let kFAFeedBackListWebUrl = FACampaignWebURL + "/pages/leave/list"
|
||||
///反馈详情
|
||||
let kFAFeedBackDetailWebUrl = FACampaignWebURL + "/pages/leave/detail"
|
||||
|
||||
///注销账号
|
||||
let kFALogoutWebUrl = FACampaignWebURL + "/pages/setting/logout"
|
||||
|
||||
@ -186,7 +186,8 @@ extension FANetworkManager {
|
||||
"model" : UIDevice.current.machineModelName ?? "",
|
||||
"idfa" : ASIdentifierManager.shared().advertisingIdentifier.uuidString,
|
||||
"device-id" : FADeviceIDManager.shared.id, //设备id
|
||||
"device-gaid" : UIDevice.current.identifierForVendor?.uuidString ?? ""
|
||||
"device-gaid" : UIDevice.current.identifierForVendor?.uuidString ?? "",
|
||||
"product-prefix" : FAIapManager.IAPPrefix
|
||||
]
|
||||
return HTTPHeaders(dic)
|
||||
}
|
||||
|
||||
@ -14,7 +14,7 @@ class FAAppWebViewController: FABaseWebViewController {
|
||||
|
||||
private var receiveDataCount = 0
|
||||
|
||||
var theme: String? = "theme_1"
|
||||
var theme: String? = "theme_3"
|
||||
|
||||
override func viewDidLoad() {
|
||||
super.viewDidLoad()
|
||||
@ -26,6 +26,8 @@ class FAAppWebViewController: FABaseWebViewController {
|
||||
self.title = "Feedback".localized
|
||||
} else if webUrl == kFAFeedBackDetailWebUrl {
|
||||
self.title = "Feedback Details".localized
|
||||
} else if webUrl == kFALogoutWebUrl {
|
||||
self.title = "Account Deletion".localized
|
||||
}
|
||||
|
||||
}
|
||||
@ -51,6 +53,7 @@ extension FAAppWebViewController {
|
||||
"time_zone" : String.timeZone(),
|
||||
"lang" : FALocalized.manager.currentLocalizedKey,
|
||||
"type" : "ios",
|
||||
"device-id" : FADeviceIDManager.shared.id
|
||||
]
|
||||
|
||||
if let theme = theme {
|
||||
|
||||
@ -18,6 +18,8 @@ let kFAWebMessageOpenFeedbackList = "openFeedbackList"
|
||||
let kFAWebMessageOpenFeedbackDetail = "openFeedbackDetail"
|
||||
///打开相册
|
||||
let kFAWebMessageOpenPhotoPicker = "openPhotoPicker"
|
||||
///删除账号成功
|
||||
let kFAWebMessageAccountDeletionFinish = "accountLogout"
|
||||
|
||||
extension FABaseWebViewController {
|
||||
|
||||
@ -50,7 +52,8 @@ extension FABaseWebViewController {
|
||||
let data = model.data
|
||||
|
||||
if type == "login" {
|
||||
// VPLoginManager.manager.openLogin()
|
||||
let view = FALoginView()
|
||||
view.present(in: nil)
|
||||
|
||||
} else if type == "open_notify" {
|
||||
// openNotify()
|
||||
@ -69,6 +72,9 @@ extension FABaseWebViewController {
|
||||
}
|
||||
}
|
||||
|
||||
case kFAWebMessageAccountDeletionFinish:
|
||||
self.navigationController?.popToRootViewController(animated: true)
|
||||
|
||||
|
||||
default:
|
||||
break
|
||||
|
||||
@ -38,6 +38,7 @@ class FAWebView: WKWebView {
|
||||
kFAWebMessageOpenFeedbackList,
|
||||
kFAWebMessageOpenFeedbackDetail,
|
||||
kFAWebMessageOpenPhotoPicker,
|
||||
kFAWebMessageAccountDeletionFinish,
|
||||
]
|
||||
|
||||
|
||||
|
||||
@ -62,6 +62,17 @@ class FAHomeViewController: FAViewController {
|
||||
return view
|
||||
}()
|
||||
|
||||
private lazy var coinPackButton: FAHomeCoinsPackButton = {
|
||||
let view = FAHomeCoinsPackButton()
|
||||
view.addAction(UIAction(handler: { [weak self] _ in
|
||||
guard let self = self else { return }
|
||||
let vc = FACoinPackViewController()
|
||||
self.navigationController?.pushViewController(vc, animated: true)
|
||||
|
||||
}), for: .touchUpInside)
|
||||
return view
|
||||
}()
|
||||
|
||||
deinit {
|
||||
NotificationCenter.default.removeObserver(self)
|
||||
}
|
||||
@ -72,6 +83,8 @@ class FAHomeViewController: FAViewController {
|
||||
fa_setupLayout()
|
||||
|
||||
requestAllData(completer: nil)
|
||||
|
||||
requestCoinBagCanReceiveInfo()
|
||||
}
|
||||
|
||||
override func viewWillAppear(_ animated: Bool) {
|
||||
@ -104,6 +117,7 @@ extension FAHomeViewController {
|
||||
view.addSubview(searchButton)
|
||||
view.addSubview(collectionView)
|
||||
view.addSubview(playHistoryView)
|
||||
view.addSubview(coinPackButton)
|
||||
|
||||
titleView.snp.makeConstraints { make in
|
||||
make.left.equalToSuperview().offset(16)
|
||||
@ -125,6 +139,11 @@ extension FAHomeViewController {
|
||||
make.centerX.equalToSuperview()
|
||||
make.bottom.equalToSuperview().offset(-10)
|
||||
}
|
||||
|
||||
coinPackButton.snp.makeConstraints { make in
|
||||
make.right.equalToSuperview().offset(-21)
|
||||
make.bottom.equalTo(playHistoryView.snp.top).offset(5)
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@ -280,4 +299,22 @@ extension FAHomeViewController {
|
||||
}
|
||||
}
|
||||
|
||||
private func requestCoinBagCanReceiveInfo() {
|
||||
|
||||
FAStoreAPI.requestCoinBagCanReceiveInfo { [weak self] model in
|
||||
guard let self = self else { return }
|
||||
guard let model = model else { return }
|
||||
let coins = model.coins ?? 0
|
||||
if coins > 0 {
|
||||
let view = FACoinsPackAlert()
|
||||
view.coinsCount = coins
|
||||
view.show(in: self.view)
|
||||
view.clickHighlightButton = { [weak self] in
|
||||
let vc = FACoinPackViewController()
|
||||
self?.navigationController?.pushViewController(vc, animated: true)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
50
Fableon/Object/Class/Home/V/FAHomeCoinsPackButton.swift
Normal file
@ -0,0 +1,50 @@
|
||||
//
|
||||
// FAHomeCoinsPackButton.swift
|
||||
// Fableon
|
||||
//
|
||||
// Created by 湖北秦九 on 2025/10/30.
|
||||
//
|
||||
|
||||
import UIKit
|
||||
import SnapKit
|
||||
|
||||
class FAHomeCoinsPackButton: UIControl {
|
||||
|
||||
private lazy var bgImageView = UIImageView(image: UIImage(named: "Group 2072750470"))
|
||||
private lazy var textBgImageView = UIImageView(image: UIImage(named: "按钮"))
|
||||
|
||||
private lazy var textLabel: UILabel = {
|
||||
let label = UILabel()
|
||||
label.font = .font(ofSize: 10, weight: .init(900)).withBoldItalic()
|
||||
label.textColor = .FFFFFF
|
||||
label.text = "Daily Coins".localized
|
||||
return label
|
||||
}()
|
||||
|
||||
override init(frame: CGRect) {
|
||||
super.init(frame: frame)
|
||||
|
||||
addSubview(bgImageView)
|
||||
addSubview(textBgImageView)
|
||||
textBgImageView.addSubview(textLabel)
|
||||
|
||||
bgImageView.snp.makeConstraints { make in
|
||||
make.left.right.top.equalToSuperview()
|
||||
}
|
||||
|
||||
textBgImageView.snp.makeConstraints { make in
|
||||
make.centerX.equalToSuperview()
|
||||
make.bottom.equalToSuperview()
|
||||
make.top.equalToSuperview().offset(50)
|
||||
}
|
||||
|
||||
textLabel.snp.makeConstraints { make in
|
||||
make.centerY.equalToSuperview()
|
||||
make.centerX.equalToSuperview()
|
||||
}
|
||||
}
|
||||
|
||||
required init?(coder: NSCoder) {
|
||||
fatalError("init(coder:) has not been implemented")
|
||||
}
|
||||
}
|
||||
216
Fableon/Object/Class/Me/C/FACoinPackViewController.swift
Normal file
@ -0,0 +1,216 @@
|
||||
//
|
||||
// FACoinPackViewController.swift
|
||||
// Fableon
|
||||
//
|
||||
// Created by 湖北秦九 on 2025/10/29.
|
||||
//
|
||||
|
||||
import UIKit
|
||||
import YYText
|
||||
|
||||
class FACoinPackViewController: FAViewController {
|
||||
|
||||
private var model: FACoinsPackModel? {
|
||||
didSet {
|
||||
headerView.model = model
|
||||
claimView.dataArr = model?.receive_list ?? []
|
||||
}
|
||||
}
|
||||
|
||||
private var payDataModel : FAPayDateModel? {
|
||||
didSet {
|
||||
var arr: [FAPayItem] = []
|
||||
|
||||
payDataModel?.list_coins?.forEach {
|
||||
if $0.buy_type == .subCoins {
|
||||
arr.append($0)
|
||||
}
|
||||
}
|
||||
self.buyView.dataArr = arr
|
||||
}
|
||||
}
|
||||
|
||||
private var payDataRequest: FAPayDataRequest?
|
||||
|
||||
private lazy var bgIconImageView: UIImageView = {
|
||||
let imageView = UIImageView(image: UIImage(named: "查看图片 25"))
|
||||
return imageView
|
||||
}()
|
||||
|
||||
private lazy var scrollView: FAScrollView = {
|
||||
let scrollView = FAScrollView()
|
||||
return scrollView
|
||||
}()
|
||||
|
||||
private lazy var headerView: FACoinPackHeaderView = {
|
||||
let view = FACoinPackHeaderView()
|
||||
view.clickClaimButton = { [weak self] in
|
||||
self?.requestReceiveCoins(nil)
|
||||
}
|
||||
return view
|
||||
}()
|
||||
|
||||
private lazy var stackView: UIStackView = {
|
||||
let stackView = UIStackView()
|
||||
stackView.axis = .vertical
|
||||
stackView.spacing = 19
|
||||
return stackView
|
||||
}()
|
||||
|
||||
private lazy var claimView: FACoinsPackClaimListView = {
|
||||
let view = FACoinsPackClaimListView()
|
||||
view.clickClaimButton = { [weak self] id in
|
||||
guard let self = self else { return }
|
||||
self.requestReceiveCoins(id)
|
||||
}
|
||||
return view
|
||||
}()
|
||||
|
||||
private lazy var buyView: FACoinsPackBuyView = {
|
||||
let view = FACoinsPackBuyView()
|
||||
view.buyFinishHandle = { [weak self] in
|
||||
self?.requestCoinsPackData()
|
||||
}
|
||||
return view
|
||||
}()
|
||||
|
||||
private lazy var tipView: UIView = {
|
||||
let view = UIView()
|
||||
view.addSubview(tipTitleLabel)
|
||||
view.addSubview(tipTextLabel)
|
||||
|
||||
tipTitleLabel.snp.makeConstraints { make in
|
||||
make.top.equalToSuperview()
|
||||
make.left.equalToSuperview().offset(16)
|
||||
}
|
||||
|
||||
tipTextLabel.snp.makeConstraints { make in
|
||||
make.left.equalToSuperview().offset(16)
|
||||
make.right.lessThanOrEqualToSuperview().offset(-16)
|
||||
make.top.equalTo(tipTitleLabel.snp.bottom).offset(4)
|
||||
make.bottom.equalToSuperview()
|
||||
}
|
||||
return view
|
||||
}()
|
||||
|
||||
private lazy var tipTitleLabel: UILabel = {
|
||||
let label = UILabel()
|
||||
label.font = .font(ofSize: 12, weight: .medium)
|
||||
label.textColor = .FFFFFF.withAlphaComponent(0.5)
|
||||
label.text = "coins_pack_tips_title".localized
|
||||
return label
|
||||
}()
|
||||
|
||||
private lazy var tipTextLabel: UILabel = {
|
||||
let att = NSMutableAttributedString(string: "coins_pack_tips".localized)
|
||||
att.yy_lineSpacing = 3
|
||||
|
||||
let label = UILabel()
|
||||
label.font = .font(ofSize: 10, weight: .regular)
|
||||
label.textColor = .FFFFFF.withAlphaComponent(0.5)
|
||||
label.attributedText = att
|
||||
label.numberOfLines = 0
|
||||
return label
|
||||
}()
|
||||
|
||||
override func viewDidLoad() {
|
||||
super.viewDidLoad()
|
||||
self.title = "My Refills".localized
|
||||
payDataModel = FAIapManager.manager.payDateModel
|
||||
|
||||
fa_setupLayout()
|
||||
|
||||
requestCoinsPackData()
|
||||
|
||||
updateLayout()
|
||||
}
|
||||
|
||||
override func viewWillAppear(_ animated: Bool) {
|
||||
super.viewWillAppear(animated)
|
||||
self.navigationController?.setNavigationBarHidden(false, animated: true)
|
||||
self.fa_setNavigationStyle()
|
||||
}
|
||||
|
||||
private func updateLayout() {
|
||||
stackView.fa_removeAllArrangedSubview()
|
||||
|
||||
if self.claimView.dataArr.count > 0 {
|
||||
stackView.addArrangedSubview(self.claimView)
|
||||
} else if self.buyView.dataArr.count > 0 {
|
||||
stackView.addArrangedSubview(self.buyView)
|
||||
}
|
||||
|
||||
stackView.addArrangedSubview(tipView)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
extension FACoinPackViewController {
|
||||
|
||||
private func fa_setupLayout() {
|
||||
view.addSubview(bgIconImageView)
|
||||
view.addSubview(scrollView)
|
||||
scrollView.addSubview(headerView)
|
||||
scrollView.addSubview(stackView)
|
||||
|
||||
bgIconImageView.snp.makeConstraints { make in
|
||||
make.right.equalToSuperview()
|
||||
make.top.equalToSuperview()
|
||||
}
|
||||
|
||||
scrollView.snp.makeConstraints { make in
|
||||
make.left.right.equalToSuperview()
|
||||
make.top.equalToSuperview().offset(UIScreen.navBarHeight)
|
||||
make.bottom.equalToSuperview()
|
||||
}
|
||||
|
||||
headerView.snp.makeConstraints { make in
|
||||
make.left.centerX.equalToSuperview()
|
||||
make.top.equalToSuperview()
|
||||
}
|
||||
|
||||
stackView.snp.makeConstraints { make in
|
||||
make.left.centerX.equalToSuperview()
|
||||
make.top.equalTo(headerView.snp.bottom).offset(16)
|
||||
make.bottom.equalToSuperview().offset(-(UIScreen.safeBottom + 10))
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
extension FACoinPackViewController {
|
||||
|
||||
private func requestCoinsPackData() {
|
||||
FAStoreAPI.requestCoinsPackData { [weak self] model in
|
||||
guard let self = self else { return }
|
||||
guard let model = model else { return }
|
||||
self.model = model
|
||||
|
||||
if (model.receive_list?.count ?? 0) == 0 {
|
||||
self.requestPayData()
|
||||
}
|
||||
|
||||
self.updateLayout()
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private func requestPayData() {
|
||||
self.payDataRequest = FAPayDataRequest()
|
||||
self.payDataRequest?.requestProducts { [weak self] model in
|
||||
guard let self = self else { return }
|
||||
guard let model = model else { return }
|
||||
self.payDataModel = model
|
||||
|
||||
self.updateLayout()
|
||||
}
|
||||
}
|
||||
|
||||
private func requestReceiveCoins(_ id: String?) {
|
||||
FAStoreAPI.requestReceiveCoinsPackCoins(id: id) { [weak self] finish in
|
||||
guard let self = self else { return }
|
||||
self.requestCoinsPackData()
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@ -16,11 +16,12 @@ class FAMeListViewController: FAViewController, JXPagingViewListViewDelegate {
|
||||
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")),
|
||||
|
||||
FAMeItemModel(type: .setting, name: "Setting".localized, icon: UIImage(named: "icon_setting"))
|
||||
]
|
||||
return arr
|
||||
}()
|
||||
|
||||
@ -9,10 +9,34 @@ import UIKit
|
||||
|
||||
class FASettingViewController: FAViewController {
|
||||
|
||||
private lazy var dataArr: [FAMeItemModel] = [
|
||||
FAMeItemModel(type: .deleteAccount, name: "Account Deletion".localized, icon: nil)
|
||||
]
|
||||
|
||||
private lazy var tableView: FATableView = {
|
||||
let tableView = FATableView(frame: .zero, style: .plain)
|
||||
tableView.delegate = self
|
||||
tableView.dataSource = self
|
||||
tableView.rowHeight = 48
|
||||
tableView.contentInset = .init(top: 25, left: 0, bottom: 0, right: 0)
|
||||
tableView.separatorStyle = .none
|
||||
tableView.register(UINib(nibName: "FASettingCell", bundle: nil), forCellReuseIdentifier: "cell")
|
||||
return tableView
|
||||
}()
|
||||
|
||||
private lazy var footerView: FASettingFooterView = {
|
||||
let view = FASettingFooterView(frame: .init(x: 0, y: 0, width: UIScreen.width, height: 60))
|
||||
return view
|
||||
}()
|
||||
|
||||
override func viewDidLoad() {
|
||||
super.viewDidLoad()
|
||||
self.title = "Settings".localized
|
||||
NotificationCenter.default.addObserver(self, selector: #selector(userInfoUpdateNotification), name: FALogin.userInfoUpdateNotification, object: nil)
|
||||
|
||||
|
||||
userInfoUpdateNotification()
|
||||
fa_setupLayout()
|
||||
}
|
||||
|
||||
override func viewWillAppear(_ animated: Bool) {
|
||||
@ -21,6 +45,51 @@ class FASettingViewController: FAViewController {
|
||||
self.fa_setNavigationStyle()
|
||||
}
|
||||
|
||||
@objc private func userInfoUpdateNotification() {
|
||||
if FALogin.manager.isLogin {
|
||||
tableView.tableFooterView = footerView
|
||||
} else {
|
||||
tableView.tableFooterView = nil
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
extension FASettingViewController {
|
||||
|
||||
private func fa_setupLayout() {
|
||||
|
||||
|
||||
view.addSubview(tableView)
|
||||
|
||||
tableView.snp.makeConstraints { make in
|
||||
make.left.right.equalToSuperview()
|
||||
make.top.equalToSuperview().offset(UIScreen.navBarHeight)
|
||||
make.bottom.equalToSuperview()
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
//MARK: UITableViewDelegate UITableViewDataSource
|
||||
extension FASettingViewController: UITableViewDelegate, UITableViewDataSource {
|
||||
|
||||
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
|
||||
let item = dataArr[indexPath.row]
|
||||
let cell = tableView.dequeueReusableCell(withIdentifier: "cell", for: indexPath) as! FASettingCell
|
||||
cell.titleLabel.text = item.name
|
||||
return cell
|
||||
}
|
||||
|
||||
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
|
||||
return self.dataArr.count
|
||||
}
|
||||
|
||||
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
|
||||
let vc = FAAppWebViewController()
|
||||
vc.webUrl = kFALogoutWebUrl
|
||||
vc.theme = "theme_4"
|
||||
self.navigationController?.pushViewController(vc, animated: true)
|
||||
}
|
||||
}
|
||||
|
||||
@ -22,6 +22,7 @@ struct FAMeItemModel {
|
||||
case purchaseRecords
|
||||
///金币奖励
|
||||
case rewardCoins
|
||||
case deleteAccount
|
||||
}
|
||||
|
||||
|
||||
|
||||
266
Fableon/Object/Class/Me/V/FACoinPackHeaderView.swift
Normal file
@ -0,0 +1,266 @@
|
||||
//
|
||||
// FACoinPackHeaderView.swift
|
||||
// Fableon
|
||||
//
|
||||
// Created by 湖北秦九 on 2025/10/29.
|
||||
//
|
||||
|
||||
import UIKit
|
||||
|
||||
class FACoinPackHeaderView: UIView {
|
||||
|
||||
var clickClaimButton: (() -> Void)?
|
||||
|
||||
var model: FACoinsPackModel? {
|
||||
didSet {
|
||||
coinsView1.coins = model?.week_max_total
|
||||
coinsView2.coins = model?.week_total
|
||||
|
||||
activeCountLabel.text = "\(model?.receive_count ?? 0)"
|
||||
|
||||
if let coin = model?.receive_coins, coin > 0 {
|
||||
claimButton.isEnabled = true
|
||||
} else {
|
||||
claimButton.isEnabled = false
|
||||
}
|
||||
|
||||
claimButton.setNeedsUpdateConfiguration()
|
||||
}
|
||||
}
|
||||
|
||||
private lazy var titleView: FACoinPackTitleView = {
|
||||
let view = FACoinPackTitleView()
|
||||
view.dotColor = .C_5_DDF_5
|
||||
view.font = .font(ofSize: 14, weight: .regular)
|
||||
view.textColors = [UIColor.C_5_DDF_5.cgColor, UIColor.C_5_DDF_5.cgColor]
|
||||
view.text = "REWARDS OVERVIEW".localized
|
||||
return view
|
||||
}()
|
||||
|
||||
private lazy var coinsView1: CoinsView = {
|
||||
let view = CoinsView()
|
||||
view.title = "Weekly Total".localized
|
||||
view.coins = 0
|
||||
return view
|
||||
}()
|
||||
|
||||
private lazy var coinsView2: CoinsView = {
|
||||
let view = CoinsView()
|
||||
view.title = "Claimable Coins".localized
|
||||
view.coins = 0
|
||||
return view
|
||||
}()
|
||||
|
||||
private lazy var lineView1: UIView = {
|
||||
let view = UIImageView(image: UIImage(named: "间隔线"))
|
||||
return view
|
||||
}()
|
||||
|
||||
private lazy var lineView2: UIView = {
|
||||
let view = UIImageView(image: UIImage(named: "横间隔虚线"))
|
||||
return view
|
||||
}()
|
||||
|
||||
private lazy var activeCountTitleLabel: UILabel = {
|
||||
let label = UILabel()
|
||||
label.font = .font(ofSize: 12, weight: .regular)
|
||||
label.textColor = .FFFFFF.withAlphaComponent(0.5)
|
||||
label.text = "Active Refills".localized + ": "
|
||||
return label
|
||||
}()
|
||||
|
||||
private lazy var activeCountLabel: UILabel = {
|
||||
let label = UILabel()
|
||||
label.font = .font(ofSize: 12, weight: .medium)
|
||||
label.textColor = ._53_A_2_F_1
|
||||
label.text = "0"
|
||||
return label
|
||||
}()
|
||||
|
||||
private lazy var claimButton: UIButton = {
|
||||
let config = UIButton.Configuration.plain()
|
||||
let button = FAGradientButton(configuration: config, primaryAction: UIAction(handler: { [weak self] _ in
|
||||
self?.clickClaimButton?()
|
||||
}))
|
||||
button.isEnabled = false
|
||||
button.layer.cornerRadius = 24
|
||||
button.layer.masksToBounds = true
|
||||
button.fa_locations = [0, 1]
|
||||
button.fa_startPoint = .init(x: 0, y: 0.5)
|
||||
button.fa_endPoint = .init(x: 1, y: 0.5)
|
||||
button.configurationUpdateHandler = { [weak self] button in
|
||||
guard let self = self else { return }
|
||||
guard let button = button as? FAGradientButton else { return }
|
||||
if button.isEnabled {
|
||||
button.fa_colors = [UIColor._53_A_2_F_1.cgColor, UIColor.C_5_DDF_5.cgColor]
|
||||
|
||||
let coinImage = UIImage(named: "coins_icon_03")!
|
||||
let coinText = NSTextAttachment(image: coinImage)
|
||||
coinText.bounds = .init(x: 0, y: -2.5, width: coinImage.size.width, height: coinImage.size.height)
|
||||
let coinAtt = AttributedString(NSAttributedString(attachment: coinText))
|
||||
|
||||
let textAtt = AttributedString("Claim All".localized + " ", attributes: AttributeContainer([
|
||||
.font : UIFont.font(ofSize: 14, weight: .bold),
|
||||
.foregroundColor : UIColor.FFFFFF
|
||||
]))
|
||||
|
||||
let countAtt = AttributedString(" \(0)".localized, attributes: AttributeContainer([
|
||||
.font : UIFont.font(ofSize: 14, weight: .bold),
|
||||
.foregroundColor : UIColor.FFFFFF
|
||||
]))
|
||||
|
||||
button.configuration?.attributedTitle = textAtt + coinAtt + countAtt
|
||||
|
||||
|
||||
} else {
|
||||
button.fa_colors = [UIColor._6_D_6_D_6_D.cgColor, UIColor._6_D_6_D_6_D.cgColor]
|
||||
button.configuration?.attributedTitle = AttributedString("Get a Refill to Claim".localized, attributes: AttributeContainer([
|
||||
.font : UIFont.font(ofSize: 14, weight: .bold),
|
||||
.foregroundColor : UIColor.FFFFFF.withAlphaComponent(0.5)
|
||||
]))
|
||||
}
|
||||
|
||||
}
|
||||
return button
|
||||
}()
|
||||
|
||||
override init(frame: CGRect) {
|
||||
super.init(frame: frame)
|
||||
fa_setupLayout()
|
||||
}
|
||||
|
||||
required init?(coder: NSCoder) {
|
||||
fatalError("init(coder:) has not been implemented")
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
extension FACoinPackHeaderView {
|
||||
|
||||
private func fa_setupLayout() {
|
||||
addSubview(titleView)
|
||||
addSubview(coinsView1)
|
||||
addSubview(coinsView2)
|
||||
addSubview(lineView1)
|
||||
addSubview(activeCountTitleLabel)
|
||||
addSubview(activeCountLabel)
|
||||
addSubview(claimButton)
|
||||
addSubview(lineView2)
|
||||
|
||||
titleView.snp.makeConstraints { make in
|
||||
make.left.equalToSuperview().offset(16)
|
||||
make.top.equalToSuperview().offset(20)
|
||||
}
|
||||
|
||||
coinsView1.snp.makeConstraints { make in
|
||||
make.left.equalToSuperview().offset(28)
|
||||
make.top.equalTo(titleView.snp.bottom).offset(23)
|
||||
}
|
||||
|
||||
lineView1.snp.makeConstraints { make in
|
||||
make.centerY.equalTo(coinsView1)
|
||||
make.left.equalTo(coinsView1.snp.right).offset(18)
|
||||
}
|
||||
|
||||
coinsView2.snp.makeConstraints { make in
|
||||
make.centerY.equalTo(lineView1)
|
||||
make.left.equalTo(lineView1.snp.right).offset(18)
|
||||
}
|
||||
|
||||
activeCountTitleLabel.snp.makeConstraints { make in
|
||||
make.left.equalTo(coinsView1)
|
||||
make.top.equalTo(coinsView1.snp.bottom).offset(23)
|
||||
}
|
||||
|
||||
activeCountLabel.snp.makeConstraints { make in
|
||||
make.left.equalTo(activeCountTitleLabel.snp.right)
|
||||
make.centerY.equalTo(activeCountTitleLabel)
|
||||
}
|
||||
|
||||
claimButton.snp.makeConstraints { make in
|
||||
make.left.equalToSuperview().offset(23)
|
||||
make.centerX.equalToSuperview()
|
||||
make.top.equalTo(activeCountTitleLabel.snp.bottom).offset(12)
|
||||
make.height.equalTo(48)
|
||||
make.bottom.equalToSuperview().offset(-16)
|
||||
}
|
||||
|
||||
lineView2.snp.makeConstraints { make in
|
||||
make.left.equalTo(claimButton)
|
||||
make.right.equalTo(claimButton)
|
||||
make.bottom.equalToSuperview()
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
extension FACoinPackHeaderView {
|
||||
|
||||
class CoinsView: UIView {
|
||||
var title: String? {
|
||||
didSet {
|
||||
titleLabel.text = title
|
||||
}
|
||||
}
|
||||
|
||||
var coins: Int? {
|
||||
didSet {
|
||||
coinsLabel.text = "\(coins ?? 0)"
|
||||
}
|
||||
}
|
||||
|
||||
private lazy var titleLabel: UILabel = {
|
||||
let label = UILabel()
|
||||
label.font = .font(ofSize: 12, weight: .bold)
|
||||
label.textColor = .FFFFFF.withAlphaComponent(0.5)
|
||||
return label
|
||||
}()
|
||||
|
||||
private lazy var iconImageView: UIImageView = {
|
||||
let imageView = UIImageView(image: UIImage(named: "coins_icon_09"))
|
||||
return imageView
|
||||
}()
|
||||
|
||||
private lazy var coinsLabel: UILabel = {
|
||||
let label = FALabel()
|
||||
label.font = .font(ofSize: 18, weight: .bold)
|
||||
label.textColors = [UIColor._53_A_2_F_1.cgColor, UIColor.C_5_DDF_5.cgColor]
|
||||
label.textStartPoint = .init(x: 0, y: 0.5)
|
||||
label.textEndPoint = .init(x: 1, y: 0.5)
|
||||
return label
|
||||
}()
|
||||
|
||||
override init(frame: CGRect) {
|
||||
super.init(frame: frame)
|
||||
|
||||
addSubview(titleLabel)
|
||||
addSubview(iconImageView)
|
||||
addSubview(coinsLabel)
|
||||
|
||||
titleLabel.snp.makeConstraints { make in
|
||||
make.left.equalToSuperview()
|
||||
make.top.equalToSuperview()
|
||||
make.right.lessThanOrEqualToSuperview()
|
||||
}
|
||||
|
||||
iconImageView.snp.makeConstraints { make in
|
||||
make.left.equalToSuperview()
|
||||
make.top.equalTo(titleLabel.snp.bottom).offset(4)
|
||||
make.bottom.equalToSuperview()
|
||||
}
|
||||
|
||||
coinsLabel.snp.makeConstraints { make in
|
||||
make.centerY.equalTo(iconImageView)
|
||||
make.left.equalTo(iconImageView.snp.right).offset(4)
|
||||
make.right.lessThanOrEqualToSuperview()
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@MainActor required init?(coder: NSCoder) {
|
||||
fatalError("init(coder:) has not been implemented")
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
91
Fableon/Object/Class/Me/V/FACoinPackTitleView.swift
Normal file
@ -0,0 +1,91 @@
|
||||
//
|
||||
// FACoinPackTitleView.swift
|
||||
// Fableon
|
||||
//
|
||||
// Created by 湖北秦九 on 2025/10/29.
|
||||
//
|
||||
|
||||
import UIKit
|
||||
|
||||
class FACoinPackTitleView: UIView {
|
||||
|
||||
var text: String? {
|
||||
didSet {
|
||||
label.text = text
|
||||
}
|
||||
}
|
||||
|
||||
var font: UIFont? {
|
||||
didSet {
|
||||
label.font = font
|
||||
}
|
||||
}
|
||||
|
||||
var textColors: [CGColor]? {
|
||||
didSet {
|
||||
label.textColors = textColors
|
||||
}
|
||||
}
|
||||
|
||||
var dotColor: UIColor? {
|
||||
didSet {
|
||||
dotView1.backgroundColor = dotColor
|
||||
dotView2.backgroundColor = dotColor
|
||||
}
|
||||
}
|
||||
|
||||
private lazy var dotView1: UIView = {
|
||||
let view = UIView()
|
||||
view.layer.cornerRadius = 3
|
||||
view.layer.masksToBounds = true
|
||||
return view
|
||||
}()
|
||||
|
||||
private lazy var dotView2: UIView = {
|
||||
let view = UIView()
|
||||
view.layer.cornerRadius = 3
|
||||
view.layer.masksToBounds = true
|
||||
return view
|
||||
}()
|
||||
|
||||
private lazy var label: FALabel = {
|
||||
let label = FALabel()
|
||||
label.textStartPoint = .init(x: 0, y: 0.5)
|
||||
label.textEndPoint = .init(x: 1, y: 0.5)
|
||||
return label
|
||||
}()
|
||||
|
||||
override init(frame: CGRect) {
|
||||
super.init(frame: frame)
|
||||
addSubview(dotView1)
|
||||
addSubview(dotView2)
|
||||
addSubview(label)
|
||||
|
||||
dotView1.snp.makeConstraints { make in
|
||||
make.centerY.equalToSuperview()
|
||||
make.left.equalToSuperview()
|
||||
make.width.height.equalTo(6)
|
||||
make.bottom.lessThanOrEqualToSuperview()
|
||||
}
|
||||
|
||||
label.snp.makeConstraints { make in
|
||||
make.centerY.equalToSuperview()
|
||||
make.bottom.lessThanOrEqualToSuperview()
|
||||
make.left.equalTo(dotView1.snp.right).offset(6)
|
||||
}
|
||||
|
||||
dotView2.snp.makeConstraints { make in
|
||||
make.centerY.equalToSuperview()
|
||||
make.bottom.lessThanOrEqualToSuperview()
|
||||
make.right.equalToSuperview()
|
||||
make.width.height.equalTo(dotView1)
|
||||
make.left.equalTo(label.snp.right).offset(6)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
required init?(coder: NSCoder) {
|
||||
fatalError("init(coder:) has not been implemented")
|
||||
}
|
||||
|
||||
}
|
||||
112
Fableon/Object/Class/Me/V/FACoinsPackBuyView.swift
Normal file
@ -0,0 +1,112 @@
|
||||
//
|
||||
// FACoinsPackBuyView.swift
|
||||
// Fableon
|
||||
//
|
||||
// Created by 湖北秦九 on 2025/10/29.
|
||||
//
|
||||
|
||||
import UIKit
|
||||
|
||||
class FACoinsPackBuyView: UIView {
|
||||
|
||||
var buyFinishHandle: (() -> Void)?
|
||||
|
||||
var dataArr: [FAPayItem] = []
|
||||
|
||||
private lazy var titleView: FACoinPackTitleView = {
|
||||
let view = FACoinPackTitleView()
|
||||
view.dotColor = .C_5_DDF_5
|
||||
view.textColors = [UIColor.C_5_DDF_5.cgColor, UIColor.C_5_DDF_5.cgColor]
|
||||
view.font = .font(ofSize: 14, weight: .regular)
|
||||
view.text = "Weekly Refill".localized.uppercased()
|
||||
return view
|
||||
}()
|
||||
|
||||
private lazy var collectionViewLayout: UICollectionViewFlowLayout = {
|
||||
let layout = UICollectionViewFlowLayout()
|
||||
layout.itemSize = .init(width: UIScreen.width - 32, height: 84)
|
||||
layout.minimumLineSpacing = 12
|
||||
return layout
|
||||
}()
|
||||
|
||||
private lazy var collectionView: FACollectionView = {
|
||||
let collectionView = FACollectionView(frame: .zero, collectionViewLayout: collectionViewLayout)
|
||||
collectionView.delegate = self
|
||||
collectionView.dataSource = self
|
||||
collectionView.addObserver(self, forKeyPath: "contentSize", context: nil)
|
||||
collectionView.register(FAStoreCoinsPackCell.self, forCellWithReuseIdentifier: "cell")
|
||||
return collectionView
|
||||
}()
|
||||
|
||||
deinit {
|
||||
collectionView.removeObserver(self, forKeyPath: "contentSize")
|
||||
}
|
||||
|
||||
override init(frame: CGRect) {
|
||||
super.init(frame: frame)
|
||||
|
||||
fa_setupLayout()
|
||||
}
|
||||
|
||||
required init?(coder: NSCoder) {
|
||||
fatalError("init(coder:) has not been implemented")
|
||||
}
|
||||
|
||||
override func observeValue(forKeyPath keyPath: String?, of object: Any?, change: [NSKeyValueChangeKey : Any]?, context: UnsafeMutableRawPointer?) {
|
||||
if keyPath == "contentSize" {
|
||||
let height = self.collectionView.contentSize.height + 1
|
||||
collectionView.snp.updateConstraints { make in
|
||||
make.height.equalTo(height)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
extension FACoinsPackBuyView {
|
||||
|
||||
private func fa_setupLayout() {
|
||||
addSubview(titleView)
|
||||
addSubview(collectionView)
|
||||
|
||||
titleView.snp.makeConstraints { make in
|
||||
make.top.equalToSuperview()
|
||||
make.centerX.equalToSuperview()
|
||||
}
|
||||
|
||||
collectionView.snp.makeConstraints { make in
|
||||
make.left.right.bottom.equalToSuperview()
|
||||
make.top.equalToSuperview().offset(30)
|
||||
make.height.equalTo(1)
|
||||
make.bottom.equalToSuperview()
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
//MARK: UICollectionViewDelegate UICollectionViewDataSource
|
||||
extension FACoinsPackBuyView: UICollectionViewDelegate, UICollectionViewDataSource {
|
||||
|
||||
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
|
||||
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "cell", for: indexPath) as! FAStoreCoinsPackCell
|
||||
cell.model = self.dataArr[indexPath.row]
|
||||
return cell
|
||||
}
|
||||
|
||||
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
|
||||
return dataArr.count
|
||||
}
|
||||
|
||||
func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
|
||||
let model = self.dataArr[indexPath.row]
|
||||
|
||||
let view = FACoinPackConfirmView()
|
||||
view.model = model
|
||||
view.buyFinishHandle = { [weak self] in
|
||||
guard let self = self else { return }
|
||||
FALogin.manager.requestUserInfo(completer: nil)
|
||||
self.buyFinishHandle?()
|
||||
}
|
||||
view.present(in: nil)
|
||||
}
|
||||
|
||||
}
|
||||
280
Fableon/Object/Class/Me/V/FACoinsPackClaimListCell.swift
Normal file
@ -0,0 +1,280 @@
|
||||
//
|
||||
// FACoinsPackClaimListCell.swift
|
||||
// Fableon
|
||||
//
|
||||
// Created by 湖北秦九 on 2025/10/29.
|
||||
//
|
||||
|
||||
import UIKit
|
||||
import YYText
|
||||
|
||||
class FACoinsPackClaimListCell: UICollectionViewCell {
|
||||
|
||||
var clickClaimButton: ((_ id: String?) -> Void)?
|
||||
|
||||
var model: FACoinsPackReceiveModel? {
|
||||
didSet {
|
||||
coinsView1.coins = model?.week_max_total
|
||||
coinsView2.coins = model?.week_remaining_total
|
||||
|
||||
claimButton.isEnabled = (model?.receive_coins ?? 0) > 0
|
||||
claimButton.setNeedsUpdateConfiguration()
|
||||
|
||||
let titleAtt = NSMutableAttributedString(string: "\(model?.title ?? "")")
|
||||
titleAtt.yy_color = .FFFFFF
|
||||
titleAtt.yy_font = .font(ofSize: 14, weight: .bold)
|
||||
|
||||
let dayAtt = NSMutableAttributedString(string: " (Day \(model?.day_text ?? ""))")
|
||||
dayAtt.yy_color = ._20_A_1_FF
|
||||
dayAtt.yy_font = .font(ofSize: 14, weight: .regular)
|
||||
titleAtt.append(dayAtt)
|
||||
|
||||
titleLabel.attributedText = titleAtt
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
private lazy var bgView: FAGradientView = {
|
||||
let view = FAGradientView()
|
||||
view.fa_colors = [UIColor._524_B_8_E.cgColor, UIColor._303265.cgColor]
|
||||
view.fa_locations = [0, 1]
|
||||
view.fa_startPoint = .init(x: 0, y: 0.5)
|
||||
view.fa_endPoint = .init(x: 1, y: 0.5)
|
||||
view.layer.cornerRadius = 12
|
||||
view.layer.masksToBounds = true
|
||||
view.layer.borderWidth = 1
|
||||
view.layer.borderColor = UIColor.E_5_E_5_E_5.cgColor
|
||||
return view
|
||||
}()
|
||||
|
||||
private lazy var bgIconImageView1 = UIImageView(image: UIImage(named: "coin_attachment_01"))
|
||||
private lazy var bgIconImageView2 = UIImageView(image: UIImage(named: "coin_attachment_03"))
|
||||
private lazy var bgIconImageView4 = UIImageView(image: UIImage(named: "coin_attachment_04"))
|
||||
private lazy var bgIconImageView5 = UIImageView(image: UIImage(named: "coin_attachment_05"))
|
||||
|
||||
private lazy var titleLabel: UILabel = {
|
||||
let label = UILabel()
|
||||
label.numberOfLines = 0
|
||||
return label
|
||||
}()
|
||||
|
||||
private lazy var lineView1 = UIImageView(image: UIImage(named: "横间隔虚线"))
|
||||
private lazy var lineView2 = UIImageView(image: UIImage(named: "间隔线"))
|
||||
|
||||
private lazy var coinsView1: CoinsView = {
|
||||
let view = CoinsView()
|
||||
view.title = "Total Reward".localized
|
||||
return view
|
||||
}()
|
||||
|
||||
private lazy var coinsView2: CoinsView = {
|
||||
let view = CoinsView()
|
||||
view.title = "Remaining".localized
|
||||
return view
|
||||
}()
|
||||
|
||||
private lazy var claimButton: UIButton = {
|
||||
var config = UIButton.Configuration.plain()
|
||||
config.titleAlignment = .center
|
||||
|
||||
let button = FAGradientButton(configuration: config, primaryAction: UIAction(handler: { [weak self] _ in
|
||||
guard let self = self else { return }
|
||||
self.clickClaimButton?(self.model?.id)
|
||||
}))
|
||||
button.layer.cornerRadius = 24
|
||||
button.layer.masksToBounds = true
|
||||
button.fa_locations = [0, 1]
|
||||
button.fa_startPoint = .init(x: 0, y: 0.5)
|
||||
button.fa_endPoint = .init(x: 1, y: 0.5)
|
||||
button.configurationUpdateHandler = { [weak self] button in
|
||||
guard let self = self else { return }
|
||||
guard let button = button as? FAGradientButton else { return }
|
||||
|
||||
if button.isEnabled {
|
||||
button.fa_colors = [UIColor._53_A_2_F_1.cgColor, UIColor.C_5_DDF_5.cgColor]
|
||||
|
||||
let coinImage = UIImage(named: "coins_icon_03")!
|
||||
let coinText = NSTextAttachment(image: coinImage)
|
||||
coinText.bounds = .init(x: 0, y: -2.5, width: coinImage.size.width, height: coinImage.size.height)
|
||||
let coinAtt = AttributedString(NSAttributedString(attachment: coinText))
|
||||
let countAtt = AttributedString(" \(self.model?.receive_coins ?? 0)", attributes: AttributeContainer([
|
||||
.font : UIFont.font(ofSize: 12, weight: .bold),
|
||||
.foregroundColor : UIColor._000000.withAlphaComponent(0.5)
|
||||
]))
|
||||
|
||||
|
||||
button.configuration?.attributedTitle = AttributedString("Claim".localized, attributes: AttributeContainer([
|
||||
.font : UIFont.font(ofSize: 14, weight: .bold),
|
||||
.foregroundColor : UIColor._114_CEE
|
||||
]))
|
||||
|
||||
button.configuration?.attributedSubtitle = coinAtt + countAtt
|
||||
|
||||
} else {
|
||||
button.fa_colors = [UIColor.BCBCBC.cgColor, UIColor.BCBCBC.cgColor]
|
||||
button.configuration?.attributedTitle = AttributedString("Claim".localized, attributes: AttributeContainer([
|
||||
.font : UIFont.font(ofSize: 14, weight: .bold),
|
||||
.foregroundColor : UIColor.FFFFFF_0_8
|
||||
]))
|
||||
|
||||
button.configuration?.attributedSubtitle = nil
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
return button
|
||||
}()
|
||||
|
||||
override init(frame: CGRect) {
|
||||
super.init(frame: frame)
|
||||
|
||||
fa_setupLayout()
|
||||
}
|
||||
|
||||
required init?(coder: NSCoder) {
|
||||
fatalError("init(coder:) has not been implemented")
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
extension FACoinsPackClaimListCell {
|
||||
|
||||
private func fa_setupLayout() {
|
||||
contentView.addSubview(bgView)
|
||||
bgView.addSubview(bgIconImageView5)
|
||||
bgView.addSubview(bgIconImageView4)
|
||||
bgView.addSubview(bgIconImageView1)
|
||||
bgView.addSubview(bgIconImageView2)
|
||||
bgView.addSubview(titleLabel)
|
||||
bgView.addSubview(lineView1)
|
||||
bgView.addSubview(lineView2)
|
||||
bgView.addSubview(coinsView1)
|
||||
bgView.addSubview(coinsView2)
|
||||
bgView.addSubview(claimButton)
|
||||
|
||||
bgView.snp.makeConstraints { make in
|
||||
make.edges.equalToSuperview()
|
||||
}
|
||||
|
||||
bgIconImageView1.snp.makeConstraints { make in
|
||||
make.left.top.equalToSuperview()
|
||||
}
|
||||
|
||||
bgIconImageView2.snp.makeConstraints { make in
|
||||
make.centerY.equalToSuperview()
|
||||
make.right.equalToSuperview().offset(-8)
|
||||
}
|
||||
|
||||
bgIconImageView4.snp.makeConstraints { make in
|
||||
make.top.equalToSuperview()
|
||||
make.centerX.equalTo(bgIconImageView2)
|
||||
}
|
||||
|
||||
bgIconImageView5.snp.makeConstraints { make in
|
||||
make.bottom.equalToSuperview()
|
||||
make.left.equalToSuperview().offset(0)
|
||||
}
|
||||
|
||||
titleLabel.snp.makeConstraints { make in
|
||||
make.left.equalToSuperview().offset(12)
|
||||
make.centerY.equalTo(self.bgView.snp.top).offset(25)
|
||||
make.right.lessThanOrEqualToSuperview().offset(-12)
|
||||
}
|
||||
|
||||
lineView1.snp.makeConstraints { make in
|
||||
make.left.equalToSuperview().offset(12)
|
||||
make.centerX.equalToSuperview()
|
||||
make.top.equalToSuperview().offset(48)
|
||||
}
|
||||
|
||||
coinsView1.snp.makeConstraints { make in
|
||||
make.left.equalToSuperview().offset(12)
|
||||
make.bottom.equalToSuperview().offset(-18)
|
||||
}
|
||||
|
||||
lineView2.snp.makeConstraints { make in
|
||||
make.centerY.equalTo(coinsView1)
|
||||
make.left.equalTo(coinsView1.snp.right).offset(12)
|
||||
}
|
||||
|
||||
coinsView2.snp.makeConstraints { make in
|
||||
make.centerY.equalTo(coinsView1)
|
||||
make.left.equalTo(lineView2.snp.right).offset(12)
|
||||
}
|
||||
|
||||
claimButton.snp.makeConstraints { make in
|
||||
make.right.equalToSuperview().offset(-12)
|
||||
make.centerY.equalTo(coinsView1)
|
||||
make.height.equalTo(48)
|
||||
make.width.equalTo(120)
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
extension FACoinsPackClaimListCell {
|
||||
|
||||
class CoinsView: UIView {
|
||||
|
||||
var title: String? {
|
||||
didSet {
|
||||
titleLabel.text = title
|
||||
}
|
||||
}
|
||||
|
||||
var coins: Int? {
|
||||
didSet {
|
||||
coinsLabel.text = "\(coins ?? 0)"
|
||||
}
|
||||
}
|
||||
|
||||
private lazy var titleLabel: UILabel = {
|
||||
let label = UILabel()
|
||||
label.font = .font(ofSize: 12, weight: .bold)
|
||||
label.textColor = .DFEFFF
|
||||
return label
|
||||
}()
|
||||
|
||||
private lazy var iconImageView = UIImageView(image: UIImage(named: "coins_icon_03"))
|
||||
|
||||
private lazy var coinsLabel: UILabel = {
|
||||
let label = FALabel()
|
||||
label.font = .font(ofSize: 14, weight: .bold)
|
||||
label.textColors = [UIColor.FFCE_63.cgColor, UIColor.FFE_1_AA.cgColor]
|
||||
label.textStartPoint = .init(x: 0, y: 0.5)
|
||||
label.textEndPoint = .init(x: 1, y: 0.5)
|
||||
label.text = "0"
|
||||
return label
|
||||
}()
|
||||
|
||||
override init(frame: CGRect) {
|
||||
super.init(frame: frame)
|
||||
addSubview(titleLabel)
|
||||
addSubview(iconImageView)
|
||||
addSubview(coinsLabel)
|
||||
|
||||
titleLabel.snp.makeConstraints { make in
|
||||
make.left.equalToSuperview()
|
||||
make.top.equalToSuperview()
|
||||
make.right.lessThanOrEqualToSuperview()
|
||||
}
|
||||
|
||||
iconImageView.snp.makeConstraints { make in
|
||||
make.left.equalToSuperview()
|
||||
make.bottom.equalToSuperview()
|
||||
make.top.equalTo(titleLabel.snp.bottom).offset(8)
|
||||
}
|
||||
|
||||
coinsLabel.snp.makeConstraints { make in
|
||||
make.centerY.equalTo(iconImageView)
|
||||
make.left.equalTo(iconImageView.snp.right).offset(4)
|
||||
make.right.lessThanOrEqualToSuperview()
|
||||
}
|
||||
}
|
||||
|
||||
@MainActor required init?(coder: NSCoder) {
|
||||
fatalError("init(coder:) has not been implemented")
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
106
Fableon/Object/Class/Me/V/FACoinsPackClaimListView.swift
Normal file
@ -0,0 +1,106 @@
|
||||
//
|
||||
// FACoinsPackClaimListView.swift
|
||||
// Fableon
|
||||
//
|
||||
// Created by 湖北秦九 on 2025/10/29.
|
||||
//
|
||||
|
||||
import UIKit
|
||||
|
||||
class FACoinsPackClaimListView: UIView {
|
||||
|
||||
var clickClaimButton: ((_ id: String?) -> Void)?
|
||||
|
||||
var dataArr: [FACoinsPackReceiveModel] = [] {
|
||||
didSet {
|
||||
collectionView.reloadData()
|
||||
}
|
||||
}
|
||||
|
||||
private lazy var titleView: FACoinPackTitleView = {
|
||||
let view = FACoinPackTitleView()
|
||||
view.dotColor = .C_5_DDF_5
|
||||
view.textColors = [UIColor.C_5_DDF_5.cgColor, UIColor.C_5_DDF_5.cgColor]
|
||||
view.font = .font(ofSize: 14, weight: .regular)
|
||||
view.text = "Active Refills".localized.uppercased()
|
||||
return view
|
||||
}()
|
||||
|
||||
private lazy var collectionViewLayout: UICollectionViewFlowLayout = {
|
||||
let layout = UICollectionViewFlowLayout()
|
||||
layout.itemSize = .init(width: UIScreen.width - 32, height: 122)
|
||||
layout.minimumLineSpacing = 12
|
||||
return layout
|
||||
}()
|
||||
|
||||
private lazy var collectionView: FACollectionView = {
|
||||
let collectionView = FACollectionView(frame: .zero, collectionViewLayout: collectionViewLayout)
|
||||
collectionView.delegate = self
|
||||
collectionView.dataSource = self
|
||||
collectionView.addObserver(self, forKeyPath: "contentSize", context: nil)
|
||||
collectionView.register(FACoinsPackClaimListCell.self, forCellWithReuseIdentifier: "cell")
|
||||
return collectionView
|
||||
}()
|
||||
|
||||
deinit {
|
||||
collectionView.removeObserver(self, forKeyPath: "contentSize")
|
||||
}
|
||||
|
||||
override init(frame: CGRect) {
|
||||
super.init(frame: frame)
|
||||
|
||||
fa_setupLayout()
|
||||
}
|
||||
|
||||
required init?(coder: NSCoder) {
|
||||
fatalError("init(coder:) has not been implemented")
|
||||
}
|
||||
|
||||
override func observeValue(forKeyPath keyPath: String?, of object: Any?, change: [NSKeyValueChangeKey : Any]?, context: UnsafeMutableRawPointer?) {
|
||||
if keyPath == "contentSize" {
|
||||
let height = self.collectionView.contentSize.height + 1
|
||||
collectionView.snp.updateConstraints { make in
|
||||
make.height.equalTo(height)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
extension FACoinsPackClaimListView {
|
||||
|
||||
private func fa_setupLayout() {
|
||||
addSubview(titleView)
|
||||
addSubview(collectionView)
|
||||
|
||||
titleView.snp.makeConstraints { make in
|
||||
make.top.equalToSuperview()
|
||||
make.centerX.equalToSuperview()
|
||||
}
|
||||
|
||||
collectionView.snp.makeConstraints { make in
|
||||
make.left.right.bottom.equalToSuperview()
|
||||
make.top.equalToSuperview().offset(30)
|
||||
make.height.equalTo(1)
|
||||
make.bottom.equalToSuperview()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//MARK: UICollectionViewDelegate UICollectionViewDataSource
|
||||
extension FACoinsPackClaimListView: UICollectionViewDelegate, UICollectionViewDataSource {
|
||||
|
||||
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
|
||||
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "cell", for: indexPath) as! FACoinsPackClaimListCell
|
||||
cell.model = self.dataArr[indexPath.row]
|
||||
cell.clickClaimButton = { [weak self] id in
|
||||
self?.clickClaimButton?(id)
|
||||
}
|
||||
return cell
|
||||
}
|
||||
|
||||
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
|
||||
return dataArr.count
|
||||
}
|
||||
|
||||
}
|
||||
121
Fableon/Object/Class/Me/V/FALoginView.swift
Normal file
@ -0,0 +1,121 @@
|
||||
//
|
||||
// FALoginView.swift
|
||||
// Fableon
|
||||
//
|
||||
// Created by 湖北秦九 on 2025/10/30.
|
||||
//
|
||||
|
||||
import UIKit
|
||||
|
||||
class FALoginView: FAPanModalContentView {
|
||||
|
||||
|
||||
private lazy var bgView = UIImageView(image: UIImage(named: "弹窗背景色"))
|
||||
private lazy var bgIconImageView = UIImageView(image: UIImage(named: "Ellipse 873"))
|
||||
private lazy var logoImageView = UIImageView(image: UIImage(named: "logo_image_02"))
|
||||
|
||||
private lazy var stackView: UIStackView = {
|
||||
let view = UIStackView(arrangedSubviews: [appleButton, facebookButton])
|
||||
view.axis = .vertical
|
||||
view.spacing = 18
|
||||
return view
|
||||
}()
|
||||
|
||||
private lazy var appleButton: UIButton = {
|
||||
let button = self.createButton(image: UIImage(named: "apple_logo_icon_01"), title: "Login with Apple".localized)
|
||||
button.addAction(UIAction(handler: { [weak self] _ in
|
||||
self?.login(type: .apple)
|
||||
}), for: .touchUpInside)
|
||||
return button
|
||||
}()
|
||||
|
||||
private lazy var facebookButton: UIButton = {
|
||||
let button = self.createButton(image: UIImage(named: "facebook_logo_icon_01"), title: "Login with Facebook".localized)
|
||||
button.addAction(UIAction(handler: { [weak self] _ in
|
||||
self?.login(type: .faceBook)
|
||||
}), for: .touchUpInside)
|
||||
return button
|
||||
}()
|
||||
|
||||
|
||||
override init(frame: CGRect) {
|
||||
super.init(frame: frame)
|
||||
backgroundColor = .clear
|
||||
contentHeight = 300
|
||||
fa_setupLayout()
|
||||
}
|
||||
|
||||
@MainActor required init?(coder: NSCoder) {
|
||||
fatalError("init(coder:) has not been implemented")
|
||||
}
|
||||
|
||||
override func cornerRadius() -> CGFloat {
|
||||
return 0
|
||||
}
|
||||
|
||||
private func createButton(image: UIImage?, title: String) -> UIButton {
|
||||
var config = UIButton.Configuration.plain()
|
||||
config.image = image
|
||||
config.imagePadding = 12
|
||||
config.attributedTitle = AttributedString(title, attributes: AttributeContainer([
|
||||
.font : UIFont.font(ofSize: 14, weight: .bold),
|
||||
.foregroundColor : UIColor._333333
|
||||
]))
|
||||
config.background.backgroundColor = .FFFFFF
|
||||
|
||||
let button = UIButton(configuration: config)
|
||||
button.layer.cornerRadius = 24
|
||||
button.layer.masksToBounds = true
|
||||
|
||||
button.snp.makeConstraints { make in
|
||||
make.height.equalTo(48)
|
||||
}
|
||||
|
||||
return button
|
||||
}
|
||||
|
||||
private func login(type: FALogin.LoginType) {
|
||||
FAHUD.show()
|
||||
FALogin.manager.thirdLogin(type: type, presentingViewController: nil) { [weak self] isFinish in
|
||||
FAHUD.dismiss()
|
||||
guard let self = self else { return }
|
||||
if isFinish {
|
||||
Task {
|
||||
await self.dismiss(animated: true)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
extension FALoginView {
|
||||
|
||||
private func fa_setupLayout() {
|
||||
addSubview(bgView)
|
||||
bgView.addSubview(bgIconImageView)
|
||||
bgView.addSubview(logoImageView)
|
||||
addSubview(stackView)
|
||||
|
||||
bgView.snp.makeConstraints { make in
|
||||
make.edges.equalToSuperview()
|
||||
}
|
||||
|
||||
bgIconImageView.snp.makeConstraints { make in
|
||||
make.top.centerX.equalToSuperview()
|
||||
}
|
||||
|
||||
logoImageView.snp.makeConstraints { make in
|
||||
make.centerX.equalToSuperview()
|
||||
make.top.equalToSuperview().offset(20)
|
||||
}
|
||||
|
||||
stackView.snp.makeConstraints { make in
|
||||
make.top.equalToSuperview().offset(112)
|
||||
make.left.equalToSuperview().offset(37)
|
||||
make.centerX.equalToSuperview()
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
95
Fableon/Object/Class/Me/V/FAMeCoinsPackButton.swift
Normal file
@ -0,0 +1,95 @@
|
||||
//
|
||||
// FAMeCoinsPackButton.swift
|
||||
// Fableon
|
||||
//
|
||||
// Created by 湖北秦九 on 2025/10/29.
|
||||
//
|
||||
|
||||
import UIKit
|
||||
|
||||
class FAMeCoinsPackButton: UIControl {
|
||||
|
||||
private lazy var bgView: FAGradientView = {
|
||||
let view = FAGradientView()
|
||||
view.isUserInteractionEnabled = false
|
||||
view.fa_colors = [UIColor._114_CEE.cgColor, UIColor._000000.cgColor]
|
||||
view.fa_locations = [0, 1]
|
||||
view.fa_startPoint = .init(x: 0, y: 0.5)
|
||||
view.fa_endPoint = .init(x: 1, y: 0.5)
|
||||
view.layer.cornerRadius = 12
|
||||
view.layer.masksToBounds = true
|
||||
view.layer.borderWidth = 1
|
||||
view.layer.borderColor = UIColor._629_DFA.cgColor
|
||||
return view
|
||||
}()
|
||||
|
||||
private lazy var iconImageView: UIImageView = {
|
||||
let imageView = UIImageView(image: UIImage(named: "礼物11"))
|
||||
return imageView
|
||||
}()
|
||||
|
||||
private lazy var titleLabel: FALabel = {
|
||||
let label = FALabel()
|
||||
label.font = .font(ofSize: 14, weight: .init(900)).withBoldItalic()
|
||||
label.textColors = [UIColor._53_A_2_F_1.cgColor, UIColor.C_5_DDF_5.cgColor]
|
||||
label.textStartPoint = .init(x: 0, y: 0.5)
|
||||
label.textEndPoint = .init(x: 0.7, y: 0.5)
|
||||
label.text = "Daily reward ready!".localized
|
||||
return label
|
||||
}()
|
||||
|
||||
private lazy var subtitleLabel: UILabel = {
|
||||
let label = UILabel()
|
||||
label.font = .font(ofSize: 12, weight: .medium).withBoldItalic()
|
||||
label.textColor = .FFFFFF
|
||||
label.text = "Claim your rewards now.".localized
|
||||
return label
|
||||
}()
|
||||
|
||||
private lazy var indicatorImageView = UIImageView(image: UIImage(named: "arrow"))
|
||||
|
||||
override init(frame: CGRect) {
|
||||
super.init(frame: frame)
|
||||
fa_setupLayout()
|
||||
}
|
||||
|
||||
required init?(coder: NSCoder) {
|
||||
fatalError("init(coder:) has not been implemented")
|
||||
}
|
||||
}
|
||||
|
||||
extension FAMeCoinsPackButton {
|
||||
|
||||
private func fa_setupLayout() {
|
||||
addSubview(bgView)
|
||||
bgView.addSubview(iconImageView)
|
||||
bgView.addSubview(titleLabel)
|
||||
bgView.addSubview(subtitleLabel)
|
||||
bgView.addSubview(indicatorImageView)
|
||||
|
||||
bgView.snp.makeConstraints { make in
|
||||
make.edges.equalToSuperview()
|
||||
}
|
||||
|
||||
iconImageView.snp.makeConstraints { make in
|
||||
make.centerY.equalToSuperview()
|
||||
make.left.equalToSuperview().offset(12)
|
||||
}
|
||||
|
||||
titleLabel.snp.makeConstraints { make in
|
||||
make.top.equalToSuperview().offset(13)
|
||||
make.left.equalTo(iconImageView.snp.right).offset(8)
|
||||
}
|
||||
|
||||
subtitleLabel.snp.makeConstraints { make in
|
||||
make.left.equalTo(titleLabel)
|
||||
make.bottom.equalToSuperview().offset(-13)
|
||||
}
|
||||
|
||||
indicatorImageView.snp.makeConstraints { make in
|
||||
make.centerY.equalToSuperview()
|
||||
make.right.equalToSuperview().offset(-12)
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@ -9,7 +9,7 @@ import UIKit
|
||||
|
||||
class FAMeHeaderView: UIView {
|
||||
|
||||
var contentHeight: CGFloat = 40 + 66 + 40 + 28 + 24
|
||||
var contentHeight: CGFloat = 40 + 66 + 40 + 28 + 16 + 60 + 16
|
||||
|
||||
var userInfo: FAUserInfo? {
|
||||
didSet {
|
||||
@ -22,6 +22,8 @@ class FAMeHeaderView: UIView {
|
||||
coinsView.count = userInfo?.coin_left_total ?? 0
|
||||
|
||||
bonusCoinsView.count = userInfo?.send_coin_left_total ?? 0
|
||||
|
||||
loginButton.isHidden = FALogin.manager.isLogin
|
||||
}
|
||||
}
|
||||
|
||||
@ -69,6 +71,32 @@ class FAMeHeaderView: UIView {
|
||||
return view
|
||||
}()
|
||||
|
||||
private lazy var coinPackButton: FAMeCoinsPackButton = {
|
||||
let button = FAMeCoinsPackButton()
|
||||
button.addAction(UIAction(handler: { [weak self] _ in
|
||||
guard let self = self else { return }
|
||||
let vc = FACoinPackViewController()
|
||||
self.viewController?.navigationController?.pushViewController(vc, animated: true)
|
||||
}), for: .touchUpInside)
|
||||
return button
|
||||
}()
|
||||
|
||||
private lazy var loginButton: UIButton = {
|
||||
let button = UIButton(type: .custom, primaryAction: UIAction(handler: { [weak self] _ in
|
||||
guard let self = self else { return }
|
||||
let view = FALoginView()
|
||||
view.present(in: nil)
|
||||
}))
|
||||
button.layer.cornerRadius = 14
|
||||
button.layer.masksToBounds = true
|
||||
button.layer.borderWidth = 1
|
||||
button.layer.borderColor = UIColor.FFFEE_9.cgColor
|
||||
button.setTitle("Log in".localized, for: .normal)
|
||||
button.setTitleColor(.FFFFFF, for: .normal)
|
||||
button.titleLabel?.font = .font(ofSize: 14, weight: .medium)
|
||||
return button
|
||||
}()
|
||||
|
||||
|
||||
override init(frame: CGRect) {
|
||||
super.init(frame: frame)
|
||||
@ -88,6 +116,8 @@ extension FAMeHeaderView {
|
||||
addSubview(idLabel)
|
||||
addSubview(coinsView)
|
||||
addSubview(bonusCoinsView)
|
||||
addSubview(coinPackButton)
|
||||
addSubview(loginButton)
|
||||
|
||||
avatarImageView.snp.makeConstraints { make in
|
||||
make.left.equalToSuperview().offset(16)
|
||||
@ -115,6 +145,20 @@ extension FAMeHeaderView {
|
||||
make.top.equalTo(coinsView)
|
||||
make.left.equalTo(coinsView.snp.right).offset(40)
|
||||
}
|
||||
|
||||
coinPackButton.snp.makeConstraints { make in
|
||||
make.left.equalToSuperview().offset(16)
|
||||
make.centerX.equalToSuperview()
|
||||
make.top.equalTo(coinsView.snp.bottom).offset(16)
|
||||
make.height.equalTo(60)
|
||||
}
|
||||
|
||||
loginButton.snp.makeConstraints { make in
|
||||
make.right.equalToSuperview().offset(-16)
|
||||
make.centerY.equalTo(avatarImageView)
|
||||
make.width.equalTo(76)
|
||||
make.height.equalTo(28)
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
26
Fableon/Object/Class/Me/V/FASettingCell.swift
Normal file
@ -0,0 +1,26 @@
|
||||
//
|
||||
// FASettingCell.swift
|
||||
// Fableon
|
||||
//
|
||||
// Created by 湖北秦九 on 2025/10/30.
|
||||
//
|
||||
|
||||
import UIKit
|
||||
|
||||
class FASettingCell: FATableViewCell {
|
||||
|
||||
|
||||
@IBOutlet weak var titleLabel: UILabel!
|
||||
|
||||
override func awakeFromNib() {
|
||||
super.awakeFromNib()
|
||||
|
||||
}
|
||||
|
||||
override func setSelected(_ selected: Bool, animated: Bool) {
|
||||
super.setSelected(selected, animated: animated)
|
||||
|
||||
// Configure the view for the selected state
|
||||
}
|
||||
|
||||
}
|
||||
72
Fableon/Object/Class/Me/V/FASettingCell.xib
Normal file
@ -0,0 +1,72 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<document type="com.apple.InterfaceBuilder3.CocoaTouch.XIB" version="3.0" toolsVersion="24128" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" useSafeAreas="YES" colorMatched="YES">
|
||||
<device id="retina6_12" orientation="portrait" appearance="light"/>
|
||||
<dependencies>
|
||||
<deployment identifier="iOS"/>
|
||||
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="24063"/>
|
||||
<capability name="Named colors" minToolsVersion="9.0"/>
|
||||
<capability name="Safe area layout guides" minToolsVersion="9.0"/>
|
||||
<capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
|
||||
</dependencies>
|
||||
<objects>
|
||||
<placeholder placeholderIdentifier="IBFilesOwner" id="-1" userLabel="File's Owner"/>
|
||||
<placeholder placeholderIdentifier="IBFirstResponder" id="-2" customClass="UIResponder"/>
|
||||
<tableViewCell contentMode="scaleToFill" selectionStyle="default" indentationWidth="10" rowHeight="91" id="KGk-i7-Jjw" customClass="FASettingCell" customModule="Fableon" customModuleProvider="target">
|
||||
<rect key="frame" x="0.0" y="0.0" width="362" height="91"/>
|
||||
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
|
||||
<tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" tableViewCell="KGk-i7-Jjw" id="H2p-sc-9uM">
|
||||
<rect key="frame" x="0.0" y="0.0" width="362" height="91"/>
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
<subviews>
|
||||
<view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="eS3-W5-VR6">
|
||||
<rect key="frame" x="16" y="0.0" width="330" height="91"/>
|
||||
<subviews>
|
||||
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Label" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="A4A-hn-CZz">
|
||||
<rect key="frame" x="16" y="37" width="36" height="17"/>
|
||||
<fontDescription key="fontDescription" type="system" weight="medium" pointSize="14"/>
|
||||
<color key="textColor" name="#FFFFFF"/>
|
||||
<nil key="highlightedColor"/>
|
||||
</label>
|
||||
<imageView clipsSubviews="YES" userInteractionEnabled="NO" contentMode="scaleAspectFit" image="Frame 3015" translatesAutoresizingMaskIntoConstraints="NO" id="f2b-1S-BSh">
|
||||
<rect key="frame" x="304" y="40.666666666666664" width="10" height="10"/>
|
||||
</imageView>
|
||||
</subviews>
|
||||
<color key="backgroundColor" name="#5CA8FF_0.2"/>
|
||||
<constraints>
|
||||
<constraint firstItem="A4A-hn-CZz" firstAttribute="leading" secondItem="eS3-W5-VR6" secondAttribute="leading" constant="16" id="OqO-BA-gyr"/>
|
||||
<constraint firstItem="A4A-hn-CZz" firstAttribute="centerY" secondItem="eS3-W5-VR6" secondAttribute="centerY" id="WQz-Lc-m7d"/>
|
||||
<constraint firstAttribute="trailing" secondItem="f2b-1S-BSh" secondAttribute="trailing" constant="16" id="ppx-bH-uVc"/>
|
||||
<constraint firstItem="f2b-1S-BSh" firstAttribute="centerY" secondItem="eS3-W5-VR6" secondAttribute="centerY" id="sJc-Wi-mjw"/>
|
||||
</constraints>
|
||||
<userDefinedRuntimeAttributes>
|
||||
<userDefinedRuntimeAttribute type="number" keyPath="layer.cornerRadius">
|
||||
<integer key="value" value="12"/>
|
||||
</userDefinedRuntimeAttribute>
|
||||
<userDefinedRuntimeAttribute type="boolean" keyPath="masksToBounds" value="YES"/>
|
||||
</userDefinedRuntimeAttributes>
|
||||
</view>
|
||||
</subviews>
|
||||
<constraints>
|
||||
<constraint firstAttribute="bottom" secondItem="eS3-W5-VR6" secondAttribute="bottom" id="7pH-iM-ihT"/>
|
||||
<constraint firstItem="eS3-W5-VR6" firstAttribute="top" secondItem="H2p-sc-9uM" secondAttribute="top" id="MKW-Dz-3xN"/>
|
||||
<constraint firstAttribute="trailing" secondItem="eS3-W5-VR6" secondAttribute="trailing" constant="16" id="bZG-Qv-nXN"/>
|
||||
<constraint firstItem="eS3-W5-VR6" firstAttribute="leading" secondItem="H2p-sc-9uM" secondAttribute="leading" constant="16" id="fSl-zo-SIR"/>
|
||||
</constraints>
|
||||
</tableViewCellContentView>
|
||||
<viewLayoutGuide key="safeArea" id="njF-e1-oar"/>
|
||||
<connections>
|
||||
<outlet property="titleLabel" destination="A4A-hn-CZz" id="yn4-Ke-t3P"/>
|
||||
</connections>
|
||||
<point key="canvasLocation" x="117.55725190839694" y="119.36619718309859"/>
|
||||
</tableViewCell>
|
||||
</objects>
|
||||
<resources>
|
||||
<image name="Frame 3015" width="10" height="10"/>
|
||||
<namedColor name="#5CA8FF_0.2">
|
||||
<color red="0.36078431372549019" green="0.6588235294117647" blue="1" alpha="0.20000000298023224" colorSpace="custom" customColorSpace="sRGB"/>
|
||||
</namedColor>
|
||||
<namedColor name="#FFFFFF">
|
||||
<color red="1" green="1" blue="1" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
|
||||
</namedColor>
|
||||
</resources>
|
||||
</document>
|
||||
48
Fableon/Object/Class/Me/V/FASettingFooterView.swift
Normal file
@ -0,0 +1,48 @@
|
||||
//
|
||||
// FASettingFooterView.swift
|
||||
// Fableon
|
||||
//
|
||||
// Created by 湖北秦九 on 2025/10/30.
|
||||
//
|
||||
|
||||
import UIKit
|
||||
|
||||
class FASettingFooterView: UIView {
|
||||
|
||||
|
||||
private lazy var logoutButton: UIButton = {
|
||||
let button = FAGradientButton(type: .custom, primaryAction: UIAction(handler: { [weak self] _ in
|
||||
guard let self = self else { return }
|
||||
FALogin.manager.logout(completer: nil)
|
||||
}))
|
||||
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("Log out".localized, for: .normal)
|
||||
button.setTitleColor(._000000, for: .normal)
|
||||
button.titleLabel?.font = .font(ofSize: 18, weight: .semibold)
|
||||
return button
|
||||
}()
|
||||
|
||||
override init(frame: CGRect) {
|
||||
super.init(frame: frame)
|
||||
|
||||
addSubview(logoutButton)
|
||||
|
||||
logoutButton.snp.makeConstraints { make in
|
||||
make.left.equalToSuperview().offset(16)
|
||||
make.centerX.equalToSuperview()
|
||||
make.bottom.equalToSuperview()
|
||||
make.height.equalTo(48)
|
||||
}
|
||||
}
|
||||
|
||||
required init?(coder: NSCoder) {
|
||||
fatalError("init(coder:) has not been implemented")
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -122,6 +122,22 @@ class FACollectViewController: FAViewController {
|
||||
}
|
||||
}
|
||||
|
||||
private func removeCollect(_ indexPath: IndexPath) {
|
||||
|
||||
let alert = FARemoveCollectAlert()
|
||||
alert.show()
|
||||
alert.clickHighlightButton = { [weak self] in
|
||||
guard let self = self else { return }
|
||||
let model = self.dataArr[indexPath.row]
|
||||
guard let shortPlayId = model.short_play_id else { return }
|
||||
FAAPI.requestShortCollect(isCollect: false, shortPlayId: shortPlayId, videoId: model.short_play_video_id) { [weak self] in
|
||||
guard let self = self else { return }
|
||||
self.dataArr.remove(at: indexPath.row)
|
||||
self.collectionView.deleteItems(at: [indexPath])
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
extension FACollectViewController {
|
||||
@ -147,13 +163,10 @@ extension FACollectViewController: UICollectionViewDataSource, UICollectionViewD
|
||||
cell.clickDeleteButton = { [weak self] cell in
|
||||
guard let self = self else { return }
|
||||
guard let indexPath = self.collectionView.indexPath(for: cell) else { return }
|
||||
guard let shortPlayId = cell.model?.short_play_id else { return }
|
||||
|
||||
FAAPI.requestShortCollect(isCollect: false, shortPlayId: shortPlayId, videoId: cell.model?.short_play_video_id) { [weak self] in
|
||||
guard let self = self else { return }
|
||||
self.dataArr.remove(at: indexPath.row)
|
||||
self.collectionView.deleteItems(at: [indexPath])
|
||||
}
|
||||
self.removeCollect(indexPath)
|
||||
|
||||
|
||||
}
|
||||
return cell
|
||||
}
|
||||
|
||||
@ -173,12 +173,24 @@ extension FAEpSelectorView: UICollectionViewDelegate, UICollectionViewDataSource
|
||||
}
|
||||
|
||||
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
|
||||
model?.episodeList?.count ?? 0
|
||||
return model?.episodeList?.count ?? 0
|
||||
}
|
||||
|
||||
func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
|
||||
guard let epList = self.model?.episodeList else { return }
|
||||
if self.selectedIndex == indexPath.row { return }
|
||||
self.selectedIndex = indexPath.row
|
||||
|
||||
let lastIndex = indexPath.row - 1
|
||||
var lastIsLock = false
|
||||
if lastIndex > 0 && lastIndex < epList.count {
|
||||
let lastModel = epList[lastIndex]
|
||||
lastIsLock = lastModel.is_lock ?? false
|
||||
}
|
||||
|
||||
if lastIsLock {
|
||||
FAToast.show(text: "buy_fail_toast_02".localized)
|
||||
return
|
||||
}
|
||||
|
||||
self.didSelected?(indexPath.row)
|
||||
self.dismiss(animated: true) {
|
||||
|
||||
@ -11,6 +11,7 @@ import HWPanModal
|
||||
class FAOldVideoRechargeView: FAPanModalContentView {
|
||||
|
||||
var buyFinishHandle: (() -> Void)?
|
||||
var didDismissHandle: (() -> Void)?
|
||||
|
||||
var model: FAPayDateModel? {
|
||||
didSet {
|
||||
@ -35,7 +36,7 @@ class FAOldVideoRechargeView: FAPanModalContentView {
|
||||
}
|
||||
}
|
||||
|
||||
// self.stackView.addArrangedSubview(self.tipView)
|
||||
self.stackView.addArrangedSubview(self.tipView)
|
||||
|
||||
self.setNeedsLayoutUpdate()
|
||||
}
|
||||
@ -62,6 +63,7 @@ class FAOldVideoRechargeView: FAPanModalContentView {
|
||||
Task {
|
||||
await self.dismiss(animated: true)
|
||||
}
|
||||
self.didDismissHandle?()
|
||||
}))
|
||||
button.setImage(UIImage(named: "close_icon_02"), for: .normal)
|
||||
return button
|
||||
@ -123,6 +125,42 @@ class FAOldVideoRechargeView: FAPanModalContentView {
|
||||
return label
|
||||
}()
|
||||
|
||||
private lazy var tipView: UIView = {
|
||||
let view = UIView()
|
||||
view.addSubview(tipTitleLabel)
|
||||
view.addSubview(tipTextLabel)
|
||||
|
||||
tipTitleLabel.snp.makeConstraints { make in
|
||||
make.top.equalToSuperview().offset(7)
|
||||
make.left.equalToSuperview().offset(16)
|
||||
}
|
||||
|
||||
tipTextLabel.snp.makeConstraints { make in
|
||||
make.left.equalToSuperview().offset(16)
|
||||
make.right.lessThanOrEqualToSuperview().offset(-16)
|
||||
make.top.equalTo(tipTitleLabel.snp.bottom).offset(4)
|
||||
make.bottom.equalToSuperview()
|
||||
}
|
||||
return view
|
||||
}()
|
||||
|
||||
private lazy var tipTitleLabel: UILabel = {
|
||||
let label = UILabel()
|
||||
label.font = .font(ofSize: 12, weight: .medium)
|
||||
label.textColor = .FFFFFF
|
||||
label.text = "store_tips_title".localized
|
||||
return label
|
||||
}()
|
||||
|
||||
private lazy var tipTextLabel: UILabel = {
|
||||
let label = UILabel()
|
||||
label.font = .font(ofSize: 10, weight: .regular)
|
||||
label.textColor = .FFFFFF
|
||||
label.text = "store_tips".localized
|
||||
label.numberOfLines = 0
|
||||
return label
|
||||
}()
|
||||
|
||||
deinit {
|
||||
NotificationCenter.default.removeObserver(self)
|
||||
}
|
||||
|
||||
@ -171,6 +171,10 @@ extension FAShortDetailViewModel {
|
||||
guard let self = self else { return }
|
||||
self.requestDetailData(indexPath: self.currentIndexPath, completer: nil)
|
||||
}
|
||||
view.didDismissHandle = { [weak self] in
|
||||
guard let self = self else { return }
|
||||
self._showVipRetainAlert(videoInfo)
|
||||
}
|
||||
view.present(in: nil)
|
||||
self.popView = view
|
||||
}
|
||||
@ -182,6 +186,25 @@ extension FAShortDetailViewModel {
|
||||
view.present(in: nil)
|
||||
self.popView = view
|
||||
}
|
||||
|
||||
private func _showVipRetainAlert(_ videoInfo: FAVideoInfoModel) {
|
||||
|
||||
|
||||
payDataRequest = FAPayDataRequest()
|
||||
|
||||
payDataRequest?.requestVipRetainPayInfo { [weak self] model in
|
||||
guard let self = self else { return }
|
||||
guard let model = model else { return }
|
||||
let view = FAVipRetainAlert()
|
||||
view.model = model
|
||||
view.videoInfo = videoInfo
|
||||
view.buyFinishHandle = { [weak self] in
|
||||
guard let self = self else { return }
|
||||
self.requestDetailData(indexPath: self.currentIndexPath, completer: nil)
|
||||
}
|
||||
view.show(in: FATool.keyWindow)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
extension FAShortDetailViewModel {
|
||||
|
||||
13
Fableon/Object/Class/Store/M/FACoinPackCanReceiveModel.swift
Normal file
@ -0,0 +1,13 @@
|
||||
//
|
||||
// FACoinPackCanReceiveModel.swift
|
||||
// Fableon
|
||||
//
|
||||
// Created by 湖北秦九 on 2025/10/30.
|
||||
//
|
||||
|
||||
import UIKit
|
||||
import SmartCodable
|
||||
|
||||
struct FACoinPackCanReceiveModel: SmartCodable {
|
||||
var coins: Int?
|
||||
}
|
||||
25
Fableon/Object/Class/Store/M/FACoinsPackModel.swift
Normal file
@ -0,0 +1,25 @@
|
||||
//
|
||||
// FACoinsPackModel.swift
|
||||
// Fableon
|
||||
//
|
||||
// Created by 湖北秦九 on 2025/10/29.
|
||||
//
|
||||
|
||||
import UIKit
|
||||
import SmartCodable
|
||||
|
||||
struct FACoinsPackModel: SmartCodable {
|
||||
|
||||
//当前可领取订阅数
|
||||
var receive_count: Int?
|
||||
//已领取累计金币总数
|
||||
var week_total: Int?
|
||||
//剩余可领取金币数
|
||||
var week_remaining_total: Int?
|
||||
//订阅可领取累计金币总数
|
||||
var week_max_total: Int?
|
||||
//当前可领取金币总数
|
||||
var receive_coins: Int?
|
||||
|
||||
var receive_list: [FACoinsPackReceiveModel]?
|
||||
}
|
||||
25
Fableon/Object/Class/Store/M/FACoinsPackReceiveModel.swift
Normal file
@ -0,0 +1,25 @@
|
||||
//
|
||||
// FACoinsPackReceiveModel.swift
|
||||
// Fableon
|
||||
//
|
||||
// Created by 湖北秦九 on 2025/10/29.
|
||||
//
|
||||
|
||||
import UIKit
|
||||
import SmartCodable
|
||||
|
||||
struct FACoinsPackReceiveModel: SmartCodable {
|
||||
|
||||
var id: String?
|
||||
var title: String?
|
||||
//剩余可领取金币数
|
||||
var week_remaining_total: Int?
|
||||
//当前可领取金币数
|
||||
var receive_coins: Int?
|
||||
//已领取累计金币总数
|
||||
var week_total: Int?
|
||||
//可领取累计金币总数
|
||||
var week_max_total: Int?
|
||||
//领取天数文本
|
||||
var day_text: String?
|
||||
}
|
||||
@ -10,14 +10,15 @@ import UIKit
|
||||
class FAAdjustStateManager {
|
||||
static let manager = FAAdjustStateManager()
|
||||
|
||||
var allowOpenMessage = true
|
||||
|
||||
var webpageURL: URL?
|
||||
///是否需要重试
|
||||
var isNeedRetry = false
|
||||
|
||||
var allowOpenMessage = true
|
||||
|
||||
var isOpenApp = false
|
||||
|
||||
var idfaAuthorizationFinish = false
|
||||
|
||||
var apnsAuthorizationFinish = false
|
||||
}
|
||||
|
||||
104
Fableon/Object/Libs/Alert/FAApnsAlert.swift
Normal file
@ -0,0 +1,104 @@
|
||||
//
|
||||
// FAApnsAlert.swift
|
||||
// Fableon
|
||||
//
|
||||
// Created by 湖北秦九 on 2025/10/31.
|
||||
//
|
||||
|
||||
import UIKit
|
||||
|
||||
class FAApnsAlert: FABaseAlert {
|
||||
|
||||
private lazy var imageView = UIImageView(image: UIImage(named: "__magnifying"))
|
||||
|
||||
private lazy var titleLabel: UILabel = {
|
||||
let label = UILabel()
|
||||
label.textAlignment = .center
|
||||
label.numberOfLines = 0
|
||||
label.font = .font(ofSize: 18, weight: .semibold)
|
||||
label.textColor = .FFFFFF
|
||||
label.text = "apns_alert_title".localized
|
||||
return label
|
||||
}()
|
||||
|
||||
private lazy var textLabel: UILabel = {
|
||||
let label = UILabel()
|
||||
label.textAlignment = .center
|
||||
label.numberOfLines = 0
|
||||
label.font = .font(ofSize: 12, weight: .regular)
|
||||
label.textColor = .FFFFFF
|
||||
label.text = "apns_alert_text".localized
|
||||
return label
|
||||
}()
|
||||
|
||||
private lazy var laterButton: UIButton = {
|
||||
let button = UIButton(type: .custom)
|
||||
button.layer.cornerRadius = 18
|
||||
button.layer.masksToBounds = true
|
||||
button.layer.borderWidth = 1
|
||||
button.layer.borderColor = UIColor.FFFFFF.cgColor
|
||||
button.setTitle("Later".localized, for: .normal)
|
||||
button.setTitleColor(.FFFFFF, for: .normal)
|
||||
button.titleLabel?.font = .font(ofSize: 14, weight: .semibold)
|
||||
button.addTarget(self, action: #selector(dismiss), for: .touchUpInside)
|
||||
return button
|
||||
}()
|
||||
|
||||
override init(frame: CGRect) {
|
||||
super.init(frame: frame)
|
||||
highlightButton.setTitle("Open".localized, for: .normal)
|
||||
|
||||
fa_setupLayout()
|
||||
}
|
||||
|
||||
@MainActor required init?(coder: NSCoder) {
|
||||
fatalError("init(coder:) has not been implemented")
|
||||
}
|
||||
|
||||
override func handleHighlightButton() {
|
||||
super.handleHighlightButton()
|
||||
FATool.openApnsSetting()
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
extension FAApnsAlert {
|
||||
|
||||
private func fa_setupLayout() {
|
||||
containerView.addSubview(imageView)
|
||||
contentView.addSubview(titleLabel)
|
||||
contentView.addSubview(textLabel)
|
||||
contentView.addSubview(laterButton)
|
||||
contentView.addSubview(highlightButton)
|
||||
|
||||
imageView.snp.makeConstraints { make in
|
||||
make.centerX.equalToSuperview()
|
||||
make.top.equalToSuperview().offset(-62)
|
||||
}
|
||||
|
||||
titleLabel.snp.makeConstraints { make in
|
||||
make.centerX.equalToSuperview()
|
||||
make.right.lessThanOrEqualToSuperview().offset(-10)
|
||||
make.top.equalTo(imageView.snp.bottom).offset(10)
|
||||
}
|
||||
|
||||
textLabel.snp.makeConstraints { make in
|
||||
make.centerX.equalToSuperview()
|
||||
make.right.lessThanOrEqualToSuperview().offset(-20)
|
||||
make.top.equalTo(titleLabel.snp.bottom).offset(12)
|
||||
}
|
||||
|
||||
laterButton.snp.makeConstraints { make in
|
||||
make.left.equalToSuperview().offset(23)
|
||||
make.top.equalTo(textLabel.snp.bottom).offset(21)
|
||||
make.bottom.equalToSuperview().offset(-20)
|
||||
make.height.equalTo(36)
|
||||
}
|
||||
|
||||
highlightButton.snp.makeConstraints { make in
|
||||
make.width.height.top.equalTo(laterButton)
|
||||
make.left.equalTo(laterButton.snp.right).offset(11)
|
||||
make.right.equalToSuperview().offset(-23)
|
||||
}
|
||||
}
|
||||
}
|
||||
169
Fableon/Object/Libs/Alert/FABaseAlert.swift
Normal file
@ -0,0 +1,169 @@
|
||||
//
|
||||
// FABaseAlert.swift
|
||||
// Fableon
|
||||
//
|
||||
// Created by 湖北秦九 on 2025/10/30.
|
||||
//
|
||||
|
||||
import UIKit
|
||||
import SnapKit
|
||||
|
||||
class FABaseAlert: UIView {
|
||||
|
||||
var clickHighlightButton: (() -> Void)?
|
||||
|
||||
var contentWidth: CGFloat = UIScreen.width - 70 {
|
||||
didSet {
|
||||
containerView.snp.updateConstraints { make in
|
||||
make.width.equalTo(contentWidth)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private(set) var containerView: UIView = {
|
||||
let view = UIView()
|
||||
return view
|
||||
}()
|
||||
|
||||
private(set) var contentView: UIView = {
|
||||
let view = UIView()
|
||||
view.backgroundColor = ._404040
|
||||
view.layer.cornerRadius = 16
|
||||
view.layer.masksToBounds = true
|
||||
return view
|
||||
}()
|
||||
|
||||
private(set) lazy var closeButton: UIButton = {
|
||||
let button = UIButton(type: .custom)
|
||||
button.setImage(UIImage(named: "close_icon_03"), for: .normal)
|
||||
button.addTarget(self, action: #selector(dismiss), for: .touchUpInside)
|
||||
return button
|
||||
}()
|
||||
|
||||
lazy var highlightButton: FAGradientButton = {
|
||||
let button = FAGradientButton(type: .custom)
|
||||
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.layer.cornerRadius = 16
|
||||
button.layer.masksToBounds = true
|
||||
button.setTitleColor(._000000, for: .normal)
|
||||
button.titleLabel?.font = .font(ofSize: 14, weight: .semibold)
|
||||
button.addTarget(self, action: #selector(handleHighlightButton), for: .touchUpInside)
|
||||
return button
|
||||
}()
|
||||
|
||||
override init(frame: CGRect) {
|
||||
super.init(frame: frame)
|
||||
backgroundColor = ._000000.withAlphaComponent(0.5)
|
||||
|
||||
addSubview(containerView)
|
||||
containerView.addSubview(contentView)
|
||||
containerView.addSubview(closeButton)
|
||||
|
||||
containerView.snp.makeConstraints { make in
|
||||
make.center.equalToSuperview()
|
||||
make.width.equalTo(contentWidth)
|
||||
}
|
||||
|
||||
contentView.snp.makeConstraints { make in
|
||||
make.left.right.top.equalToSuperview()
|
||||
make.bottom.equalToSuperview().offset(-66)
|
||||
}
|
||||
|
||||
closeButton.snp.makeConstraints { make in
|
||||
make.centerX.equalToSuperview()
|
||||
make.bottom.equalToSuperview()
|
||||
}
|
||||
}
|
||||
|
||||
required init?(coder: NSCoder) {
|
||||
fatalError("init(coder:) has not been implemented")
|
||||
}
|
||||
|
||||
@discardableResult
|
||||
@objc func show(in view: UIView? = nil) -> Self {
|
||||
guard self.superview == nil else { return self }
|
||||
|
||||
var inView: UIView
|
||||
if let view = view {
|
||||
inView = view
|
||||
} else {
|
||||
inView = FABaseAlert.Window.manager.createWindow()
|
||||
}
|
||||
|
||||
inView.addSubview(self)
|
||||
self.frame = inView.bounds
|
||||
showAnimation()
|
||||
|
||||
return self
|
||||
}
|
||||
@objc func dismiss() {
|
||||
dismissAnimation()
|
||||
}
|
||||
|
||||
@objc func handleHighlightButton() {
|
||||
self.dismissAnimation()
|
||||
self.clickHighlightButton?()
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
extension FABaseAlert {
|
||||
private func showAnimation() {
|
||||
containerView.transform = CGAffineTransform(translationX: 0, y: 200)
|
||||
|
||||
UIView.animate(withDuration: 0.5, delay: 0, usingSpringWithDamping: 0.7, initialSpringVelocity: 0) {
|
||||
self.containerView.transform = CGAffineTransform.identity
|
||||
}
|
||||
}
|
||||
|
||||
private func dismissAnimation() {
|
||||
|
||||
UIView.animate(withDuration: 0.3) {
|
||||
self.alpha = 0
|
||||
self.containerView.transform = CGAffineTransform(translationX: 0, y: 500)
|
||||
} completion: { _ in
|
||||
self.removeFromSuperview()
|
||||
FABaseAlert.Window.manager.dismissWindow()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
extension FABaseAlert {
|
||||
class Window {
|
||||
static let manager = Window()
|
||||
|
||||
private(set) var window: UIWindow?
|
||||
|
||||
func createWindow() -> UIWindow {
|
||||
guard let window = window else {
|
||||
let window = UIWindow(windowScene: FATool.windowScene!)
|
||||
window.backgroundColor = .clear
|
||||
window.windowLevel = .alert
|
||||
window.isHidden = false
|
||||
self.window = window
|
||||
return window
|
||||
}
|
||||
return window
|
||||
}
|
||||
|
||||
func dismissWindow() {
|
||||
guard let window = self.window else { return }
|
||||
|
||||
var isHidden = true
|
||||
|
||||
window.subviews.forEach {
|
||||
if $0.isKind(of: FABaseAlert.self) {
|
||||
isHidden = false
|
||||
}
|
||||
}
|
||||
if isHidden {
|
||||
window.isHidden = true
|
||||
self.window = nil
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
117
Fableon/Object/Libs/Alert/FACoinsPackAlert.swift
Normal file
@ -0,0 +1,117 @@
|
||||
//
|
||||
// FACoinsPackAlert.swift
|
||||
// Fableon
|
||||
//
|
||||
// Created by 湖北秦九 on 2025/10/30.
|
||||
//
|
||||
|
||||
import UIKit
|
||||
|
||||
class FACoinsPackAlert: FABaseAlert {
|
||||
|
||||
var coinsCount: Int? {
|
||||
didSet {
|
||||
coinsView.setNeedsUpdateConfiguration()
|
||||
}
|
||||
}
|
||||
|
||||
private lazy var imageView = UIImageView(image: UIImage(named: "签到"))
|
||||
|
||||
private lazy var titleLabel: UILabel = {
|
||||
let label = UILabel()
|
||||
label.font = .font(ofSize: 18, weight: .bold)
|
||||
label.textColor = .FFFFFF
|
||||
label.textAlignment = .center
|
||||
label.numberOfLines = 0
|
||||
label.text = "coins_pack_alert_title".localized
|
||||
return label
|
||||
}()
|
||||
|
||||
private lazy var coinsView: UIButton = {
|
||||
var config = UIButton.Configuration.plain()
|
||||
config.image = UIImage(named: "coins_icon_10")
|
||||
config.imagePadding = 8
|
||||
config.contentInsets = .zero
|
||||
let button = UIButton(configuration: config)
|
||||
button.isUserInteractionEnabled = false
|
||||
button.configurationUpdateHandler = { [weak self] button in
|
||||
guard let self = self else { return }
|
||||
button.configuration?.attributedTitle = AttributedString("+\(self.coinsCount ?? 0)", attributes: AttributeContainer([
|
||||
.font : UIFont.font(ofSize: 24, weight: .init(700)),
|
||||
.foregroundColor : UIColor.F_6_CF_87
|
||||
]))
|
||||
}
|
||||
return button
|
||||
}()
|
||||
|
||||
private lazy var laterButton: UIButton = {
|
||||
let button = UIButton(type: .custom)
|
||||
button.layer.cornerRadius = 24
|
||||
button.layer.masksToBounds = true
|
||||
button.layer.borderColor = UIColor._777777.cgColor
|
||||
button.layer.borderWidth = 1
|
||||
button.setTitle("Later".localized, for: .normal)
|
||||
button.setTitleColor(._777777, for: .normal)
|
||||
button.titleLabel?.font = .font(ofSize: 14, weight: .bold)
|
||||
button.addTarget(self, action: #selector(dismiss), for: .touchUpInside)
|
||||
return button
|
||||
}()
|
||||
|
||||
override init(frame: CGRect) {
|
||||
super.init(frame: frame)
|
||||
|
||||
self.highlightButton.setTitle("Claim Now".localized, for: .normal)
|
||||
self.highlightButton.setTitleColor(.FFFFFF, for: .normal)
|
||||
self.highlightButton.fa_colors = [UIColor._53_A_2_F_1.cgColor, UIColor.C_5_DDF_5.cgColor]
|
||||
self.highlightButton.layer.cornerRadius = 24
|
||||
self.highlightButton.titleLabel?.font = .font(ofSize: 14, weight: .bold)
|
||||
|
||||
fa_setupLayout()
|
||||
}
|
||||
|
||||
@MainActor required init?(coder: NSCoder) {
|
||||
fatalError("init(coder:) has not been implemented")
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
extension FACoinsPackAlert {
|
||||
|
||||
private func fa_setupLayout() {
|
||||
contentView.addSubview(imageView)
|
||||
contentView.addSubview(titleLabel)
|
||||
contentView.addSubview(coinsView)
|
||||
contentView.addSubview(highlightButton)
|
||||
contentView.addSubview(laterButton)
|
||||
|
||||
imageView.snp.makeConstraints { make in
|
||||
make.centerX.equalToSuperview()
|
||||
make.top.equalToSuperview().offset(24)
|
||||
}
|
||||
|
||||
titleLabel.snp.makeConstraints { make in
|
||||
make.centerX.equalToSuperview()
|
||||
make.right.lessThanOrEqualToSuperview().offset(-10)
|
||||
make.top.equalTo(imageView.snp.bottom).offset(16)
|
||||
}
|
||||
|
||||
coinsView.snp.makeConstraints { make in
|
||||
make.centerX.equalToSuperview()
|
||||
make.top.equalTo(titleLabel.snp.bottom).offset(16)
|
||||
}
|
||||
|
||||
highlightButton.snp.makeConstraints { make in
|
||||
make.left.equalToSuperview().offset(18)
|
||||
make.centerX.equalToSuperview()
|
||||
make.top.equalTo(coinsView.snp.bottom).offset(16)
|
||||
make.height.equalTo(48)
|
||||
}
|
||||
|
||||
laterButton.snp.makeConstraints { make in
|
||||
make.left.right.height.equalTo(highlightButton)
|
||||
make.top.equalTo(highlightButton.snp.bottom).offset(12)
|
||||
make.bottom.equalToSuperview().offset(-24)
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
93
Fableon/Object/Libs/Alert/FARemoveCollectAlert.swift
Normal file
@ -0,0 +1,93 @@
|
||||
//
|
||||
// FARemoveCollectAlert.swift
|
||||
// Fableon
|
||||
//
|
||||
// Created by 湖北秦九 on 2025/10/30.
|
||||
//
|
||||
|
||||
import UIKit
|
||||
|
||||
class FARemoveCollectAlert: FABaseAlert {
|
||||
|
||||
|
||||
private lazy var imageView = UIImageView(image: UIImage(named: "alert_image_01"))
|
||||
|
||||
private lazy var titleLabel: UILabel = {
|
||||
let label = UILabel()
|
||||
label.font = .font(ofSize: 18, weight: .semibold)
|
||||
label.textColor = .FFFFFF
|
||||
label.text = "remove_collect_alert_title".localized
|
||||
label.numberOfLines = 0
|
||||
label.textAlignment = .center
|
||||
return label
|
||||
}()
|
||||
|
||||
private lazy var textLabel: UILabel = {
|
||||
let label = UILabel()
|
||||
label.font = .font(ofSize: 12, weight: .regular)
|
||||
label.textColor = .FFFFFF
|
||||
label.numberOfLines = 0
|
||||
label.textAlignment = .center
|
||||
label.text = "remove_collect_alert_text".localized
|
||||
return label
|
||||
}()
|
||||
|
||||
private lazy var cancelButton: UIButton = {
|
||||
let button = UIButton(type: .custom)
|
||||
button.layer.cornerRadius = 18
|
||||
button.layer.masksToBounds = true
|
||||
button.layer.borderWidth = 1
|
||||
button.layer.borderColor = UIColor.FFFFFF.cgColor
|
||||
button.setTitle("Cancel".localized, for: .normal)
|
||||
button.setTitleColor(.FFFFFF, for: .normal)
|
||||
button.titleLabel?.font = .font(ofSize: 14, weight: .medium)
|
||||
button.addTarget(self, action: #selector(dismiss), for: .touchUpInside)
|
||||
return button
|
||||
}()
|
||||
|
||||
override init(frame: CGRect) {
|
||||
super.init(frame: frame)
|
||||
|
||||
highlightButton.setTitle("Remove".localized, for: .normal)
|
||||
|
||||
containerView.addSubview(imageView)
|
||||
contentView.addSubview(titleLabel)
|
||||
contentView.addSubview(textLabel)
|
||||
contentView.addSubview(cancelButton)
|
||||
contentView.addSubview(highlightButton)
|
||||
|
||||
imageView.snp.makeConstraints { make in
|
||||
make.centerX.equalToSuperview()
|
||||
make.top.equalToSuperview().offset(-62)
|
||||
}
|
||||
|
||||
titleLabel.snp.makeConstraints { make in
|
||||
make.centerX.equalToSuperview()
|
||||
make.top.equalTo(imageView.snp.bottom).offset(10)
|
||||
make.right.lessThanOrEqualToSuperview().offset(-10)
|
||||
}
|
||||
|
||||
textLabel.snp.makeConstraints { make in
|
||||
make.centerX.equalToSuperview()
|
||||
make.right.lessThanOrEqualToSuperview().offset(-20)
|
||||
make.top.equalTo(titleLabel.snp.bottom).offset(12)
|
||||
}
|
||||
|
||||
cancelButton.snp.makeConstraints { make in
|
||||
make.left.equalToSuperview().offset(24)
|
||||
make.top.equalTo(textLabel.snp.bottom).offset(21)
|
||||
make.bottom.equalTo(-20)
|
||||
make.height.equalTo(36)
|
||||
}
|
||||
|
||||
highlightButton.snp.makeConstraints { make in
|
||||
make.left.equalTo(cancelButton.snp.right).offset(11)
|
||||
make.right.equalToSuperview().offset(-24)
|
||||
make.width.height.top.equalTo(cancelButton)
|
||||
}
|
||||
}
|
||||
|
||||
@MainActor required init?(coder: NSCoder) {
|
||||
fatalError("init(coder:) has not been implemented")
|
||||
}
|
||||
}
|
||||
307
Fableon/Object/Libs/Alert/FAVipRetainAlert.swift
Normal file
@ -0,0 +1,307 @@
|
||||
//
|
||||
// FAVipRetainAlert.swift
|
||||
// Fableon
|
||||
//
|
||||
// Created by 湖北秦九 on 2025/10/30.
|
||||
//
|
||||
|
||||
import UIKit
|
||||
|
||||
class FAVipRetainAlert: FABaseAlert {
|
||||
|
||||
var buyFinishHandle: (() -> Void)?
|
||||
|
||||
var model: FAPayAlertModel? {
|
||||
didSet {
|
||||
let payItem = model?.info
|
||||
titleView.text = payItem?.getVipTitle()
|
||||
itemView.payItem = payItem
|
||||
}
|
||||
}
|
||||
|
||||
var videoInfo: FAVideoInfoModel?
|
||||
|
||||
|
||||
private lazy var titleView: FACoinPackTitleView = {
|
||||
let view = FACoinPackTitleView()
|
||||
view.dotColor = ._20_A_1_FF
|
||||
view.textColors = [UIColor._53_A_2_F_1.cgColor, UIColor.C_5_DDF_5.cgColor]
|
||||
view.font = .font(ofSize: 24, weight: .init(900))
|
||||
view.text = "Weekly Refill".localized.uppercased()
|
||||
return view
|
||||
}()
|
||||
|
||||
private lazy var itemView: ItemView = {
|
||||
let view = ItemView()
|
||||
return view
|
||||
}()
|
||||
|
||||
private lazy var textLabel: UILabel = {
|
||||
let label = UILabel()
|
||||
label.font = .font(ofSize: 18, weight: .bold).withBoldItalic()
|
||||
label.textColor = .C_5_DDF_5
|
||||
label.text = "vip_retain_alert_text".localized
|
||||
label.textAlignment = .center
|
||||
label.numberOfLines = 0
|
||||
return label
|
||||
}()
|
||||
|
||||
private lazy var buyButton: UIButton = {
|
||||
let button = FAGradientButton(type: .custom, primaryAction: UIAction(handler: { [weak self] _ in
|
||||
guard let self = self else { return }
|
||||
guard let payItem = self.model?.info else { return }
|
||||
FAIapManager.manager.start(model: payItem, shortPlayId: self.videoInfo?.short_play_id, videoId: self.videoInfo?.short_play_video_id) { [weak self] finish in
|
||||
guard let self = self else { return }
|
||||
if finish {
|
||||
FALogin.manager.requestUserInfo(completer: nil)
|
||||
self.dismiss()
|
||||
self.buyFinishHandle?()
|
||||
}
|
||||
}
|
||||
|
||||
}))
|
||||
button.layer.cornerRadius = 24
|
||||
button.layer.masksToBounds = true
|
||||
button.fa_colors = [UIColor._53_A_2_F_1.cgColor, UIColor.C_5_DDF_5.cgColor]
|
||||
button.fa_locations = [0, 1]
|
||||
button.fa_startPoint = .init(x: 0, y: 0.5)
|
||||
button.fa_endPoint = .init(x: 0.7, y: 0.5)
|
||||
button.setTitle("Buy Now".localized, for: .normal)
|
||||
button.setTitleColor(.FFFFFF, for: .normal)
|
||||
button.titleLabel?.font = .font(ofSize: 14, weight: .bold)
|
||||
return button
|
||||
}()
|
||||
|
||||
override init(frame: CGRect) {
|
||||
super.init(frame: frame)
|
||||
contentWidth = UIScreen.width - 55
|
||||
contentView.backgroundColor = .clear
|
||||
|
||||
fa_setupLayout()
|
||||
}
|
||||
|
||||
@MainActor required init?(coder: NSCoder) {
|
||||
fatalError("init(coder:) has not been implemented")
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
extension FAVipRetainAlert {
|
||||
|
||||
private func fa_setupLayout() {
|
||||
contentView.addSubview(titleView)
|
||||
contentView.addSubview(itemView)
|
||||
contentView.addSubview(textLabel)
|
||||
contentView.addSubview(buyButton)
|
||||
|
||||
titleView.snp.makeConstraints { make in
|
||||
make.top.equalToSuperview()
|
||||
make.centerX.equalToSuperview()
|
||||
}
|
||||
|
||||
itemView.snp.makeConstraints { make in
|
||||
make.left.right.equalToSuperview()
|
||||
make.top.equalTo(titleView.snp.bottom).offset(12)
|
||||
make.height.equalTo(84)
|
||||
}
|
||||
|
||||
textLabel.snp.makeConstraints { make in
|
||||
make.centerX.equalToSuperview()
|
||||
make.right.lessThanOrEqualToSuperview().offset(-10)
|
||||
make.top.equalTo(itemView.snp.bottom).offset(12)
|
||||
}
|
||||
|
||||
buyButton.snp.makeConstraints { make in
|
||||
make.left.equalToSuperview().offset(20)
|
||||
make.centerX.equalToSuperview()
|
||||
make.top.equalTo(textLabel.snp.bottom).offset(12)
|
||||
make.height.equalTo(48)
|
||||
make.bottom.equalToSuperview()
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
extension FAVipRetainAlert {
|
||||
|
||||
|
||||
|
||||
class ItemView: UIView {
|
||||
|
||||
var payItem: FAPayItem? {
|
||||
didSet {
|
||||
nameLabel.text = payItem?.getVipTitle()
|
||||
|
||||
button.setNeedsUpdateConfiguration()
|
||||
}
|
||||
}
|
||||
|
||||
private lazy var bgView: FAGradientView = {
|
||||
let view = FAGradientView()
|
||||
view.fa_colors = [UIColor._524_B_8_E.cgColor, UIColor._303265.cgColor]
|
||||
view.fa_locations = [0, 1]
|
||||
view.fa_startPoint = .init(x: 0, y: 0.5)
|
||||
view.fa_endPoint = .init(x: 1, y: 0.5)
|
||||
view.layer.cornerRadius = 12
|
||||
view.layer.masksToBounds = true
|
||||
view.layer.borderWidth = 1
|
||||
view.layer.borderColor = UIColor.E_5_E_5_E_5.cgColor
|
||||
return view
|
||||
}()
|
||||
|
||||
private lazy var bgIconImageView1: UIImageView = {
|
||||
let imageView = UIImageView(image: UIImage(named: "coin_attachment_01"))
|
||||
return imageView
|
||||
}()
|
||||
|
||||
private lazy var bgIconImageView2: UIImageView = {
|
||||
let imageView = UIImageView(image: UIImage(named: "coin_attachment_02"))
|
||||
return imageView
|
||||
}()
|
||||
private lazy var bgIconImageView3 = UIImageView(image: UIImage(named: "coin_attachment_04"))
|
||||
private lazy var bgIconImageView4 = UIImageView(image: UIImage(named: "coin_attachment_05"))
|
||||
|
||||
private lazy var vipIconImageView = UIImageView(image: UIImage(named: "皇冠-金"))
|
||||
|
||||
private lazy var nameLabel: UILabel = {
|
||||
let label = UILabel()
|
||||
label.font = .font(ofSize: 18, weight: .bold)
|
||||
label.textColor = .FFFFFF
|
||||
return label
|
||||
}()
|
||||
|
||||
private lazy var textLabel: UILabel = {
|
||||
let label = FALabel()
|
||||
label.textColors = [UIColor._53_A_2_F_1.cgColor, UIColor.C_5_DDF_5.cgColor]
|
||||
label.textStartPoint = .init(x: 0, y: 0.5)
|
||||
label.textEndPoint = .init(x: 0.7, y: 0.5)
|
||||
label.font = .font(ofSize: 12, weight: .regular)
|
||||
return label
|
||||
}()
|
||||
|
||||
private lazy var button: UIButton = {
|
||||
var config = UIButton.Configuration.plain()
|
||||
config.contentInsets = .init(top: 0, leading: 10, bottom: 0, trailing: 10)
|
||||
config.titleAlignment = .center
|
||||
|
||||
let button = FAGradientButton(configuration: config)
|
||||
button.isUserInteractionEnabled = false
|
||||
button.fa_colors = [UIColor._53_A_2_F_1.cgColor, UIColor.C_5_DDF_5.cgColor]
|
||||
button.fa_locations = [0, 1]
|
||||
button.fa_startPoint = .init(x: 0, y: 0.5)
|
||||
button.fa_endPoint = .init(x: 0.5, y: 0.5)
|
||||
button.layer.cornerRadius = 24
|
||||
button.layer.masksToBounds = true
|
||||
button.configurationUpdateHandler = { [weak self] button in
|
||||
guard let self = self else { return }
|
||||
|
||||
let currency = self.payItem?.currency ?? ""
|
||||
let timeString = self.payItem?.getTimeString() ?? ""
|
||||
let oldPrice = self.payItem?.price ?? ""
|
||||
var discountPrice: String? = nil
|
||||
|
||||
if self.payItem?.discount_type == 1, let introductoryPrice = self.payItem?.introductionaryOffer {
|
||||
discountPrice = introductoryPrice.price.stringValue
|
||||
} else if self.payItem?.discount_type == 2, let discount = self.payItem?.promotionalOffers?.first {
|
||||
discountPrice = discount.price.stringValue
|
||||
}
|
||||
|
||||
if let discountPrice = discountPrice {
|
||||
button.configuration?.attributedTitle = AttributedString("\(currency)\(discountPrice)", attributes: AttributeContainer([
|
||||
.font : UIFont.font(ofSize: 18, weight: .bold),
|
||||
.foregroundColor : UIColor._114_CEE
|
||||
]))
|
||||
|
||||
button.configuration?.attributedSubtitle = AttributedString("\(currency)\(oldPrice)", attributes: AttributeContainer([
|
||||
.font : UIFont.font(ofSize: 12, weight: .regular),
|
||||
.foregroundColor : UIColor._000000.withAlphaComponent(0.5),
|
||||
.strikethroughStyle: NSUnderlineStyle.single.rawValue,
|
||||
.strikethroughColor: UIColor._000000.withAlphaComponent(0.5)
|
||||
]))
|
||||
|
||||
} else {
|
||||
button.configuration?.attributedTitle = AttributedString("\(currency)\(oldPrice)", attributes: AttributeContainer([
|
||||
.font : UIFont.font(ofSize: 18, weight: .bold),
|
||||
.foregroundColor : UIColor._114_CEE
|
||||
]))
|
||||
|
||||
button.configuration?.attributedSubtitle = AttributedString("/\(timeString)", attributes: AttributeContainer([
|
||||
.font : UIFont.font(ofSize: 12, weight: .regular),
|
||||
.foregroundColor : UIColor._000000.withAlphaComponent(0.5)
|
||||
]))
|
||||
}
|
||||
|
||||
}
|
||||
return button
|
||||
}()
|
||||
|
||||
override init(frame: CGRect) {
|
||||
super.init(frame: frame)
|
||||
nameLabel.text = "Weekly VIP"
|
||||
textLabel.text = "Unlimited access to all series"
|
||||
|
||||
addSubview(bgView)
|
||||
bgView.addSubview(bgIconImageView4)
|
||||
bgView.addSubview(bgIconImageView3)
|
||||
bgView.addSubview(bgIconImageView1)
|
||||
bgView.addSubview(bgIconImageView2)
|
||||
bgView.addSubview(vipIconImageView)
|
||||
bgView.addSubview(nameLabel)
|
||||
bgView.addSubview(textLabel)
|
||||
bgView.addSubview(button)
|
||||
|
||||
bgView.snp.makeConstraints { make in
|
||||
make.edges.equalToSuperview()
|
||||
}
|
||||
|
||||
bgIconImageView1.snp.makeConstraints { make in
|
||||
make.left.equalToSuperview().offset(0)
|
||||
make.top.equalToSuperview().offset(0)
|
||||
}
|
||||
|
||||
bgIconImageView2.snp.makeConstraints { make in
|
||||
make.right.equalToSuperview().offset(-26)
|
||||
make.centerY.equalToSuperview()
|
||||
}
|
||||
|
||||
bgIconImageView3.snp.makeConstraints { make in
|
||||
make.centerY.equalToSuperview()
|
||||
make.centerX.equalTo(bgIconImageView2)
|
||||
}
|
||||
|
||||
bgIconImageView4.snp.makeConstraints { make in
|
||||
make.left.bottom.equalToSuperview()
|
||||
}
|
||||
|
||||
vipIconImageView.snp.makeConstraints { make in
|
||||
make.left.equalToSuperview().offset(16)
|
||||
make.top.equalToSuperview().offset(18)
|
||||
}
|
||||
|
||||
nameLabel.snp.makeConstraints { make in
|
||||
make.centerY.equalTo(vipIconImageView)
|
||||
make.left.equalTo(vipIconImageView.snp.right).offset(4)
|
||||
}
|
||||
|
||||
textLabel.snp.makeConstraints { make in
|
||||
make.left.equalTo(vipIconImageView)
|
||||
make.bottom.equalToSuperview().offset(-18)
|
||||
}
|
||||
|
||||
button.snp.makeConstraints { make in
|
||||
make.centerY.equalToSuperview()
|
||||
make.right.equalToSuperview().offset(-12)
|
||||
make.height.equalTo(48)
|
||||
make.width.greaterThanOrEqualTo(88)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@MainActor required init?(coder: NSCoder) {
|
||||
fatalError("init(coder:) has not been implemented")
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@ -83,25 +83,25 @@ class FAPayDataRequest: NSObject {
|
||||
}
|
||||
|
||||
///挽留信息
|
||||
func requestRetainVipPayInfo(completer: ((_ model: FAPayAlertModel?) -> Void)?) {
|
||||
func requestVipRetainPayInfo(completer: ((_ model: FAPayAlertModel?) -> Void)?) {
|
||||
self.completerBlock = nil
|
||||
self.payAlertBlock = completer
|
||||
|
||||
// FAStoreAPI.requestRetainVipPayInfo { [weak self] model in
|
||||
// guard let self = self else { return }
|
||||
// guard let model = model else {
|
||||
// self.payAlertBlock?(nil)
|
||||
// return
|
||||
// }
|
||||
// self.payAlertModel = model
|
||||
//
|
||||
// let productId = BRIAP.manager.getProductId(templateId: model.info?.ios_template_id) ?? ""
|
||||
//
|
||||
// let set = Set([productId])
|
||||
// let productsRequest = SKProductsRequest(productIdentifiers: set)
|
||||
// productsRequest.delegate = self
|
||||
// productsRequest.start()
|
||||
// }
|
||||
FAStoreAPI.requestVipRetainPayInfo { [weak self] model in
|
||||
guard let self = self else { return }
|
||||
guard let model = model else {
|
||||
self.payAlertBlock?(nil)
|
||||
return
|
||||
}
|
||||
self.payAlertModel = model
|
||||
|
||||
let productId = FAIapManager.manager.getProductId(templateId: model.info?.ios_template_id) ?? ""
|
||||
|
||||
let set = Set([productId])
|
||||
let productsRequest = SKProductsRequest(productIdentifiers: set)
|
||||
productsRequest.delegate = self
|
||||
productsRequest.start()
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
115
Fableon/Object/Libs/FALogin/FALogin+Apple.swift
Normal file
@ -0,0 +1,115 @@
|
||||
//
|
||||
// FALogin+Apple.swift
|
||||
// Fableon
|
||||
//
|
||||
// Created by 湖北秦九 on 2025/10/30.
|
||||
//
|
||||
|
||||
import UIKit
|
||||
import AuthenticationServices
|
||||
|
||||
extension FALogin {
|
||||
|
||||
private struct AssociatedKeys {
|
||||
static var appleLoginHandle: Int?
|
||||
}
|
||||
|
||||
private var appleLoginHandle: ((_ model: FAThirdSignModel?) -> Void)? {
|
||||
set {
|
||||
objc_setAssociatedObject(self, &AssociatedKeys.appleLoginHandle, newValue, .OBJC_ASSOCIATION_COPY_NONATOMIC)
|
||||
}
|
||||
get {
|
||||
return objc_getAssociatedObject(self, &AssociatedKeys.appleLoginHandle) as? ((_ model: FAThirdSignModel?) -> Void)
|
||||
}
|
||||
}
|
||||
|
||||
func appleLogin(completer: ((_ model: FAThirdSignModel?) -> Void)?) {
|
||||
self.appleLoginHandle = completer
|
||||
|
||||
let appleIDProvider = ASAuthorizationAppleIDProvider()
|
||||
let request = appleIDProvider.createRequest()
|
||||
request.requestedScopes = [.fullName, .email]
|
||||
|
||||
let authorizationController = ASAuthorizationController(authorizationRequests: [request])
|
||||
authorizationController.delegate = self
|
||||
authorizationController.presentationContextProvider = self
|
||||
authorizationController.performRequests()
|
||||
}
|
||||
|
||||
private func jwtDecode(jwtStr: String) -> [String: Any]? {
|
||||
let segments = jwtStr.components(separatedBy: ".")
|
||||
guard segments.count > 1 else { return nil }
|
||||
|
||||
var base64String = segments[1]
|
||||
|
||||
// 处理 Base64 补齐
|
||||
let requiredLength = 4 * Int(ceil(Double(base64String.count) / 4.0))
|
||||
let paddingLength = requiredLength - base64String.count
|
||||
if paddingLength > 0 {
|
||||
base64String += String(repeating: "=", count: paddingLength)
|
||||
}
|
||||
|
||||
// 替换 URL 安全字符
|
||||
base64String = base64String.replacingOccurrences(of: "-", with: "+")
|
||||
base64String = base64String.replacingOccurrences(of: "_", with: "/")
|
||||
|
||||
// 解码 Base64 数据
|
||||
guard let data = Data(base64Encoded: base64String),
|
||||
let jsonObject = try? JSONSerialization.jsonObject(with: data, options: []),
|
||||
let payload = jsonObject as? [String: Any] else {
|
||||
return nil
|
||||
}
|
||||
|
||||
return payload
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
//MARK: ASAuthorizationControllerDelegate
|
||||
extension FALogin: ASAuthorizationControllerDelegate {
|
||||
|
||||
func authorizationController(controller: ASAuthorizationController, didCompleteWithAuthorization authorization: ASAuthorization) {
|
||||
if let appleIDCredential = authorization.credential as? ASAuthorizationAppleIDCredential {
|
||||
|
||||
let userIdentifier = appleIDCredential.user
|
||||
let fullName = appleIDCredential.fullName
|
||||
let email = appleIDCredential.email
|
||||
|
||||
let identityToken = appleIDCredential.identityToken.flatMap { String(data: $0, encoding: .utf8) }
|
||||
let identityTokenParams = self.jwtDecode(jwtStr: identityToken ?? "")
|
||||
|
||||
|
||||
var model = FAThirdSignModel()
|
||||
model.platform = .apple
|
||||
model.third_id = userIdentifier
|
||||
model.giving_name = fullName?.givenName
|
||||
model.family_name = fullName?.familyName
|
||||
model.avator = identityTokenParams?["picture"] as? String
|
||||
model.email = identityTokenParams?["email"] as? String
|
||||
|
||||
|
||||
debugLog(userIdentifier)
|
||||
debugLog(fullName)
|
||||
debugLog(email)
|
||||
|
||||
appleLoginHandle?(model)
|
||||
appleLoginHandle = nil
|
||||
}
|
||||
}
|
||||
|
||||
func authorizationController(controller: ASAuthorizationController, didCompleteWithError error: Error) {
|
||||
appleLoginHandle?(nil)
|
||||
appleLoginHandle = nil
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
//MARK: ASAuthorizationControllerPresentationContextProviding
|
||||
extension FALogin: ASAuthorizationControllerPresentationContextProviding {
|
||||
|
||||
func presentationAnchor(for controller: ASAuthorizationController) -> ASPresentationAnchor {
|
||||
return FATool.keyWindow!
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
58
Fableon/Object/Libs/FALogin/FALogin+Facebook.swift
Normal file
@ -0,0 +1,58 @@
|
||||
//
|
||||
// FALogin+Facebook.swift
|
||||
// Fableon
|
||||
//
|
||||
// Created by 湖北秦九 on 2025/10/30.
|
||||
//
|
||||
import UIKit
|
||||
import FacebookLogin
|
||||
|
||||
extension FALogin {
|
||||
|
||||
func facebookLogin(presentingViewController: UIViewController?, completer: ((_ model: FAThirdSignModel?) -> Void)?) {
|
||||
|
||||
let loginManager = LoginManager()
|
||||
loginManager.logOut()
|
||||
loginManager.defaultAudience = .everyone
|
||||
|
||||
loginManager.logIn(permissions: ["public_profile", "email"], from: presentingViewController) { result, error in
|
||||
guard error == nil, let result = result else {
|
||||
completer?(nil)
|
||||
return
|
||||
}
|
||||
if result.isCancelled {
|
||||
completer?(nil)
|
||||
return
|
||||
}
|
||||
let request = GraphRequest(graphPath: "me", parameters: ["fields" : "id,name,email,picture"], httpMethod: .get)
|
||||
request.start { connection, result, error in
|
||||
guard let result = result as? [String : Any] else {
|
||||
completer?(nil)
|
||||
return
|
||||
}
|
||||
var model = FAThirdSignModel()
|
||||
model.platform = .faceBook
|
||||
model.third_id = result["id"] as? String
|
||||
model.email = result["email"] as? String
|
||||
|
||||
if let picture = result["picture"] as? [String : Any],
|
||||
let data = picture["data"] as? [String : Any],
|
||||
let url = data["url"] as? String
|
||||
{
|
||||
model.avator = url
|
||||
}
|
||||
|
||||
if let name = result["name"] as? String {
|
||||
model.family_name = name
|
||||
} else {
|
||||
model.family_name = result["first_name"] as? String
|
||||
model.giving_name = result["last_name"] as? String
|
||||
}
|
||||
completer?(model)
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@ -6,16 +6,28 @@
|
||||
//
|
||||
|
||||
import UIKit
|
||||
import SmartCodable
|
||||
|
||||
let kFAUserTokenDefaultsKey = "kFAUserTokenDefaultsKey"
|
||||
let kFAUserInfoDefaultsKey = "kFAUserInfoDefaultsKey"
|
||||
|
||||
class FALogin: NSObject {
|
||||
|
||||
enum LoginType: String, SmartCaseDefaultable {
|
||||
case apple = "Apple"
|
||||
case faceBook = "Facebook"
|
||||
case google = "Google"
|
||||
case tiktok = "Tiktok"
|
||||
}
|
||||
|
||||
static let manager = FALogin()
|
||||
|
||||
private(set) var token = UserDefaults.fa_object(forKey: kFAUserTokenDefaultsKey, as: FATokenModel.self)
|
||||
private(set) var userInfo = UserDefaults.fa_object(forKey: kFAUserInfoDefaultsKey, as: FAUserInfo.self)
|
||||
|
||||
var isLogin: Bool {
|
||||
return !(userInfo?.is_tourist ?? true)
|
||||
}
|
||||
|
||||
private func setToken(_ token: FATokenModel?) {
|
||||
self.token = token
|
||||
@ -27,6 +39,67 @@ class FALogin: NSObject {
|
||||
UserDefaults.fa_setObject(userInfo, forKey: kFAUserInfoDefaultsKey)
|
||||
}
|
||||
|
||||
///第三方登录
|
||||
func thirdLogin(type: LoginType, presentingViewController: UIViewController?, completer: ((_ isFinish: Bool) -> Void)?) {
|
||||
switch type {
|
||||
case .apple:
|
||||
appleLogin { [weak self] model in
|
||||
self?.requestSignThirdLogin(thirdSignModel: model, completer: completer)
|
||||
}
|
||||
|
||||
case .faceBook:
|
||||
facebookLogin(presentingViewController: presentingViewController) { [weak self] model in
|
||||
self?.requestSignThirdLogin(thirdSignModel: model, completer: completer)
|
||||
}
|
||||
|
||||
default:
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
///后台验证三方登录
|
||||
private func requestSignThirdLogin(thirdSignModel: FAThirdSignModel?, completer: ((_ isFinish: Bool) -> Void)?) {
|
||||
guard let thirdSignModel = thirdSignModel else {
|
||||
completer?(false)
|
||||
return
|
||||
}
|
||||
FAStatAPI.requestLeaveApp()
|
||||
FAAPI.requestSignThirdLogin(model: thirdSignModel) { [weak self] token in
|
||||
guard let self = self else { return }
|
||||
guard let token = token else {
|
||||
completer?(false)
|
||||
return
|
||||
}
|
||||
self.setToken(token)
|
||||
self.userInfo?.is_tourist = false
|
||||
self.requestUserInfo(completer: nil)
|
||||
FAStatAPI.requestEnterApp()
|
||||
FAStatAPI.requestStatOnLine()
|
||||
completer?(true)
|
||||
NotificationCenter.default.post(name: FALogin.userInfoUpdateNotification, object: nil)
|
||||
}
|
||||
}
|
||||
|
||||
func logout(completer: ((_ isFinish: Bool) -> Void)?) {
|
||||
FAStatAPI.requestLeaveApp()
|
||||
|
||||
FAAPI.requestLogout { [weak self] token in
|
||||
guard let self = self else { return }
|
||||
if let token = token {
|
||||
self.setToken(token)
|
||||
self.userInfo?.is_tourist = true
|
||||
self.requestUserInfo(completer: nil)
|
||||
FAStatAPI.requestEnterApp()
|
||||
FAStatAPI.requestStatOnLine()
|
||||
completer?(true)
|
||||
NotificationCenter.default.post(name: FALogin.userInfoUpdateNotification, object: nil)
|
||||
} else {
|
||||
completer?(false)
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
extension FALogin {
|
||||
|
||||
23
Fableon/Object/Libs/FALogin/FAThirdSignModel.swift
Normal file
@ -0,0 +1,23 @@
|
||||
//
|
||||
// FAThirdSignModel.swift
|
||||
// Fableon
|
||||
//
|
||||
// Created by 湖北秦九 on 2025/10/30.
|
||||
//
|
||||
|
||||
import UIKit
|
||||
import SmartCodable
|
||||
|
||||
struct FAThirdSignModel: SmartCodable {
|
||||
|
||||
var third_id: String?
|
||||
var email: String?
|
||||
//姓
|
||||
var family_name: String?
|
||||
//名
|
||||
var giving_name: String?
|
||||
|
||||
var avator: String?
|
||||
|
||||
var platform: FALogin.LoginType?
|
||||
}
|
||||
@ -6,6 +6,8 @@
|
||||
//
|
||||
import Foundation
|
||||
import UIKit
|
||||
import AppTrackingTransparency
|
||||
import AdSupport
|
||||
|
||||
#if DEBUG
|
||||
func debugLog(_ msg: Any, file: String = #file, function: String = #function, line: Int = #line) {
|
||||
@ -18,6 +20,8 @@ func debugLog(_ msg: Any) { }
|
||||
|
||||
class FATool {
|
||||
|
||||
static var sceneDelegate: SceneDelegate?
|
||||
|
||||
static var windowScene: UIWindowScene?
|
||||
|
||||
static var keyWindow: UIWindow? {
|
||||
@ -52,3 +56,38 @@ class FATool {
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
extension FATool {
|
||||
|
||||
static func requestIDFAAuthorization(_ completion: ((String?) -> Void)? = nil) {
|
||||
if FAAdjustStateManager.manager.idfaAuthorizationFinish {
|
||||
completion?(ASIdentifierManager.shared().advertisingIdentifier.uuidString)
|
||||
return
|
||||
}
|
||||
guard FANetworkMonitor.manager.isReachable == true, FAAdjustStateManager.manager.apnsAuthorizationFinish, FAAdjustStateManager.manager.isOpenApp else {
|
||||
return
|
||||
}
|
||||
|
||||
DispatchQueue.main.asyncAfter(deadline: .now() + 0.5) {
|
||||
ATTrackingManager.requestTrackingAuthorization { status in
|
||||
FAAdjustStateManager.manager.idfaAuthorizationFinish = true
|
||||
let idfa = ASIdentifierManager.shared().advertisingIdentifier.uuidString
|
||||
FATool.sceneDelegate?.retryHandleOpenAppMessage()
|
||||
completion?(idfa)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
///打开消息通知设置页面
|
||||
static func openApnsSetting() {
|
||||
if #available(iOS 16.0, *) {
|
||||
if let url = URL(string: UIApplication.openNotificationSettingsURLString) {
|
||||
UIApplication.shared.open(url)
|
||||
}
|
||||
} else {
|
||||
if let url = URL(string: UIApplication.openSettingsURLString) {
|
||||
UIApplication.shared.open(url)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -0,0 +1,20 @@
|
||||
{
|
||||
"colors" : [
|
||||
{
|
||||
"color" : {
|
||||
"color-space" : "srgb",
|
||||
"components" : {
|
||||
"alpha" : "1.000",
|
||||
"blue" : "0x40",
|
||||
"green" : "0x40",
|
||||
"red" : "0x40"
|
||||
}
|
||||
},
|
||||
"idiom" : "universal"
|
||||
}
|
||||
],
|
||||
"info" : {
|
||||
"author" : "xcode",
|
||||
"version" : 1
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,20 @@
|
||||
{
|
||||
"colors" : [
|
||||
{
|
||||
"color" : {
|
||||
"color-space" : "srgb",
|
||||
"components" : {
|
||||
"alpha" : "1.000",
|
||||
"blue" : "0xFA",
|
||||
"green" : "0x9D",
|
||||
"red" : "0x62"
|
||||
}
|
||||
},
|
||||
"idiom" : "universal"
|
||||
}
|
||||
],
|
||||
"info" : {
|
||||
"author" : "xcode",
|
||||
"version" : 1
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,20 @@
|
||||
{
|
||||
"colors" : [
|
||||
{
|
||||
"color" : {
|
||||
"color-space" : "srgb",
|
||||
"components" : {
|
||||
"alpha" : "1.000",
|
||||
"blue" : "0x6D",
|
||||
"green" : "0x6D",
|
||||
"red" : "0x6D"
|
||||
}
|
||||
},
|
||||
"idiom" : "universal"
|
||||
}
|
||||
],
|
||||
"info" : {
|
||||
"author" : "xcode",
|
||||
"version" : 1
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,20 @@
|
||||
{
|
||||
"colors" : [
|
||||
{
|
||||
"color" : {
|
||||
"color-space" : "srgb",
|
||||
"components" : {
|
||||
"alpha" : "1.000",
|
||||
"blue" : "0xBC",
|
||||
"green" : "0xBC",
|
||||
"red" : "0xBC"
|
||||
}
|
||||
},
|
||||
"idiom" : "universal"
|
||||
}
|
||||
],
|
||||
"info" : {
|
||||
"author" : "xcode",
|
||||
"version" : 1
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,20 @@
|
||||
{
|
||||
"colors" : [
|
||||
{
|
||||
"color" : {
|
||||
"color-space" : "srgb",
|
||||
"components" : {
|
||||
"alpha" : "1.000",
|
||||
"blue" : "0xFF",
|
||||
"green" : "0xEF",
|
||||
"red" : "0xDF"
|
||||
}
|
||||
},
|
||||
"idiom" : "universal"
|
||||
}
|
||||
],
|
||||
"info" : {
|
||||
"author" : "xcode",
|
||||
"version" : 1
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,20 @@
|
||||
{
|
||||
"colors" : [
|
||||
{
|
||||
"color" : {
|
||||
"color-space" : "srgb",
|
||||
"components" : {
|
||||
"alpha" : "1.000",
|
||||
"blue" : "0x87",
|
||||
"green" : "0xCF",
|
||||
"red" : "0xF6"
|
||||
}
|
||||
},
|
||||
"idiom" : "universal"
|
||||
}
|
||||
],
|
||||
"info" : {
|
||||
"author" : "xcode",
|
||||
"version" : 1
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,20 @@
|
||||
{
|
||||
"colors" : [
|
||||
{
|
||||
"color" : {
|
||||
"color-space" : "srgb",
|
||||
"components" : {
|
||||
"alpha" : "1.000",
|
||||
"blue" : "0xE9",
|
||||
"green" : "0xFE",
|
||||
"red" : "0xFF"
|
||||
}
|
||||
},
|
||||
"idiom" : "universal"
|
||||
}
|
||||
],
|
||||
"info" : {
|
||||
"author" : "xcode",
|
||||
"version" : 1
|
||||
}
|
||||
}
|
||||
22
Fableon/Source/Assets.xcassets/image/Group 2072750470.imageset/Contents.json
vendored
Normal file
@ -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
|
||||
}
|
||||
}
|
||||
BIN
Fableon/Source/Assets.xcassets/image/Group 2072750470.imageset/浮窗@2x.png
vendored
Normal file
|
After Width: | Height: | Size: 31 KiB |
BIN
Fableon/Source/Assets.xcassets/image/Group 2072750470.imageset/浮窗@3x.png
vendored
Normal file
|
After Width: | Height: | Size: 61 KiB |
22
Fableon/Source/Assets.xcassets/image/__magnifying.imageset/Contents.json
vendored
Normal file
@ -0,0 +1,22 @@
|
||||
{
|
||||
"images" : [
|
||||
{
|
||||
"idiom" : "universal",
|
||||
"scale" : "1x"
|
||||
},
|
||||
{
|
||||
"filename" : "__magnifying@2x.png",
|
||||
"idiom" : "universal",
|
||||
"scale" : "2x"
|
||||
},
|
||||
{
|
||||
"filename" : "__magnifying@3x.png",
|
||||
"idiom" : "universal",
|
||||
"scale" : "3x"
|
||||
}
|
||||
],
|
||||
"info" : {
|
||||
"author" : "xcode",
|
||||
"version" : 1
|
||||
}
|
||||
}
|
||||
BIN
Fableon/Source/Assets.xcassets/image/__magnifying.imageset/__magnifying@2x.png
vendored
Normal file
|
After Width: | Height: | Size: 39 KiB |
BIN
Fableon/Source/Assets.xcassets/image/__magnifying.imageset/__magnifying@3x.png
vendored
Normal file
|
After Width: | Height: | Size: 63 KiB |
22
Fableon/Source/Assets.xcassets/image/alert_image_01.imageset/Contents.json
vendored
Normal file
@ -0,0 +1,22 @@
|
||||
{
|
||||
"images" : [
|
||||
{
|
||||
"idiom" : "universal",
|
||||
"scale" : "1x"
|
||||
},
|
||||
{
|
||||
"filename" : "__to remove 1@2x.png",
|
||||
"idiom" : "universal",
|
||||
"scale" : "2x"
|
||||
},
|
||||
{
|
||||
"filename" : "__to remove 1@3x.png",
|
||||
"idiom" : "universal",
|
||||
"scale" : "3x"
|
||||
}
|
||||
],
|
||||
"info" : {
|
||||
"author" : "xcode",
|
||||
"version" : 1
|
||||
}
|
||||
}
|
||||
BIN
Fableon/Source/Assets.xcassets/image/alert_image_01.imageset/__to remove 1@2x.png
vendored
Normal file
|
After Width: | Height: | Size: 28 KiB |
BIN
Fableon/Source/Assets.xcassets/image/alert_image_01.imageset/__to remove 1@3x.png
vendored
Normal file
|
After Width: | Height: | Size: 45 KiB |
22
Fableon/Source/Assets.xcassets/image/apple_logo_icon_01.imageset/Contents.json
vendored
Normal file
@ -0,0 +1,22 @@
|
||||
{
|
||||
"images" : [
|
||||
{
|
||||
"idiom" : "universal",
|
||||
"scale" : "1x"
|
||||
},
|
||||
{
|
||||
"filename" : "Vector@2x.png",
|
||||
"idiom" : "universal",
|
||||
"scale" : "2x"
|
||||
},
|
||||
{
|
||||
"filename" : "Vector@3x.png",
|
||||
"idiom" : "universal",
|
||||
"scale" : "3x"
|
||||
}
|
||||
],
|
||||
"info" : {
|
||||
"author" : "xcode",
|
||||
"version" : 1
|
||||
}
|
||||
}
|
||||
BIN
Fableon/Source/Assets.xcassets/image/apple_logo_icon_01.imageset/Vector@2x.png
vendored
Normal file
|
After Width: | Height: | Size: 696 B |
BIN
Fableon/Source/Assets.xcassets/image/apple_logo_icon_01.imageset/Vector@3x.png
vendored
Normal file
|
After Width: | Height: | Size: 994 B |
22
Fableon/Source/Assets.xcassets/image/arrow.imageset/Contents.json
vendored
Normal file
@ -0,0 +1,22 @@
|
||||
{
|
||||
"images" : [
|
||||
{
|
||||
"idiom" : "universal",
|
||||
"scale" : "1x"
|
||||
},
|
||||
{
|
||||
"filename" : "arrow@2x.png",
|
||||
"idiom" : "universal",
|
||||
"scale" : "2x"
|
||||
},
|
||||
{
|
||||
"filename" : "arrow@3x.png",
|
||||
"idiom" : "universal",
|
||||
"scale" : "3x"
|
||||
}
|
||||
],
|
||||
"info" : {
|
||||
"author" : "xcode",
|
||||
"version" : 1
|
||||
}
|
||||
}
|
||||
BIN
Fableon/Source/Assets.xcassets/image/arrow.imageset/arrow@2x.png
vendored
Normal file
|
After Width: | Height: | Size: 399 B |
BIN
Fableon/Source/Assets.xcassets/image/arrow.imageset/arrow@3x.png
vendored
Normal file
|
After Width: | Height: | Size: 537 B |
22
Fableon/Source/Assets.xcassets/image/close_icon_03.imageset/Contents.json
vendored
Normal file
@ -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
|
||||
}
|
||||
}
|
||||
BIN
Fableon/Source/Assets.xcassets/image/close_icon_03.imageset/关闭按钮@2x.png
vendored
Normal file
|
After Width: | Height: | Size: 1.3 KiB |
BIN
Fableon/Source/Assets.xcassets/image/close_icon_03.imageset/关闭按钮@3x.png
vendored
Normal file
|
After Width: | Height: | Size: 1.9 KiB |
|
After Width: | Height: | Size: 45 KiB |
|
After Width: | Height: | Size: 88 KiB |
22
Fableon/Source/Assets.xcassets/image/coin_attachment_03.imageset/Contents.json
vendored
Normal file
@ -0,0 +1,22 @@
|
||||
{
|
||||
"images" : [
|
||||
{
|
||||
"idiom" : "universal",
|
||||
"scale" : "1x"
|
||||
},
|
||||
{
|
||||
"filename" : "90ad09d41707261a78f7b0c4f06813390209096846c76-uqCzGu_fw240webp 1@2x.png",
|
||||
"idiom" : "universal",
|
||||
"scale" : "2x"
|
||||
},
|
||||
{
|
||||
"filename" : "90ad09d41707261a78f7b0c4f06813390209096846c76-uqCzGu_fw240webp 1@3x.png",
|
||||
"idiom" : "universal",
|
||||
"scale" : "3x"
|
||||
}
|
||||
],
|
||||
"info" : {
|
||||
"author" : "xcode",
|
||||
"version" : 1
|
||||
}
|
||||
}
|
||||
22
Fableon/Source/Assets.xcassets/image/coin_attachment_04.imageset/Contents.json
vendored
Normal file
@ -0,0 +1,22 @@
|
||||
{
|
||||
"images" : [
|
||||
{
|
||||
"idiom" : "universal",
|
||||
"scale" : "1x"
|
||||
},
|
||||
{
|
||||
"filename" : "Ellipse 2325@2x.png",
|
||||
"idiom" : "universal",
|
||||
"scale" : "2x"
|
||||
},
|
||||
{
|
||||
"filename" : "Ellipse 2325@3x.png",
|
||||
"idiom" : "universal",
|
||||
"scale" : "3x"
|
||||
}
|
||||
],
|
||||
"info" : {
|
||||
"author" : "xcode",
|
||||
"version" : 1
|
||||
}
|
||||
}
|
||||
BIN
Fableon/Source/Assets.xcassets/image/coin_attachment_04.imageset/Ellipse 2325@2x.png
vendored
Normal file
|
After Width: | Height: | Size: 166 KiB |
BIN
Fableon/Source/Assets.xcassets/image/coin_attachment_04.imageset/Ellipse 2325@3x.png
vendored
Normal file
|
After Width: | Height: | Size: 344 KiB |
22
Fableon/Source/Assets.xcassets/image/coin_attachment_05.imageset/Contents.json
vendored
Normal file
@ -0,0 +1,22 @@
|
||||
{
|
||||
"images" : [
|
||||
{
|
||||
"idiom" : "universal",
|
||||
"scale" : "1x"
|
||||
},
|
||||
{
|
||||
"filename" : "Ellipse 2326@2x.png",
|
||||
"idiom" : "universal",
|
||||
"scale" : "2x"
|
||||
},
|
||||
{
|
||||
"filename" : "Ellipse 2326@3x.png",
|
||||
"idiom" : "universal",
|
||||
"scale" : "3x"
|
||||
}
|
||||
],
|
||||
"info" : {
|
||||
"author" : "xcode",
|
||||
"version" : 1
|
||||
}
|
||||
}
|
||||
BIN
Fableon/Source/Assets.xcassets/image/coin_attachment_05.imageset/Ellipse 2326@2x.png
vendored
Normal file
|
After Width: | Height: | Size: 122 KiB |
BIN
Fableon/Source/Assets.xcassets/image/coin_attachment_05.imageset/Ellipse 2326@3x.png
vendored
Normal file
|
After Width: | Height: | Size: 263 KiB |
22
Fableon/Source/Assets.xcassets/image/coins_icon_09.imageset/Contents.json
vendored
Normal file
@ -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
|
||||
}
|
||||
}
|
||||
BIN
Fableon/Source/Assets.xcassets/image/coins_icon_09.imageset/金币@2x.png
vendored
Normal file
|
After Width: | Height: | Size: 3.3 KiB |
BIN
Fableon/Source/Assets.xcassets/image/coins_icon_09.imageset/金币@3x.png
vendored
Normal file
|
After Width: | Height: | Size: 6.5 KiB |
22
Fableon/Source/Assets.xcassets/image/coins_icon_10.imageset/Contents.json
vendored
Normal file
@ -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
|
||||
}
|
||||
}
|
||||
BIN
Fableon/Source/Assets.xcassets/image/coins_icon_10.imageset/金币@2x.png
vendored
Normal file
|
After Width: | Height: | Size: 5.3 KiB |
BIN
Fableon/Source/Assets.xcassets/image/coins_icon_10.imageset/金币@3x.png
vendored
Normal file
|
After Width: | Height: | Size: 11 KiB |
22
Fableon/Source/Assets.xcassets/image/facebook_logo_icon_01.imageset/Contents.json
vendored
Normal file
@ -0,0 +1,22 @@
|
||||
{
|
||||
"images" : [
|
||||
{
|
||||
"idiom" : "universal",
|
||||
"scale" : "1x"
|
||||
},
|
||||
{
|
||||
"filename" : "Vector@2x 2.png",
|
||||
"idiom" : "universal",
|
||||
"scale" : "2x"
|
||||
},
|
||||
{
|
||||
"filename" : "Vector@3x 2.png",
|
||||
"idiom" : "universal",
|
||||
"scale" : "3x"
|
||||
}
|
||||
],
|
||||
"info" : {
|
||||
"author" : "xcode",
|
||||
"version" : 1
|
||||
}
|
||||
}
|
||||
BIN
Fableon/Source/Assets.xcassets/image/facebook_logo_icon_01.imageset/Vector@2x 2.png
vendored
Normal file
|
After Width: | Height: | Size: 804 B |
BIN
Fableon/Source/Assets.xcassets/image/facebook_logo_icon_01.imageset/Vector@3x 2.png
vendored
Normal file
|
After Width: | Height: | Size: 1.1 KiB |
22
Fableon/Source/Assets.xcassets/image/logo_image_02.imageset/Contents.json
vendored
Normal file
@ -0,0 +1,22 @@
|
||||
{
|
||||
"images" : [
|
||||
{
|
||||
"idiom" : "universal",
|
||||
"scale" : "1x"
|
||||
},
|
||||
{
|
||||
"filename" : "Group 2414@2x.png",
|
||||
"idiom" : "universal",
|
||||
"scale" : "2x"
|
||||
},
|
||||
{
|
||||
"filename" : "Group 2414@3x.png",
|
||||
"idiom" : "universal",
|
||||
"scale" : "3x"
|
||||
}
|
||||
],
|
||||
"info" : {
|
||||
"author" : "xcode",
|
||||
"version" : 1
|
||||
}
|
||||
}
|
||||
BIN
Fableon/Source/Assets.xcassets/image/logo_image_02.imageset/Group 2414@2x.png
vendored
Normal file
|
After Width: | Height: | Size: 13 KiB |
BIN
Fableon/Source/Assets.xcassets/image/logo_image_02.imageset/Group 2414@3x.png
vendored
Normal file
|
After Width: | Height: | Size: 24 KiB |
22
Fableon/Source/Assets.xcassets/image/按钮.imageset/Contents.json
vendored
Normal file
@ -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
|
||||
}
|
||||
}
|
||||