多语言开发完成
@ -209,7 +209,7 @@
|
||||
03E23AB42EAA1A7F004A8CEC /* FAPagerViewTransformer.swift in Sources */ = {isa = PBXBuildFile; fileRef = 03E23AA42EAA1A7F004A8CEC /* FAPagerViewTransformer.swift */; };
|
||||
03E23AB52EAA1A7F004A8CEC /* FAToast.swift in Sources */ = {isa = PBXBuildFile; fileRef = 03E23AA82EAA1A7F004A8CEC /* FAToast.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 */; };
|
||||
03E23ABA2EAA1D85004A8CEC /* MNNItemController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 03E23AB92EAA1D85004A8CEC /* MNNItemController.swift */; };
|
||||
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 */; };
|
||||
03E9A73C2EB45507000D1067 /* GoogleService-Info.plist in Resources */ = {isa = PBXBuildFile; fileRef = 03E9A73B2EB45507000D1067 /* GoogleService-Info.plist */; };
|
||||
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 */; };
|
||||
F3019606DA7P36H41G408X13 /* ZStreamCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = F38E33739F391364D0151P7Z /* ZStreamCell.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>"; };
|
||||
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>"; };
|
||||
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>"; };
|
||||
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>"; };
|
||||
@ -532,6 +542,16 @@
|
||||
03E9A7392EB45149000D1067 /* AppDelegate+FAApns.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "AppDelegate+FAApns.swift"; sourceTree = "<group>"; };
|
||||
03E9A73B2EB45507000D1067 /* GoogleService-Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = "GoogleService-Info.plist"; sourceTree = "<group>"; };
|
||||
03E9A73D2EB460F2000D1067 /* FAApnsAlert.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FAApnsAlert.swift; sourceTree = "<group>"; };
|
||||
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>"; };
|
||||
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>"; };
|
||||
@ -665,6 +685,8 @@
|
||||
031FDEEB2EB35DF600F4CAC7 /* FACoinsPackAlert.swift */,
|
||||
031FDEED2EB3682000F4CAC7 /* FAVipRetainAlert.swift */,
|
||||
03E9A73D2EB460F2000D1067 /* FAApnsAlert.swift */,
|
||||
03E9A73F2EB49BE6000D1067 /* FAUpdatesAlert.swift */,
|
||||
03E9A7472EB5D2CB000D1067 /* FALogoutAlert.swift */,
|
||||
);
|
||||
path = Alert;
|
||||
sourceTree = "<group>";
|
||||
@ -750,6 +772,7 @@
|
||||
03E239672EAA1A29004A8CEC /* FANavigationController.swift */,
|
||||
03E239682EAA1A29004A8CEC /* FATabBarController.swift */,
|
||||
03E239692EAA1A29004A8CEC /* FAViewController.swift */,
|
||||
03E9A7512EB83A58000D1067 /* FAAppStartViewController.swift */,
|
||||
);
|
||||
path = Controller;
|
||||
sourceTree = "<group>";
|
||||
@ -955,6 +978,7 @@
|
||||
03E239EA2EAA1A4E004A8CEC /* FAMeViewController.swift */,
|
||||
03E239EB2EAA1A4E004A8CEC /* FASettingViewController.swift */,
|
||||
031FDEC12EB1E19D00F4CAC7 /* FACoinPackViewController.swift */,
|
||||
03E9A7492EB5DA7E000D1067 /* FALanguageViewController.swift */,
|
||||
);
|
||||
path = C;
|
||||
sourceTree = "<group>";
|
||||
@ -963,6 +987,7 @@
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
03E239ED2EAA1A4E004A8CEC /* FAMeItemModel.swift */,
|
||||
03E9A7412EB4A603000D1067 /* FAVersionUpdateModel.swift */,
|
||||
);
|
||||
path = M;
|
||||
sourceTree = "<group>";
|
||||
@ -988,6 +1013,7 @@
|
||||
031FDED72EB30D6E00F4CAC7 /* FASettingCell.swift */,
|
||||
031FDED82EB30D6E00F4CAC7 /* FASettingCell.xib */,
|
||||
031FDEDB2EB3141E00F4CAC7 /* FASettingFooterView.swift */,
|
||||
03E9A74B2EB5DB92000D1067 /* FALanguageCell.swift */,
|
||||
);
|
||||
path = V;
|
||||
sourceTree = "<group>";
|
||||
@ -1063,6 +1089,8 @@
|
||||
03E23A102EAA1A4E004A8CEC /* FAVideoLockView.swift */,
|
||||
031FDEBB2EB0C97A00F4CAC7 /* FAOldVideoRechargeView.swift */,
|
||||
031FDEBD2EB0C99900F4CAC7 /* FANewVideoRechargeView.swift */,
|
||||
03E9A7432EB4B80B000D1067 /* FADetailRecommendView.swift */,
|
||||
03E9A7452EB5ACE5000D1067 /* FADetailRecommendCell.swift */,
|
||||
);
|
||||
path = V;
|
||||
sourceTree = "<group>";
|
||||
@ -1220,7 +1248,9 @@
|
||||
03E23A9D2EAA1A7F004A8CEC /* FALocalized */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
03E23A9C2EAA1A7F004A8CEC /* FALocalized.swift */,
|
||||
03E23A9C2EAA1A7F004A8CEC /* FALanguageManager.swift */,
|
||||
03E9A74D2EB5E0F7000D1067 /* FALanguageModel.swift */,
|
||||
03E9A74F2EB5EAC0000D1067 /* FALanguageDataModel.swift */,
|
||||
);
|
||||
path = FALocalized;
|
||||
sourceTree = "<group>";
|
||||
@ -1945,6 +1975,7 @@
|
||||
F3019606DA7P36H41G408X13 /* ZStreamCell.swift in Sources */,
|
||||
F392T441X031FH7N0HA03SZ7 /* WPSectionView.swift in Sources */,
|
||||
F3D05387002315ZAQC97D7BT /* JHYHeader.swift in Sources */,
|
||||
03E9A7422EB4A603000D1067 /* FAVersionUpdateModel.swift in Sources */,
|
||||
F33IOYM854R4C48ZU602K4L2 /* CHelper.swift in Sources */,
|
||||
F3327L1BJ30974SY08905774 /* KDelegateOllectionView.swift in Sources */,
|
||||
F3P6F8433LVRV052SEY9W3N1 /* KWMptyLaunchController.swift in Sources */,
|
||||
@ -1974,6 +2005,7 @@
|
||||
F3N346893L1U6DP8228XK227 /* UOLaunch.swift in Sources */,
|
||||
F39S0H806843N21RM0O95488 /* VARResultController.swift in Sources */,
|
||||
F3D03219Y8NV50N2S66014LX /* GPOOllectionFableon.swift in Sources */,
|
||||
03E9A74E2EB5E0F7000D1067 /* FALanguageModel.swift in Sources */,
|
||||
F399V72654D56W408WQO18D5 /* OOSelectorSection.swift in Sources */,
|
||||
F31RUU6I99967458M4X40V5C /* HNFDramaController.swift in Sources */,
|
||||
F3MIE47471I04686Y131BPU5 /* TGleeScreenView.swift in Sources */,
|
||||
@ -1992,8 +2024,9 @@
|
||||
039CE6242EAB29D1007B5EED /* FAPayDataRequest.swift in Sources */,
|
||||
03E23AB52EAA1A7F004A8CEC /* FAToast.swift in Sources */,
|
||||
03E23AB62EAA1A7F004A8CEC /* FAUserInfo.swift in Sources */,
|
||||
03E23AB72EAA1A7F004A8CEC /* FALocalized.swift in Sources */,
|
||||
03E23AB72EAA1A7F004A8CEC /* FALanguageManager.swift in Sources */,
|
||||
039CE6222EAB1340007B5EED /* FAUserDefaultsKey.swift in Sources */,
|
||||
03E9A7442EB4B80B000D1067 /* FADetailRecommendView.swift in Sources */,
|
||||
03E23AB82EAA1A7F004A8CEC /* FAWaterfallFlowLayout.swift in Sources */,
|
||||
031FDEC62EB1E4E600F4CAC7 /* FACoinPackTitleView.swift in Sources */,
|
||||
F3K238643L913I6RK4G7S006 /* CSceneRegister.swift in Sources */,
|
||||
@ -2040,11 +2073,13 @@
|
||||
03E23A512EAA1A4E004A8CEC /* FAConsumptionRecordsCell.swift in Sources */,
|
||||
03E23A522EAA1A4E004A8CEC /* FARankingListHeaderView.swift in Sources */,
|
||||
03E23A532EAA1A4E004A8CEC /* FAVideoLockView.swift in Sources */,
|
||||
03E9A7482EB5D2CB000D1067 /* FALogoutAlert.swift in Sources */,
|
||||
03E23A542EAA1A4E004A8CEC /* FAHomeViewController.swift in Sources */,
|
||||
03E23A552EAA1A4E004A8CEC /* FAPopularListViewController.swift in Sources */,
|
||||
039CE6042EAA2621007B5EED /* AppDelegate+FAAdjust.swift in Sources */,
|
||||
03E23A562EAA1A4E004A8CEC /* FAPlayerEpUIButton.swift in Sources */,
|
||||
031FDEE42EB348AA00F4CAC7 /* FABaseAlert.swift in Sources */,
|
||||
03E9A74C2EB5DB92000D1067 /* FALanguageCell.swift in Sources */,
|
||||
03E23A572EAA1A4E004A8CEC /* FAHistoryCell.swift in Sources */,
|
||||
03E23A582EAA1A4E004A8CEC /* FASearchViewController.swift in Sources */,
|
||||
03E23A592EAA1A4E004A8CEC /* FAWalletCell.swift in Sources */,
|
||||
@ -2087,6 +2122,7 @@
|
||||
03E23A762EAA1A4E004A8CEC /* FASearchHomeView.swift in Sources */,
|
||||
03E23A772EAA1A4E004A8CEC /* FAHomeNewContentCell.swift in Sources */,
|
||||
03E23A782EAA1A4E004A8CEC /* FAOrderRecordsViewController.swift in Sources */,
|
||||
03E9A7462EB5ACE5000D1067 /* FADetailRecommendCell.swift in Sources */,
|
||||
03E23A792EAA1A4E004A8CEC /* FAEpMenuView.swift in Sources */,
|
||||
03E23A7A2EAA1A4E004A8CEC /* FASearchRecordView.swift in Sources */,
|
||||
03E23A7B2EAA1A4E004A8CEC /* FACollectViewController.swift in Sources */,
|
||||
@ -2122,6 +2158,7 @@
|
||||
F3774560U03XA8151BTQ2Z61 /* HYLLayoutView.swift in Sources */,
|
||||
F3N85463XSRG9VFK665G9028 /* XKRefreshCell.swift in Sources */,
|
||||
039CE6282EAB50A9007B5EED /* FAStoreCoinsView.swift in Sources */,
|
||||
03E9A7402EB49BE6000D1067 /* FAUpdatesAlert.swift in Sources */,
|
||||
F35K41930D96476I83FHZ0D9 /* YLZFableonAlignmentCell.swift in Sources */,
|
||||
F3M8439X72Q55JY9G8U502D9 /* DXYFire.swift in Sources */,
|
||||
03E239912EAA1A29004A8CEC /* Dictionary+FAAdd.swift in Sources */,
|
||||
@ -2132,6 +2169,7 @@
|
||||
031FDEDA2EB30D6E00F4CAC7 /* FASettingCell.swift in Sources */,
|
||||
03E239942EAA1A29004A8CEC /* UserDefaults+FAAdd.swift in Sources */,
|
||||
039CE6322EAB796F007B5EED /* FALabel.swift in Sources */,
|
||||
03E9A7502EB5EAC0000D1067 /* FALanguageDataModel.swift in Sources */,
|
||||
03E239952EAA1A29004A8CEC /* Font+FAAdd.swift in Sources */,
|
||||
031FDEEE2EB3682000F4CAC7 /* FAVipRetainAlert.swift in Sources */,
|
||||
03E239962EAA1A29004A8CEC /* FACryptorService.swift in Sources */,
|
||||
@ -2169,12 +2207,14 @@
|
||||
031FDECA2EB1F8F200F4CAC7 /* FACoinsPackReceiveModel.swift in Sources */,
|
||||
03E239B02EAA1A29004A8CEC /* FAWebView.swift in Sources */,
|
||||
039CE61C2EAB0F29007B5EED /* FAIapOrderModel.swift in Sources */,
|
||||
03E9A7522EB83A58000D1067 /* FAAppStartViewController.swift in Sources */,
|
||||
03E239B12EAA1A29004A8CEC /* FANetworkMonitor.swift in Sources */,
|
||||
03E239B22EAA1A29004A8CEC /* UINavigationBar+FAAdd.swift in Sources */,
|
||||
F3EKB04Y9O2888900KQEO504 /* NHCornerController.swift in Sources */,
|
||||
F32A7R4096386F976XT2W958 /* YKConfigMain.swift in Sources */,
|
||||
F3NKHD424DW5B04NK4D6ZC43 /* SCCrollFddebcdbeeffcebdf.swift in Sources */,
|
||||
F3374375770O0338ZQOL63EF /* OControlView.swift in Sources */,
|
||||
03E9A74A2EB5DA7E000D1067 /* FALanguageViewController.swift in Sources */,
|
||||
F3224PD65IO4R5M40JGK6Z59 /* TOkenView.swift in Sources */,
|
||||
F3C25CQ448629S8947842301 /* JXMInfoCell.swift in Sources */,
|
||||
F33732269456Q82561503YIR /* KZOgin.swift in Sources */,
|
||||
|
||||
@ -69,7 +69,7 @@ extension SceneDelegate {
|
||||
var statUrlStr: String? = webpageURL?.absoluteString
|
||||
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 query = tempArr.last
|
||||
|
||||
|
||||
@ -75,7 +75,6 @@ extension AppDelegate {
|
||||
//MARK: -------------- UNUserNotificationCenterDelegate --------------
|
||||
extension SceneDelegate: UNUserNotificationCenterDelegate {
|
||||
|
||||
|
||||
///APP处于前台是接收通知消息
|
||||
func userNotificationCenter(_ center: UNUserNotificationCenter, willPresent notification: UNNotification, withCompletionHandler completionHandler: @escaping (UNNotificationPresentationOptions) -> Void) {
|
||||
completionHandler([.badge, .banner])
|
||||
|
||||
@ -20,7 +20,7 @@ extension AppDelegate {
|
||||
FAToast.config()
|
||||
|
||||
//设置刷新控件的语言
|
||||
MJRefreshConfig.default.languageCode = "en"
|
||||
MJRefreshConfig.default.languageCode = FALanguageManager.manager.mjLanguageKey
|
||||
|
||||
IQKeyboardManager.shared.isEnabled = true
|
||||
IQKeyboardManager.shared.resignOnTouchOutside = true
|
||||
|
||||
@ -7,6 +7,7 @@
|
||||
|
||||
import UIKit
|
||||
import YYText
|
||||
import MJRefresh
|
||||
|
||||
class SceneDelegate: UIResponder, UIWindowSceneDelegate {
|
||||
|
||||
@ -17,13 +18,13 @@ class SceneDelegate: UIResponder, UIWindowSceneDelegate {
|
||||
func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) {
|
||||
guard let windowScene = (scene as? UIWindowScene) else { return }
|
||||
NotificationCenter.default.addObserver(self, selector: #selector(networkStatusDidChangeNotification), name: FANetworkMonitor.networkStatusDidChangeNotification, object: nil)
|
||||
NotificationCenter.default.addObserver(self, selector: #selector(languageDidChange), name: FALanguageManager.languageDidChange, object: nil)
|
||||
|
||||
FATool.sceneDelegate = self
|
||||
FATool.windowScene = windowScene
|
||||
|
||||
window = UIWindow(windowScene: windowScene)
|
||||
window?.rootViewController = FATabBarController()
|
||||
window?.makeKeyAndVisible()
|
||||
FAAdjustStateManager.manager.isOpenApp = true
|
||||
startApp()
|
||||
|
||||
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 {
|
||||
|
||||
@objc private func handleOnLine() {
|
||||
@ -73,7 +123,15 @@ extension SceneDelegate {
|
||||
}
|
||||
|
||||
@objc private func networkStatusDidChangeNotification() {
|
||||
FATool.requestIDFAAuthorization(nil)
|
||||
self.retryHandleOpenAppMessage()
|
||||
if FANetworkMonitor.manager.isReachable == true {
|
||||
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">
|
||||
<plist version="1.0">
|
||||
<dict>
|
||||
<key>aps-environment</key>
|
||||
<string>development</string>
|
||||
<key>com.apple.developer.applesignin</key>
|
||||
<array>
|
||||
<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() {
|
||||
super.viewDidLoad()
|
||||
|
||||
let nav1 = getNavigation(FAHomeViewController(), "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 nav3 = getNavigation(FACollectViewController(), "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 nav1 = getNavigation(FAHomeViewController(), "fableon_home".localized, UIImage(named: "tabbar_home_icon"), UIImage(named: "tabbar_home_icon_selected"))
|
||||
let nav2 = getNavigation(FARecommendViewController(), "fableon_recommend".localized, UIImage(named: "tabbar_recommend_icon"), UIImage(named: "tabbar_recommend_icon_selected"))
|
||||
let nav3 = getNavigation(FACollectViewController(), "fableon_collect".localized, UIImage(named: "tabbar_collect_icon"), UIImage(named: "tabbar_collect_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]
|
||||
|
||||
@ -47,6 +47,8 @@ class FATabBarController: UITabBarController {
|
||||
FALogin.manager.requestUserInfo(completer: nil)
|
||||
}
|
||||
}
|
||||
FATool.checkUpdates()
|
||||
// FATool.requestIDFAAuthorization(nil)
|
||||
}
|
||||
|
||||
override var childForStatusBarStyle: UIViewController? {
|
||||
|
||||
@ -9,3 +9,7 @@
|
||||
let kFAWaitRestoreIAPDefaultsKey = "kFAWaitRestoreIAPDefaultsKey"
|
||||
|
||||
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)?) {
|
||||
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)
|
||||
} else {
|
||||
if isToast {
|
||||
FAToast.show(text: "Error".localized)
|
||||
FAToast.show(text: "fableon_error".localized)
|
||||
}
|
||||
var res = FANetworkManager.Response<T>()
|
||||
res.code = -1
|
||||
@ -177,7 +177,7 @@ extension FANetworkManager {
|
||||
let dic = [
|
||||
"authorization" : token,
|
||||
"system-version" : UIDevice.current.systemVersion,
|
||||
"lang-key" : "en",
|
||||
"lang-key" : FALanguageManager.manager.currentLanguageKey,
|
||||
"time-zone" : String.timeZone(),
|
||||
"app-version" : (Bundle.main.infoDictionary!["CFBundleShortVersionString"] as? String) ?? "",
|
||||
"brand" : "apple", //品牌
|
||||
|
||||
@ -12,10 +12,10 @@ class FANetworkMonitor {
|
||||
static let manager = FANetworkMonitor()
|
||||
|
||||
///是否有网
|
||||
var isReachable: Bool?
|
||||
private(set) var isReachable: Bool?
|
||||
|
||||
private var connectionType: NWInterface.InterfaceType?
|
||||
private var status: NWPath.Status?
|
||||
private(set) var connectionType: NWInterface.InterfaceType?
|
||||
private(set) var status: NWPath.Status?
|
||||
|
||||
private let monitor = NWPathMonitor()
|
||||
private let queue = DispatchQueue(label: "NetworkMonitorQueue")
|
||||
@ -36,7 +36,6 @@ class FANetworkMonitor {
|
||||
self.connectionType = nil
|
||||
}
|
||||
|
||||
|
||||
if path.status == .satisfied, self.connectionType != nil {
|
||||
if self.isReachable == false {
|
||||
self.isReachable = true
|
||||
|
||||
@ -18,14 +18,14 @@ class FATableView: UITableView {
|
||||
self.backgroundColor = .clear
|
||||
self.contentInsetAdjustmentBehavior = .never
|
||||
|
||||
if style == .insetGrouped {
|
||||
if style == .insetGrouped || style == .grouped {
|
||||
sectionFooterHeight = 14
|
||||
sectionHeaderHeight = 0.1
|
||||
} else if style == .plain {
|
||||
if #available(iOS 15.0, *) {
|
||||
sectionHeaderTopPadding = 0
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
required init?(coder: NSCoder) {
|
||||
|
||||
@ -21,13 +21,13 @@ class FAAppWebViewController: FABaseWebViewController {
|
||||
self.autoTitle = false
|
||||
|
||||
if webUrl == kFAFeedBackListWebUrl {
|
||||
self.title = "Feedback History".localized
|
||||
self.title = "fableon_feedback_history".localized
|
||||
} else if webUrl == kFAFeedBackHomeWebUrl {
|
||||
self.title = "Feedback".localized
|
||||
self.title = "fableon_feedback".localized
|
||||
} else if webUrl == kFAFeedBackDetailWebUrl {
|
||||
self.title = "Feedback Details".localized
|
||||
self.title = "fableon_feedback_detail".localized
|
||||
} else if webUrl == kFALogoutWebUrl {
|
||||
self.title = "Account Deletion".localized
|
||||
self.title = "fableon_account_deletion".localized
|
||||
}
|
||||
|
||||
}
|
||||
@ -51,7 +51,7 @@ extension FAAppWebViewController {
|
||||
var dic = [
|
||||
"token" : FALogin.manager.token?.token ?? "",
|
||||
"time_zone" : String.timeZone(),
|
||||
"lang" : FALocalized.manager.currentLocalizedKey,
|
||||
"lang" : FALanguageManager.manager.currentLanguageKey,
|
||||
"type" : "ios",
|
||||
"device-id" : FADeviceIDManager.shared.id
|
||||
]
|
||||
|
||||
@ -41,7 +41,7 @@ class FANewListViewController: FAViewController {
|
||||
|
||||
override func viewDidLoad() {
|
||||
super.viewDidLoad()
|
||||
self.title = "New".localized
|
||||
self.title = "fableon_new".localized
|
||||
|
||||
fa_setupLayout()
|
||||
|
||||
|
||||
@ -41,7 +41,7 @@ class FAPopularListViewController: FAViewController {
|
||||
|
||||
override func viewDidLoad() {
|
||||
super.viewDidLoad()
|
||||
self.title = "Popular".localized
|
||||
self.title = "fableon_popular".localized
|
||||
|
||||
fa_setupLayout()
|
||||
|
||||
|
||||
@ -19,7 +19,7 @@ struct FAHomeMustSeeContentView: View {
|
||||
var body: some View {
|
||||
VStack(spacing: 15) {
|
||||
HStack {
|
||||
Text("Editor's Picks".localized)
|
||||
Text("fableon_editor's_picks".localized)
|
||||
.font(Font.font(size: 16, weight: .medium))
|
||||
.foregroundStyle(Color(String.color_FFFFFF))
|
||||
.padding(.leading, 10)
|
||||
|
||||
@ -47,7 +47,7 @@ struct FAHomeMustSeeShortView: View {
|
||||
HStack(spacing: 4) {
|
||||
Image("Frame 2920")
|
||||
|
||||
Text("Watch".localized)
|
||||
Text("fableon_watch".localized)
|
||||
.font(Font.font(size: 12, weight: .medium))
|
||||
.foregroundStyle(Color(String.color_000000))
|
||||
|
||||
|
||||
@ -18,7 +18,7 @@ struct FAHomeMustSeeView: View {
|
||||
var body: some View {
|
||||
VStack {
|
||||
HStack {
|
||||
Text("Must-see TV series".localized)
|
||||
Text("fableon_must_see_tv_series".localized)
|
||||
.font(Font.font(size: 18, weight: .medium))
|
||||
.foregroundStyle(Color(String.color_FFFFFF))
|
||||
.padding(.leading, 16)
|
||||
|
||||
@ -24,7 +24,7 @@ struct FAHomeNewView: View {
|
||||
let list = viewModel.homeNewItem?.list ?? []
|
||||
|
||||
VStack(spacing: 15) {
|
||||
Text("New Releases".localized)
|
||||
Text("fableon_home_new".localized)
|
||||
.font(.font(size: 18, weight: .medium))
|
||||
.foregroundStyle(Color(String.color_FFFFFF))
|
||||
.padding(.leading, 16)
|
||||
@ -60,7 +60,7 @@ struct FAHomeNewView: View {
|
||||
HStack(spacing: 4) {
|
||||
Image("Frame 2921")
|
||||
|
||||
Text("Watch".localized)
|
||||
Text("fableon_watch".localized)
|
||||
.font(.font(size: 14, weight: .medium))
|
||||
.foregroundStyle(Color(String.color_000000))
|
||||
}
|
||||
|
||||
@ -17,7 +17,7 @@ class FAHomeCoinsPackButton: UIControl {
|
||||
let label = UILabel()
|
||||
label.font = .font(ofSize: 10, weight: .init(900)).withBoldItalic()
|
||||
label.textColor = .FFFFFF
|
||||
label.text = "Daily Coins".localized
|
||||
label.text = "fableon_daily_coins".localized
|
||||
return label
|
||||
}()
|
||||
|
||||
|
||||
@ -13,7 +13,7 @@ class FAHomePlayHistoryView: UIView {
|
||||
didSet {
|
||||
coverImageView.fa_setImage(model?.image_url)
|
||||
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 {
|
||||
coverImageView.fa_setImage(model?.image_url)
|
||||
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)"
|
||||
}
|
||||
}
|
||||
|
||||
@ -40,7 +40,7 @@ class FASearchInputView: UIView {
|
||||
textField.returnKeyType = .search
|
||||
textField.font = .font(ofSize: 12, weight: .medium)
|
||||
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),
|
||||
.foregroundColor : UIColor.FFFFFF.withAlphaComponent(0.5)
|
||||
])
|
||||
|
||||
@ -15,7 +15,7 @@ class FASearchRecommendCell: UICollectionViewCell {
|
||||
coverImageView.fa_setImage(model?.image_url)
|
||||
titleLabel.text = model?.name
|
||||
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()
|
||||
label.font = .font(ofSize: 14, weight: .medium)
|
||||
label.textColor = .FFFFFF
|
||||
label.text = "Historical search".localized
|
||||
label.text = "fableon_search_history".localized
|
||||
return label
|
||||
}()
|
||||
|
||||
|
||||
@ -38,7 +38,7 @@ class FAHomeViewModel: ObservableObject {
|
||||
if $0.module_key == .banner {
|
||||
self.bannerItem = $0
|
||||
} else if $0.module_key == .v3_recommand {
|
||||
$0.title = "Popular".localized
|
||||
$0.title = "fableon_popular".localized
|
||||
popularItem = $0
|
||||
} else if $0.module_key == .week_ranking {
|
||||
$0.title = "Rankings".localized
|
||||
@ -47,7 +47,7 @@ class FAHomeViewModel: ObservableObject {
|
||||
$0.title = "Genres".localized
|
||||
genresItem = $0
|
||||
} else if $0.module_key == .new_recommand {
|
||||
$0.title = "New".localized
|
||||
$0.title = "fableon_new".localized
|
||||
newItem = $0
|
||||
self.homeNewItem = $0
|
||||
} else if $0.module_key == .week_recommend {
|
||||
|
||||
@ -11,9 +11,9 @@ class FAAboutViewController: FAViewController {
|
||||
|
||||
|
||||
private lazy var dataArr: [FAMeItemModel] = [
|
||||
FAMeItemModel(type: .privacyPolicy, name: "Privacy Policy".localized),
|
||||
FAMeItemModel(type: .userAgreement, name: "User Agreement".localized),
|
||||
FAMeItemModel(type: .visitWebsite, name: "Visit Website".localized),
|
||||
FAMeItemModel(type: .privacyPolicy, name: "fableon_privacy_policy".localized),
|
||||
FAMeItemModel(type: .userAgreement, name: "fableon_user_agreement".localized),
|
||||
FAMeItemModel(type: .visitWebsite, name: "fableon_visit_website".localized),
|
||||
]
|
||||
|
||||
private lazy var tableView: FATableView = {
|
||||
|
||||
@ -115,7 +115,7 @@ class FACoinPackViewController: FAViewController {
|
||||
|
||||
override func viewDidLoad() {
|
||||
super.viewDidLoad()
|
||||
self.title = "My Refills".localized
|
||||
self.title = "fableon_my_refills".localized
|
||||
payDataModel = FAIapManager.manager.payDateModel
|
||||
|
||||
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] = {
|
||||
let arr = [
|
||||
FAMeItemModel(type: .feedback, name: "Feedback".localized, icon: UIImage(named: "icon_feedback")),
|
||||
FAMeItemModel(type: .about, name: "About".localized, icon: UIImage(named: "icon_about")),
|
||||
FAMeItemModel(type: .language, name: "fableon_language".localized, icon: UIImage(named: "icon_language")),
|
||||
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: .userAgreement, name: "User Agreement".localized, icon: UIImage(named: "icon_user")),
|
||||
FAMeItemModel(type: .visitWebsite, name: "Visit Website".localized, icon: UIImage(named: "icon_visit")),
|
||||
FAMeItemModel(type: .privacyPolicy, name: "fableon_privacy_policy".localized, icon: UIImage(named: "icon_privacy")),
|
||||
FAMeItemModel(type: .userAgreement, name: "fableon_user_agreement".localized, icon: UIImage(named: "icon_user")),
|
||||
// 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
|
||||
}()
|
||||
@ -147,6 +148,11 @@ extension FAMeListViewController: UITableViewDelegate, UITableViewDataSource {
|
||||
UIApplication.shared.open(url)
|
||||
}
|
||||
|
||||
case .language:
|
||||
let vc = FALanguageViewController()
|
||||
self.navigationController?.pushViewController(vc, animated: true)
|
||||
|
||||
|
||||
default:
|
||||
break
|
||||
}
|
||||
|
||||
@ -10,7 +10,7 @@ import UIKit
|
||||
class FASettingViewController: FAViewController {
|
||||
|
||||
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 = {
|
||||
@ -31,7 +31,7 @@ class FASettingViewController: FAViewController {
|
||||
|
||||
override func viewDidLoad() {
|
||||
super.viewDidLoad()
|
||||
self.title = "Settings".localized
|
||||
self.title = "fableon_settings".localized
|
||||
NotificationCenter.default.addObserver(self, selector: #selector(userInfoUpdateNotification), name: FALogin.userInfoUpdateNotification, object: nil)
|
||||
|
||||
|
||||
|
||||
@ -23,6 +23,7 @@ struct FAMeItemModel {
|
||||
///金币奖励
|
||||
case rewardCoins
|
||||
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.font = .font(ofSize: 14, weight: .regular)
|
||||
view.textColors = [UIColor.C_5_DDF_5.cgColor, UIColor.C_5_DDF_5.cgColor]
|
||||
view.text = "REWARDS OVERVIEW".localized
|
||||
view.text = "fableon_rewards_overview".localized.uppercased()
|
||||
return view
|
||||
}()
|
||||
|
||||
private lazy var coinsView1: CoinsView = {
|
||||
let view = CoinsView()
|
||||
view.title = "Weekly Total".localized
|
||||
view.title = "fableon_weekly_total".localized
|
||||
view.coins = 0
|
||||
return view
|
||||
}()
|
||||
|
||||
private lazy var coinsView2: CoinsView = {
|
||||
let view = CoinsView()
|
||||
view.title = "Claimable Coins".localized
|
||||
view.title = "fableon_claimable_coins".localized
|
||||
view.coins = 0
|
||||
return view
|
||||
}()
|
||||
@ -65,7 +65,7 @@ class FACoinPackHeaderView: UIView {
|
||||
let label = UILabel()
|
||||
label.font = .font(ofSize: 12, weight: .regular)
|
||||
label.textColor = .FFFFFF.withAlphaComponent(0.5)
|
||||
label.text = "Active Refills".localized + ": "
|
||||
label.text = "fableon_active_refills".localized + ": "
|
||||
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)
|
||||
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),
|
||||
.foregroundColor : UIColor.FFFFFF
|
||||
]))
|
||||
@ -114,7 +114,7 @@ class FACoinPackHeaderView: UIView {
|
||||
|
||||
} else {
|
||||
button.fa_colors = [UIColor._6_D_6_D_6_D.cgColor, UIColor._6_D_6_D_6_D.cgColor]
|
||||
button.configuration?.attributedTitle = AttributedString("Get a Refill to Claim".localized, attributes: AttributeContainer([
|
||||
button.configuration?.attributedTitle = AttributedString("fableon_get_refill_button_text".localized, attributes: AttributeContainer([
|
||||
.font : UIFont.font(ofSize: 14, weight: .bold),
|
||||
.foregroundColor : UIColor.FFFFFF.withAlphaComponent(0.5)
|
||||
]))
|
||||
|
||||
@ -18,7 +18,7 @@ class FACoinsPackBuyView: UIView {
|
||||
view.dotColor = .C_5_DDF_5
|
||||
view.textColors = [UIColor.C_5_DDF_5.cgColor, UIColor.C_5_DDF_5.cgColor]
|
||||
view.font = .font(ofSize: 14, weight: .regular)
|
||||
view.text = "Weekly Refill".localized.uppercased()
|
||||
view.text = "fableo_weekly_refill".localized.uppercased()
|
||||
return view
|
||||
}()
|
||||
|
||||
|
||||
@ -63,13 +63,13 @@ class FACoinsPackClaimListCell: UICollectionViewCell {
|
||||
|
||||
private lazy var coinsView1: CoinsView = {
|
||||
let view = CoinsView()
|
||||
view.title = "Total Reward".localized
|
||||
view.title = "fableon_total_reward".localized
|
||||
return view
|
||||
}()
|
||||
|
||||
private lazy var coinsView2: CoinsView = {
|
||||
let view = CoinsView()
|
||||
view.title = "Remaining".localized
|
||||
view.title = "fableon_remaining".localized
|
||||
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),
|
||||
.foregroundColor : UIColor._114_CEE
|
||||
]))
|
||||
@ -112,7 +112,7 @@ class FACoinsPackClaimListCell: UICollectionViewCell {
|
||||
|
||||
} else {
|
||||
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),
|
||||
.foregroundColor : UIColor.FFFFFF_0_8
|
||||
]))
|
||||
|
||||
@ -22,7 +22,7 @@ class FACoinsPackClaimListView: UIView {
|
||||
view.dotColor = .C_5_DDF_5
|
||||
view.textColors = [UIColor.C_5_DDF_5.cgColor, UIColor.C_5_DDF_5.cgColor]
|
||||
view.font = .font(ofSize: 14, weight: .regular)
|
||||
view.text = "Active Refills".localized.uppercased()
|
||||
view.text = "fableon_active_refills".localized.uppercased()
|
||||
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 = {
|
||||
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
|
||||
self?.login(type: .apple)
|
||||
}), for: .touchUpInside)
|
||||
@ -30,7 +30,7 @@ class FALoginView: FAPanModalContentView {
|
||||
}()
|
||||
|
||||
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
|
||||
self?.login(type: .faceBook)
|
||||
}), 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.textStartPoint = .init(x: 0, 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
|
||||
}()
|
||||
|
||||
@ -42,7 +42,7 @@ class FAMeCoinsPackButton: UIControl {
|
||||
let label = UILabel()
|
||||
label.font = .font(ofSize: 12, weight: .medium).withBoldItalic()
|
||||
label.textColor = .FFFFFF
|
||||
label.text = "Claim your rewards now.".localized
|
||||
label.text = "fableo_me_daily_2".localized
|
||||
return label
|
||||
}()
|
||||
|
||||
|
||||
@ -49,7 +49,7 @@ class FAMeHeaderView: UIView {
|
||||
|
||||
private lazy var coinsView: FAMeCoinsView = {
|
||||
let view = FAMeCoinsView()
|
||||
view.title = "Coins".localized
|
||||
view.title = "fableon_coins".localized
|
||||
view.count = 0
|
||||
view.addAction(UIAction(handler: { [weak self] _ in
|
||||
guard let self = self else { return }
|
||||
@ -61,7 +61,7 @@ class FAMeHeaderView: UIView {
|
||||
|
||||
private lazy var bonusCoinsView: FAMeCoinsView = {
|
||||
let view = FAMeCoinsView()
|
||||
view.title = "Bonus"
|
||||
view.title = "fableon_bonus".localized
|
||||
view.count = 0
|
||||
view.addAction(UIAction(handler: { [weak self] _ in
|
||||
guard let self = self else { return }
|
||||
@ -91,7 +91,7 @@ class FAMeHeaderView: UIView {
|
||||
button.layer.masksToBounds = true
|
||||
button.layer.borderWidth = 1
|
||||
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.titleLabel?.font = .font(ofSize: 14, weight: .medium)
|
||||
return button
|
||||
|
||||
@ -15,13 +15,13 @@ class FAMeTableViewHeaderView: UIView {
|
||||
subscribeView.isHidden = true
|
||||
expirationView.isHidden = false
|
||||
vipImageView.image = UIImage(named: "vip_image_02")
|
||||
titleLabel.text = "Activated".localized
|
||||
titleLabel.text = "fableon_activated".localized
|
||||
subtitleLabel.text = "vip_tip_01".localized
|
||||
} else {
|
||||
subscribeView.isHidden = false
|
||||
expirationView.isHidden = true
|
||||
vipImageView.image = UIImage(named: "vip_image_01")
|
||||
titleLabel.text = "Not Activated".localized
|
||||
titleLabel.text = "fableon_not_activated".localized
|
||||
subtitleLabel.text = "vip_tip_02".localized
|
||||
}
|
||||
|
||||
@ -61,7 +61,7 @@ class FAMeTableViewHeaderView: UIView {
|
||||
|
||||
private lazy var subscribeView: UIButton = {
|
||||
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),
|
||||
.foregroundColor : UIColor._333333
|
||||
]))
|
||||
|
||||
@ -13,7 +13,7 @@ class FASettingFooterView: UIView {
|
||||
private lazy var logoutButton: UIButton = {
|
||||
let button = FAGradientButton(type: .custom, primaryAction: UIAction(handler: { [weak self] _ in
|
||||
guard let self = self else { return }
|
||||
FALogin.manager.logout(completer: nil)
|
||||
self.handleLogoutButton()
|
||||
}))
|
||||
button.layer.cornerRadius = 24
|
||||
button.layer.masksToBounds = true
|
||||
@ -21,7 +21,7 @@ class FASettingFooterView: UIView {
|
||||
button.fa_locations = [0, 1]
|
||||
button.fa_startPoint = .init(x: 0, y: 0.5)
|
||||
button.fa_endPoint = .init(x: 1, y: 0.5)
|
||||
button.setTitle("Log out".localized, for: .normal)
|
||||
button.setTitle("fableon_logout".localized, for: .normal)
|
||||
button.setTitleColor(._000000, for: .normal)
|
||||
button.titleLabel?.font = .font(ofSize: 18, weight: .semibold)
|
||||
return button
|
||||
@ -43,6 +43,16 @@ class FASettingFooterView: UIView {
|
||||
required init?(coder: NSCoder) {
|
||||
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() {
|
||||
super.viewDidLoad()
|
||||
self.edgesForExtendedLayout = .top
|
||||
self.title = "Collect".localized
|
||||
self.title = "fableon_collect".localized
|
||||
|
||||
|
||||
self.navigationItem.rightBarButtonItems = [historyButton, spaceButton, editBarButton]
|
||||
|
||||
@ -39,7 +39,7 @@ class FAHistoryViewController: FAViewController {
|
||||
|
||||
override func viewDidLoad() {
|
||||
super.viewDidLoad()
|
||||
self.title = "History".localized
|
||||
self.title = "fableon_history".localized
|
||||
self.edgesForExtendedLayout = .top
|
||||
|
||||
fa_setupLayout()
|
||||
|
||||
@ -16,7 +16,7 @@ class FACollectCell: UICollectionViewCell {
|
||||
didSet {
|
||||
nameLabel.text = model?.name
|
||||
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 {
|
||||
coverImageView.fa_setImage(model?.image_url)
|
||||
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_video_id: String?
|
||||
var video_info: FAVideoInfoModel?
|
||||
var video_url: String?
|
||||
|
||||
@SmartIgnored
|
||||
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 = {
|
||||
let view = FAOldVideoRechargeView.CoinsView()
|
||||
view.title = "Price".localized + ":"
|
||||
view.title = "fableo_price".localized + ":"
|
||||
return view
|
||||
}()
|
||||
|
||||
private lazy var totalCoinsView: FAOldVideoRechargeView.CoinsView = {
|
||||
let view = FAOldVideoRechargeView.CoinsView()
|
||||
view.title = "Balance".localized + ":"
|
||||
view.title = "fableo_balance".localized + ":"
|
||||
view.coins = FALogin.manager.userInfo?.totalCoins ?? 0
|
||||
return view
|
||||
}()
|
||||
|
||||
@ -159,7 +159,7 @@ class FAPlayerDetailControlView: JXPlayerListControlView {
|
||||
private func updateEp() {
|
||||
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)
|
||||
view.clickHandle = { [weak self] in
|
||||
self?.fa_viewModel?.onEpSelectorView()
|
||||
|
||||
@ -41,7 +41,7 @@ class FAVideoLockView: UIView {
|
||||
if hasLastEpisodeUnlocked {
|
||||
button.configuration?.attributedTitle = .init("video_lock_tip_text".localized, attributes: attributeContainer)
|
||||
} else {
|
||||
button.configuration?.attributedTitle = .init("Unlocking costs ## coins".localizedReplace(text: "\(videoInfo?.coins ?? 0)"), attributes: attributeContainer)
|
||||
button.configuration?.attributedTitle = .init("fableon_unlocking_coins_notice".localizedReplace(text: "\(videoInfo?.coins ?? 0)"), attributes: attributeContainer)
|
||||
}
|
||||
}
|
||||
button.layer.cornerRadius = 26
|
||||
|
||||
@ -12,7 +12,14 @@ import FDFullscreenPopGesture
|
||||
|
||||
class FAPlayerDetailViewController: JXPlayerListViewController {
|
||||
|
||||
var shortPlayId: String?
|
||||
var shortPlayId: String? {
|
||||
set {
|
||||
self.fa_viewModel.shortPlayId = newValue ?? ""
|
||||
}
|
||||
get {
|
||||
return self.fa_viewModel.shortPlayId
|
||||
}
|
||||
}
|
||||
var activityId: String?
|
||||
|
||||
override var ViewModelClass: JXPlayerListViewModel.Type {
|
||||
@ -27,7 +34,7 @@ class FAPlayerDetailViewController: JXPlayerListViewController {
|
||||
let button = UIButton(type: .custom)
|
||||
button.setImage(UIImage(named: "Frame 3011"), for: .normal)
|
||||
button.addAction(UIAction(handler: { [weak self] _ in
|
||||
self?.navigationController?.popViewController(animated: true)
|
||||
self?.handleBackButton()
|
||||
}), for: .touchUpInside)
|
||||
return button
|
||||
}()
|
||||
@ -44,7 +51,7 @@ class FAPlayerDetailViewController: JXPlayerListViewController {
|
||||
super.viewDidLoad()
|
||||
self.fd_interactivePopDisabled = true
|
||||
view.backgroundColor = .init(named: .color_000000)
|
||||
self.fa_viewModel.shortPlayId = shortPlayId ?? ""
|
||||
// self.fa_viewModel.shortPlayId = shortPlayId ?? ""
|
||||
self.register(FAPlayerDetailCell.self, forCellWithReuseIdentifier: "FAPlayerDetailCell")
|
||||
self.delegate = self
|
||||
self.dataSource = self
|
||||
@ -53,6 +60,8 @@ class FAPlayerDetailViewController: JXPlayerListViewController {
|
||||
requestDetailList()
|
||||
|
||||
fa_setupLayout()
|
||||
|
||||
self.fa_viewModel.requestRecommandData()
|
||||
}
|
||||
|
||||
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 {
|
||||
|
||||
@ -13,6 +13,8 @@ class FAShortDetailViewModel: JXPlayerListViewModel, ObservableObject {
|
||||
|
||||
private(set) var dataArr: [FAShortDetailModel] = []
|
||||
|
||||
private(set) var recommandDataArr: [FAShortPlayModel] = []
|
||||
|
||||
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 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)
|
||||
view.clickHandle = { [weak self] in
|
||||
self?.fa_viewModel?.pushPlayerDetail(self?.shortModel)
|
||||
|
||||
@ -66,9 +66,9 @@ extension FACoinRecordViewController: UITableViewDelegate, UITableViewDataSource
|
||||
let model = self.dataArr[indexPath.row]
|
||||
let cell = tableView.dequeueReusableCell(withIdentifier: "cell", for: indexPath) as! FAOrderRecordCell
|
||||
if model.type == "send" {
|
||||
cell.titleLabel.text = "Bonus Coins".localized
|
||||
cell.titleLabel.text = "fableo_bonus_coins".localized
|
||||
} else {
|
||||
cell.titleLabel.text = "Recharge Coins".localized
|
||||
cell.titleLabel.text = "fableo_recharge_coins".localized
|
||||
}
|
||||
cell.dateLabel.text = model.created_at
|
||||
cell.countLabel.text = "+\(model.value ?? "0")"
|
||||
|
||||
@ -33,7 +33,7 @@ class FAConsumptionRecordsViewController: FAViewController {
|
||||
|
||||
override func viewDidLoad() {
|
||||
super.viewDidLoad()
|
||||
self.title = "Consumption Records".localized
|
||||
self.title = "fableo_consumption_records".localized
|
||||
|
||||
fa_setupLayout()
|
||||
|
||||
|
||||
@ -10,7 +10,7 @@ import JXSegmentedView
|
||||
|
||||
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 segmentedDataSource: JXSegmentedTitleDataSource = {
|
||||
@ -56,7 +56,7 @@ class FAOrderRecordsViewController: FAViewController {
|
||||
|
||||
override func viewDidLoad() {
|
||||
super.viewDidLoad()
|
||||
self.title = "Order Records".localized
|
||||
self.title = "fableo_order_records".localized
|
||||
|
||||
fa_setupLayout()
|
||||
}
|
||||
|
||||
@ -33,7 +33,7 @@ class FARewardCoinsViewController: FAViewController {
|
||||
|
||||
override func viewDidLoad() {
|
||||
super.viewDidLoad()
|
||||
self.title = "Reward coins"
|
||||
self.title = "fableo_reward_coins".localized
|
||||
|
||||
view.addSubview(tableView)
|
||||
|
||||
|
||||
@ -88,8 +88,8 @@ class FAStoreViewController: FAViewController {
|
||||
|
||||
override func viewDidLoad() {
|
||||
super.viewDidLoad()
|
||||
self.title = "Store".localized
|
||||
let barButtonItem = UIBarButtonItem(title: "Restore".localized, style: .plain, target: self, action: #selector(handleRestore))
|
||||
self.title = "fableon_store".localized
|
||||
let barButtonItem = UIBarButtonItem(title: "fableo_restore".localized, style: .plain, target: self, action: #selector(handleRestore))
|
||||
barButtonItem.tintColor = .FFFFFF
|
||||
self.navigationItem.rightBarButtonItem = barButtonItem
|
||||
|
||||
|
||||
@ -10,9 +10,9 @@ import UIKit
|
||||
class FAWalletViewController: FAViewController {
|
||||
|
||||
private lazy var dataArr: [FAMeItemModel] = [
|
||||
FAMeItemModel(type: .consumptionRecords, name: "Consumption Records".localized),
|
||||
FAMeItemModel(type: .purchaseRecords, name: "Purchase Records".localized),
|
||||
FAMeItemModel(type: .rewardCoins, name: "Reward Coins".localized),
|
||||
FAMeItemModel(type: .consumptionRecords, name: "fableo_consumption_records".localized),
|
||||
FAMeItemModel(type: .purchaseRecords, name: "fableo_purchase_records".localized),
|
||||
FAMeItemModel(type: .rewardCoins, name: "fableo_reward_coins".localized),
|
||||
]
|
||||
|
||||
private lazy var tableView: FATableView = {
|
||||
@ -38,7 +38,7 @@ class FAWalletViewController: FAViewController {
|
||||
|
||||
override func 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)
|
||||
|
||||
fa_setupLayout()
|
||||
|
||||
@ -116,16 +116,16 @@ class FAPayItem: NSObject, SmartCodable {
|
||||
func getTimeString() -> String? {
|
||||
switch self.vip_type_key {
|
||||
case .week:
|
||||
return "week".localized
|
||||
return "w_complex".localized
|
||||
|
||||
case .month:
|
||||
return "month".localized
|
||||
return "m_complex".localized
|
||||
|
||||
case .quarter:
|
||||
return "quarter".localized
|
||||
return "q_complex".localized
|
||||
|
||||
case .year:
|
||||
return "year".localized
|
||||
return "Y_complex".localized
|
||||
|
||||
default:
|
||||
return nil
|
||||
@ -135,16 +135,16 @@ class FAPayItem: NSObject, SmartCodable {
|
||||
func getVipTitle() -> String? {
|
||||
switch self.vip_type_key {
|
||||
case .week:
|
||||
return "Weekly VIP".localized
|
||||
return "fableon_weekly_vip".localized
|
||||
|
||||
case .month:
|
||||
return "Monthly VIP".localized
|
||||
return "fableon_monthly_vip".localized
|
||||
|
||||
case .quarter:
|
||||
return "Quarterly VIP".localized
|
||||
return "fableon_quarterly_vip".localized
|
||||
|
||||
case .year:
|
||||
return "Yearly VIP".localized
|
||||
return "fableon_yearly_vip".localized
|
||||
|
||||
default:
|
||||
return nil
|
||||
|
||||
@ -11,10 +11,10 @@ class FACoinPackConfirmItem1View: FACoinPackConfirmItemView {
|
||||
|
||||
override init(frame: CGRect) {
|
||||
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 view2 = getItemView(image: UIImage(named: "Group 2072750451"), text: "Dailu Bonuses".localized)
|
||||
let view1 = getItemView(image: UIImage(named: "Group 2072750450"), text: "fableo_weekly_refill_package".localized)
|
||||
let view2 = getItemView(image: UIImage(named: "Group 2072750451"), text: "fableo_dailu_bonuses".localized)
|
||||
|
||||
addSubview(view1)
|
||||
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.textStartPoint = .init(x: 0, 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
|
||||
}()
|
||||
|
||||
@ -105,7 +105,7 @@ class FACoinPackConfirmView: FAPanModalContentView {
|
||||
button.fa_locations = [0, 1]
|
||||
button.fa_startPoint = .init(x: 0, y: 0.5)
|
||||
button.fa_endPoint = .init(x: 1, y: 0.5)
|
||||
button.setTitle("Continue".localized, for: .normal)
|
||||
button.setTitle("fableo_continue".localized, for: .normal)
|
||||
button.setTitleColor(.FFFFFF, for: .normal)
|
||||
button.titleLabel?.font = .font(ofSize: 14, weight: .bold)
|
||||
return button
|
||||
|
||||
@ -11,10 +11,10 @@ class FAConsumptionRecordsCell: FATableViewCell {
|
||||
|
||||
var model: FABuyRecordsModel? {
|
||||
didSet {
|
||||
titleLabel.text = "Purchase Single Episode".localized
|
||||
subtitleLabel.text = "Ep.##".localizedReplace(text: "\(model?.episode ?? "")") + " " + "\(model?.name ?? "")"
|
||||
titleLabel.text = "fableo_single_episode".localized
|
||||
subtitleLabel.text = "fableon_episode_set".localizedReplace(text: "\(model?.episode ?? "")") + " " + "\(model?.name ?? "")"
|
||||
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
|
||||
expiresLabel.isHidden = false
|
||||
expiredLabel.isHidden = true
|
||||
expiresLabel.text = "Expires in ## days".localizedReplace(text: model?.diff_datetime ?? "")
|
||||
expiresLabel.text = "fableo_expires_#_days".localizedReplace(text: model?.diff_datetime ?? "")
|
||||
} else {
|
||||
expiresIconImageView.isHidden = true
|
||||
expiresLabel.isHidden = true
|
||||
|
||||
@ -31,7 +31,7 @@ class FAStoreCoinsBigCell: FAStoreCoinsCell {
|
||||
if sendCoins > 0 {
|
||||
sendCoinsLabel.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)
|
||||
sendCoinsRatioLabel.text = "+\(ratio)%"
|
||||
|
||||
@ -51,7 +51,7 @@ class FAStoreCoinsPackCell: FAStoreCoinsCell {
|
||||
let label = UILabel()
|
||||
label.font = .font(ofSize: 14, weight: .init(700))
|
||||
label.textColor = .FFFFFF
|
||||
label.text = "Weekly Refill".localized
|
||||
label.text = "fableo_weekly_refill".localized
|
||||
return label
|
||||
}()
|
||||
|
||||
|
||||
@ -27,7 +27,7 @@ class FAStoreCoinsSmallCell: FAStoreCoinsCell {
|
||||
if sendCoins > 0 {
|
||||
sendCoinsLabel.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)
|
||||
sendCoinsRatioLabel.text = "+\(ratio)%"
|
||||
|
||||
@ -17,7 +17,7 @@ class FAStoreVipCell: UICollectionViewCell {
|
||||
// coinTimeLabel.text = item?.auto_sub
|
||||
|
||||
if let coins = item?.send_coins, coins > 0 {
|
||||
sendCoinLabel.text = "+\("extra".localized) \(coins)"
|
||||
sendCoinLabel.text = "+\("fableo_extra".localized) \(coins)"
|
||||
sendCoinLabel.isHidden = false
|
||||
coinImageView.isHidden = false
|
||||
} else {
|
||||
|
||||
@ -36,7 +36,7 @@ class FAWalletHeaderView: UIView {
|
||||
button.fa_locations = [0, 1]
|
||||
button.fa_startPoint = .init(x: 0, y: 0.5)
|
||||
button.fa_endPoint = .init(x: 1, y: 0.5)
|
||||
button.setTitle("Store".localized, for: .normal)
|
||||
button.setTitle("fableon_store".localized, for: .normal)
|
||||
button.setTitleColor(._000000, for: .normal)
|
||||
button.titleLabel?.font = .font(ofSize: 18, weight: .bold)
|
||||
return button
|
||||
@ -52,7 +52,7 @@ class FAWalletHeaderView: UIView {
|
||||
var config = UIButton.Configuration.plain()
|
||||
config.image = UIImage(named: "coins_icon_02")
|
||||
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),
|
||||
.foregroundColor : UIColor.F_7_F_497
|
||||
]))
|
||||
@ -77,7 +77,7 @@ class FAWalletHeaderView: UIView {
|
||||
config.imagePadding = 11
|
||||
config.imagePlacement = .trailing
|
||||
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),
|
||||
.foregroundColor : UIColor.F_7_F_497
|
||||
]))
|
||||
|
||||
@ -37,7 +37,7 @@ class FAApnsAlert: FABaseAlert {
|
||||
button.layer.masksToBounds = true
|
||||
button.layer.borderWidth = 1
|
||||
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.titleLabel?.font = .font(ofSize: 14, weight: .semibold)
|
||||
button.addTarget(self, action: #selector(dismiss), for: .touchUpInside)
|
||||
@ -46,7 +46,7 @@ class FAApnsAlert: FABaseAlert {
|
||||
|
||||
override init(frame: CGRect) {
|
||||
super.init(frame: frame)
|
||||
highlightButton.setTitle("Open".localized, for: .normal)
|
||||
highlightButton.setTitle("fableon_open".localized, for: .normal)
|
||||
|
||||
fa_setupLayout()
|
||||
}
|
||||
|
||||
@ -50,7 +50,7 @@ class FACoinsPackAlert: FABaseAlert {
|
||||
button.layer.masksToBounds = true
|
||||
button.layer.borderColor = UIColor._777777.cgColor
|
||||
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.titleLabel?.font = .font(ofSize: 14, weight: .bold)
|
||||
button.addTarget(self, action: #selector(dismiss), for: .touchUpInside)
|
||||
@ -60,7 +60,7 @@ class FACoinsPackAlert: FABaseAlert {
|
||||
override init(frame: CGRect) {
|
||||
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.fa_colors = [UIColor._53_A_2_F_1.cgColor, UIColor.C_5_DDF_5.cgColor]
|
||||
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.borderWidth = 1
|
||||
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.titleLabel?.font = .font(ofSize: 14, weight: .medium)
|
||||
button.addTarget(self, action: #selector(dismiss), for: .touchUpInside)
|
||||
@ -48,7 +48,7 @@ class FARemoveCollectAlert: FABaseAlert {
|
||||
override init(frame: CGRect) {
|
||||
super.init(frame: frame)
|
||||
|
||||
highlightButton.setTitle("Remove".localized, for: .normal)
|
||||
highlightButton.setTitle("fableon_remove".localized, for: .normal)
|
||||
|
||||
containerView.addSubview(imageView)
|
||||
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.textColors = [UIColor._53_A_2_F_1.cgColor, UIColor.C_5_DDF_5.cgColor]
|
||||
view.font = .font(ofSize: 24, weight: .init(900))
|
||||
view.text = "Weekly Refill".localized.uppercased()
|
||||
view.text = "fableo_weekly_refill".localized.uppercased()
|
||||
return view
|
||||
}()
|
||||
|
||||
@ -66,7 +66,7 @@ class FAVipRetainAlert: FABaseAlert {
|
||||
button.fa_locations = [0, 1]
|
||||
button.fa_startPoint = .init(x: 0, y: 0.5)
|
||||
button.fa_endPoint = .init(x: 0.7, y: 0.5)
|
||||
button.setTitle("Buy Now".localized, for: .normal)
|
||||
button.setTitle("fableon_buy_now".localized, for: .normal)
|
||||
button.setTitleColor(.FFFFFF, for: .normal)
|
||||
button.titleLabel?.font = .font(ofSize: 14, weight: .bold)
|
||||
return button
|
||||
|
||||
@ -152,7 +152,7 @@ class FAIapManager {
|
||||
}
|
||||
|
||||
if isLoding {
|
||||
FAToast.show(text: "success".localized)
|
||||
FAToast.show(text: "fableo_success".localized)
|
||||
}
|
||||
completer?(true, buyType)
|
||||
if buyType == .subVip {
|
||||
@ -223,7 +223,7 @@ extension FAIapManager: JXIAPManagerDelegate {
|
||||
FALogin.manager.userInfo?.is_vip = true
|
||||
}
|
||||
|
||||
FAToast.show(text: "success".localized)
|
||||
FAToast.show(text: "fableo_success".localized)
|
||||
self.completionHandler?(true)
|
||||
if buyType == .subVip {
|
||||
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
|
||||
}
|
||||
|
||||
///获得启动图
|
||||
static func getLanuchViewController() -> UIViewController? {
|
||||
let storyboard = UIStoryboard(name: "LaunchScreen", bundle: nil)
|
||||
let vc = storyboard.instantiateInitialViewController()
|
||||
return vc
|
||||
}
|
||||
|
||||
static var topViewController: UIViewController? {
|
||||
var resultVC: UIViewController? = self.rootViewController
|
||||
if let rootNav = resultVC as? UINavigationController {
|
||||
@ -64,7 +71,7 @@ extension FATool {
|
||||
completion?(ASIdentifierManager.shared().advertisingIdentifier.uuidString)
|
||||
return
|
||||
}
|
||||
guard FANetworkMonitor.manager.isReachable == true, FAAdjustStateManager.manager.apnsAuthorizationFinish, FAAdjustStateManager.manager.isOpenApp else {
|
||||
guard FANetworkMonitor.manager.isReachable == true, FAAdjustStateManager.manager.apnsAuthorizationFinish else {
|
||||
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 |