多语言开发完成
@ -209,7 +209,7 @@
|
|||||||
03E23AB42EAA1A7F004A8CEC /* FAPagerViewTransformer.swift in Sources */ = {isa = PBXBuildFile; fileRef = 03E23AA42EAA1A7F004A8CEC /* FAPagerViewTransformer.swift */; };
|
03E23AB42EAA1A7F004A8CEC /* FAPagerViewTransformer.swift in Sources */ = {isa = PBXBuildFile; fileRef = 03E23AA42EAA1A7F004A8CEC /* FAPagerViewTransformer.swift */; };
|
||||||
03E23AB52EAA1A7F004A8CEC /* FAToast.swift in Sources */ = {isa = PBXBuildFile; fileRef = 03E23AA82EAA1A7F004A8CEC /* FAToast.swift */; };
|
03E23AB52EAA1A7F004A8CEC /* FAToast.swift in Sources */ = {isa = PBXBuildFile; fileRef = 03E23AA82EAA1A7F004A8CEC /* FAToast.swift */; };
|
||||||
03E23AB62EAA1A7F004A8CEC /* FAUserInfo.swift in Sources */ = {isa = PBXBuildFile; fileRef = 03E23AA02EAA1A7F004A8CEC /* FAUserInfo.swift */; };
|
03E23AB62EAA1A7F004A8CEC /* FAUserInfo.swift in Sources */ = {isa = PBXBuildFile; fileRef = 03E23AA02EAA1A7F004A8CEC /* FAUserInfo.swift */; };
|
||||||
03E23AB72EAA1A7F004A8CEC /* FALocalized.swift in Sources */ = {isa = PBXBuildFile; fileRef = 03E23A9C2EAA1A7F004A8CEC /* FALocalized.swift */; };
|
03E23AB72EAA1A7F004A8CEC /* FALanguageManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = 03E23A9C2EAA1A7F004A8CEC /* FALanguageManager.swift */; };
|
||||||
03E23AB82EAA1A7F004A8CEC /* FAWaterfallFlowLayout.swift in Sources */ = {isa = PBXBuildFile; fileRef = 03E23AAA2EAA1A7F004A8CEC /* FAWaterfallFlowLayout.swift */; };
|
03E23AB82EAA1A7F004A8CEC /* FAWaterfallFlowLayout.swift in Sources */ = {isa = PBXBuildFile; fileRef = 03E23AAA2EAA1A7F004A8CEC /* FAWaterfallFlowLayout.swift */; };
|
||||||
03E23ABA2EAA1D85004A8CEC /* MNNItemController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 03E23AB92EAA1D85004A8CEC /* MNNItemController.swift */; };
|
03E23ABA2EAA1D85004A8CEC /* MNNItemController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 03E23AB92EAA1D85004A8CEC /* MNNItemController.swift */; };
|
||||||
03E9A7362EB44F26000D1067 /* FirebaseMessaging in Frameworks */ = {isa = PBXBuildFile; productRef = 03E9A7352EB44F26000D1067 /* FirebaseMessaging */; };
|
03E9A7362EB44F26000D1067 /* FirebaseMessaging in Frameworks */ = {isa = PBXBuildFile; productRef = 03E9A7352EB44F26000D1067 /* FirebaseMessaging */; };
|
||||||
@ -217,6 +217,16 @@
|
|||||||
03E9A73A2EB45154000D1067 /* AppDelegate+FAApns.swift in Sources */ = {isa = PBXBuildFile; fileRef = 03E9A7392EB45149000D1067 /* AppDelegate+FAApns.swift */; };
|
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 */; };
|
03E9A73C2EB45507000D1067 /* GoogleService-Info.plist in Resources */ = {isa = PBXBuildFile; fileRef = 03E9A73B2EB45507000D1067 /* GoogleService-Info.plist */; };
|
||||||
03E9A73E2EB460F2000D1067 /* FAApnsAlert.swift in Sources */ = {isa = PBXBuildFile; fileRef = 03E9A73D2EB460F2000D1067 /* FAApnsAlert.swift */; };
|
03E9A73E2EB460F2000D1067 /* FAApnsAlert.swift in Sources */ = {isa = PBXBuildFile; fileRef = 03E9A73D2EB460F2000D1067 /* FAApnsAlert.swift */; };
|
||||||
|
03E9A7402EB49BE6000D1067 /* FAUpdatesAlert.swift in Sources */ = {isa = PBXBuildFile; fileRef = 03E9A73F2EB49BE6000D1067 /* FAUpdatesAlert.swift */; };
|
||||||
|
03E9A7422EB4A603000D1067 /* FAVersionUpdateModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 03E9A7412EB4A603000D1067 /* FAVersionUpdateModel.swift */; };
|
||||||
|
03E9A7442EB4B80B000D1067 /* FADetailRecommendView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 03E9A7432EB4B80B000D1067 /* FADetailRecommendView.swift */; };
|
||||||
|
03E9A7462EB5ACE5000D1067 /* FADetailRecommendCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 03E9A7452EB5ACE5000D1067 /* FADetailRecommendCell.swift */; };
|
||||||
|
03E9A7482EB5D2CB000D1067 /* FALogoutAlert.swift in Sources */ = {isa = PBXBuildFile; fileRef = 03E9A7472EB5D2CB000D1067 /* FALogoutAlert.swift */; };
|
||||||
|
03E9A74A2EB5DA7E000D1067 /* FALanguageViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 03E9A7492EB5DA7E000D1067 /* FALanguageViewController.swift */; };
|
||||||
|
03E9A74C2EB5DB92000D1067 /* FALanguageCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 03E9A74B2EB5DB92000D1067 /* FALanguageCell.swift */; };
|
||||||
|
03E9A74E2EB5E0F7000D1067 /* FALanguageModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 03E9A74D2EB5E0F7000D1067 /* FALanguageModel.swift */; };
|
||||||
|
03E9A7502EB5EAC0000D1067 /* FALanguageDataModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 03E9A74F2EB5EAC0000D1067 /* FALanguageDataModel.swift */; };
|
||||||
|
03E9A7522EB83A58000D1067 /* FAAppStartViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 03E9A7512EB83A58000D1067 /* FAAppStartViewController.swift */; };
|
||||||
B86XD3O90WO2R4725L084287 /* Pods_Fableon.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = C4THBP0A1283PFXW440071Q5 /* Pods_Fableon.framework */; };
|
B86XD3O90WO2R4725L084287 /* Pods_Fableon.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = C4THBP0A1283PFXW440071Q5 /* Pods_Fableon.framework */; };
|
||||||
F3019606DA7P36H41G408X13 /* ZStreamCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = F38E33739F391364D0151P7Z /* ZStreamCell.swift */; };
|
F3019606DA7P36H41G408X13 /* ZStreamCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = F38E33739F391364D0151P7Z /* ZStreamCell.swift */; };
|
||||||
F30470W590T8274E1642349G /* CControlCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = F32MR5F8X6Q3HSZ560BD0159 /* CControlCell.swift */; };
|
F30470W590T8274E1642349G /* CControlCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = F32MR5F8X6Q3HSZ560BD0159 /* CControlCell.swift */; };
|
||||||
@ -518,7 +528,7 @@
|
|||||||
03E23A972EAA1A7F004A8CEC /* FAEmpty.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FAEmpty.swift; sourceTree = "<group>"; };
|
03E23A972EAA1A7F004A8CEC /* FAEmpty.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FAEmpty.swift; sourceTree = "<group>"; };
|
||||||
03E23A992EAA1A7F004A8CEC /* FADeviceIDManager.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FADeviceIDManager.swift; sourceTree = "<group>"; };
|
03E23A992EAA1A7F004A8CEC /* FADeviceIDManager.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FADeviceIDManager.swift; sourceTree = "<group>"; };
|
||||||
03E23A9A2EAA1A7F004A8CEC /* FAKeychainHelper.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FAKeychainHelper.swift; sourceTree = "<group>"; };
|
03E23A9A2EAA1A7F004A8CEC /* FAKeychainHelper.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FAKeychainHelper.swift; sourceTree = "<group>"; };
|
||||||
03E23A9C2EAA1A7F004A8CEC /* FALocalized.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FALocalized.swift; sourceTree = "<group>"; };
|
03E23A9C2EAA1A7F004A8CEC /* FALanguageManager.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FALanguageManager.swift; sourceTree = "<group>"; };
|
||||||
03E23A9E2EAA1A7F004A8CEC /* FALogin.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FALogin.swift; sourceTree = "<group>"; };
|
03E23A9E2EAA1A7F004A8CEC /* FALogin.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FALogin.swift; sourceTree = "<group>"; };
|
||||||
03E23A9F2EAA1A7F004A8CEC /* FATokenModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FATokenModel.swift; sourceTree = "<group>"; };
|
03E23A9F2EAA1A7F004A8CEC /* FATokenModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FATokenModel.swift; sourceTree = "<group>"; };
|
||||||
03E23AA02EAA1A7F004A8CEC /* FAUserInfo.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FAUserInfo.swift; sourceTree = "<group>"; };
|
03E23AA02EAA1A7F004A8CEC /* FAUserInfo.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FAUserInfo.swift; sourceTree = "<group>"; };
|
||||||
@ -532,6 +542,16 @@
|
|||||||
03E9A7392EB45149000D1067 /* AppDelegate+FAApns.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "AppDelegate+FAApns.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>"; };
|
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>"; };
|
03E9A73D2EB460F2000D1067 /* FAApnsAlert.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FAApnsAlert.swift; sourceTree = "<group>"; };
|
||||||
|
03E9A73F2EB49BE6000D1067 /* FAUpdatesAlert.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FAUpdatesAlert.swift; sourceTree = "<group>"; };
|
||||||
|
03E9A7412EB4A603000D1067 /* FAVersionUpdateModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FAVersionUpdateModel.swift; sourceTree = "<group>"; };
|
||||||
|
03E9A7432EB4B80B000D1067 /* FADetailRecommendView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FADetailRecommendView.swift; sourceTree = "<group>"; };
|
||||||
|
03E9A7452EB5ACE5000D1067 /* FADetailRecommendCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FADetailRecommendCell.swift; sourceTree = "<group>"; };
|
||||||
|
03E9A7472EB5D2CB000D1067 /* FALogoutAlert.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FALogoutAlert.swift; sourceTree = "<group>"; };
|
||||||
|
03E9A7492EB5DA7E000D1067 /* FALanguageViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FALanguageViewController.swift; sourceTree = "<group>"; };
|
||||||
|
03E9A74B2EB5DB92000D1067 /* FALanguageCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FALanguageCell.swift; sourceTree = "<group>"; };
|
||||||
|
03E9A74D2EB5E0F7000D1067 /* FALanguageModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FALanguageModel.swift; sourceTree = "<group>"; };
|
||||||
|
03E9A74F2EB5EAC0000D1067 /* FALanguageDataModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FALanguageDataModel.swift; sourceTree = "<group>"; };
|
||||||
|
03E9A7512EB83A58000D1067 /* FAAppStartViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FAAppStartViewController.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>"; };
|
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; };
|
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>"; };
|
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>"; };
|
||||||
@ -665,6 +685,8 @@
|
|||||||
031FDEEB2EB35DF600F4CAC7 /* FACoinsPackAlert.swift */,
|
031FDEEB2EB35DF600F4CAC7 /* FACoinsPackAlert.swift */,
|
||||||
031FDEED2EB3682000F4CAC7 /* FAVipRetainAlert.swift */,
|
031FDEED2EB3682000F4CAC7 /* FAVipRetainAlert.swift */,
|
||||||
03E9A73D2EB460F2000D1067 /* FAApnsAlert.swift */,
|
03E9A73D2EB460F2000D1067 /* FAApnsAlert.swift */,
|
||||||
|
03E9A73F2EB49BE6000D1067 /* FAUpdatesAlert.swift */,
|
||||||
|
03E9A7472EB5D2CB000D1067 /* FALogoutAlert.swift */,
|
||||||
);
|
);
|
||||||
path = Alert;
|
path = Alert;
|
||||||
sourceTree = "<group>";
|
sourceTree = "<group>";
|
||||||
@ -750,6 +772,7 @@
|
|||||||
03E239672EAA1A29004A8CEC /* FANavigationController.swift */,
|
03E239672EAA1A29004A8CEC /* FANavigationController.swift */,
|
||||||
03E239682EAA1A29004A8CEC /* FATabBarController.swift */,
|
03E239682EAA1A29004A8CEC /* FATabBarController.swift */,
|
||||||
03E239692EAA1A29004A8CEC /* FAViewController.swift */,
|
03E239692EAA1A29004A8CEC /* FAViewController.swift */,
|
||||||
|
03E9A7512EB83A58000D1067 /* FAAppStartViewController.swift */,
|
||||||
);
|
);
|
||||||
path = Controller;
|
path = Controller;
|
||||||
sourceTree = "<group>";
|
sourceTree = "<group>";
|
||||||
@ -955,6 +978,7 @@
|
|||||||
03E239EA2EAA1A4E004A8CEC /* FAMeViewController.swift */,
|
03E239EA2EAA1A4E004A8CEC /* FAMeViewController.swift */,
|
||||||
03E239EB2EAA1A4E004A8CEC /* FASettingViewController.swift */,
|
03E239EB2EAA1A4E004A8CEC /* FASettingViewController.swift */,
|
||||||
031FDEC12EB1E19D00F4CAC7 /* FACoinPackViewController.swift */,
|
031FDEC12EB1E19D00F4CAC7 /* FACoinPackViewController.swift */,
|
||||||
|
03E9A7492EB5DA7E000D1067 /* FALanguageViewController.swift */,
|
||||||
);
|
);
|
||||||
path = C;
|
path = C;
|
||||||
sourceTree = "<group>";
|
sourceTree = "<group>";
|
||||||
@ -963,6 +987,7 @@
|
|||||||
isa = PBXGroup;
|
isa = PBXGroup;
|
||||||
children = (
|
children = (
|
||||||
03E239ED2EAA1A4E004A8CEC /* FAMeItemModel.swift */,
|
03E239ED2EAA1A4E004A8CEC /* FAMeItemModel.swift */,
|
||||||
|
03E9A7412EB4A603000D1067 /* FAVersionUpdateModel.swift */,
|
||||||
);
|
);
|
||||||
path = M;
|
path = M;
|
||||||
sourceTree = "<group>";
|
sourceTree = "<group>";
|
||||||
@ -988,6 +1013,7 @@
|
|||||||
031FDED72EB30D6E00F4CAC7 /* FASettingCell.swift */,
|
031FDED72EB30D6E00F4CAC7 /* FASettingCell.swift */,
|
||||||
031FDED82EB30D6E00F4CAC7 /* FASettingCell.xib */,
|
031FDED82EB30D6E00F4CAC7 /* FASettingCell.xib */,
|
||||||
031FDEDB2EB3141E00F4CAC7 /* FASettingFooterView.swift */,
|
031FDEDB2EB3141E00F4CAC7 /* FASettingFooterView.swift */,
|
||||||
|
03E9A74B2EB5DB92000D1067 /* FALanguageCell.swift */,
|
||||||
);
|
);
|
||||||
path = V;
|
path = V;
|
||||||
sourceTree = "<group>";
|
sourceTree = "<group>";
|
||||||
@ -1063,6 +1089,8 @@
|
|||||||
03E23A102EAA1A4E004A8CEC /* FAVideoLockView.swift */,
|
03E23A102EAA1A4E004A8CEC /* FAVideoLockView.swift */,
|
||||||
031FDEBB2EB0C97A00F4CAC7 /* FAOldVideoRechargeView.swift */,
|
031FDEBB2EB0C97A00F4CAC7 /* FAOldVideoRechargeView.swift */,
|
||||||
031FDEBD2EB0C99900F4CAC7 /* FANewVideoRechargeView.swift */,
|
031FDEBD2EB0C99900F4CAC7 /* FANewVideoRechargeView.swift */,
|
||||||
|
03E9A7432EB4B80B000D1067 /* FADetailRecommendView.swift */,
|
||||||
|
03E9A7452EB5ACE5000D1067 /* FADetailRecommendCell.swift */,
|
||||||
);
|
);
|
||||||
path = V;
|
path = V;
|
||||||
sourceTree = "<group>";
|
sourceTree = "<group>";
|
||||||
@ -1220,7 +1248,9 @@
|
|||||||
03E23A9D2EAA1A7F004A8CEC /* FALocalized */ = {
|
03E23A9D2EAA1A7F004A8CEC /* FALocalized */ = {
|
||||||
isa = PBXGroup;
|
isa = PBXGroup;
|
||||||
children = (
|
children = (
|
||||||
03E23A9C2EAA1A7F004A8CEC /* FALocalized.swift */,
|
03E23A9C2EAA1A7F004A8CEC /* FALanguageManager.swift */,
|
||||||
|
03E9A74D2EB5E0F7000D1067 /* FALanguageModel.swift */,
|
||||||
|
03E9A74F2EB5EAC0000D1067 /* FALanguageDataModel.swift */,
|
||||||
);
|
);
|
||||||
path = FALocalized;
|
path = FALocalized;
|
||||||
sourceTree = "<group>";
|
sourceTree = "<group>";
|
||||||
@ -1945,6 +1975,7 @@
|
|||||||
F3019606DA7P36H41G408X13 /* ZStreamCell.swift in Sources */,
|
F3019606DA7P36H41G408X13 /* ZStreamCell.swift in Sources */,
|
||||||
F392T441X031FH7N0HA03SZ7 /* WPSectionView.swift in Sources */,
|
F392T441X031FH7N0HA03SZ7 /* WPSectionView.swift in Sources */,
|
||||||
F3D05387002315ZAQC97D7BT /* JHYHeader.swift in Sources */,
|
F3D05387002315ZAQC97D7BT /* JHYHeader.swift in Sources */,
|
||||||
|
03E9A7422EB4A603000D1067 /* FAVersionUpdateModel.swift in Sources */,
|
||||||
F33IOYM854R4C48ZU602K4L2 /* CHelper.swift in Sources */,
|
F33IOYM854R4C48ZU602K4L2 /* CHelper.swift in Sources */,
|
||||||
F3327L1BJ30974SY08905774 /* KDelegateOllectionView.swift in Sources */,
|
F3327L1BJ30974SY08905774 /* KDelegateOllectionView.swift in Sources */,
|
||||||
F3P6F8433LVRV052SEY9W3N1 /* KWMptyLaunchController.swift in Sources */,
|
F3P6F8433LVRV052SEY9W3N1 /* KWMptyLaunchController.swift in Sources */,
|
||||||
@ -1974,6 +2005,7 @@
|
|||||||
F3N346893L1U6DP8228XK227 /* UOLaunch.swift in Sources */,
|
F3N346893L1U6DP8228XK227 /* UOLaunch.swift in Sources */,
|
||||||
F39S0H806843N21RM0O95488 /* VARResultController.swift in Sources */,
|
F39S0H806843N21RM0O95488 /* VARResultController.swift in Sources */,
|
||||||
F3D03219Y8NV50N2S66014LX /* GPOOllectionFableon.swift in Sources */,
|
F3D03219Y8NV50N2S66014LX /* GPOOllectionFableon.swift in Sources */,
|
||||||
|
03E9A74E2EB5E0F7000D1067 /* FALanguageModel.swift in Sources */,
|
||||||
F399V72654D56W408WQO18D5 /* OOSelectorSection.swift in Sources */,
|
F399V72654D56W408WQO18D5 /* OOSelectorSection.swift in Sources */,
|
||||||
F31RUU6I99967458M4X40V5C /* HNFDramaController.swift in Sources */,
|
F31RUU6I99967458M4X40V5C /* HNFDramaController.swift in Sources */,
|
||||||
F3MIE47471I04686Y131BPU5 /* TGleeScreenView.swift in Sources */,
|
F3MIE47471I04686Y131BPU5 /* TGleeScreenView.swift in Sources */,
|
||||||
@ -1992,8 +2024,9 @@
|
|||||||
039CE6242EAB29D1007B5EED /* FAPayDataRequest.swift in Sources */,
|
039CE6242EAB29D1007B5EED /* FAPayDataRequest.swift in Sources */,
|
||||||
03E23AB52EAA1A7F004A8CEC /* FAToast.swift in Sources */,
|
03E23AB52EAA1A7F004A8CEC /* FAToast.swift in Sources */,
|
||||||
03E23AB62EAA1A7F004A8CEC /* FAUserInfo.swift in Sources */,
|
03E23AB62EAA1A7F004A8CEC /* FAUserInfo.swift in Sources */,
|
||||||
03E23AB72EAA1A7F004A8CEC /* FALocalized.swift in Sources */,
|
03E23AB72EAA1A7F004A8CEC /* FALanguageManager.swift in Sources */,
|
||||||
039CE6222EAB1340007B5EED /* FAUserDefaultsKey.swift in Sources */,
|
039CE6222EAB1340007B5EED /* FAUserDefaultsKey.swift in Sources */,
|
||||||
|
03E9A7442EB4B80B000D1067 /* FADetailRecommendView.swift in Sources */,
|
||||||
03E23AB82EAA1A7F004A8CEC /* FAWaterfallFlowLayout.swift in Sources */,
|
03E23AB82EAA1A7F004A8CEC /* FAWaterfallFlowLayout.swift in Sources */,
|
||||||
031FDEC62EB1E4E600F4CAC7 /* FACoinPackTitleView.swift in Sources */,
|
031FDEC62EB1E4E600F4CAC7 /* FACoinPackTitleView.swift in Sources */,
|
||||||
F3K238643L913I6RK4G7S006 /* CSceneRegister.swift in Sources */,
|
F3K238643L913I6RK4G7S006 /* CSceneRegister.swift in Sources */,
|
||||||
@ -2040,11 +2073,13 @@
|
|||||||
03E23A512EAA1A4E004A8CEC /* FAConsumptionRecordsCell.swift in Sources */,
|
03E23A512EAA1A4E004A8CEC /* FAConsumptionRecordsCell.swift in Sources */,
|
||||||
03E23A522EAA1A4E004A8CEC /* FARankingListHeaderView.swift in Sources */,
|
03E23A522EAA1A4E004A8CEC /* FARankingListHeaderView.swift in Sources */,
|
||||||
03E23A532EAA1A4E004A8CEC /* FAVideoLockView.swift in Sources */,
|
03E23A532EAA1A4E004A8CEC /* FAVideoLockView.swift in Sources */,
|
||||||
|
03E9A7482EB5D2CB000D1067 /* FALogoutAlert.swift in Sources */,
|
||||||
03E23A542EAA1A4E004A8CEC /* FAHomeViewController.swift in Sources */,
|
03E23A542EAA1A4E004A8CEC /* FAHomeViewController.swift in Sources */,
|
||||||
03E23A552EAA1A4E004A8CEC /* FAPopularListViewController.swift in Sources */,
|
03E23A552EAA1A4E004A8CEC /* FAPopularListViewController.swift in Sources */,
|
||||||
039CE6042EAA2621007B5EED /* AppDelegate+FAAdjust.swift in Sources */,
|
039CE6042EAA2621007B5EED /* AppDelegate+FAAdjust.swift in Sources */,
|
||||||
03E23A562EAA1A4E004A8CEC /* FAPlayerEpUIButton.swift in Sources */,
|
03E23A562EAA1A4E004A8CEC /* FAPlayerEpUIButton.swift in Sources */,
|
||||||
031FDEE42EB348AA00F4CAC7 /* FABaseAlert.swift in Sources */,
|
031FDEE42EB348AA00F4CAC7 /* FABaseAlert.swift in Sources */,
|
||||||
|
03E9A74C2EB5DB92000D1067 /* FALanguageCell.swift in Sources */,
|
||||||
03E23A572EAA1A4E004A8CEC /* FAHistoryCell.swift in Sources */,
|
03E23A572EAA1A4E004A8CEC /* FAHistoryCell.swift in Sources */,
|
||||||
03E23A582EAA1A4E004A8CEC /* FASearchViewController.swift in Sources */,
|
03E23A582EAA1A4E004A8CEC /* FASearchViewController.swift in Sources */,
|
||||||
03E23A592EAA1A4E004A8CEC /* FAWalletCell.swift in Sources */,
|
03E23A592EAA1A4E004A8CEC /* FAWalletCell.swift in Sources */,
|
||||||
@ -2087,6 +2122,7 @@
|
|||||||
03E23A762EAA1A4E004A8CEC /* FASearchHomeView.swift in Sources */,
|
03E23A762EAA1A4E004A8CEC /* FASearchHomeView.swift in Sources */,
|
||||||
03E23A772EAA1A4E004A8CEC /* FAHomeNewContentCell.swift in Sources */,
|
03E23A772EAA1A4E004A8CEC /* FAHomeNewContentCell.swift in Sources */,
|
||||||
03E23A782EAA1A4E004A8CEC /* FAOrderRecordsViewController.swift in Sources */,
|
03E23A782EAA1A4E004A8CEC /* FAOrderRecordsViewController.swift in Sources */,
|
||||||
|
03E9A7462EB5ACE5000D1067 /* FADetailRecommendCell.swift in Sources */,
|
||||||
03E23A792EAA1A4E004A8CEC /* FAEpMenuView.swift in Sources */,
|
03E23A792EAA1A4E004A8CEC /* FAEpMenuView.swift in Sources */,
|
||||||
03E23A7A2EAA1A4E004A8CEC /* FASearchRecordView.swift in Sources */,
|
03E23A7A2EAA1A4E004A8CEC /* FASearchRecordView.swift in Sources */,
|
||||||
03E23A7B2EAA1A4E004A8CEC /* FACollectViewController.swift in Sources */,
|
03E23A7B2EAA1A4E004A8CEC /* FACollectViewController.swift in Sources */,
|
||||||
@ -2122,6 +2158,7 @@
|
|||||||
F3774560U03XA8151BTQ2Z61 /* HYLLayoutView.swift in Sources */,
|
F3774560U03XA8151BTQ2Z61 /* HYLLayoutView.swift in Sources */,
|
||||||
F3N85463XSRG9VFK665G9028 /* XKRefreshCell.swift in Sources */,
|
F3N85463XSRG9VFK665G9028 /* XKRefreshCell.swift in Sources */,
|
||||||
039CE6282EAB50A9007B5EED /* FAStoreCoinsView.swift in Sources */,
|
039CE6282EAB50A9007B5EED /* FAStoreCoinsView.swift in Sources */,
|
||||||
|
03E9A7402EB49BE6000D1067 /* FAUpdatesAlert.swift in Sources */,
|
||||||
F35K41930D96476I83FHZ0D9 /* YLZFableonAlignmentCell.swift in Sources */,
|
F35K41930D96476I83FHZ0D9 /* YLZFableonAlignmentCell.swift in Sources */,
|
||||||
F3M8439X72Q55JY9G8U502D9 /* DXYFire.swift in Sources */,
|
F3M8439X72Q55JY9G8U502D9 /* DXYFire.swift in Sources */,
|
||||||
03E239912EAA1A29004A8CEC /* Dictionary+FAAdd.swift in Sources */,
|
03E239912EAA1A29004A8CEC /* Dictionary+FAAdd.swift in Sources */,
|
||||||
@ -2132,6 +2169,7 @@
|
|||||||
031FDEDA2EB30D6E00F4CAC7 /* FASettingCell.swift in Sources */,
|
031FDEDA2EB30D6E00F4CAC7 /* FASettingCell.swift in Sources */,
|
||||||
03E239942EAA1A29004A8CEC /* UserDefaults+FAAdd.swift in Sources */,
|
03E239942EAA1A29004A8CEC /* UserDefaults+FAAdd.swift in Sources */,
|
||||||
039CE6322EAB796F007B5EED /* FALabel.swift in Sources */,
|
039CE6322EAB796F007B5EED /* FALabel.swift in Sources */,
|
||||||
|
03E9A7502EB5EAC0000D1067 /* FALanguageDataModel.swift in Sources */,
|
||||||
03E239952EAA1A29004A8CEC /* Font+FAAdd.swift in Sources */,
|
03E239952EAA1A29004A8CEC /* Font+FAAdd.swift in Sources */,
|
||||||
031FDEEE2EB3682000F4CAC7 /* FAVipRetainAlert.swift in Sources */,
|
031FDEEE2EB3682000F4CAC7 /* FAVipRetainAlert.swift in Sources */,
|
||||||
03E239962EAA1A29004A8CEC /* FACryptorService.swift in Sources */,
|
03E239962EAA1A29004A8CEC /* FACryptorService.swift in Sources */,
|
||||||
@ -2169,12 +2207,14 @@
|
|||||||
031FDECA2EB1F8F200F4CAC7 /* FACoinsPackReceiveModel.swift in Sources */,
|
031FDECA2EB1F8F200F4CAC7 /* FACoinsPackReceiveModel.swift in Sources */,
|
||||||
03E239B02EAA1A29004A8CEC /* FAWebView.swift in Sources */,
|
03E239B02EAA1A29004A8CEC /* FAWebView.swift in Sources */,
|
||||||
039CE61C2EAB0F29007B5EED /* FAIapOrderModel.swift in Sources */,
|
039CE61C2EAB0F29007B5EED /* FAIapOrderModel.swift in Sources */,
|
||||||
|
03E9A7522EB83A58000D1067 /* FAAppStartViewController.swift in Sources */,
|
||||||
03E239B12EAA1A29004A8CEC /* FANetworkMonitor.swift in Sources */,
|
03E239B12EAA1A29004A8CEC /* FANetworkMonitor.swift in Sources */,
|
||||||
03E239B22EAA1A29004A8CEC /* UINavigationBar+FAAdd.swift in Sources */,
|
03E239B22EAA1A29004A8CEC /* UINavigationBar+FAAdd.swift in Sources */,
|
||||||
F3EKB04Y9O2888900KQEO504 /* NHCornerController.swift in Sources */,
|
F3EKB04Y9O2888900KQEO504 /* NHCornerController.swift in Sources */,
|
||||||
F32A7R4096386F976XT2W958 /* YKConfigMain.swift in Sources */,
|
F32A7R4096386F976XT2W958 /* YKConfigMain.swift in Sources */,
|
||||||
F3NKHD424DW5B04NK4D6ZC43 /* SCCrollFddebcdbeeffcebdf.swift in Sources */,
|
F3NKHD424DW5B04NK4D6ZC43 /* SCCrollFddebcdbeeffcebdf.swift in Sources */,
|
||||||
F3374375770O0338ZQOL63EF /* OControlView.swift in Sources */,
|
F3374375770O0338ZQOL63EF /* OControlView.swift in Sources */,
|
||||||
|
03E9A74A2EB5DA7E000D1067 /* FALanguageViewController.swift in Sources */,
|
||||||
F3224PD65IO4R5M40JGK6Z59 /* TOkenView.swift in Sources */,
|
F3224PD65IO4R5M40JGK6Z59 /* TOkenView.swift in Sources */,
|
||||||
F3C25CQ448629S8947842301 /* JXMInfoCell.swift in Sources */,
|
F3C25CQ448629S8947842301 /* JXMInfoCell.swift in Sources */,
|
||||||
F33732269456Q82561503YIR /* KZOgin.swift in Sources */,
|
F33732269456Q82561503YIR /* KZOgin.swift in Sources */,
|
||||||
|
|||||||
@ -69,7 +69,7 @@ extension SceneDelegate {
|
|||||||
var statUrlStr: String? = webpageURL?.absoluteString
|
var statUrlStr: String? = webpageURL?.absoluteString
|
||||||
var data: [String : Any]? = webpageURL?.query?.urlQuryToDictionary()
|
var data: [String : Any]? = webpageURL?.query?.urlQuryToDictionary()
|
||||||
|
|
||||||
if statUrlStr == nil, let pasteStr = UIPasteboard.general.string, pasteStr.contains("movia") {
|
if statUrlStr == nil, let pasteStr = UIPasteboard.general.string, pasteStr.contains("fableon") {
|
||||||
let tempArr = pasteStr.components(separatedBy: "?")
|
let tempArr = pasteStr.components(separatedBy: "?")
|
||||||
let query = tempArr.last
|
let query = tempArr.last
|
||||||
|
|
||||||
|
|||||||
@ -75,7 +75,6 @@ extension AppDelegate {
|
|||||||
//MARK: -------------- UNUserNotificationCenterDelegate --------------
|
//MARK: -------------- UNUserNotificationCenterDelegate --------------
|
||||||
extension SceneDelegate: UNUserNotificationCenterDelegate {
|
extension SceneDelegate: UNUserNotificationCenterDelegate {
|
||||||
|
|
||||||
|
|
||||||
///APP处于前台是接收通知消息
|
///APP处于前台是接收通知消息
|
||||||
func userNotificationCenter(_ center: UNUserNotificationCenter, willPresent notification: UNNotification, withCompletionHandler completionHandler: @escaping (UNNotificationPresentationOptions) -> Void) {
|
func userNotificationCenter(_ center: UNUserNotificationCenter, willPresent notification: UNNotification, withCompletionHandler completionHandler: @escaping (UNNotificationPresentationOptions) -> Void) {
|
||||||
completionHandler([.badge, .banner])
|
completionHandler([.badge, .banner])
|
||||||
|
|||||||
@ -20,7 +20,7 @@ extension AppDelegate {
|
|||||||
FAToast.config()
|
FAToast.config()
|
||||||
|
|
||||||
//设置刷新控件的语言
|
//设置刷新控件的语言
|
||||||
MJRefreshConfig.default.languageCode = "en"
|
MJRefreshConfig.default.languageCode = FALanguageManager.manager.mjLanguageKey
|
||||||
|
|
||||||
IQKeyboardManager.shared.isEnabled = true
|
IQKeyboardManager.shared.isEnabled = true
|
||||||
IQKeyboardManager.shared.resignOnTouchOutside = true
|
IQKeyboardManager.shared.resignOnTouchOutside = true
|
||||||
|
|||||||
@ -7,6 +7,7 @@
|
|||||||
|
|
||||||
import UIKit
|
import UIKit
|
||||||
import YYText
|
import YYText
|
||||||
|
import MJRefresh
|
||||||
|
|
||||||
class SceneDelegate: UIResponder, UIWindowSceneDelegate {
|
class SceneDelegate: UIResponder, UIWindowSceneDelegate {
|
||||||
|
|
||||||
@ -17,13 +18,13 @@ class SceneDelegate: UIResponder, UIWindowSceneDelegate {
|
|||||||
func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) {
|
func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) {
|
||||||
guard let windowScene = (scene as? UIWindowScene) else { return }
|
guard let windowScene = (scene as? UIWindowScene) else { return }
|
||||||
NotificationCenter.default.addObserver(self, selector: #selector(networkStatusDidChangeNotification), name: FANetworkMonitor.networkStatusDidChangeNotification, object: nil)
|
NotificationCenter.default.addObserver(self, selector: #selector(networkStatusDidChangeNotification), name: FANetworkMonitor.networkStatusDidChangeNotification, object: nil)
|
||||||
|
NotificationCenter.default.addObserver(self, selector: #selector(languageDidChange), name: FALanguageManager.languageDidChange, object: nil)
|
||||||
|
|
||||||
FATool.sceneDelegate = self
|
FATool.sceneDelegate = self
|
||||||
FATool.windowScene = windowScene
|
FATool.windowScene = windowScene
|
||||||
|
|
||||||
window = UIWindow(windowScene: windowScene)
|
window = UIWindow(windowScene: windowScene)
|
||||||
window?.rootViewController = FATabBarController()
|
startApp()
|
||||||
window?.makeKeyAndVisible()
|
|
||||||
FAAdjustStateManager.manager.isOpenApp = true
|
|
||||||
|
|
||||||
onLineTimer = Timer.scheduledTimer(timeInterval: 60 * 10, target: YYTextWeakProxy(target: self), selector: #selector(handleOnLine), userInfo: nil, repeats: true)
|
onLineTimer = Timer.scheduledTimer(timeInterval: 60 * 10, target: YYTextWeakProxy(target: self), selector: #selector(handleOnLine), userInfo: nil, repeats: true)
|
||||||
|
|
||||||
@ -66,6 +67,55 @@ class SceneDelegate: UIResponder, UIWindowSceneDelegate {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
extension SceneDelegate {
|
||||||
|
|
||||||
|
private func startApp() {
|
||||||
|
setRootVC()
|
||||||
|
let languageManager = FALanguageManager.manager
|
||||||
|
|
||||||
|
if languageManager.languageDataLanguageKey != languageManager.currentLanguageKey {
|
||||||
|
let vc = FATool.getLanuchViewController()
|
||||||
|
window?.rootViewController = vc
|
||||||
|
window?.makeKeyAndVisible()
|
||||||
|
|
||||||
|
languageManager.updateLanguageData { [weak self] finish in
|
||||||
|
guard let self = self else { return }
|
||||||
|
self.setRootVC()
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
languageManager.updateLanguageData(completer: nil)
|
||||||
|
setRootVC()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private func setRootVC() {
|
||||||
|
///是否首次开启过
|
||||||
|
let hasOpenApp = UserDefaults.standard.object(forKey: kFAHasBeenOpenedAPPDefaultsKey) as? Bool
|
||||||
|
|
||||||
|
if hasOpenApp != true {
|
||||||
|
let vc = FAAppStartViewController()
|
||||||
|
vc.openAppBlock = { [weak self] in
|
||||||
|
guard let self = self else { return }
|
||||||
|
UserDefaults.standard.set(true, forKey: kFAHasBeenOpenedAPPDefaultsKey)
|
||||||
|
self.setTabBarController()
|
||||||
|
self.retryHandleOpenAppMessage()
|
||||||
|
}
|
||||||
|
window?.rootViewController = vc
|
||||||
|
window?.makeKeyAndVisible()
|
||||||
|
} else {
|
||||||
|
self.setTabBarController()
|
||||||
|
self.retryHandleOpenAppMessage()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private func setTabBarController() {
|
||||||
|
FAAdjustStateManager.manager.isOpenApp = true
|
||||||
|
|
||||||
|
window?.rootViewController = FATabBarController()
|
||||||
|
window?.makeKeyAndVisible()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
extension SceneDelegate {
|
extension SceneDelegate {
|
||||||
|
|
||||||
@objc private func handleOnLine() {
|
@objc private func handleOnLine() {
|
||||||
@ -73,7 +123,15 @@ extension SceneDelegate {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@objc private func networkStatusDidChangeNotification() {
|
@objc private func networkStatusDidChangeNotification() {
|
||||||
FATool.requestIDFAAuthorization(nil)
|
if FANetworkMonitor.manager.isReachable == true {
|
||||||
self.retryHandleOpenAppMessage()
|
FATool.requestIDFAAuthorization(nil)
|
||||||
|
self.retryHandleOpenAppMessage()
|
||||||
|
FAIapManager.manager.preloadingProducts()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@objc private func languageDidChange() {
|
||||||
|
MJRefreshConfig.default.languageCode = FALanguageManager.manager.mjLanguageKey
|
||||||
|
setTabBarController()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -2,6 +2,8 @@
|
|||||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||||
<plist version="1.0">
|
<plist version="1.0">
|
||||||
<dict>
|
<dict>
|
||||||
|
<key>aps-environment</key>
|
||||||
|
<string>development</string>
|
||||||
<key>com.apple.developer.applesignin</key>
|
<key>com.apple.developer.applesignin</key>
|
||||||
<array>
|
<array>
|
||||||
<string>Default</string>
|
<string>Default</string>
|
||||||
|
|||||||
@ -0,0 +1,59 @@
|
|||||||
|
//
|
||||||
|
// FAAppStartViewController.swift
|
||||||
|
// Fableon
|
||||||
|
//
|
||||||
|
// Created by 湖北秦九 on 2025/11/3.
|
||||||
|
//
|
||||||
|
|
||||||
|
import UIKit
|
||||||
|
|
||||||
|
class FAAppStartViewController: FAViewController {
|
||||||
|
|
||||||
|
var openAppBlock: (() -> Void)?
|
||||||
|
|
||||||
|
private lazy var lanuchVC: UIViewController? = {
|
||||||
|
let vc = FATool.getLanuchViewController()
|
||||||
|
return vc
|
||||||
|
}()
|
||||||
|
|
||||||
|
private lazy var startButton: UIButton = {
|
||||||
|
let button = FAGradientButton(type: .custom, primaryAction: UIAction(handler: { [weak self] _ in
|
||||||
|
guard let self = self else { return }
|
||||||
|
self.openAppBlock?()
|
||||||
|
}))
|
||||||
|
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("fableon_open".localized, for: .normal)
|
||||||
|
button.setTitleColor(._000000, for: .normal)
|
||||||
|
button.titleLabel?.font = .font(ofSize: 18, weight: .semibold)
|
||||||
|
return button
|
||||||
|
}()
|
||||||
|
|
||||||
|
override func viewDidLoad() {
|
||||||
|
super.viewDidLoad()
|
||||||
|
|
||||||
|
if let vc = lanuchVC {
|
||||||
|
addChild(vc)
|
||||||
|
view.addSubview(vc.view)
|
||||||
|
}
|
||||||
|
|
||||||
|
view.addSubview(startButton)
|
||||||
|
|
||||||
|
startButton.snp.makeConstraints { make in
|
||||||
|
make.centerX.equalToSuperview()
|
||||||
|
make.height.equalTo(48)
|
||||||
|
make.bottom.equalToSuperview().offset(-(UIScreen.safeBottom + 110))
|
||||||
|
make.width.equalTo(150)
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
@ -12,10 +12,10 @@ class FATabBarController: UITabBarController {
|
|||||||
override func viewDidLoad() {
|
override func viewDidLoad() {
|
||||||
super.viewDidLoad()
|
super.viewDidLoad()
|
||||||
|
|
||||||
let nav1 = getNavigation(FAHomeViewController(), "Home".localized, UIImage(named: "tabbar_home_icon"), UIImage(named: "tabbar_home_icon_selected"))
|
let nav1 = getNavigation(FAHomeViewController(), "fableon_home".localized, UIImage(named: "tabbar_home_icon"), UIImage(named: "tabbar_home_icon_selected"))
|
||||||
let nav2 = getNavigation(FARecommendViewController(), "Recommend".localized, UIImage(named: "tabbar_recommend_icon"), UIImage(named: "tabbar_recommend_icon_selected"))
|
let nav2 = getNavigation(FARecommendViewController(), "fableon_recommend".localized, UIImage(named: "tabbar_recommend_icon"), UIImage(named: "tabbar_recommend_icon_selected"))
|
||||||
let nav3 = getNavigation(FACollectViewController(), "Collect".localized, UIImage(named: "tabbar_collect_icon"), UIImage(named: "tabbar_collect_icon_selected"))
|
let nav3 = getNavigation(FACollectViewController(), "fableon_collect".localized, UIImage(named: "tabbar_collect_icon"), UIImage(named: "tabbar_collect_icon_selected"))
|
||||||
let nav4 = getNavigation(FAMeViewController(), "Me".localized, UIImage(named: "tabbar_me_icon"), UIImage(named: "tabbar_me_icon_selected"))
|
let nav4 = getNavigation(FAMeViewController(), "fableon_me".localized, UIImage(named: "tabbar_me_icon"), UIImage(named: "tabbar_me_icon_selected"))
|
||||||
|
|
||||||
viewControllers = [nav1, nav2, nav3, nav4]
|
viewControllers = [nav1, nav2, nav3, nav4]
|
||||||
|
|
||||||
@ -47,6 +47,8 @@ class FATabBarController: UITabBarController {
|
|||||||
FALogin.manager.requestUserInfo(completer: nil)
|
FALogin.manager.requestUserInfo(completer: nil)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
FATool.checkUpdates()
|
||||||
|
// FATool.requestIDFAAuthorization(nil)
|
||||||
}
|
}
|
||||||
|
|
||||||
override var childForStatusBarStyle: UIViewController? {
|
override var childForStatusBarStyle: UIViewController? {
|
||||||
|
|||||||
@ -9,3 +9,7 @@
|
|||||||
let kFAWaitRestoreIAPDefaultsKey = "kFAWaitRestoreIAPDefaultsKey"
|
let kFAWaitRestoreIAPDefaultsKey = "kFAWaitRestoreIAPDefaultsKey"
|
||||||
|
|
||||||
let kFAApnsAlertDefaultsKey = "kFAApnsAlertDefaultsKey"
|
let kFAApnsAlertDefaultsKey = "kFAApnsAlertDefaultsKey"
|
||||||
|
|
||||||
|
let kFAVersionUpdateAlertDefaultsKey = "kFAVersionUpdateAlertDefaultsKey"
|
||||||
|
|
||||||
|
let kFAHasBeenOpenedAPPDefaultsKey = "kFAHasBeenOpenedAPPDefaultsKey"
|
||||||
|
|||||||
@ -130,6 +130,17 @@ struct FAAPI {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static func requestDetailRecommendVideo( completer: ((_ list: [FAShortPlayModel]?) -> Void)?) {
|
||||||
|
|
||||||
|
FANetworkManager.manager.request(FABaseURL + "/getDetailsRecommand",
|
||||||
|
method: .get,
|
||||||
|
parameters: nil,
|
||||||
|
isLoding: false,
|
||||||
|
isToast: false) { (response: FANetworkManager.Response<FANetworkManager.List<FAShortPlayModel>>) in
|
||||||
|
completer?(response.data?.list)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
///收藏列表
|
///收藏列表
|
||||||
static func requestCollectList(page: Int, completer: ((_ listModel: FANetworkManager.List<FAShortPlayModel>?) -> Void)?) {
|
static func requestCollectList(page: Int, completer: ((_ listModel: FANetworkManager.List<FAShortPlayModel>?) -> Void)?) {
|
||||||
let parameters: [String : Any] = [
|
let parameters: [String : Any] = [
|
||||||
@ -251,6 +262,45 @@ struct FAAPI {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static func requestVersionUpdateData(completer: ((_ model: FAVersionUpdateModel?) -> Void)?) {
|
||||||
|
|
||||||
|
FANetworkManager.manager.request(FABaseURL + "/customer/versionControl",
|
||||||
|
method: .get,
|
||||||
|
parameters: nil,
|
||||||
|
isLoding: false,
|
||||||
|
isToast: false) { (response: FANetworkManager.Response<FAVersionUpdateModel>) in
|
||||||
|
completer?(response.data)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
///获取语言列表
|
||||||
|
static func requestLanguageList(completer: ((_ list: [FALanguageModel]?) -> Void)?) {
|
||||||
|
|
||||||
|
FANetworkManager.manager.request(FABaseURL + "/languges",
|
||||||
|
method: .get,
|
||||||
|
parameters: nil,
|
||||||
|
isLoding: false,
|
||||||
|
isToast: true) { (response: FANetworkManager.Response<FANetworkManager.List<FALanguageModel>>) in
|
||||||
|
completer?(response.data?.list)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
///获取语言列表
|
||||||
|
static func requestLanguageDataList(key: String, completer: ((_ model: FALanguageDataModel?) -> Void)?) {
|
||||||
|
|
||||||
|
var parameters = [
|
||||||
|
"lang_key" : key
|
||||||
|
]
|
||||||
|
|
||||||
|
FANetworkManager.manager.request(FABaseURL + "/translates",
|
||||||
|
method: .get,
|
||||||
|
parameters: parameters,
|
||||||
|
isLoding: false,
|
||||||
|
isToast: true) { (response: FANetworkManager.Response<FALanguageDataModel>) in
|
||||||
|
completer?(response.data)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -96,7 +96,7 @@ class FANetworkManager {
|
|||||||
completion?(response)
|
completion?(response)
|
||||||
} else {
|
} else {
|
||||||
if isToast {
|
if isToast {
|
||||||
FAToast.show(text: "Error".localized)
|
FAToast.show(text: "fableon_error".localized)
|
||||||
}
|
}
|
||||||
var res = FANetworkManager.Response<T>()
|
var res = FANetworkManager.Response<T>()
|
||||||
res.code = -1
|
res.code = -1
|
||||||
@ -177,7 +177,7 @@ extension FANetworkManager {
|
|||||||
let dic = [
|
let dic = [
|
||||||
"authorization" : token,
|
"authorization" : token,
|
||||||
"system-version" : UIDevice.current.systemVersion,
|
"system-version" : UIDevice.current.systemVersion,
|
||||||
"lang-key" : "en",
|
"lang-key" : FALanguageManager.manager.currentLanguageKey,
|
||||||
"time-zone" : String.timeZone(),
|
"time-zone" : String.timeZone(),
|
||||||
"app-version" : (Bundle.main.infoDictionary!["CFBundleShortVersionString"] as? String) ?? "",
|
"app-version" : (Bundle.main.infoDictionary!["CFBundleShortVersionString"] as? String) ?? "",
|
||||||
"brand" : "apple", //品牌
|
"brand" : "apple", //品牌
|
||||||
|
|||||||
@ -12,10 +12,10 @@ class FANetworkMonitor {
|
|||||||
static let manager = FANetworkMonitor()
|
static let manager = FANetworkMonitor()
|
||||||
|
|
||||||
///是否有网
|
///是否有网
|
||||||
var isReachable: Bool?
|
private(set) var isReachable: Bool?
|
||||||
|
|
||||||
private var connectionType: NWInterface.InterfaceType?
|
private(set) var connectionType: NWInterface.InterfaceType?
|
||||||
private var status: NWPath.Status?
|
private(set) var status: NWPath.Status?
|
||||||
|
|
||||||
private let monitor = NWPathMonitor()
|
private let monitor = NWPathMonitor()
|
||||||
private let queue = DispatchQueue(label: "NetworkMonitorQueue")
|
private let queue = DispatchQueue(label: "NetworkMonitorQueue")
|
||||||
@ -36,7 +36,6 @@ class FANetworkMonitor {
|
|||||||
self.connectionType = nil
|
self.connectionType = nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
if path.status == .satisfied, self.connectionType != nil {
|
if path.status == .satisfied, self.connectionType != nil {
|
||||||
if self.isReachable == false {
|
if self.isReachable == false {
|
||||||
self.isReachable = true
|
self.isReachable = true
|
||||||
|
|||||||
@ -18,7 +18,7 @@ class FATableView: UITableView {
|
|||||||
self.backgroundColor = .clear
|
self.backgroundColor = .clear
|
||||||
self.contentInsetAdjustmentBehavior = .never
|
self.contentInsetAdjustmentBehavior = .never
|
||||||
|
|
||||||
if style == .insetGrouped {
|
if style == .insetGrouped || style == .grouped {
|
||||||
sectionFooterHeight = 14
|
sectionFooterHeight = 14
|
||||||
sectionHeaderHeight = 0.1
|
sectionHeaderHeight = 0.1
|
||||||
} else if style == .plain {
|
} else if style == .plain {
|
||||||
|
|||||||
@ -21,13 +21,13 @@ class FAAppWebViewController: FABaseWebViewController {
|
|||||||
self.autoTitle = false
|
self.autoTitle = false
|
||||||
|
|
||||||
if webUrl == kFAFeedBackListWebUrl {
|
if webUrl == kFAFeedBackListWebUrl {
|
||||||
self.title = "Feedback History".localized
|
self.title = "fableon_feedback_history".localized
|
||||||
} else if webUrl == kFAFeedBackHomeWebUrl {
|
} else if webUrl == kFAFeedBackHomeWebUrl {
|
||||||
self.title = "Feedback".localized
|
self.title = "fableon_feedback".localized
|
||||||
} else if webUrl == kFAFeedBackDetailWebUrl {
|
} else if webUrl == kFAFeedBackDetailWebUrl {
|
||||||
self.title = "Feedback Details".localized
|
self.title = "fableon_feedback_detail".localized
|
||||||
} else if webUrl == kFALogoutWebUrl {
|
} else if webUrl == kFALogoutWebUrl {
|
||||||
self.title = "Account Deletion".localized
|
self.title = "fableon_account_deletion".localized
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
@ -51,7 +51,7 @@ extension FAAppWebViewController {
|
|||||||
var dic = [
|
var dic = [
|
||||||
"token" : FALogin.manager.token?.token ?? "",
|
"token" : FALogin.manager.token?.token ?? "",
|
||||||
"time_zone" : String.timeZone(),
|
"time_zone" : String.timeZone(),
|
||||||
"lang" : FALocalized.manager.currentLocalizedKey,
|
"lang" : FALanguageManager.manager.currentLanguageKey,
|
||||||
"type" : "ios",
|
"type" : "ios",
|
||||||
"device-id" : FADeviceIDManager.shared.id
|
"device-id" : FADeviceIDManager.shared.id
|
||||||
]
|
]
|
||||||
|
|||||||
@ -41,7 +41,7 @@ class FANewListViewController: FAViewController {
|
|||||||
|
|
||||||
override func viewDidLoad() {
|
override func viewDidLoad() {
|
||||||
super.viewDidLoad()
|
super.viewDidLoad()
|
||||||
self.title = "New".localized
|
self.title = "fableon_new".localized
|
||||||
|
|
||||||
fa_setupLayout()
|
fa_setupLayout()
|
||||||
|
|
||||||
|
|||||||
@ -41,7 +41,7 @@ class FAPopularListViewController: FAViewController {
|
|||||||
|
|
||||||
override func viewDidLoad() {
|
override func viewDidLoad() {
|
||||||
super.viewDidLoad()
|
super.viewDidLoad()
|
||||||
self.title = "Popular".localized
|
self.title = "fableon_popular".localized
|
||||||
|
|
||||||
fa_setupLayout()
|
fa_setupLayout()
|
||||||
|
|
||||||
|
|||||||
@ -19,7 +19,7 @@ struct FAHomeMustSeeContentView: View {
|
|||||||
var body: some View {
|
var body: some View {
|
||||||
VStack(spacing: 15) {
|
VStack(spacing: 15) {
|
||||||
HStack {
|
HStack {
|
||||||
Text("Editor's Picks".localized)
|
Text("fableon_editor's_picks".localized)
|
||||||
.font(Font.font(size: 16, weight: .medium))
|
.font(Font.font(size: 16, weight: .medium))
|
||||||
.foregroundStyle(Color(String.color_FFFFFF))
|
.foregroundStyle(Color(String.color_FFFFFF))
|
||||||
.padding(.leading, 10)
|
.padding(.leading, 10)
|
||||||
|
|||||||
@ -47,7 +47,7 @@ struct FAHomeMustSeeShortView: View {
|
|||||||
HStack(spacing: 4) {
|
HStack(spacing: 4) {
|
||||||
Image("Frame 2920")
|
Image("Frame 2920")
|
||||||
|
|
||||||
Text("Watch".localized)
|
Text("fableon_watch".localized)
|
||||||
.font(Font.font(size: 12, weight: .medium))
|
.font(Font.font(size: 12, weight: .medium))
|
||||||
.foregroundStyle(Color(String.color_000000))
|
.foregroundStyle(Color(String.color_000000))
|
||||||
|
|
||||||
|
|||||||
@ -18,7 +18,7 @@ struct FAHomeMustSeeView: View {
|
|||||||
var body: some View {
|
var body: some View {
|
||||||
VStack {
|
VStack {
|
||||||
HStack {
|
HStack {
|
||||||
Text("Must-see TV series".localized)
|
Text("fableon_must_see_tv_series".localized)
|
||||||
.font(Font.font(size: 18, weight: .medium))
|
.font(Font.font(size: 18, weight: .medium))
|
||||||
.foregroundStyle(Color(String.color_FFFFFF))
|
.foregroundStyle(Color(String.color_FFFFFF))
|
||||||
.padding(.leading, 16)
|
.padding(.leading, 16)
|
||||||
|
|||||||
@ -24,7 +24,7 @@ struct FAHomeNewView: View {
|
|||||||
let list = viewModel.homeNewItem?.list ?? []
|
let list = viewModel.homeNewItem?.list ?? []
|
||||||
|
|
||||||
VStack(spacing: 15) {
|
VStack(spacing: 15) {
|
||||||
Text("New Releases".localized)
|
Text("fableon_home_new".localized)
|
||||||
.font(.font(size: 18, weight: .medium))
|
.font(.font(size: 18, weight: .medium))
|
||||||
.foregroundStyle(Color(String.color_FFFFFF))
|
.foregroundStyle(Color(String.color_FFFFFF))
|
||||||
.padding(.leading, 16)
|
.padding(.leading, 16)
|
||||||
@ -60,7 +60,7 @@ struct FAHomeNewView: View {
|
|||||||
HStack(spacing: 4) {
|
HStack(spacing: 4) {
|
||||||
Image("Frame 2921")
|
Image("Frame 2921")
|
||||||
|
|
||||||
Text("Watch".localized)
|
Text("fableon_watch".localized)
|
||||||
.font(.font(size: 14, weight: .medium))
|
.font(.font(size: 14, weight: .medium))
|
||||||
.foregroundStyle(Color(String.color_000000))
|
.foregroundStyle(Color(String.color_000000))
|
||||||
}
|
}
|
||||||
|
|||||||
@ -17,7 +17,7 @@ class FAHomeCoinsPackButton: UIControl {
|
|||||||
let label = UILabel()
|
let label = UILabel()
|
||||||
label.font = .font(ofSize: 10, weight: .init(900)).withBoldItalic()
|
label.font = .font(ofSize: 10, weight: .init(900)).withBoldItalic()
|
||||||
label.textColor = .FFFFFF
|
label.textColor = .FFFFFF
|
||||||
label.text = "Daily Coins".localized
|
label.text = "fableon_daily_coins".localized
|
||||||
return label
|
return label
|
||||||
}()
|
}()
|
||||||
|
|
||||||
|
|||||||
@ -13,7 +13,7 @@ class FAHomePlayHistoryView: UIView {
|
|||||||
didSet {
|
didSet {
|
||||||
coverImageView.fa_setImage(model?.image_url)
|
coverImageView.fa_setImage(model?.image_url)
|
||||||
titleLabel.text = model?.name
|
titleLabel.text = model?.name
|
||||||
epLabel.text = "Last Watch:Ep.##".localizedReplace(text: model?.current_episode ?? "")
|
epLabel.text = "fableon_last_watch_ep".localizedReplace(text: model?.current_episode ?? "")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -13,7 +13,7 @@ class FARankingListCell: UICollectionViewCell {
|
|||||||
didSet {
|
didSet {
|
||||||
coverImageView.fa_setImage(model?.image_url)
|
coverImageView.fa_setImage(model?.image_url)
|
||||||
nameLabel.text = model?.name
|
nameLabel.text = model?.name
|
||||||
epLabel.text = "Ep.##".localizedReplace(text: "\(model?.episode_total ?? 0)")
|
epLabel.text = "fableon_episode_set".localizedReplace(text: "\(model?.episode_total ?? 0)")
|
||||||
countLabel.text = "\(model?.watch_total ?? 0)"
|
countLabel.text = "\(model?.watch_total ?? 0)"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -40,7 +40,7 @@ class FASearchInputView: UIView {
|
|||||||
textField.returnKeyType = .search
|
textField.returnKeyType = .search
|
||||||
textField.font = .font(ofSize: 12, weight: .medium)
|
textField.font = .font(ofSize: 12, weight: .medium)
|
||||||
textField.textColor = .FFFFFF
|
textField.textColor = .FFFFFF
|
||||||
textField.attributedPlaceholder = NSAttributedString(string: "Search".localized, attributes: [
|
textField.attributedPlaceholder = NSAttributedString(string: "fableon_search".localized, attributes: [
|
||||||
.font : UIFont.font(ofSize: 12, weight: .medium),
|
.font : UIFont.font(ofSize: 12, weight: .medium),
|
||||||
.foregroundColor : UIColor.FFFFFF.withAlphaComponent(0.5)
|
.foregroundColor : UIColor.FFFFFF.withAlphaComponent(0.5)
|
||||||
])
|
])
|
||||||
|
|||||||
@ -15,7 +15,7 @@ class FASearchRecommendCell: UICollectionViewCell {
|
|||||||
coverImageView.fa_setImage(model?.image_url)
|
coverImageView.fa_setImage(model?.image_url)
|
||||||
titleLabel.text = model?.name
|
titleLabel.text = model?.name
|
||||||
countLabel.text = "\(model?.watch_total ?? 0)"
|
countLabel.text = "\(model?.watch_total ?? 0)"
|
||||||
epLabel.text = "Ep.##".localizedReplace(text: "\(model?.episode_total ?? 0)")
|
epLabel.text = "fableon_episode_set".localizedReplace(text: "\(model?.episode_total ?? 0)")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -23,7 +23,7 @@ class FASearchRecordView: UIView {
|
|||||||
let label = UILabel()
|
let label = UILabel()
|
||||||
label.font = .font(ofSize: 14, weight: .medium)
|
label.font = .font(ofSize: 14, weight: .medium)
|
||||||
label.textColor = .FFFFFF
|
label.textColor = .FFFFFF
|
||||||
label.text = "Historical search".localized
|
label.text = "fableon_search_history".localized
|
||||||
return label
|
return label
|
||||||
}()
|
}()
|
||||||
|
|
||||||
|
|||||||
@ -38,7 +38,7 @@ class FAHomeViewModel: ObservableObject {
|
|||||||
if $0.module_key == .banner {
|
if $0.module_key == .banner {
|
||||||
self.bannerItem = $0
|
self.bannerItem = $0
|
||||||
} else if $0.module_key == .v3_recommand {
|
} else if $0.module_key == .v3_recommand {
|
||||||
$0.title = "Popular".localized
|
$0.title = "fableon_popular".localized
|
||||||
popularItem = $0
|
popularItem = $0
|
||||||
} else if $0.module_key == .week_ranking {
|
} else if $0.module_key == .week_ranking {
|
||||||
$0.title = "Rankings".localized
|
$0.title = "Rankings".localized
|
||||||
@ -47,7 +47,7 @@ class FAHomeViewModel: ObservableObject {
|
|||||||
$0.title = "Genres".localized
|
$0.title = "Genres".localized
|
||||||
genresItem = $0
|
genresItem = $0
|
||||||
} else if $0.module_key == .new_recommand {
|
} else if $0.module_key == .new_recommand {
|
||||||
$0.title = "New".localized
|
$0.title = "fableon_new".localized
|
||||||
newItem = $0
|
newItem = $0
|
||||||
self.homeNewItem = $0
|
self.homeNewItem = $0
|
||||||
} else if $0.module_key == .week_recommend {
|
} else if $0.module_key == .week_recommend {
|
||||||
|
|||||||
@ -11,9 +11,9 @@ class FAAboutViewController: FAViewController {
|
|||||||
|
|
||||||
|
|
||||||
private lazy var dataArr: [FAMeItemModel] = [
|
private lazy var dataArr: [FAMeItemModel] = [
|
||||||
FAMeItemModel(type: .privacyPolicy, name: "Privacy Policy".localized),
|
FAMeItemModel(type: .privacyPolicy, name: "fableon_privacy_policy".localized),
|
||||||
FAMeItemModel(type: .userAgreement, name: "User Agreement".localized),
|
FAMeItemModel(type: .userAgreement, name: "fableon_user_agreement".localized),
|
||||||
FAMeItemModel(type: .visitWebsite, name: "Visit Website".localized),
|
FAMeItemModel(type: .visitWebsite, name: "fableon_visit_website".localized),
|
||||||
]
|
]
|
||||||
|
|
||||||
private lazy var tableView: FATableView = {
|
private lazy var tableView: FATableView = {
|
||||||
|
|||||||
@ -115,7 +115,7 @@ class FACoinPackViewController: FAViewController {
|
|||||||
|
|
||||||
override func viewDidLoad() {
|
override func viewDidLoad() {
|
||||||
super.viewDidLoad()
|
super.viewDidLoad()
|
||||||
self.title = "My Refills".localized
|
self.title = "fableon_my_refills".localized
|
||||||
payDataModel = FAIapManager.manager.payDateModel
|
payDataModel = FAIapManager.manager.payDateModel
|
||||||
|
|
||||||
fa_setupLayout()
|
fa_setupLayout()
|
||||||
|
|||||||
99
Fableon/Object/Class/Me/C/FALanguageViewController.swift
Normal file
@ -0,0 +1,99 @@
|
|||||||
|
//
|
||||||
|
// FALanguageViewController.swift
|
||||||
|
// Fableon
|
||||||
|
//
|
||||||
|
// Created by 湖北秦九 on 2025/11/1.
|
||||||
|
//
|
||||||
|
|
||||||
|
import UIKit
|
||||||
|
|
||||||
|
class FALanguageViewController: FAViewController {
|
||||||
|
|
||||||
|
private var dataArr: [FALanguageModel] = []
|
||||||
|
|
||||||
|
private lazy var tableView: FATableView = {
|
||||||
|
let tableView = FATableView(frame: .zero, style: .grouped)
|
||||||
|
tableView.delegate = self
|
||||||
|
tableView.dataSource = self
|
||||||
|
tableView.separatorStyle = .none
|
||||||
|
tableView.rowHeight = 60
|
||||||
|
tableView.contentInset = .init(top: 20, left: 0, bottom: UIScreen.safeBottom, right: 0)
|
||||||
|
tableView.register(FALanguageCell.self, forCellReuseIdentifier: "cell")
|
||||||
|
return tableView
|
||||||
|
}()
|
||||||
|
|
||||||
|
override func viewDidLoad() {
|
||||||
|
super.viewDidLoad()
|
||||||
|
title = "fableon_language".localized
|
||||||
|
|
||||||
|
view.addSubview(tableView)
|
||||||
|
tableView.snp.makeConstraints { make in
|
||||||
|
make.left.right.bottom.equalToSuperview()
|
||||||
|
make.top.equalToSuperview().offset(UIScreen.navBarHeight)
|
||||||
|
}
|
||||||
|
self.tableView.contentOffset = .init(x: 0, y: -self.tableView.contentInset.top)
|
||||||
|
|
||||||
|
requestDataArr()
|
||||||
|
}
|
||||||
|
|
||||||
|
override func viewWillAppear(_ animated: Bool) {
|
||||||
|
super.viewWillAppear(animated)
|
||||||
|
self.navigationController?.setNavigationBarHidden(false, animated: true)
|
||||||
|
fa_setNavigationStyle()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//MARK: UITableViewDelegate UITableViewDataSource
|
||||||
|
extension FALanguageViewController: UITableViewDelegate, UITableViewDataSource {
|
||||||
|
|
||||||
|
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
|
||||||
|
let model = dataArr[indexPath.section]
|
||||||
|
|
||||||
|
let cell = tableView.dequeueReusableCell(withIdentifier: "cell", for: indexPath) as! FALanguageCell
|
||||||
|
cell.fa_isSelected = true
|
||||||
|
cell.model = model
|
||||||
|
cell.fa_isSelected = model.lang_key == FALanguageManager.manager.currentLanguageKey
|
||||||
|
return cell
|
||||||
|
}
|
||||||
|
|
||||||
|
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
|
||||||
|
return 1
|
||||||
|
}
|
||||||
|
|
||||||
|
func numberOfSections(in tableView: UITableView) -> Int {
|
||||||
|
return dataArr.count
|
||||||
|
}
|
||||||
|
|
||||||
|
func tableView(_ tableView: UITableView, heightForFooterInSection section: Int) -> CGFloat {
|
||||||
|
return 12
|
||||||
|
}
|
||||||
|
|
||||||
|
func tableView(_ tableView: UITableView, heightForHeaderInSection section: Int) -> CGFloat {
|
||||||
|
return 1
|
||||||
|
}
|
||||||
|
|
||||||
|
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
|
||||||
|
let model = dataArr[indexPath.section]
|
||||||
|
guard let key = model.lang_key else { return }
|
||||||
|
|
||||||
|
FALanguageManager.manager.switchLanguage(key) { finish in
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
extension FALanguageViewController {
|
||||||
|
|
||||||
|
private func requestDataArr() {
|
||||||
|
FAAPI.requestLanguageList { [weak self] list in
|
||||||
|
guard let self = self else { return }
|
||||||
|
guard let list = list else { return }
|
||||||
|
self.dataArr = list
|
||||||
|
self.tableView.reloadData()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@ -14,14 +14,15 @@ class FAMeListViewController: FAViewController, JXPagingViewListViewDelegate {
|
|||||||
|
|
||||||
private lazy var dataArr: [FAMeItemModel] = {
|
private lazy var dataArr: [FAMeItemModel] = {
|
||||||
let arr = [
|
let arr = [
|
||||||
FAMeItemModel(type: .feedback, name: "Feedback".localized, icon: UIImage(named: "icon_feedback")),
|
FAMeItemModel(type: .language, name: "fableon_language".localized, icon: UIImage(named: "icon_language")),
|
||||||
FAMeItemModel(type: .about, name: "About".localized, icon: UIImage(named: "icon_about")),
|
FAMeItemModel(type: .feedback, name: "fableon_feedback".localized, icon: UIImage(named: "icon_feedback")),
|
||||||
|
FAMeItemModel(type: .about, name: "fableon_about_us".localized, icon: UIImage(named: "icon_about")),
|
||||||
|
|
||||||
FAMeItemModel(type: .privacyPolicy, name: "Privacy Policy".localized, icon: UIImage(named: "icon_privacy")),
|
FAMeItemModel(type: .privacyPolicy, name: "fableon_privacy_policy".localized, icon: UIImage(named: "icon_privacy")),
|
||||||
FAMeItemModel(type: .userAgreement, name: "User Agreement".localized, icon: UIImage(named: "icon_user")),
|
FAMeItemModel(type: .userAgreement, name: "fableon_user_agreement".localized, icon: UIImage(named: "icon_user")),
|
||||||
FAMeItemModel(type: .visitWebsite, name: "Visit Website".localized, icon: UIImage(named: "icon_visit")),
|
// FAMeItemModel(type: .visitWebsite, name: "fableon_visit_website".localized, icon: UIImage(named: "icon_visit")),
|
||||||
|
|
||||||
FAMeItemModel(type: .setting, name: "Setting".localized, icon: UIImage(named: "icon_setting"))
|
FAMeItemModel(type: .setting, name: "fableon_settings".localized, icon: UIImage(named: "icon_setting"))
|
||||||
]
|
]
|
||||||
return arr
|
return arr
|
||||||
}()
|
}()
|
||||||
@ -147,6 +148,11 @@ extension FAMeListViewController: UITableViewDelegate, UITableViewDataSource {
|
|||||||
UIApplication.shared.open(url)
|
UIApplication.shared.open(url)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
case .language:
|
||||||
|
let vc = FALanguageViewController()
|
||||||
|
self.navigationController?.pushViewController(vc, animated: true)
|
||||||
|
|
||||||
|
|
||||||
default:
|
default:
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
|
|||||||
@ -10,7 +10,7 @@ import UIKit
|
|||||||
class FASettingViewController: FAViewController {
|
class FASettingViewController: FAViewController {
|
||||||
|
|
||||||
private lazy var dataArr: [FAMeItemModel] = [
|
private lazy var dataArr: [FAMeItemModel] = [
|
||||||
FAMeItemModel(type: .deleteAccount, name: "Account Deletion".localized, icon: nil)
|
FAMeItemModel(type: .deleteAccount, name: "fableon_account_deletion".localized, icon: nil)
|
||||||
]
|
]
|
||||||
|
|
||||||
private lazy var tableView: FATableView = {
|
private lazy var tableView: FATableView = {
|
||||||
@ -31,7 +31,7 @@ class FASettingViewController: FAViewController {
|
|||||||
|
|
||||||
override func viewDidLoad() {
|
override func viewDidLoad() {
|
||||||
super.viewDidLoad()
|
super.viewDidLoad()
|
||||||
self.title = "Settings".localized
|
self.title = "fableon_settings".localized
|
||||||
NotificationCenter.default.addObserver(self, selector: #selector(userInfoUpdateNotification), name: FALogin.userInfoUpdateNotification, object: nil)
|
NotificationCenter.default.addObserver(self, selector: #selector(userInfoUpdateNotification), name: FALogin.userInfoUpdateNotification, object: nil)
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@ -23,6 +23,7 @@ struct FAMeItemModel {
|
|||||||
///金币奖励
|
///金币奖励
|
||||||
case rewardCoins
|
case rewardCoins
|
||||||
case deleteAccount
|
case deleteAccount
|
||||||
|
case language
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
38
Fableon/Object/Class/Me/M/FAVersionUpdateModel.swift
Normal file
@ -0,0 +1,38 @@
|
|||||||
|
//
|
||||||
|
// FAVersionUpdateModel.swift
|
||||||
|
// Fableon
|
||||||
|
//
|
||||||
|
// Created by 湖北秦九 on 2025/10/31.
|
||||||
|
//
|
||||||
|
|
||||||
|
import UIKit
|
||||||
|
import SmartCodable
|
||||||
|
|
||||||
|
struct FAVersionUpdateModel: SmartCodable {
|
||||||
|
|
||||||
|
var version_code: String?
|
||||||
|
var des: String?
|
||||||
|
var version_name: String?
|
||||||
|
|
||||||
|
var force: Bool?
|
||||||
|
|
||||||
|
|
||||||
|
func canUpdate() -> Bool {
|
||||||
|
guard let version = version_code else { return false }
|
||||||
|
|
||||||
|
let result = kFAAPPVersion.compare(version, options: .numeric)
|
||||||
|
if result == .orderedAscending {
|
||||||
|
return true
|
||||||
|
} else {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static func mappingForKey() -> [SmartKeyTransformer]? {
|
||||||
|
return [
|
||||||
|
CodingKeys.des <--- ["description"]
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@ -33,20 +33,20 @@ class FACoinPackHeaderView: UIView {
|
|||||||
view.dotColor = .C_5_DDF_5
|
view.dotColor = .C_5_DDF_5
|
||||||
view.font = .font(ofSize: 14, weight: .regular)
|
view.font = .font(ofSize: 14, weight: .regular)
|
||||||
view.textColors = [UIColor.C_5_DDF_5.cgColor, UIColor.C_5_DDF_5.cgColor]
|
view.textColors = [UIColor.C_5_DDF_5.cgColor, UIColor.C_5_DDF_5.cgColor]
|
||||||
view.text = "REWARDS OVERVIEW".localized
|
view.text = "fableon_rewards_overview".localized.uppercased()
|
||||||
return view
|
return view
|
||||||
}()
|
}()
|
||||||
|
|
||||||
private lazy var coinsView1: CoinsView = {
|
private lazy var coinsView1: CoinsView = {
|
||||||
let view = CoinsView()
|
let view = CoinsView()
|
||||||
view.title = "Weekly Total".localized
|
view.title = "fableon_weekly_total".localized
|
||||||
view.coins = 0
|
view.coins = 0
|
||||||
return view
|
return view
|
||||||
}()
|
}()
|
||||||
|
|
||||||
private lazy var coinsView2: CoinsView = {
|
private lazy var coinsView2: CoinsView = {
|
||||||
let view = CoinsView()
|
let view = CoinsView()
|
||||||
view.title = "Claimable Coins".localized
|
view.title = "fableon_claimable_coins".localized
|
||||||
view.coins = 0
|
view.coins = 0
|
||||||
return view
|
return view
|
||||||
}()
|
}()
|
||||||
@ -65,7 +65,7 @@ class FACoinPackHeaderView: UIView {
|
|||||||
let label = UILabel()
|
let label = UILabel()
|
||||||
label.font = .font(ofSize: 12, weight: .regular)
|
label.font = .font(ofSize: 12, weight: .regular)
|
||||||
label.textColor = .FFFFFF.withAlphaComponent(0.5)
|
label.textColor = .FFFFFF.withAlphaComponent(0.5)
|
||||||
label.text = "Active Refills".localized + ": "
|
label.text = "fableon_active_refills".localized + ": "
|
||||||
return label
|
return label
|
||||||
}()
|
}()
|
||||||
|
|
||||||
@ -99,7 +99,7 @@ class FACoinPackHeaderView: UIView {
|
|||||||
coinText.bounds = .init(x: 0, y: -2.5, width: coinImage.size.width, height: coinImage.size.height)
|
coinText.bounds = .init(x: 0, y: -2.5, width: coinImage.size.width, height: coinImage.size.height)
|
||||||
let coinAtt = AttributedString(NSAttributedString(attachment: coinText))
|
let coinAtt = AttributedString(NSAttributedString(attachment: coinText))
|
||||||
|
|
||||||
let textAtt = AttributedString("Claim All".localized + " ", attributes: AttributeContainer([
|
let textAtt = AttributedString("fableon_claim_all".localized + " ", attributes: AttributeContainer([
|
||||||
.font : UIFont.font(ofSize: 14, weight: .bold),
|
.font : UIFont.font(ofSize: 14, weight: .bold),
|
||||||
.foregroundColor : UIColor.FFFFFF
|
.foregroundColor : UIColor.FFFFFF
|
||||||
]))
|
]))
|
||||||
@ -114,7 +114,7 @@ class FACoinPackHeaderView: UIView {
|
|||||||
|
|
||||||
} else {
|
} else {
|
||||||
button.fa_colors = [UIColor._6_D_6_D_6_D.cgColor, UIColor._6_D_6_D_6_D.cgColor]
|
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([
|
button.configuration?.attributedTitle = AttributedString("fableon_get_refill_button_text".localized, attributes: AttributeContainer([
|
||||||
.font : UIFont.font(ofSize: 14, weight: .bold),
|
.font : UIFont.font(ofSize: 14, weight: .bold),
|
||||||
.foregroundColor : UIColor.FFFFFF.withAlphaComponent(0.5)
|
.foregroundColor : UIColor.FFFFFF.withAlphaComponent(0.5)
|
||||||
]))
|
]))
|
||||||
|
|||||||
@ -18,7 +18,7 @@ class FACoinsPackBuyView: UIView {
|
|||||||
view.dotColor = .C_5_DDF_5
|
view.dotColor = .C_5_DDF_5
|
||||||
view.textColors = [UIColor.C_5_DDF_5.cgColor, UIColor.C_5_DDF_5.cgColor]
|
view.textColors = [UIColor.C_5_DDF_5.cgColor, UIColor.C_5_DDF_5.cgColor]
|
||||||
view.font = .font(ofSize: 14, weight: .regular)
|
view.font = .font(ofSize: 14, weight: .regular)
|
||||||
view.text = "Weekly Refill".localized.uppercased()
|
view.text = "fableo_weekly_refill".localized.uppercased()
|
||||||
return view
|
return view
|
||||||
}()
|
}()
|
||||||
|
|
||||||
|
|||||||
@ -63,13 +63,13 @@ class FACoinsPackClaimListCell: UICollectionViewCell {
|
|||||||
|
|
||||||
private lazy var coinsView1: CoinsView = {
|
private lazy var coinsView1: CoinsView = {
|
||||||
let view = CoinsView()
|
let view = CoinsView()
|
||||||
view.title = "Total Reward".localized
|
view.title = "fableon_total_reward".localized
|
||||||
return view
|
return view
|
||||||
}()
|
}()
|
||||||
|
|
||||||
private lazy var coinsView2: CoinsView = {
|
private lazy var coinsView2: CoinsView = {
|
||||||
let view = CoinsView()
|
let view = CoinsView()
|
||||||
view.title = "Remaining".localized
|
view.title = "fableon_remaining".localized
|
||||||
return view
|
return view
|
||||||
}()
|
}()
|
||||||
|
|
||||||
@ -103,7 +103,7 @@ class FACoinsPackClaimListCell: UICollectionViewCell {
|
|||||||
]))
|
]))
|
||||||
|
|
||||||
|
|
||||||
button.configuration?.attributedTitle = AttributedString("Claim".localized, attributes: AttributeContainer([
|
button.configuration?.attributedTitle = AttributedString("fableon_claim".localized, attributes: AttributeContainer([
|
||||||
.font : UIFont.font(ofSize: 14, weight: .bold),
|
.font : UIFont.font(ofSize: 14, weight: .bold),
|
||||||
.foregroundColor : UIColor._114_CEE
|
.foregroundColor : UIColor._114_CEE
|
||||||
]))
|
]))
|
||||||
@ -112,7 +112,7 @@ class FACoinsPackClaimListCell: UICollectionViewCell {
|
|||||||
|
|
||||||
} else {
|
} else {
|
||||||
button.fa_colors = [UIColor.BCBCBC.cgColor, UIColor.BCBCBC.cgColor]
|
button.fa_colors = [UIColor.BCBCBC.cgColor, UIColor.BCBCBC.cgColor]
|
||||||
button.configuration?.attributedTitle = AttributedString("Claim".localized, attributes: AttributeContainer([
|
button.configuration?.attributedTitle = AttributedString("fableon_claim".localized, attributes: AttributeContainer([
|
||||||
.font : UIFont.font(ofSize: 14, weight: .bold),
|
.font : UIFont.font(ofSize: 14, weight: .bold),
|
||||||
.foregroundColor : UIColor.FFFFFF_0_8
|
.foregroundColor : UIColor.FFFFFF_0_8
|
||||||
]))
|
]))
|
||||||
|
|||||||
@ -22,7 +22,7 @@ class FACoinsPackClaimListView: UIView {
|
|||||||
view.dotColor = .C_5_DDF_5
|
view.dotColor = .C_5_DDF_5
|
||||||
view.textColors = [UIColor.C_5_DDF_5.cgColor, UIColor.C_5_DDF_5.cgColor]
|
view.textColors = [UIColor.C_5_DDF_5.cgColor, UIColor.C_5_DDF_5.cgColor]
|
||||||
view.font = .font(ofSize: 14, weight: .regular)
|
view.font = .font(ofSize: 14, weight: .regular)
|
||||||
view.text = "Active Refills".localized.uppercased()
|
view.text = "fableon_active_refills".localized.uppercased()
|
||||||
return view
|
return view
|
||||||
}()
|
}()
|
||||||
|
|
||||||
|
|||||||
78
Fableon/Object/Class/Me/V/FALanguageCell.swift
Normal file
@ -0,0 +1,78 @@
|
|||||||
|
//
|
||||||
|
// FALanguageCell.swift
|
||||||
|
// Fableon
|
||||||
|
//
|
||||||
|
// Created by 湖北秦九 on 2025/11/1.
|
||||||
|
//
|
||||||
|
|
||||||
|
import UIKit
|
||||||
|
|
||||||
|
class FALanguageCell: FATableViewCell {
|
||||||
|
|
||||||
|
var model: FALanguageModel? {
|
||||||
|
didSet {
|
||||||
|
titleLabel.text = model?.show_name
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
var fa_isSelected: Bool = false {
|
||||||
|
didSet {
|
||||||
|
if fa_isSelected {
|
||||||
|
selectedImageView.image = UIImage(named: "Vector")
|
||||||
|
} else {
|
||||||
|
selectedImageView.image = UIImage(named: "Ellipse 45")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private lazy var bgView: UIView = {
|
||||||
|
let view = UIView()
|
||||||
|
view.backgroundColor = ._5_CA_8_FF_0_2
|
||||||
|
view.layer.cornerRadius = 12
|
||||||
|
view.layer.masksToBounds = true
|
||||||
|
return view
|
||||||
|
}()
|
||||||
|
|
||||||
|
private lazy var titleLabel: UILabel = {
|
||||||
|
let label = UILabel()
|
||||||
|
label.font = .font(ofSize: 14, weight: .semibold)
|
||||||
|
label.textColor = .FFFFFF
|
||||||
|
return label
|
||||||
|
}()
|
||||||
|
|
||||||
|
private lazy var selectedImageView: UIImageView = {
|
||||||
|
let imageView = UIImageView()
|
||||||
|
return imageView
|
||||||
|
}()
|
||||||
|
|
||||||
|
override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) {
|
||||||
|
super.init(style: style, reuseIdentifier: reuseIdentifier)
|
||||||
|
|
||||||
|
contentView.addSubview(bgView)
|
||||||
|
bgView.addSubview(titleLabel)
|
||||||
|
bgView.addSubview(selectedImageView)
|
||||||
|
|
||||||
|
bgView.snp.makeConstraints { make in
|
||||||
|
make.top.bottom.equalToSuperview()
|
||||||
|
make.left.equalToSuperview().offset(16)
|
||||||
|
make.centerX.equalToSuperview()
|
||||||
|
}
|
||||||
|
|
||||||
|
titleLabel.snp.makeConstraints { make in
|
||||||
|
make.centerY.equalToSuperview()
|
||||||
|
make.left.equalToSuperview().offset(16)
|
||||||
|
}
|
||||||
|
|
||||||
|
selectedImageView.snp.makeConstraints { make in
|
||||||
|
make.centerY.equalToSuperview()
|
||||||
|
make.right.equalToSuperview().offset(-16)
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@MainActor required init?(coder: NSCoder) {
|
||||||
|
fatalError("init(coder:) has not been implemented")
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@ -22,7 +22,7 @@ class FALoginView: FAPanModalContentView {
|
|||||||
}()
|
}()
|
||||||
|
|
||||||
private lazy var appleButton: UIButton = {
|
private lazy var appleButton: UIButton = {
|
||||||
let button = self.createButton(image: UIImage(named: "apple_logo_icon_01"), title: "Login with Apple".localized)
|
let button = self.createButton(image: UIImage(named: "apple_logo_icon_01"), title: "fableon_login_title_apple".localized)
|
||||||
button.addAction(UIAction(handler: { [weak self] _ in
|
button.addAction(UIAction(handler: { [weak self] _ in
|
||||||
self?.login(type: .apple)
|
self?.login(type: .apple)
|
||||||
}), for: .touchUpInside)
|
}), for: .touchUpInside)
|
||||||
@ -30,7 +30,7 @@ class FALoginView: FAPanModalContentView {
|
|||||||
}()
|
}()
|
||||||
|
|
||||||
private lazy var facebookButton: UIButton = {
|
private lazy var facebookButton: UIButton = {
|
||||||
let button = self.createButton(image: UIImage(named: "facebook_logo_icon_01"), title: "Login with Facebook".localized)
|
let button = self.createButton(image: UIImage(named: "facebook_logo_icon_01"), title: "fableon_login_title_facebook".localized)
|
||||||
button.addAction(UIAction(handler: { [weak self] _ in
|
button.addAction(UIAction(handler: { [weak self] _ in
|
||||||
self?.login(type: .faceBook)
|
self?.login(type: .faceBook)
|
||||||
}), for: .touchUpInside)
|
}), for: .touchUpInside)
|
||||||
|
|||||||
@ -34,7 +34,7 @@ class FAMeCoinsPackButton: UIControl {
|
|||||||
label.textColors = [UIColor._53_A_2_F_1.cgColor, UIColor.C_5_DDF_5.cgColor]
|
label.textColors = [UIColor._53_A_2_F_1.cgColor, UIColor.C_5_DDF_5.cgColor]
|
||||||
label.textStartPoint = .init(x: 0, y: 0.5)
|
label.textStartPoint = .init(x: 0, y: 0.5)
|
||||||
label.textEndPoint = .init(x: 0.7, y: 0.5)
|
label.textEndPoint = .init(x: 0.7, y: 0.5)
|
||||||
label.text = "Daily reward ready!".localized
|
label.text = "fableo_me_daily_1".localized
|
||||||
return label
|
return label
|
||||||
}()
|
}()
|
||||||
|
|
||||||
@ -42,7 +42,7 @@ class FAMeCoinsPackButton: UIControl {
|
|||||||
let label = UILabel()
|
let label = UILabel()
|
||||||
label.font = .font(ofSize: 12, weight: .medium).withBoldItalic()
|
label.font = .font(ofSize: 12, weight: .medium).withBoldItalic()
|
||||||
label.textColor = .FFFFFF
|
label.textColor = .FFFFFF
|
||||||
label.text = "Claim your rewards now.".localized
|
label.text = "fableo_me_daily_2".localized
|
||||||
return label
|
return label
|
||||||
}()
|
}()
|
||||||
|
|
||||||
|
|||||||
@ -49,7 +49,7 @@ class FAMeHeaderView: UIView {
|
|||||||
|
|
||||||
private lazy var coinsView: FAMeCoinsView = {
|
private lazy var coinsView: FAMeCoinsView = {
|
||||||
let view = FAMeCoinsView()
|
let view = FAMeCoinsView()
|
||||||
view.title = "Coins".localized
|
view.title = "fableon_coins".localized
|
||||||
view.count = 0
|
view.count = 0
|
||||||
view.addAction(UIAction(handler: { [weak self] _ in
|
view.addAction(UIAction(handler: { [weak self] _ in
|
||||||
guard let self = self else { return }
|
guard let self = self else { return }
|
||||||
@ -61,7 +61,7 @@ class FAMeHeaderView: UIView {
|
|||||||
|
|
||||||
private lazy var bonusCoinsView: FAMeCoinsView = {
|
private lazy var bonusCoinsView: FAMeCoinsView = {
|
||||||
let view = FAMeCoinsView()
|
let view = FAMeCoinsView()
|
||||||
view.title = "Bonus"
|
view.title = "fableon_bonus".localized
|
||||||
view.count = 0
|
view.count = 0
|
||||||
view.addAction(UIAction(handler: { [weak self] _ in
|
view.addAction(UIAction(handler: { [weak self] _ in
|
||||||
guard let self = self else { return }
|
guard let self = self else { return }
|
||||||
@ -91,7 +91,7 @@ class FAMeHeaderView: UIView {
|
|||||||
button.layer.masksToBounds = true
|
button.layer.masksToBounds = true
|
||||||
button.layer.borderWidth = 1
|
button.layer.borderWidth = 1
|
||||||
button.layer.borderColor = UIColor.FFFEE_9.cgColor
|
button.layer.borderColor = UIColor.FFFEE_9.cgColor
|
||||||
button.setTitle("Log in".localized, for: .normal)
|
button.setTitle("fableon_login".localized, for: .normal)
|
||||||
button.setTitleColor(.FFFFFF, for: .normal)
|
button.setTitleColor(.FFFFFF, for: .normal)
|
||||||
button.titleLabel?.font = .font(ofSize: 14, weight: .medium)
|
button.titleLabel?.font = .font(ofSize: 14, weight: .medium)
|
||||||
return button
|
return button
|
||||||
|
|||||||
@ -15,13 +15,13 @@ class FAMeTableViewHeaderView: UIView {
|
|||||||
subscribeView.isHidden = true
|
subscribeView.isHidden = true
|
||||||
expirationView.isHidden = false
|
expirationView.isHidden = false
|
||||||
vipImageView.image = UIImage(named: "vip_image_02")
|
vipImageView.image = UIImage(named: "vip_image_02")
|
||||||
titleLabel.text = "Activated".localized
|
titleLabel.text = "fableon_activated".localized
|
||||||
subtitleLabel.text = "vip_tip_01".localized
|
subtitleLabel.text = "vip_tip_01".localized
|
||||||
} else {
|
} else {
|
||||||
subscribeView.isHidden = false
|
subscribeView.isHidden = false
|
||||||
expirationView.isHidden = true
|
expirationView.isHidden = true
|
||||||
vipImageView.image = UIImage(named: "vip_image_01")
|
vipImageView.image = UIImage(named: "vip_image_01")
|
||||||
titleLabel.text = "Not Activated".localized
|
titleLabel.text = "fableon_not_activated".localized
|
||||||
subtitleLabel.text = "vip_tip_02".localized
|
subtitleLabel.text = "vip_tip_02".localized
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -61,7 +61,7 @@ class FAMeTableViewHeaderView: UIView {
|
|||||||
|
|
||||||
private lazy var subscribeView: UIButton = {
|
private lazy var subscribeView: UIButton = {
|
||||||
var config = UIButton.Configuration.plain()
|
var config = UIButton.Configuration.plain()
|
||||||
config.attributedTitle = AttributedString("Subscribe".localized, attributes: AttributeContainer([
|
config.attributedTitle = AttributedString("fableon_subscribe".localized, attributes: AttributeContainer([
|
||||||
.font : UIFont.font(ofSize: 14, weight: .bold),
|
.font : UIFont.font(ofSize: 14, weight: .bold),
|
||||||
.foregroundColor : UIColor._333333
|
.foregroundColor : UIColor._333333
|
||||||
]))
|
]))
|
||||||
|
|||||||
@ -13,7 +13,7 @@ class FASettingFooterView: UIView {
|
|||||||
private lazy var logoutButton: UIButton = {
|
private lazy var logoutButton: UIButton = {
|
||||||
let button = FAGradientButton(type: .custom, primaryAction: UIAction(handler: { [weak self] _ in
|
let button = FAGradientButton(type: .custom, primaryAction: UIAction(handler: { [weak self] _ in
|
||||||
guard let self = self else { return }
|
guard let self = self else { return }
|
||||||
FALogin.manager.logout(completer: nil)
|
self.handleLogoutButton()
|
||||||
}))
|
}))
|
||||||
button.layer.cornerRadius = 24
|
button.layer.cornerRadius = 24
|
||||||
button.layer.masksToBounds = true
|
button.layer.masksToBounds = true
|
||||||
@ -21,7 +21,7 @@ class FASettingFooterView: UIView {
|
|||||||
button.fa_locations = [0, 1]
|
button.fa_locations = [0, 1]
|
||||||
button.fa_startPoint = .init(x: 0, y: 0.5)
|
button.fa_startPoint = .init(x: 0, y: 0.5)
|
||||||
button.fa_endPoint = .init(x: 1, y: 0.5)
|
button.fa_endPoint = .init(x: 1, y: 0.5)
|
||||||
button.setTitle("Log out".localized, for: .normal)
|
button.setTitle("fableon_logout".localized, for: .normal)
|
||||||
button.setTitleColor(._000000, for: .normal)
|
button.setTitleColor(._000000, for: .normal)
|
||||||
button.titleLabel?.font = .font(ofSize: 18, weight: .semibold)
|
button.titleLabel?.font = .font(ofSize: 18, weight: .semibold)
|
||||||
return button
|
return button
|
||||||
@ -43,6 +43,16 @@ class FASettingFooterView: UIView {
|
|||||||
required init?(coder: NSCoder) {
|
required init?(coder: NSCoder) {
|
||||||
fatalError("init(coder:) has not been implemented")
|
fatalError("init(coder:) has not been implemented")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private func handleLogoutButton() {
|
||||||
|
|
||||||
|
|
||||||
|
let view = FALogoutAlert()
|
||||||
|
view.clickHighlightButton = {
|
||||||
|
FALogin.manager.logout(completer: nil)
|
||||||
|
}
|
||||||
|
view.show()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@ -70,7 +70,7 @@ class FACollectViewController: FAViewController {
|
|||||||
override func viewDidLoad() {
|
override func viewDidLoad() {
|
||||||
super.viewDidLoad()
|
super.viewDidLoad()
|
||||||
self.edgesForExtendedLayout = .top
|
self.edgesForExtendedLayout = .top
|
||||||
self.title = "Collect".localized
|
self.title = "fableon_collect".localized
|
||||||
|
|
||||||
|
|
||||||
self.navigationItem.rightBarButtonItems = [historyButton, spaceButton, editBarButton]
|
self.navigationItem.rightBarButtonItems = [historyButton, spaceButton, editBarButton]
|
||||||
|
|||||||
@ -39,7 +39,7 @@ class FAHistoryViewController: FAViewController {
|
|||||||
|
|
||||||
override func viewDidLoad() {
|
override func viewDidLoad() {
|
||||||
super.viewDidLoad()
|
super.viewDidLoad()
|
||||||
self.title = "History".localized
|
self.title = "fableon_history".localized
|
||||||
self.edgesForExtendedLayout = .top
|
self.edgesForExtendedLayout = .top
|
||||||
|
|
||||||
fa_setupLayout()
|
fa_setupLayout()
|
||||||
|
|||||||
@ -16,7 +16,7 @@ class FACollectCell: UICollectionViewCell {
|
|||||||
didSet {
|
didSet {
|
||||||
nameLabel.text = model?.name
|
nameLabel.text = model?.name
|
||||||
coverImageView.fa_setImage(model?.image_url)
|
coverImageView.fa_setImage(model?.image_url)
|
||||||
epLabel.text = "Ep.##".localizedReplace(text: "\(model?.episode_total ?? 0)")
|
epLabel.text = "fableon_episode_set".localizedReplace(text: "\(model?.episode_total ?? 0)")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -13,7 +13,7 @@ class FAHistoryCell: UICollectionViewCell {
|
|||||||
didSet {
|
didSet {
|
||||||
coverImageView.fa_setImage(model?.image_url)
|
coverImageView.fa_setImage(model?.image_url)
|
||||||
nameLabel.text = model?.name
|
nameLabel.text = model?.name
|
||||||
epLabel.text = "Ep.##".localizedReplace(text: model?.current_episode) + "/" + "Ep.##".localizedReplace(text: "\(model?.episode_total ?? 0)")
|
epLabel.text = "fableon_episode_set".localizedReplace(text: model?.current_episode) + "/" + "fableon_episode_set".localizedReplace(text: "\(model?.episode_total ?? 0)")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -25,6 +25,7 @@ class FAShortPlayModel: NSObject, Identifiable, SmartCodable {
|
|||||||
var short_play_id: String?
|
var short_play_id: String?
|
||||||
var short_play_video_id: String?
|
var short_play_video_id: String?
|
||||||
var video_info: FAVideoInfoModel?
|
var video_info: FAVideoInfoModel?
|
||||||
|
var video_url: String?
|
||||||
|
|
||||||
@SmartIgnored
|
@SmartIgnored
|
||||||
var cellHeight: CGFloat = 0
|
var cellHeight: CGFloat = 0
|
||||||
|
|||||||
57
Fableon/Object/Class/Player/V/FADetailRecommendCell.swift
Normal file
@ -0,0 +1,57 @@
|
|||||||
|
//
|
||||||
|
// FADetailRecommendCell.swift
|
||||||
|
// Fableon
|
||||||
|
//
|
||||||
|
// Created by 湖北秦九 on 2025/11/1.
|
||||||
|
//
|
||||||
|
|
||||||
|
import UIKit
|
||||||
|
import FSPagerView
|
||||||
|
import JXPlayer
|
||||||
|
|
||||||
|
class FADetailRecommendCell: FSPagerViewCell {
|
||||||
|
|
||||||
|
var model: FAShortPlayModel? {
|
||||||
|
didSet {
|
||||||
|
player.coverImageView?.fa_setImage(model?.image_url)
|
||||||
|
player.setPlayUrl(url: model?.video_url ?? "")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private lazy var player: JXPlayer = {
|
||||||
|
let player = JXPlayer(controlView: nil)
|
||||||
|
player.playerView = self.playerView
|
||||||
|
return player
|
||||||
|
}()
|
||||||
|
|
||||||
|
private lazy var playerView: UIView = {
|
||||||
|
let view = UIView()
|
||||||
|
view.isUserInteractionEnabled = false
|
||||||
|
return view
|
||||||
|
}()
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
override init(frame: CGRect) {
|
||||||
|
super.init(frame: frame)
|
||||||
|
|
||||||
|
addSubview(playerView)
|
||||||
|
|
||||||
|
playerView.snp.makeConstraints { make in
|
||||||
|
make.edges.equalToSuperview()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@MainActor required init?(coder aDecoder: NSCoder) {
|
||||||
|
fatalError("init(coder:) has not been implemented")
|
||||||
|
}
|
||||||
|
|
||||||
|
func play() {
|
||||||
|
self.player.start()
|
||||||
|
}
|
||||||
|
|
||||||
|
func pause() {
|
||||||
|
self.player.pause()
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
160
Fableon/Object/Class/Player/V/FADetailRecommendView.swift
Normal file
@ -0,0 +1,160 @@
|
|||||||
|
//
|
||||||
|
// FADetailRecommendView.swift
|
||||||
|
// Fableon
|
||||||
|
//
|
||||||
|
// Created by 湖北秦九 on 2025/10/31.
|
||||||
|
//
|
||||||
|
|
||||||
|
import UIKit
|
||||||
|
import FSPagerView
|
||||||
|
|
||||||
|
class FADetailRecommendView: FABaseAlert {
|
||||||
|
|
||||||
|
var clickCloseButton: (() -> Void)?
|
||||||
|
var didSelectedVideo: ((_ model: FAShortPlayModel) -> Void)?
|
||||||
|
|
||||||
|
var dataArr: [FAShortPlayModel] = [] {
|
||||||
|
didSet {
|
||||||
|
self.pagerView.reloadData()
|
||||||
|
|
||||||
|
DispatchQueue.main.asyncAfter(deadline: .now() + 0.2) { [weak self] in
|
||||||
|
self?.updateCurrentData()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private weak var currentCell: FADetailRecommendCell? {
|
||||||
|
didSet {
|
||||||
|
oldValue?.pause()
|
||||||
|
|
||||||
|
currentCell?.play()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private lazy var titleLabel: UILabel = {
|
||||||
|
let label = UILabel()
|
||||||
|
label.font = .font(ofSize: 18, weight: .init(900))
|
||||||
|
label.textColor = .FFFFFF
|
||||||
|
label.text = "fableon_recommend_for_you".localized
|
||||||
|
return label
|
||||||
|
}()
|
||||||
|
|
||||||
|
private lazy var bgView: UIImageView = {
|
||||||
|
let view = UIImageView(image: UIImage(named: "bj"))
|
||||||
|
view.isUserInteractionEnabled = true
|
||||||
|
return view
|
||||||
|
}()
|
||||||
|
|
||||||
|
private lazy var cancelButton: UIButton = {
|
||||||
|
let button = UIButton(type: .custom)
|
||||||
|
button.setImage(UIImage(named: "close_icon_04"), for: .normal)
|
||||||
|
button.addTarget(self, action: #selector(handleCancelButton), for: .touchUpInside)
|
||||||
|
return button
|
||||||
|
}()
|
||||||
|
|
||||||
|
private lazy var pagerView: FSPagerView = {
|
||||||
|
let transformer = FSPagerViewTransformer(type: .crossFading)
|
||||||
|
|
||||||
|
let view = FSPagerView()
|
||||||
|
view.layer.cornerRadius = 6
|
||||||
|
view.layer.masksToBounds = true
|
||||||
|
view.itemSize = .init(width: 178, height: 267)
|
||||||
|
view.transformer = transformer
|
||||||
|
view.delegate = self
|
||||||
|
view.dataSource = self
|
||||||
|
view.isInfinite = true
|
||||||
|
view.interitemSpacing = 0
|
||||||
|
view.register(FADetailRecommendCell.self, forCellWithReuseIdentifier: "cell")
|
||||||
|
return view
|
||||||
|
}()
|
||||||
|
|
||||||
|
override init(frame: CGRect) {
|
||||||
|
super.init(frame: frame)
|
||||||
|
contentWidth = UIScreen.width
|
||||||
|
self.closeButton.isHidden = true
|
||||||
|
|
||||||
|
self.contentView.backgroundColor = .clear
|
||||||
|
self.contentView.layer.cornerRadius = 0
|
||||||
|
self.contentView.layer.masksToBounds = false
|
||||||
|
|
||||||
|
fa_setupLayout()
|
||||||
|
}
|
||||||
|
|
||||||
|
@MainActor required init?(coder: NSCoder) {
|
||||||
|
fatalError("init(coder:) has not been implemented")
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@objc private func handleCancelButton() {
|
||||||
|
|
||||||
|
self.dismiss()
|
||||||
|
self.clickCloseButton?()
|
||||||
|
}
|
||||||
|
|
||||||
|
///更新当前数据
|
||||||
|
private func updateCurrentData() {
|
||||||
|
guard let cell = self.pagerView.cellForItem(at: self.pagerView.currentIndex) as? FADetailRecommendCell else { return }
|
||||||
|
|
||||||
|
self.currentCell = cell
|
||||||
|
// let model = cell.model
|
||||||
|
// self.videoNameLabel.text = model?.name
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
extension FADetailRecommendView {
|
||||||
|
|
||||||
|
private func fa_setupLayout() {
|
||||||
|
contentView.addSubview(titleLabel)
|
||||||
|
contentView.addSubview(bgView)
|
||||||
|
contentView.addSubview(cancelButton)
|
||||||
|
bgView.addSubview(pagerView)
|
||||||
|
|
||||||
|
titleLabel.snp.makeConstraints { make in
|
||||||
|
make.top.equalToSuperview()
|
||||||
|
make.centerX.equalToSuperview()
|
||||||
|
}
|
||||||
|
|
||||||
|
bgView.snp.makeConstraints { make in
|
||||||
|
make.centerX.equalToSuperview()
|
||||||
|
make.top.equalToSuperview().offset(-25)
|
||||||
|
make.bottom.equalToSuperview()
|
||||||
|
}
|
||||||
|
|
||||||
|
cancelButton.snp.makeConstraints { make in
|
||||||
|
make.centerX.equalToSuperview()
|
||||||
|
make.bottom.equalTo(bgView).offset(-10)
|
||||||
|
}
|
||||||
|
|
||||||
|
pagerView.snp.makeConstraints { make in
|
||||||
|
make.width.equalTo(178)
|
||||||
|
make.height.equalTo(267)
|
||||||
|
make.center.equalToSuperview()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
//MARK: FSPagerViewDelegate FSPagerViewDataSource
|
||||||
|
extension FADetailRecommendView: FSPagerViewDelegate, FSPagerViewDataSource {
|
||||||
|
|
||||||
|
func pagerView(_ pagerView: FSPagerView, cellForItemAt index: Int) -> FSPagerViewCell {
|
||||||
|
let cell = pagerView.dequeueReusableCell(withReuseIdentifier: "cell", at: index) as! FADetailRecommendCell
|
||||||
|
cell.model = self.dataArr[index]
|
||||||
|
return cell
|
||||||
|
}
|
||||||
|
|
||||||
|
func numberOfItems(in pagerView: FSPagerView) -> Int {
|
||||||
|
return self.dataArr.count
|
||||||
|
}
|
||||||
|
|
||||||
|
func pagerView(_ pagerView: FSPagerView, didSelectItemAt index: Int) {
|
||||||
|
didSelectedVideo?(self.dataArr[index])
|
||||||
|
self.dismiss()
|
||||||
|
}
|
||||||
|
|
||||||
|
func pagerViewDidEndDecelerating(_ pagerView: FSPagerView) {
|
||||||
|
self.updateCurrentData()
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@ -106,13 +106,13 @@ class FAOldVideoRechargeView: FAPanModalContentView {
|
|||||||
|
|
||||||
private lazy var videoCoinsView: FAOldVideoRechargeView.CoinsView = {
|
private lazy var videoCoinsView: FAOldVideoRechargeView.CoinsView = {
|
||||||
let view = FAOldVideoRechargeView.CoinsView()
|
let view = FAOldVideoRechargeView.CoinsView()
|
||||||
view.title = "Price".localized + ":"
|
view.title = "fableo_price".localized + ":"
|
||||||
return view
|
return view
|
||||||
}()
|
}()
|
||||||
|
|
||||||
private lazy var totalCoinsView: FAOldVideoRechargeView.CoinsView = {
|
private lazy var totalCoinsView: FAOldVideoRechargeView.CoinsView = {
|
||||||
let view = FAOldVideoRechargeView.CoinsView()
|
let view = FAOldVideoRechargeView.CoinsView()
|
||||||
view.title = "Balance".localized + ":"
|
view.title = "fableo_balance".localized + ":"
|
||||||
view.coins = FALogin.manager.userInfo?.totalCoins ?? 0
|
view.coins = FALogin.manager.userInfo?.totalCoins ?? 0
|
||||||
return view
|
return view
|
||||||
}()
|
}()
|
||||||
|
|||||||
@ -159,7 +159,7 @@ class FAPlayerDetailControlView: JXPlayerListControlView {
|
|||||||
private func updateEp() {
|
private func updateEp() {
|
||||||
let model = self.model as? FAVideoInfoModel
|
let model = self.model as? FAVideoInfoModel
|
||||||
|
|
||||||
let text = "Ep.##".localizedReplace(text: model?.episode ?? "") + "/" + "Ep.##".localizedReplace(text: "\(shortModel?.episode_total ?? 0)")
|
let text = "fableon_episode_set".localizedReplace(text: model?.episode ?? "") + "/" + "fableon_episode_set".localizedReplace(text: "\(shortModel?.episode_total ?? 0)")
|
||||||
var view = FAPlayerEpUIButton(text: text)
|
var view = FAPlayerEpUIButton(text: text)
|
||||||
view.clickHandle = { [weak self] in
|
view.clickHandle = { [weak self] in
|
||||||
self?.fa_viewModel?.onEpSelectorView()
|
self?.fa_viewModel?.onEpSelectorView()
|
||||||
|
|||||||
@ -41,7 +41,7 @@ class FAVideoLockView: UIView {
|
|||||||
if hasLastEpisodeUnlocked {
|
if hasLastEpisodeUnlocked {
|
||||||
button.configuration?.attributedTitle = .init("video_lock_tip_text".localized, attributes: attributeContainer)
|
button.configuration?.attributedTitle = .init("video_lock_tip_text".localized, attributes: attributeContainer)
|
||||||
} else {
|
} else {
|
||||||
button.configuration?.attributedTitle = .init("Unlocking costs ## coins".localizedReplace(text: "\(videoInfo?.coins ?? 0)"), attributes: attributeContainer)
|
button.configuration?.attributedTitle = .init("fableon_unlocking_coins_notice".localizedReplace(text: "\(videoInfo?.coins ?? 0)"), attributes: attributeContainer)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
button.layer.cornerRadius = 26
|
button.layer.cornerRadius = 26
|
||||||
|
|||||||
@ -12,7 +12,14 @@ import FDFullscreenPopGesture
|
|||||||
|
|
||||||
class FAPlayerDetailViewController: JXPlayerListViewController {
|
class FAPlayerDetailViewController: JXPlayerListViewController {
|
||||||
|
|
||||||
var shortPlayId: String?
|
var shortPlayId: String? {
|
||||||
|
set {
|
||||||
|
self.fa_viewModel.shortPlayId = newValue ?? ""
|
||||||
|
}
|
||||||
|
get {
|
||||||
|
return self.fa_viewModel.shortPlayId
|
||||||
|
}
|
||||||
|
}
|
||||||
var activityId: String?
|
var activityId: String?
|
||||||
|
|
||||||
override var ViewModelClass: JXPlayerListViewModel.Type {
|
override var ViewModelClass: JXPlayerListViewModel.Type {
|
||||||
@ -27,7 +34,7 @@ class FAPlayerDetailViewController: JXPlayerListViewController {
|
|||||||
let button = UIButton(type: .custom)
|
let button = UIButton(type: .custom)
|
||||||
button.setImage(UIImage(named: "Frame 3011"), for: .normal)
|
button.setImage(UIImage(named: "Frame 3011"), for: .normal)
|
||||||
button.addAction(UIAction(handler: { [weak self] _ in
|
button.addAction(UIAction(handler: { [weak self] _ in
|
||||||
self?.navigationController?.popViewController(animated: true)
|
self?.handleBackButton()
|
||||||
}), for: .touchUpInside)
|
}), for: .touchUpInside)
|
||||||
return button
|
return button
|
||||||
}()
|
}()
|
||||||
@ -44,7 +51,7 @@ class FAPlayerDetailViewController: JXPlayerListViewController {
|
|||||||
super.viewDidLoad()
|
super.viewDidLoad()
|
||||||
self.fd_interactivePopDisabled = true
|
self.fd_interactivePopDisabled = true
|
||||||
view.backgroundColor = .init(named: .color_000000)
|
view.backgroundColor = .init(named: .color_000000)
|
||||||
self.fa_viewModel.shortPlayId = shortPlayId ?? ""
|
// self.fa_viewModel.shortPlayId = shortPlayId ?? ""
|
||||||
self.register(FAPlayerDetailCell.self, forCellWithReuseIdentifier: "FAPlayerDetailCell")
|
self.register(FAPlayerDetailCell.self, forCellWithReuseIdentifier: "FAPlayerDetailCell")
|
||||||
self.delegate = self
|
self.delegate = self
|
||||||
self.dataSource = self
|
self.dataSource = self
|
||||||
@ -53,6 +60,8 @@ class FAPlayerDetailViewController: JXPlayerListViewController {
|
|||||||
requestDetailList()
|
requestDetailList()
|
||||||
|
|
||||||
fa_setupLayout()
|
fa_setupLayout()
|
||||||
|
|
||||||
|
self.fa_viewModel.requestRecommandData()
|
||||||
}
|
}
|
||||||
|
|
||||||
override func viewWillAppear(_ animated: Bool) {
|
override func viewWillAppear(_ animated: Bool) {
|
||||||
@ -101,6 +110,26 @@ class FAPlayerDetailViewController: JXPlayerListViewController {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@objc private func handleBackButton() {
|
||||||
|
self.pause()
|
||||||
|
|
||||||
|
if !self.fa_viewModel.recommandDataArr.isEmpty {
|
||||||
|
let view = FADetailRecommendView()
|
||||||
|
view.dataArr = self.fa_viewModel.recommandDataArr
|
||||||
|
view.clickCloseButton = { [weak self] in
|
||||||
|
self?.handleNavigationBack()
|
||||||
|
}
|
||||||
|
view.didSelectedVideo = { [weak self] model in
|
||||||
|
guard let self = self else { return }
|
||||||
|
self.shortPlayId = model.short_play_id
|
||||||
|
self.requestDetailList()
|
||||||
|
}
|
||||||
|
view.show(in: FATool.keyWindow)
|
||||||
|
}
|
||||||
|
|
||||||
|
// self.handleNavigationBack()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
extension FAPlayerDetailViewController {
|
extension FAPlayerDetailViewController {
|
||||||
|
|||||||
@ -13,6 +13,8 @@ class FAShortDetailViewModel: JXPlayerListViewModel, ObservableObject {
|
|||||||
|
|
||||||
private(set) var dataArr: [FAShortDetailModel] = []
|
private(set) var dataArr: [FAShortDetailModel] = []
|
||||||
|
|
||||||
|
private(set) var recommandDataArr: [FAShortPlayModel] = []
|
||||||
|
|
||||||
var shortPlayId: String = ""
|
var shortPlayId: String = ""
|
||||||
|
|
||||||
///上一次上报播放时长的节点
|
///上一次上报播放时长的节点
|
||||||
@ -242,4 +244,13 @@ extension FAShortDetailViewModel {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
///请求推荐数据
|
||||||
|
func requestRecommandData() {
|
||||||
|
FAAPI.requestDetailRecommendVideo { [weak self] list in
|
||||||
|
guard let self = self else { return }
|
||||||
|
guard let list = list else { return }
|
||||||
|
self.recommandDataArr = list
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -159,7 +159,7 @@ class FARecommendPlayerControlView: JXPlayerListControlView {
|
|||||||
let videoInfo = model?.video_info
|
let videoInfo = model?.video_info
|
||||||
|
|
||||||
|
|
||||||
let text = "Ep.##".localizedReplace(text: videoInfo?.episode ?? "") + "/" + "Ep.##".localizedReplace(text: "\(model?.episode_total ?? 0)")
|
let text = "fableon_episode_set".localizedReplace(text: videoInfo?.episode ?? "") + "/" + "fableon_episode_set".localizedReplace(text: "\(model?.episode_total ?? 0)")
|
||||||
var view = FAPlayerEpUIButton(text: text)
|
var view = FAPlayerEpUIButton(text: text)
|
||||||
view.clickHandle = { [weak self] in
|
view.clickHandle = { [weak self] in
|
||||||
self?.fa_viewModel?.pushPlayerDetail(self?.shortModel)
|
self?.fa_viewModel?.pushPlayerDetail(self?.shortModel)
|
||||||
|
|||||||
@ -66,9 +66,9 @@ extension FACoinRecordViewController: UITableViewDelegate, UITableViewDataSource
|
|||||||
let model = self.dataArr[indexPath.row]
|
let model = self.dataArr[indexPath.row]
|
||||||
let cell = tableView.dequeueReusableCell(withIdentifier: "cell", for: indexPath) as! FAOrderRecordCell
|
let cell = tableView.dequeueReusableCell(withIdentifier: "cell", for: indexPath) as! FAOrderRecordCell
|
||||||
if model.type == "send" {
|
if model.type == "send" {
|
||||||
cell.titleLabel.text = "Bonus Coins".localized
|
cell.titleLabel.text = "fableo_bonus_coins".localized
|
||||||
} else {
|
} else {
|
||||||
cell.titleLabel.text = "Recharge Coins".localized
|
cell.titleLabel.text = "fableo_recharge_coins".localized
|
||||||
}
|
}
|
||||||
cell.dateLabel.text = model.created_at
|
cell.dateLabel.text = model.created_at
|
||||||
cell.countLabel.text = "+\(model.value ?? "0")"
|
cell.countLabel.text = "+\(model.value ?? "0")"
|
||||||
|
|||||||
@ -33,7 +33,7 @@ class FAConsumptionRecordsViewController: FAViewController {
|
|||||||
|
|
||||||
override func viewDidLoad() {
|
override func viewDidLoad() {
|
||||||
super.viewDidLoad()
|
super.viewDidLoad()
|
||||||
self.title = "Consumption Records".localized
|
self.title = "fableo_consumption_records".localized
|
||||||
|
|
||||||
fa_setupLayout()
|
fa_setupLayout()
|
||||||
|
|
||||||
|
|||||||
@ -10,7 +10,7 @@ import JXSegmentedView
|
|||||||
|
|
||||||
class FAOrderRecordsViewController: FAViewController {
|
class FAOrderRecordsViewController: FAViewController {
|
||||||
|
|
||||||
private lazy var titles = ["Coin Record".localized, "VIP Record".localized]
|
private lazy var titles = ["fableo_coin_record".localized, "fableo_VIP_Record".localized]
|
||||||
private lazy var viewControllers = [FACoinRecordViewController(), FAVipRecordViewController()]
|
private lazy var viewControllers = [FACoinRecordViewController(), FAVipRecordViewController()]
|
||||||
|
|
||||||
private lazy var segmentedDataSource: JXSegmentedTitleDataSource = {
|
private lazy var segmentedDataSource: JXSegmentedTitleDataSource = {
|
||||||
@ -56,7 +56,7 @@ class FAOrderRecordsViewController: FAViewController {
|
|||||||
|
|
||||||
override func viewDidLoad() {
|
override func viewDidLoad() {
|
||||||
super.viewDidLoad()
|
super.viewDidLoad()
|
||||||
self.title = "Order Records".localized
|
self.title = "fableo_order_records".localized
|
||||||
|
|
||||||
fa_setupLayout()
|
fa_setupLayout()
|
||||||
}
|
}
|
||||||
|
|||||||
@ -33,7 +33,7 @@ class FARewardCoinsViewController: FAViewController {
|
|||||||
|
|
||||||
override func viewDidLoad() {
|
override func viewDidLoad() {
|
||||||
super.viewDidLoad()
|
super.viewDidLoad()
|
||||||
self.title = "Reward coins"
|
self.title = "fableo_reward_coins".localized
|
||||||
|
|
||||||
view.addSubview(tableView)
|
view.addSubview(tableView)
|
||||||
|
|
||||||
|
|||||||
@ -88,8 +88,8 @@ class FAStoreViewController: FAViewController {
|
|||||||
|
|
||||||
override func viewDidLoad() {
|
override func viewDidLoad() {
|
||||||
super.viewDidLoad()
|
super.viewDidLoad()
|
||||||
self.title = "Store".localized
|
self.title = "fableon_store".localized
|
||||||
let barButtonItem = UIBarButtonItem(title: "Restore".localized, style: .plain, target: self, action: #selector(handleRestore))
|
let barButtonItem = UIBarButtonItem(title: "fableo_restore".localized, style: .plain, target: self, action: #selector(handleRestore))
|
||||||
barButtonItem.tintColor = .FFFFFF
|
barButtonItem.tintColor = .FFFFFF
|
||||||
self.navigationItem.rightBarButtonItem = barButtonItem
|
self.navigationItem.rightBarButtonItem = barButtonItem
|
||||||
|
|
||||||
|
|||||||
@ -10,9 +10,9 @@ import UIKit
|
|||||||
class FAWalletViewController: FAViewController {
|
class FAWalletViewController: FAViewController {
|
||||||
|
|
||||||
private lazy var dataArr: [FAMeItemModel] = [
|
private lazy var dataArr: [FAMeItemModel] = [
|
||||||
FAMeItemModel(type: .consumptionRecords, name: "Consumption Records".localized),
|
FAMeItemModel(type: .consumptionRecords, name: "fableo_consumption_records".localized),
|
||||||
FAMeItemModel(type: .purchaseRecords, name: "Purchase Records".localized),
|
FAMeItemModel(type: .purchaseRecords, name: "fableo_purchase_records".localized),
|
||||||
FAMeItemModel(type: .rewardCoins, name: "Reward Coins".localized),
|
FAMeItemModel(type: .rewardCoins, name: "fableo_reward_coins".localized),
|
||||||
]
|
]
|
||||||
|
|
||||||
private lazy var tableView: FATableView = {
|
private lazy var tableView: FATableView = {
|
||||||
@ -38,7 +38,7 @@ class FAWalletViewController: FAViewController {
|
|||||||
|
|
||||||
override func viewDidLoad() {
|
override func viewDidLoad() {
|
||||||
super.viewDidLoad()
|
super.viewDidLoad()
|
||||||
self.title = "My Wallet".localized
|
self.title = "fableo_my_wallet".localized
|
||||||
NotificationCenter.default.addObserver(self, selector: #selector(userInfoUpdateNotification), name: FALogin.userInfoUpdateNotification, object: nil)
|
NotificationCenter.default.addObserver(self, selector: #selector(userInfoUpdateNotification), name: FALogin.userInfoUpdateNotification, object: nil)
|
||||||
|
|
||||||
fa_setupLayout()
|
fa_setupLayout()
|
||||||
|
|||||||
@ -116,16 +116,16 @@ class FAPayItem: NSObject, SmartCodable {
|
|||||||
func getTimeString() -> String? {
|
func getTimeString() -> String? {
|
||||||
switch self.vip_type_key {
|
switch self.vip_type_key {
|
||||||
case .week:
|
case .week:
|
||||||
return "week".localized
|
return "w_complex".localized
|
||||||
|
|
||||||
case .month:
|
case .month:
|
||||||
return "month".localized
|
return "m_complex".localized
|
||||||
|
|
||||||
case .quarter:
|
case .quarter:
|
||||||
return "quarter".localized
|
return "q_complex".localized
|
||||||
|
|
||||||
case .year:
|
case .year:
|
||||||
return "year".localized
|
return "Y_complex".localized
|
||||||
|
|
||||||
default:
|
default:
|
||||||
return nil
|
return nil
|
||||||
@ -135,16 +135,16 @@ class FAPayItem: NSObject, SmartCodable {
|
|||||||
func getVipTitle() -> String? {
|
func getVipTitle() -> String? {
|
||||||
switch self.vip_type_key {
|
switch self.vip_type_key {
|
||||||
case .week:
|
case .week:
|
||||||
return "Weekly VIP".localized
|
return "fableon_weekly_vip".localized
|
||||||
|
|
||||||
case .month:
|
case .month:
|
||||||
return "Monthly VIP".localized
|
return "fableon_monthly_vip".localized
|
||||||
|
|
||||||
case .quarter:
|
case .quarter:
|
||||||
return "Quarterly VIP".localized
|
return "fableon_quarterly_vip".localized
|
||||||
|
|
||||||
case .year:
|
case .year:
|
||||||
return "Yearly VIP".localized
|
return "fableon_yearly_vip".localized
|
||||||
|
|
||||||
default:
|
default:
|
||||||
return nil
|
return nil
|
||||||
|
|||||||
@ -11,10 +11,10 @@ class FACoinPackConfirmItem1View: FACoinPackConfirmItemView {
|
|||||||
|
|
||||||
override init(frame: CGRect) {
|
override init(frame: CGRect) {
|
||||||
super.init(frame: frame)
|
super.init(frame: frame)
|
||||||
titleLabel.text = "Bonus You Get".localized
|
titleLabel.text = "fableo_bonus_you_get".localized
|
||||||
|
|
||||||
let view1 = getItemView(image: UIImage(named: "Group 2072750450"), text: "Weekly Refill Package".localized)
|
let view1 = getItemView(image: UIImage(named: "Group 2072750450"), text: "fableo_weekly_refill_package".localized)
|
||||||
let view2 = getItemView(image: UIImage(named: "Group 2072750451"), text: "Dailu Bonuses".localized)
|
let view2 = getItemView(image: UIImage(named: "Group 2072750451"), text: "fableo_dailu_bonuses".localized)
|
||||||
|
|
||||||
addSubview(view1)
|
addSubview(view1)
|
||||||
addSubview(view2)
|
addSubview(view2)
|
||||||
|
|||||||
@ -47,7 +47,7 @@ class FACoinPackConfirmView: FAPanModalContentView {
|
|||||||
label.textColors = [UIColor._53_A_2_F_1.cgColor, UIColor.C_5_DDF_5.cgColor]
|
label.textColors = [UIColor._53_A_2_F_1.cgColor, UIColor.C_5_DDF_5.cgColor]
|
||||||
label.textStartPoint = .init(x: 0, y: 0.5)
|
label.textStartPoint = .init(x: 0, y: 0.5)
|
||||||
label.textEndPoint = .init(x: 1, y: 0.5)
|
label.textEndPoint = .init(x: 1, y: 0.5)
|
||||||
label.text = "What You Get".localized
|
label.text = "fableo_what_you_get".localized
|
||||||
return label
|
return label
|
||||||
}()
|
}()
|
||||||
|
|
||||||
@ -105,7 +105,7 @@ class FACoinPackConfirmView: FAPanModalContentView {
|
|||||||
button.fa_locations = [0, 1]
|
button.fa_locations = [0, 1]
|
||||||
button.fa_startPoint = .init(x: 0, y: 0.5)
|
button.fa_startPoint = .init(x: 0, y: 0.5)
|
||||||
button.fa_endPoint = .init(x: 1, y: 0.5)
|
button.fa_endPoint = .init(x: 1, y: 0.5)
|
||||||
button.setTitle("Continue".localized, for: .normal)
|
button.setTitle("fableo_continue".localized, for: .normal)
|
||||||
button.setTitleColor(.FFFFFF, for: .normal)
|
button.setTitleColor(.FFFFFF, for: .normal)
|
||||||
button.titleLabel?.font = .font(ofSize: 14, weight: .bold)
|
button.titleLabel?.font = .font(ofSize: 14, weight: .bold)
|
||||||
return button
|
return button
|
||||||
|
|||||||
@ -11,10 +11,10 @@ class FAConsumptionRecordsCell: FATableViewCell {
|
|||||||
|
|
||||||
var model: FABuyRecordsModel? {
|
var model: FABuyRecordsModel? {
|
||||||
didSet {
|
didSet {
|
||||||
titleLabel.text = "Purchase Single Episode".localized
|
titleLabel.text = "fableo_single_episode".localized
|
||||||
subtitleLabel.text = "Ep.##".localizedReplace(text: "\(model?.episode ?? "")") + " " + "\(model?.name ?? "")"
|
subtitleLabel.text = "fableon_episode_set".localizedReplace(text: "\(model?.episode ?? "")") + " " + "\(model?.name ?? "")"
|
||||||
dateLabel.text = model?.created_at
|
dateLabel.text = model?.created_at
|
||||||
coinsLabel.text = "-\(model?.coins ?? 0)" + "Coins".localized
|
coinsLabel.text = "-\(model?.coins ?? 0)" + "fableon_coins".localized
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -20,7 +20,7 @@ class FARewardCoinsCell: FATableViewCell {
|
|||||||
expiresIconImageView.isHidden = false
|
expiresIconImageView.isHidden = false
|
||||||
expiresLabel.isHidden = false
|
expiresLabel.isHidden = false
|
||||||
expiredLabel.isHidden = true
|
expiredLabel.isHidden = true
|
||||||
expiresLabel.text = "Expires in ## days".localizedReplace(text: model?.diff_datetime ?? "")
|
expiresLabel.text = "fableo_expires_#_days".localizedReplace(text: model?.diff_datetime ?? "")
|
||||||
} else {
|
} else {
|
||||||
expiresIconImageView.isHidden = true
|
expiresIconImageView.isHidden = true
|
||||||
expiresLabel.isHidden = true
|
expiresLabel.isHidden = true
|
||||||
|
|||||||
@ -31,7 +31,7 @@ class FAStoreCoinsBigCell: FAStoreCoinsCell {
|
|||||||
if sendCoins > 0 {
|
if sendCoins > 0 {
|
||||||
sendCoinsLabel.isHidden = false
|
sendCoinsLabel.isHidden = false
|
||||||
sendCoinsRatioImageView.isHidden = false
|
sendCoinsRatioImageView.isHidden = false
|
||||||
sendCoinsLabel.text = "+\(sendCoins) " + "Coins".localized
|
sendCoinsLabel.text = "+\(sendCoins) " + "fableon_coins".localized
|
||||||
|
|
||||||
let ratio = String(format: "%.0f", CGFloat(sendCoins) / CGFloat(coins) * 100)
|
let ratio = String(format: "%.0f", CGFloat(sendCoins) / CGFloat(coins) * 100)
|
||||||
sendCoinsRatioLabel.text = "+\(ratio)%"
|
sendCoinsRatioLabel.text = "+\(ratio)%"
|
||||||
|
|||||||
@ -51,7 +51,7 @@ class FAStoreCoinsPackCell: FAStoreCoinsCell {
|
|||||||
let label = UILabel()
|
let label = UILabel()
|
||||||
label.font = .font(ofSize: 14, weight: .init(700))
|
label.font = .font(ofSize: 14, weight: .init(700))
|
||||||
label.textColor = .FFFFFF
|
label.textColor = .FFFFFF
|
||||||
label.text = "Weekly Refill".localized
|
label.text = "fableo_weekly_refill".localized
|
||||||
return label
|
return label
|
||||||
}()
|
}()
|
||||||
|
|
||||||
|
|||||||
@ -27,7 +27,7 @@ class FAStoreCoinsSmallCell: FAStoreCoinsCell {
|
|||||||
if sendCoins > 0 {
|
if sendCoins > 0 {
|
||||||
sendCoinsLabel.isHidden = false
|
sendCoinsLabel.isHidden = false
|
||||||
sendCoinsRatioView.isHidden = false
|
sendCoinsRatioView.isHidden = false
|
||||||
sendCoinsLabel.text = "+\(sendCoins) " + "Coins".localized
|
sendCoinsLabel.text = "+\(sendCoins) " + "fableon_coins".localized
|
||||||
|
|
||||||
let ratio = String(format: "%.0f", CGFloat(sendCoins) / CGFloat(coins) * 100)
|
let ratio = String(format: "%.0f", CGFloat(sendCoins) / CGFloat(coins) * 100)
|
||||||
sendCoinsRatioLabel.text = "+\(ratio)%"
|
sendCoinsRatioLabel.text = "+\(ratio)%"
|
||||||
|
|||||||
@ -17,7 +17,7 @@ class FAStoreVipCell: UICollectionViewCell {
|
|||||||
// coinTimeLabel.text = item?.auto_sub
|
// coinTimeLabel.text = item?.auto_sub
|
||||||
|
|
||||||
if let coins = item?.send_coins, coins > 0 {
|
if let coins = item?.send_coins, coins > 0 {
|
||||||
sendCoinLabel.text = "+\("extra".localized) \(coins)"
|
sendCoinLabel.text = "+\("fableo_extra".localized) \(coins)"
|
||||||
sendCoinLabel.isHidden = false
|
sendCoinLabel.isHidden = false
|
||||||
coinImageView.isHidden = false
|
coinImageView.isHidden = false
|
||||||
} else {
|
} else {
|
||||||
|
|||||||
@ -36,7 +36,7 @@ class FAWalletHeaderView: UIView {
|
|||||||
button.fa_locations = [0, 1]
|
button.fa_locations = [0, 1]
|
||||||
button.fa_startPoint = .init(x: 0, y: 0.5)
|
button.fa_startPoint = .init(x: 0, y: 0.5)
|
||||||
button.fa_endPoint = .init(x: 1, y: 0.5)
|
button.fa_endPoint = .init(x: 1, y: 0.5)
|
||||||
button.setTitle("Store".localized, for: .normal)
|
button.setTitle("fableon_store".localized, for: .normal)
|
||||||
button.setTitleColor(._000000, for: .normal)
|
button.setTitleColor(._000000, for: .normal)
|
||||||
button.titleLabel?.font = .font(ofSize: 18, weight: .bold)
|
button.titleLabel?.font = .font(ofSize: 18, weight: .bold)
|
||||||
return button
|
return button
|
||||||
@ -52,7 +52,7 @@ class FAWalletHeaderView: UIView {
|
|||||||
var config = UIButton.Configuration.plain()
|
var config = UIButton.Configuration.plain()
|
||||||
config.image = UIImage(named: "coins_icon_02")
|
config.image = UIImage(named: "coins_icon_02")
|
||||||
config.imagePadding = 11
|
config.imagePadding = 11
|
||||||
config.attributedTitle = AttributedString("Coins".localized, attributes: AttributeContainer([
|
config.attributedTitle = AttributedString("fableon_coins".localized, attributes: AttributeContainer([
|
||||||
.font : UIFont.font(ofSize: 10, weight: .bold),
|
.font : UIFont.font(ofSize: 10, weight: .bold),
|
||||||
.foregroundColor : UIColor.F_7_F_497
|
.foregroundColor : UIColor.F_7_F_497
|
||||||
]))
|
]))
|
||||||
@ -77,7 +77,7 @@ class FAWalletHeaderView: UIView {
|
|||||||
config.imagePadding = 11
|
config.imagePadding = 11
|
||||||
config.imagePlacement = .trailing
|
config.imagePlacement = .trailing
|
||||||
config.titleAlignment = .leading
|
config.titleAlignment = .leading
|
||||||
config.attributedTitle = AttributedString("Bonus".localized, attributes: AttributeContainer([
|
config.attributedTitle = AttributedString("fableon_bonus".localized, attributes: AttributeContainer([
|
||||||
.font : UIFont.font(ofSize: 10, weight: .bold),
|
.font : UIFont.font(ofSize: 10, weight: .bold),
|
||||||
.foregroundColor : UIColor.F_7_F_497
|
.foregroundColor : UIColor.F_7_F_497
|
||||||
]))
|
]))
|
||||||
|
|||||||
@ -37,7 +37,7 @@ class FAApnsAlert: FABaseAlert {
|
|||||||
button.layer.masksToBounds = true
|
button.layer.masksToBounds = true
|
||||||
button.layer.borderWidth = 1
|
button.layer.borderWidth = 1
|
||||||
button.layer.borderColor = UIColor.FFFFFF.cgColor
|
button.layer.borderColor = UIColor.FFFFFF.cgColor
|
||||||
button.setTitle("Later".localized, for: .normal)
|
button.setTitle("fableon_open_notification_later".localized, for: .normal)
|
||||||
button.setTitleColor(.FFFFFF, for: .normal)
|
button.setTitleColor(.FFFFFF, for: .normal)
|
||||||
button.titleLabel?.font = .font(ofSize: 14, weight: .semibold)
|
button.titleLabel?.font = .font(ofSize: 14, weight: .semibold)
|
||||||
button.addTarget(self, action: #selector(dismiss), for: .touchUpInside)
|
button.addTarget(self, action: #selector(dismiss), for: .touchUpInside)
|
||||||
@ -46,7 +46,7 @@ class FAApnsAlert: FABaseAlert {
|
|||||||
|
|
||||||
override init(frame: CGRect) {
|
override init(frame: CGRect) {
|
||||||
super.init(frame: frame)
|
super.init(frame: frame)
|
||||||
highlightButton.setTitle("Open".localized, for: .normal)
|
highlightButton.setTitle("fableon_open".localized, for: .normal)
|
||||||
|
|
||||||
fa_setupLayout()
|
fa_setupLayout()
|
||||||
}
|
}
|
||||||
|
|||||||
@ -50,7 +50,7 @@ class FACoinsPackAlert: FABaseAlert {
|
|||||||
button.layer.masksToBounds = true
|
button.layer.masksToBounds = true
|
||||||
button.layer.borderColor = UIColor._777777.cgColor
|
button.layer.borderColor = UIColor._777777.cgColor
|
||||||
button.layer.borderWidth = 1
|
button.layer.borderWidth = 1
|
||||||
button.setTitle("Later".localized, for: .normal)
|
button.setTitle("fableon_open_notification_later".localized, for: .normal)
|
||||||
button.setTitleColor(._777777, for: .normal)
|
button.setTitleColor(._777777, for: .normal)
|
||||||
button.titleLabel?.font = .font(ofSize: 14, weight: .bold)
|
button.titleLabel?.font = .font(ofSize: 14, weight: .bold)
|
||||||
button.addTarget(self, action: #selector(dismiss), for: .touchUpInside)
|
button.addTarget(self, action: #selector(dismiss), for: .touchUpInside)
|
||||||
@ -60,7 +60,7 @@ class FACoinsPackAlert: FABaseAlert {
|
|||||||
override init(frame: CGRect) {
|
override init(frame: CGRect) {
|
||||||
super.init(frame: frame)
|
super.init(frame: frame)
|
||||||
|
|
||||||
self.highlightButton.setTitle("Claim Now".localized, for: .normal)
|
self.highlightButton.setTitle("fableon_claim_now".localized, for: .normal)
|
||||||
self.highlightButton.setTitleColor(.FFFFFF, 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.fa_colors = [UIColor._53_A_2_F_1.cgColor, UIColor.C_5_DDF_5.cgColor]
|
||||||
self.highlightButton.layer.cornerRadius = 24
|
self.highlightButton.layer.cornerRadius = 24
|
||||||
|
|||||||
92
Fableon/Object/Libs/Alert/FALogoutAlert.swift
Normal file
@ -0,0 +1,92 @@
|
|||||||
|
//
|
||||||
|
// FALogoutAlert.swift
|
||||||
|
// Fableon
|
||||||
|
//
|
||||||
|
// Created by 湖北秦九 on 2025/11/1.
|
||||||
|
//
|
||||||
|
|
||||||
|
import UIKit
|
||||||
|
|
||||||
|
class FALogoutAlert: FABaseAlert {
|
||||||
|
|
||||||
|
private lazy var imageView = UIImageView(image: UIImage(named: "退出登录"))
|
||||||
|
|
||||||
|
private lazy var titleLabel: UILabel = {
|
||||||
|
let label = UILabel()
|
||||||
|
label.font = .font(ofSize: 18, weight: .semibold)
|
||||||
|
label.textColor = .FFFFFF
|
||||||
|
label.text = "logout_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 = "logout_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("fableon_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("fableon_logout".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")
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -38,7 +38,7 @@ class FARemoveCollectAlert: FABaseAlert {
|
|||||||
button.layer.masksToBounds = true
|
button.layer.masksToBounds = true
|
||||||
button.layer.borderWidth = 1
|
button.layer.borderWidth = 1
|
||||||
button.layer.borderColor = UIColor.FFFFFF.cgColor
|
button.layer.borderColor = UIColor.FFFFFF.cgColor
|
||||||
button.setTitle("Cancel".localized, for: .normal)
|
button.setTitle("fableon_cancel".localized, for: .normal)
|
||||||
button.setTitleColor(.FFFFFF, for: .normal)
|
button.setTitleColor(.FFFFFF, for: .normal)
|
||||||
button.titleLabel?.font = .font(ofSize: 14, weight: .medium)
|
button.titleLabel?.font = .font(ofSize: 14, weight: .medium)
|
||||||
button.addTarget(self, action: #selector(dismiss), for: .touchUpInside)
|
button.addTarget(self, action: #selector(dismiss), for: .touchUpInside)
|
||||||
@ -48,7 +48,7 @@ class FARemoveCollectAlert: FABaseAlert {
|
|||||||
override init(frame: CGRect) {
|
override init(frame: CGRect) {
|
||||||
super.init(frame: frame)
|
super.init(frame: frame)
|
||||||
|
|
||||||
highlightButton.setTitle("Remove".localized, for: .normal)
|
highlightButton.setTitle("fableon_remove".localized, for: .normal)
|
||||||
|
|
||||||
containerView.addSubview(imageView)
|
containerView.addSubview(imageView)
|
||||||
contentView.addSubview(titleLabel)
|
contentView.addSubview(titleLabel)
|
||||||
|
|||||||
127
Fableon/Object/Libs/Alert/FAUpdatesAlert.swift
Normal file
@ -0,0 +1,127 @@
|
|||||||
|
//
|
||||||
|
// FAUpdatesAlert.swift
|
||||||
|
// Fableon
|
||||||
|
//
|
||||||
|
// Created by 湖北秦九 on 2025/10/31.
|
||||||
|
//
|
||||||
|
|
||||||
|
import UIKit
|
||||||
|
|
||||||
|
class FAUpdatesAlert: FABaseAlert {
|
||||||
|
|
||||||
|
var model: FAVersionUpdateModel? {
|
||||||
|
didSet {
|
||||||
|
textLabel.text = model?.des
|
||||||
|
|
||||||
|
versionLabel.text = "v\(model?.version_name ?? "")"
|
||||||
|
closeButton.isHidden = model?.force ?? false
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private lazy var imageView = UIImageView(image: UIImage(named: "__New"))
|
||||||
|
private lazy var titleLabel: UILabel = {
|
||||||
|
let label = UILabel()
|
||||||
|
label.font = .font(ofSize: 18, weight: .semibold)
|
||||||
|
label.textColor = .FFFFFF
|
||||||
|
label.textAlignment = .center
|
||||||
|
label.numberOfLines = 0
|
||||||
|
label.text = "updates_alert_title".localized
|
||||||
|
return label
|
||||||
|
}()
|
||||||
|
|
||||||
|
private lazy var textLabel: UILabel = {
|
||||||
|
let label = UILabel()
|
||||||
|
label.font = .font(ofSize: 12, weight: .regular)
|
||||||
|
label.textColor = .FFFFFF
|
||||||
|
label.numberOfLines = 0
|
||||||
|
return label
|
||||||
|
}()
|
||||||
|
|
||||||
|
private lazy var versionView: UIView = {
|
||||||
|
let view = UIView()
|
||||||
|
view.backgroundColor = .E_4275_D
|
||||||
|
view.layer.cornerRadius = 9
|
||||||
|
view.layer.masksToBounds = true
|
||||||
|
return view
|
||||||
|
}()
|
||||||
|
|
||||||
|
private lazy var versionLabel: UILabel = {
|
||||||
|
let label = UILabel()
|
||||||
|
label.font = .font(ofSize: 12, weight: .regular)
|
||||||
|
label.textColor = .FFFFFF
|
||||||
|
return label
|
||||||
|
}()
|
||||||
|
|
||||||
|
override init(frame: CGRect) {
|
||||||
|
super.init(frame: frame)
|
||||||
|
highlightButton.layer.cornerRadius = 18
|
||||||
|
highlightButton.setTitle("fableon_update_now", for: .normal)
|
||||||
|
fa_setupLayout()
|
||||||
|
}
|
||||||
|
|
||||||
|
@MainActor required init?(coder: NSCoder) {
|
||||||
|
fatalError("init(coder:) has not been implemented")
|
||||||
|
}
|
||||||
|
|
||||||
|
override func handleHighlightButton() {
|
||||||
|
// if self.model?.force != true {
|
||||||
|
// super.handleHighlightButton()
|
||||||
|
// }
|
||||||
|
guard let url = URL(string: "https://apps.apple.com/app/id6754154359") else { return }
|
||||||
|
let application = UIApplication.shared
|
||||||
|
if application.canOpenURL(url) {
|
||||||
|
application.open(url)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
extension FAUpdatesAlert {
|
||||||
|
|
||||||
|
private func fa_setupLayout() {
|
||||||
|
containerView.addSubview(imageView)
|
||||||
|
contentView.addSubview(titleLabel)
|
||||||
|
contentView.addSubview(textLabel)
|
||||||
|
contentView.addSubview(highlightButton)
|
||||||
|
contentView.addSubview(versionView)
|
||||||
|
versionView.addSubview(versionLabel)
|
||||||
|
|
||||||
|
imageView.snp.makeConstraints { make in
|
||||||
|
make.centerX.equalToSuperview()
|
||||||
|
make.top.equalToSuperview().offset(-100)
|
||||||
|
}
|
||||||
|
|
||||||
|
titleLabel.snp.makeConstraints { make in
|
||||||
|
make.centerX.equalToSuperview()
|
||||||
|
make.right.lessThanOrEqualToSuperview().offset(-20)
|
||||||
|
make.top.equalTo(imageView.snp.bottom).offset(20)
|
||||||
|
}
|
||||||
|
|
||||||
|
versionView.snp.makeConstraints { make in
|
||||||
|
make.centerX.equalToSuperview()
|
||||||
|
make.top.equalTo(titleLabel.snp.bottom).offset(10)
|
||||||
|
make.height.equalTo(18)
|
||||||
|
}
|
||||||
|
|
||||||
|
versionLabel.snp.makeConstraints { make in
|
||||||
|
make.center.equalToSuperview()
|
||||||
|
make.left.equalToSuperview().offset(7)
|
||||||
|
}
|
||||||
|
|
||||||
|
textLabel.snp.makeConstraints { make in
|
||||||
|
make.centerX.equalToSuperview()
|
||||||
|
make.right.lessThanOrEqualToSuperview().offset(-20)
|
||||||
|
// make.top.equalTo(titleLabel.snp.bottom).offset(15)
|
||||||
|
make.top.equalTo(versionView.snp.bottom).offset(10)
|
||||||
|
}
|
||||||
|
|
||||||
|
highlightButton.snp.makeConstraints { make in
|
||||||
|
make.left.equalToSuperview().offset(24)
|
||||||
|
make.centerX.equalToSuperview()
|
||||||
|
make.top.equalTo(textLabel.snp.bottom).offset(20)
|
||||||
|
make.bottom.equalToSuperview().offset(-20)
|
||||||
|
make.height.equalTo(36)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@ -27,7 +27,7 @@ class FAVipRetainAlert: FABaseAlert {
|
|||||||
view.dotColor = ._20_A_1_FF
|
view.dotColor = ._20_A_1_FF
|
||||||
view.textColors = [UIColor._53_A_2_F_1.cgColor, UIColor.C_5_DDF_5.cgColor]
|
view.textColors = [UIColor._53_A_2_F_1.cgColor, UIColor.C_5_DDF_5.cgColor]
|
||||||
view.font = .font(ofSize: 24, weight: .init(900))
|
view.font = .font(ofSize: 24, weight: .init(900))
|
||||||
view.text = "Weekly Refill".localized.uppercased()
|
view.text = "fableo_weekly_refill".localized.uppercased()
|
||||||
return view
|
return view
|
||||||
}()
|
}()
|
||||||
|
|
||||||
@ -66,7 +66,7 @@ class FAVipRetainAlert: FABaseAlert {
|
|||||||
button.fa_locations = [0, 1]
|
button.fa_locations = [0, 1]
|
||||||
button.fa_startPoint = .init(x: 0, y: 0.5)
|
button.fa_startPoint = .init(x: 0, y: 0.5)
|
||||||
button.fa_endPoint = .init(x: 0.7, y: 0.5)
|
button.fa_endPoint = .init(x: 0.7, y: 0.5)
|
||||||
button.setTitle("Buy Now".localized, for: .normal)
|
button.setTitle("fableon_buy_now".localized, for: .normal)
|
||||||
button.setTitleColor(.FFFFFF, for: .normal)
|
button.setTitleColor(.FFFFFF, for: .normal)
|
||||||
button.titleLabel?.font = .font(ofSize: 14, weight: .bold)
|
button.titleLabel?.font = .font(ofSize: 14, weight: .bold)
|
||||||
return button
|
return button
|
||||||
|
|||||||
@ -152,7 +152,7 @@ class FAIapManager {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if isLoding {
|
if isLoding {
|
||||||
FAToast.show(text: "success".localized)
|
FAToast.show(text: "fableo_success".localized)
|
||||||
}
|
}
|
||||||
completer?(true, buyType)
|
completer?(true, buyType)
|
||||||
if buyType == .subVip {
|
if buyType == .subVip {
|
||||||
@ -223,7 +223,7 @@ extension FAIapManager: JXIAPManagerDelegate {
|
|||||||
FALogin.manager.userInfo?.is_vip = true
|
FALogin.manager.userInfo?.is_vip = true
|
||||||
}
|
}
|
||||||
|
|
||||||
FAToast.show(text: "success".localized)
|
FAToast.show(text: "fableo_success".localized)
|
||||||
self.completionHandler?(true)
|
self.completionHandler?(true)
|
||||||
if buyType == .subVip {
|
if buyType == .subVip {
|
||||||
NotificationCenter.default.post(name: FAIapManager.buyVipFinishNotification, object: nil)
|
NotificationCenter.default.post(name: FAIapManager.buyVipFinishNotification, object: nil)
|
||||||
|
|||||||
16
Fableon/Object/Libs/FALocalized/FALanguageDataModel.swift
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
//
|
||||||
|
// FALanguageDataModel.swift
|
||||||
|
// Fableon
|
||||||
|
//
|
||||||
|
// Created by 湖北秦九 on 2025/11/1.
|
||||||
|
//
|
||||||
|
|
||||||
|
import UIKit
|
||||||
|
import SmartCodable
|
||||||
|
|
||||||
|
struct FALanguageDataModel: SmartCodable {
|
||||||
|
|
||||||
|
///翻译数据
|
||||||
|
var translates: [String : String]?
|
||||||
|
|
||||||
|
}
|
||||||
152
Fableon/Object/Libs/FALocalized/FALanguageManager.swift
Normal file
@ -0,0 +1,152 @@
|
|||||||
|
//
|
||||||
|
// FALanguageManager.swift
|
||||||
|
// Fableon
|
||||||
|
//
|
||||||
|
// Created by 湖北秦九 on 2025/10/15.
|
||||||
|
//
|
||||||
|
|
||||||
|
|
||||||
|
import UIKit
|
||||||
|
|
||||||
|
|
||||||
|
class FALanguageManager {
|
||||||
|
|
||||||
|
static let manager = FALanguageManager()
|
||||||
|
|
||||||
|
private let LanguageUserDefaultsKey = "FALanguageManager.LanguageUserDefaultsKey"
|
||||||
|
private let LanguageDataUserDefaultsKey = "FALanguageManager.LanguageDataUserDefaultsKey"
|
||||||
|
private let LanguageDataLanguageKeyUserDefaultsKey = "FALanguageManager.LanguageDataLanguageKeyUserDefaultsKey"
|
||||||
|
|
||||||
|
|
||||||
|
///多语言数据
|
||||||
|
private(set) lazy var languageData: [String : String]? = UserDefaults.standard.object(forKey: LanguageDataUserDefaultsKey) as? [String : String]
|
||||||
|
{
|
||||||
|
didSet {
|
||||||
|
UserDefaults.standard.set(languageData, forKey: LanguageDataUserDefaultsKey)
|
||||||
|
UserDefaults.standard.synchronize()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
///当前语言数据对应的key
|
||||||
|
private(set) lazy var languageDataLanguageKey: String? = UserDefaults.standard.object(forKey: LanguageDataLanguageKeyUserDefaultsKey) as? String
|
||||||
|
{
|
||||||
|
didSet {
|
||||||
|
UserDefaults.standard.set(languageDataLanguageKey, forKey: LanguageDataLanguageKeyUserDefaultsKey)
|
||||||
|
UserDefaults.standard.synchronize()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 获取当前语言代码(如果用户未手动设置,则返回系统语言)
|
||||||
|
var currentLanguageKey: String {
|
||||||
|
get {
|
||||||
|
var key = UserDefaults.standard.string(forKey: LanguageUserDefaultsKey) ?? Locale.preferredLanguages.first
|
||||||
|
|
||||||
|
if key?.contains("zh-Hans") == true {
|
||||||
|
key = "zh"
|
||||||
|
} else if key?.contains("zh-Hant") == true {
|
||||||
|
key = "zh_hk"
|
||||||
|
} else {
|
||||||
|
let arr = key?.components(separatedBy: "-")
|
||||||
|
key = arr?.first
|
||||||
|
}
|
||||||
|
return key ?? "en"
|
||||||
|
}
|
||||||
|
set {
|
||||||
|
UserDefaults.standard.set(newValue, forKey: LanguageUserDefaultsKey)
|
||||||
|
UserDefaults.standard.synchronize()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var mjLanguageKey: String {
|
||||||
|
let key = currentLanguageKey
|
||||||
|
if key == "zh" {
|
||||||
|
return "zh-Hans"
|
||||||
|
} else if key == "zh_hk" {
|
||||||
|
return "zh-Hant"
|
||||||
|
}
|
||||||
|
return key
|
||||||
|
}
|
||||||
|
|
||||||
|
// 判断是否跟随系统
|
||||||
|
var isFollowingSystem: Bool {
|
||||||
|
return UserDefaults.standard.string(forKey: LanguageUserDefaultsKey) == nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// 还原为系统默认语言
|
||||||
|
func resetToSystemLanguage() {
|
||||||
|
UserDefaults.standard.removeObject(forKey: LanguageUserDefaultsKey)
|
||||||
|
UserDefaults.standard.synchronize()
|
||||||
|
}
|
||||||
|
|
||||||
|
//切换语言
|
||||||
|
func switchLanguage(_ key: String, completer: ((_ finish: Bool) -> Void)?) {
|
||||||
|
FAHUD.show()
|
||||||
|
|
||||||
|
FAAPI.requestLanguageDataList(key: key) { [weak self] model in
|
||||||
|
FAHUD.dismiss()
|
||||||
|
guard let self = self else { return }
|
||||||
|
guard let list = model?.translates, list.count > 0 else {
|
||||||
|
completer?(false)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
currentLanguageKey = key
|
||||||
|
languageDataLanguageKey = key
|
||||||
|
languageData = list
|
||||||
|
completer?(true)
|
||||||
|
NotificationCenter.default.post(name: FALanguageManager.languageDidChange, object: nil)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//更新本地语言数据
|
||||||
|
func updateLanguageData(completer: ((_ finish: Bool) -> Void)?) {
|
||||||
|
let key = self.currentLanguageKey
|
||||||
|
FAAPI.requestLanguageDataList(key: key) { [weak self] model in
|
||||||
|
guard let self = self else {
|
||||||
|
completer?(false)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
guard let list = model?.translates, list.count > 0 else {
|
||||||
|
completer?(false)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
languageDataLanguageKey = key
|
||||||
|
languageData = list
|
||||||
|
completer?(true)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 获取本地化字符串
|
||||||
|
func localizedString(forKey key: String, tableName: String? = nil) -> String {
|
||||||
|
if let languageData = languageData,
|
||||||
|
let text = languageData[key] {
|
||||||
|
return text
|
||||||
|
|
||||||
|
} else if let selectedLanguage = UserDefaults.standard.string(forKey: LanguageUserDefaultsKey),
|
||||||
|
let bundlePath = Bundle.main.path(forResource: selectedLanguage, ofType: "lproj"),
|
||||||
|
let bundle = Bundle(path: bundlePath) {
|
||||||
|
|
||||||
|
return bundle.localizedString(forKey: key, value: nil, table: tableName)
|
||||||
|
} else {
|
||||||
|
return NSLocalizedString(key, tableName: tableName, bundle: .main, value: "", comment: "")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
extension FALanguageManager {
|
||||||
|
|
||||||
|
static let languageDidChange = Notification.Name(rawValue: "FALanguageManager.languageDidChange")
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
extension String {
|
||||||
|
var localized: String {
|
||||||
|
var text = FALanguageManager.manager.localizedString(forKey: self)
|
||||||
|
text = text.replacingOccurrences(of: "<br>", with: "\n")
|
||||||
|
return text
|
||||||
|
}
|
||||||
|
|
||||||
|
func localizedReplace(text: String?) -> String {
|
||||||
|
return self.localized.replacingOccurrences(of: "##", with: text ?? "")
|
||||||
|
}
|
||||||
|
}
|
||||||
18
Fableon/Object/Libs/FALocalized/FALanguageModel.swift
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
//
|
||||||
|
// FALanguageModel.swift
|
||||||
|
// Fableon
|
||||||
|
//
|
||||||
|
// Created by 湖北秦九 on 2025/11/1.
|
||||||
|
//
|
||||||
|
|
||||||
|
import UIKit
|
||||||
|
import SmartCodable
|
||||||
|
|
||||||
|
struct FALanguageModel: SmartCodable {
|
||||||
|
|
||||||
|
var cn_name: String?
|
||||||
|
var show_name: String?
|
||||||
|
var id: String?
|
||||||
|
var is_up_to_list: String?
|
||||||
|
var lang_key: String?
|
||||||
|
}
|
||||||
@ -1,110 +0,0 @@
|
|||||||
//
|
|
||||||
// FALocalized.swift
|
|
||||||
// Fableon
|
|
||||||
//
|
|
||||||
// Created by 湖北秦九 on 2025/10/15.
|
|
||||||
//
|
|
||||||
|
|
||||||
|
|
||||||
import UIKit
|
|
||||||
|
|
||||||
|
|
||||||
class FALocalized {
|
|
||||||
|
|
||||||
static let manager = FALocalized()
|
|
||||||
|
|
||||||
private let LocalizedUserDefaultsKey = "FALocalized.LocalizedUserDefaultsKey"
|
|
||||||
private let LocalizedDataUserDefaultsKey = "FALocalized.LocalizedDataUserDefaultsKey"
|
|
||||||
private let LocalizedDataLocalizedKeyUserDefaultsKey = "FALocalized.LocalizedDataLocalizedKeyUserDefaultsKey"
|
|
||||||
|
|
||||||
|
|
||||||
///多语言数据
|
|
||||||
private(set) lazy var localizedData: [String : String]? = UserDefaults.standard.object(forKey: LocalizedDataUserDefaultsKey) as? [String : String]
|
|
||||||
{
|
|
||||||
didSet {
|
|
||||||
UserDefaults.standard.set(localizedData, forKey: LocalizedDataUserDefaultsKey)
|
|
||||||
UserDefaults.standard.synchronize()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
///当前语言数据对应的key
|
|
||||||
private(set) lazy var localizedDataLocalizedKey: String? = UserDefaults.standard.object(forKey: LocalizedDataLocalizedKeyUserDefaultsKey) as? String
|
|
||||||
{
|
|
||||||
didSet {
|
|
||||||
UserDefaults.standard.set(localizedDataLocalizedKey, forKey: LocalizedDataLocalizedKeyUserDefaultsKey)
|
|
||||||
UserDefaults.standard.synchronize()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// 获取当前语言代码(如果用户未手动设置,则返回系统语言)
|
|
||||||
var currentLocalizedKey: String {
|
|
||||||
get {
|
|
||||||
return "en"
|
|
||||||
// var key = UserDefaults.standard.string(forKey: LocalizedUserDefaultsKey) ?? Locale.preferredLanguages.first
|
|
||||||
//
|
|
||||||
// if key?.contains("zh-Hans") == true {
|
|
||||||
// key = "zh"
|
|
||||||
// } else if key?.contains("zh-Hant") == true {
|
|
||||||
// key = "zh_hk"
|
|
||||||
// } else {
|
|
||||||
// let arr = key?.components(separatedBy: "-")
|
|
||||||
// key = arr?.first
|
|
||||||
// }
|
|
||||||
// return key ?? "en"
|
|
||||||
}
|
|
||||||
set {
|
|
||||||
UserDefaults.standard.set(newValue, forKey: LocalizedUserDefaultsKey)
|
|
||||||
UserDefaults.standard.synchronize()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
var mjLocalizedKey: String {
|
|
||||||
let key = currentLocalizedKey
|
|
||||||
if key == "zh" {
|
|
||||||
return "zh-Hans"
|
|
||||||
} else if key == "zh_hk" {
|
|
||||||
return "zh-Hant"
|
|
||||||
}
|
|
||||||
return key
|
|
||||||
}
|
|
||||||
|
|
||||||
// 判断是否跟随系统
|
|
||||||
var isFollowingSystem: Bool {
|
|
||||||
return UserDefaults.standard.string(forKey: LocalizedUserDefaultsKey) == nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// 还原为系统默认语言
|
|
||||||
func resetToSystemLanguage() {
|
|
||||||
UserDefaults.standard.removeObject(forKey: LocalizedUserDefaultsKey)
|
|
||||||
UserDefaults.standard.synchronize()
|
|
||||||
}
|
|
||||||
|
|
||||||
// 获取本地化字符串
|
|
||||||
func localizedString(forKey key: String, tableName: String? = nil) -> String {
|
|
||||||
if let localizedData = localizedData,
|
|
||||||
let text = localizedData[key] {
|
|
||||||
return text
|
|
||||||
|
|
||||||
} else if let selectedLanguage = UserDefaults.standard.string(forKey: LocalizedUserDefaultsKey),
|
|
||||||
let bundlePath = Bundle.main.path(forResource: selectedLanguage, ofType: "lproj"),
|
|
||||||
let bundle = Bundle(path: bundlePath) {
|
|
||||||
|
|
||||||
return bundle.localizedString(forKey: key, value: nil, table: tableName)
|
|
||||||
} else {
|
|
||||||
return NSLocalizedString(key, tableName: tableName, bundle: .main, value: "", comment: "")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
extension String {
|
|
||||||
var localized: String {
|
|
||||||
var text = FALocalized.manager.localizedString(forKey: self)
|
|
||||||
text = text.replacingOccurrences(of: "<br>", with: "\n")
|
|
||||||
return text
|
|
||||||
}
|
|
||||||
|
|
||||||
func localizedReplace(text: String?) -> String {
|
|
||||||
return self.localized.replacingOccurrences(of: "##", with: text ?? "")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -32,6 +32,13 @@ class FATool {
|
|||||||
return keyWindow?.rootViewController
|
return keyWindow?.rootViewController
|
||||||
}
|
}
|
||||||
|
|
||||||
|
///获得启动图
|
||||||
|
static func getLanuchViewController() -> UIViewController? {
|
||||||
|
let storyboard = UIStoryboard(name: "LaunchScreen", bundle: nil)
|
||||||
|
let vc = storyboard.instantiateInitialViewController()
|
||||||
|
return vc
|
||||||
|
}
|
||||||
|
|
||||||
static var topViewController: UIViewController? {
|
static var topViewController: UIViewController? {
|
||||||
var resultVC: UIViewController? = self.rootViewController
|
var resultVC: UIViewController? = self.rootViewController
|
||||||
if let rootNav = resultVC as? UINavigationController {
|
if let rootNav = resultVC as? UINavigationController {
|
||||||
@ -64,7 +71,7 @@ extension FATool {
|
|||||||
completion?(ASIdentifierManager.shared().advertisingIdentifier.uuidString)
|
completion?(ASIdentifierManager.shared().advertisingIdentifier.uuidString)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
guard FANetworkMonitor.manager.isReachable == true, FAAdjustStateManager.manager.apnsAuthorizationFinish, FAAdjustStateManager.manager.isOpenApp else {
|
guard FANetworkMonitor.manager.isReachable == true, FAAdjustStateManager.manager.apnsAuthorizationFinish else {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -91,3 +98,33 @@ extension FATool {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//MARK: 检查更新
|
||||||
|
extension FATool {
|
||||||
|
|
||||||
|
static func checkUpdates() {
|
||||||
|
FAAPI.requestVersionUpdateData { model in
|
||||||
|
guard let model = model else { return }
|
||||||
|
self.showUpdatesAlert(model)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static func showUpdatesAlert(_ model: FAVersionUpdateModel) {
|
||||||
|
#if !DEBUG
|
||||||
|
if model.force != true {
|
||||||
|
if let date = UserDefaults.standard.object(forKey: kFAVersionUpdateAlertDefaultsKey) as? Date {
|
||||||
|
if date.fa_isToday { return }
|
||||||
|
}
|
||||||
|
UserDefaults.standard.set(Date(), forKey: kFAVersionUpdateAlertDefaultsKey)
|
||||||
|
}
|
||||||
|
#endif // !DEBUG
|
||||||
|
|
||||||
|
|
||||||
|
if model.canUpdate() {
|
||||||
|
let view = FAUpdatesAlert()
|
||||||
|
view.model = model
|
||||||
|
view.show()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|||||||
@ -0,0 +1,20 @@
|
|||||||
|
{
|
||||||
|
"colors" : [
|
||||||
|
{
|
||||||
|
"color" : {
|
||||||
|
"color-space" : "srgb",
|
||||||
|
"components" : {
|
||||||
|
"alpha" : "1.000",
|
||||||
|
"blue" : "0x5D",
|
||||||
|
"green" : "0x27",
|
||||||
|
"red" : "0xE4"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"idiom" : "universal"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"info" : {
|
||||||
|
"author" : "xcode",
|
||||||
|
"version" : 1
|
||||||
|
}
|
||||||
|
}
|
||||||
22
Fableon/Source/Assets.xcassets/image/Ellipse 45.imageset/Contents.json
vendored
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
{
|
||||||
|
"images" : [
|
||||||
|
{
|
||||||
|
"idiom" : "universal",
|
||||||
|
"scale" : "1x"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"filename" : "Ellipse 45@2x.png",
|
||||||
|
"idiom" : "universal",
|
||||||
|
"scale" : "2x"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"filename" : "Ellipse 45@3x.png",
|
||||||
|
"idiom" : "universal",
|
||||||
|
"scale" : "3x"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"info" : {
|
||||||
|
"author" : "xcode",
|
||||||
|
"version" : 1
|
||||||
|
}
|
||||||
|
}
|
||||||
BIN
Fableon/Source/Assets.xcassets/image/Ellipse 45.imageset/Ellipse 45@2x.png
vendored
Normal file
|
After Width: | Height: | Size: 580 B |
BIN
Fableon/Source/Assets.xcassets/image/Ellipse 45.imageset/Ellipse 45@3x.png
vendored
Normal file
|
After Width: | Height: | Size: 897 B |
22
Fableon/Source/Assets.xcassets/image/Vector.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/Vector.imageset/Vector@2x.png
vendored
Normal file
|
After Width: | Height: | Size: 1.9 KiB |
BIN
Fableon/Source/Assets.xcassets/image/Vector.imageset/Vector@3x.png
vendored
Normal file
|
After Width: | Height: | Size: 3.4 KiB |
22
Fableon/Source/Assets.xcassets/image/__New.imageset/Contents.json
vendored
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
{
|
||||||
|
"images" : [
|
||||||
|
{
|
||||||
|
"idiom" : "universal",
|
||||||
|
"scale" : "1x"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"filename" : "__New@2x.png",
|
||||||
|
"idiom" : "universal",
|
||||||
|
"scale" : "2x"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"filename" : "__New@3x.png",
|
||||||
|
"idiom" : "universal",
|
||||||
|
"scale" : "3x"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"info" : {
|
||||||
|
"author" : "xcode",
|
||||||
|
"version" : 1
|
||||||
|
}
|
||||||
|
}
|
||||||
BIN
Fableon/Source/Assets.xcassets/image/__New.imageset/__New@2x.png
vendored
Normal file
|
After Width: | Height: | Size: 38 KiB |
BIN
Fableon/Source/Assets.xcassets/image/__New.imageset/__New@3x.png
vendored
Normal file
|
After Width: | Height: | Size: 61 KiB |
22
Fableon/Source/Assets.xcassets/image/bj.imageset/Contents.json
vendored
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
{
|
||||||
|
"images" : [
|
||||||
|
{
|
||||||
|
"idiom" : "universal",
|
||||||
|
"scale" : "1x"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"filename" : "bj@2x.png",
|
||||||
|
"idiom" : "universal",
|
||||||
|
"scale" : "2x"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"filename" : "bj@3x.png",
|
||||||
|
"idiom" : "universal",
|
||||||
|
"scale" : "3x"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"info" : {
|
||||||
|
"author" : "xcode",
|
||||||
|
"version" : 1
|
||||||
|
}
|
||||||
|
}
|
||||||
BIN
Fableon/Source/Assets.xcassets/image/bj.imageset/bj@2x.png
vendored
Normal file
|
After Width: | Height: | Size: 464 KiB |
BIN
Fableon/Source/Assets.xcassets/image/bj.imageset/bj@3x.png
vendored
Normal file
|
After Width: | Height: | Size: 964 KiB |
22
Fableon/Source/Assets.xcassets/image/close_icon_04.imageset/Contents.json
vendored
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
{
|
||||||
|
"images" : [
|
||||||
|
{
|
||||||
|
"idiom" : "universal",
|
||||||
|
"scale" : "1x"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"filename" : "Frame@2x.png",
|
||||||
|
"idiom" : "universal",
|
||||||
|
"scale" : "2x"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"filename" : "Frame@3x.png",
|
||||||
|
"idiom" : "universal",
|
||||||
|
"scale" : "3x"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"info" : {
|
||||||
|
"author" : "xcode",
|
||||||
|
"version" : 1
|
||||||
|
}
|
||||||
|
}
|
||||||
BIN
Fableon/Source/Assets.xcassets/image/close_icon_04.imageset/Frame@2x.png
vendored
Normal file
|
After Width: | Height: | Size: 1.2 KiB |