多语言开发完成

This commit is contained in:
湖北秦九 2025-11-04 16:46:56 +08:00
parent 8bbb3d10ad
commit 010ea1cd70
119 changed files with 1569 additions and 345 deletions

View File

@ -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 */,

View File

@ -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

View File

@ -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])

View File

@ -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

View File

@ -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()
}
}

View File

@ -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>

View File

@ -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)
}
}
}

View File

@ -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? {

View File

@ -9,3 +9,7 @@
let kFAWaitRestoreIAPDefaultsKey = "kFAWaitRestoreIAPDefaultsKey"
let kFAApnsAlertDefaultsKey = "kFAApnsAlertDefaultsKey"
let kFAVersionUpdateAlertDefaultsKey = "kFAVersionUpdateAlertDefaultsKey"
let kFAHasBeenOpenedAPPDefaultsKey = "kFAHasBeenOpenedAPPDefaultsKey"

View File

@ -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)
}
}
}

View File

@ -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", //

View File

@ -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

View File

@ -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) {

View File

@ -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
]

View File

@ -41,7 +41,7 @@ class FANewListViewController: FAViewController {
override func viewDidLoad() {
super.viewDidLoad()
self.title = "New".localized
self.title = "fableon_new".localized
fa_setupLayout()

View File

@ -41,7 +41,7 @@ class FAPopularListViewController: FAViewController {
override func viewDidLoad() {
super.viewDidLoad()
self.title = "Popular".localized
self.title = "fableon_popular".localized
fa_setupLayout()

View File

@ -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)

View File

@ -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))

View File

@ -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)

View File

@ -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))
}

View File

@ -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
}()

View File

@ -13,7 +13,7 @@ class FAHomePlayHistoryView: UIView {
didSet {
coverImageView.fa_setImage(model?.image_url)
titleLabel.text = model?.name
epLabel.text = "Last WatchEp.##".localizedReplace(text: model?.current_episode ?? "")
epLabel.text = "fableon_last_watch_ep".localizedReplace(text: model?.current_episode ?? "")
}
}

View File

@ -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)"
}
}

View File

@ -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)
])

View File

@ -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)")
}
}

View File

@ -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
}()

View File

@ -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 {

View File

@ -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 = {

View File

@ -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()

View 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()
}
}
}

View File

@ -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
}

View File

@ -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)

View File

@ -23,6 +23,7 @@ struct FAMeItemModel {
///
case rewardCoins
case deleteAccount
case language
}

View 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"]
]
}
}

View File

@ -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)
]))

View File

@ -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
}()

View File

@ -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
]))

View File

@ -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
}()

View 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")
}
}

View File

@ -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)

View File

@ -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
}()

View File

@ -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

View File

@ -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
]))

View File

@ -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()
}
}

View File

@ -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]

View File

@ -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()

View File

@ -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)")
}
}

View File

@ -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)")
}
}

View File

@ -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

View 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()
}
}

View 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()
}
}

View File

@ -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
}()

View File

@ -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()

View File

@ -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

View File

@ -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 {

View File

@ -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
}
}
}

View File

@ -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)

View File

@ -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")"

View File

@ -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()

View File

@ -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()
}

View File

@ -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)

View File

@ -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

View File

@ -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()

View File

@ -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

View File

@ -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)

View File

@ -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

View File

@ -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
}
}

View File

@ -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

View File

@ -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)%"

View File

@ -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
}()

View File

@ -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)%"

View File

@ -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 {

View File

@ -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
]))

View File

@ -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()
}

View File

@ -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

View 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")
}
}

View File

@ -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)

View 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)
}
}
}

View File

@ -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

View File

@ -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)

View 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]?
}

View 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 ?? "")
}
}

View 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?
}

View File

@ -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 ?? "")
}
}

View File

@ -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()
}
}
}

View File

@ -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
}
}

View 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
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 580 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 897 B

View 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
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.4 KiB

View 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
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 38 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 61 KiB

View 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
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 464 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 964 KiB

View 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
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 KiB

Some files were not shown because too many files have changed in this diff Show More