From 0232c818d890f79b6d63689c7efac56dec43078a Mon Sep 17 00:00:00 2001 From: zeng Date: Fri, 11 Jul 2025 09:41:41 +0800 Subject: [PATCH] =?UTF-8?q?=E7=9C=8B=E5=B9=BF=E5=91=8A=E7=AD=BE=E5=88=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ThimraTV.xcodeproj/project.pbxproj | 16 +++- .../Base/Controller/SPTabBarController.swift | 2 +- ThimraTV/Base/Networking/API/SPStatAPI.swift | 4 +- ThimraTV/Base/WebView/SPWebView.swift | 5 +- .../SPWebViewController+ScriptMessage.swift | 30 ++++++- .../Base/WebView/SPWebViewController.swift | 7 +- .../Controller/SPMineViewController.swift | 1 + .../Controller/SPRewardsViewController.swift | 5 +- .../AppOpenAd/SPAppOpenAdManager.swift | 83 ++++++++++++++++++ .../RewardedAd/SPRewardedAdManager.swift | 56 +++++++++--- ThimraTV/Libs/AdManager/SPStatAdModel.swift | 1 + .../tabbar_icon_03.imageset/Frame@2x.png | Bin 779 -> 958 bytes .../tabbar_icon_03.imageset/Frame@3x.png | Bin 1403 -> 1329 bytes .../Contents.json | 2 + .../Frame@2x.png | Bin 0 -> 1214 bytes .../Frame@3x.png | Bin 0 -> 2066 bytes 16 files changed, 185 insertions(+), 27 deletions(-) create mode 100644 ThimraTV/Libs/AdManager/AppOpenAd/SPAppOpenAdManager.swift create mode 100644 ThimraTV/Source/Assets.xcassets/TabBar/tabbar_icon_03_selected.imageset/Frame@2x.png create mode 100644 ThimraTV/Source/Assets.xcassets/TabBar/tabbar_icon_03_selected.imageset/Frame@3x.png diff --git a/ThimraTV.xcodeproj/project.pbxproj b/ThimraTV.xcodeproj/project.pbxproj index 57e516b..e71e64a 100644 --- a/ThimraTV.xcodeproj/project.pbxproj +++ b/ThimraTV.xcodeproj/project.pbxproj @@ -280,6 +280,7 @@ 1BF5130C2E1F4660009750EA /* SPRewardedAdManager+AppLovin.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1BF5130B2E1F4654009750EA /* SPRewardedAdManager+AppLovin.swift */; }; 1BF5130E2E1F5D9B009750EA /* SPRewardedAdManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1BF5130D2E1F5D8F009750EA /* SPRewardedAdManager.swift */; }; 1BF513112E1FA138009750EA /* SPStatAdModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1BF513102E1FA138009750EA /* SPStatAdModel.swift */; }; + 1BF513142E1FB8C1009750EA /* SPAppOpenAdManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1BF513132E1FB8C1009750EA /* SPAppOpenAdManager.swift */; }; C3D1CE788CA03A1878493356 /* Pods_ThimraTV.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = B64805795B479324EB764157 /* Pods_ThimraTV.framework */; }; /* End PBXBuildFile section */ @@ -591,6 +592,7 @@ 1BF5130B2E1F4654009750EA /* SPRewardedAdManager+AppLovin.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "SPRewardedAdManager+AppLovin.swift"; sourceTree = ""; }; 1BF5130D2E1F5D8F009750EA /* SPRewardedAdManager.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SPRewardedAdManager.swift; sourceTree = ""; }; 1BF513102E1FA138009750EA /* SPStatAdModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SPStatAdModel.swift; sourceTree = ""; }; + 1BF513132E1FB8C1009750EA /* SPAppOpenAdManager.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SPAppOpenAdManager.swift; sourceTree = ""; }; 1DBC40592DA4EDFC0093FCB0 /* ThimraTV.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = ThimraTV.app; sourceTree = BUILT_PRODUCTS_DIR; }; 1F666DE0B12C863F26BE5027 /* Pods-MoviaBox.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-MoviaBox.debug.xcconfig"; path = "Target Support Files/Pods-MoviaBox/Pods-MoviaBox.debug.xcconfig"; sourceTree = ""; }; A1174E10BCF2C606F7818792 /* Pods-ThimraTV.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-ThimraTV.release.xcconfig"; path = "Target Support Files/Pods-ThimraTV/Pods-ThimraTV.release.xcconfig"; sourceTree = ""; }; @@ -1480,6 +1482,7 @@ 1BDE20112E1E158400C2C2B5 /* AdManager */ = { isa = PBXGroup; children = ( + 1BF513122E1FB897009750EA /* AppOpenAd */, 1BF5130F2E1F5EE4009750EA /* RewardedAd */, 1BDE20122E1E159B00C2C2B5 /* SPAdManager.swift */, 1BDE20182E1E175800C2C2B5 /* SPAdInfo.swift */, @@ -1498,6 +1501,14 @@ path = RewardedAd; sourceTree = ""; }; + 1BF513122E1FB897009750EA /* AppOpenAd */ = { + isa = PBXGroup; + children = ( + 1BF513132E1FB8C1009750EA /* SPAppOpenAdManager.swift */, + ); + path = AppOpenAd; + sourceTree = ""; + }; 1DBC40502DA4EDFC0093FCB0 = { isa = PBXGroup; children = ( @@ -1773,6 +1784,7 @@ 1BB91D492E04FD6A00A2C715 /* SPTextField.swift in Sources */, 1BB91D4A2E04FD6A00A2C715 /* SPCampaignWebViewController.swift in Sources */, 1BB91D4B2E04FD6A00A2C715 /* SPWebMessageModel.swift in Sources */, + 1BF513142E1FB8C1009750EA /* SPAppOpenAdManager.swift in Sources */, 1BDE20192E1E175800C2C2B5 /* SPAdInfo.swift in Sources */, 1BB91D4C2E04FD6A00A2C715 /* SPWebView.swift in Sources */, 1BB91D4D2E04FD6A00A2C715 /* SPWebViewController.swift in Sources */, @@ -2094,7 +2106,7 @@ "$(inherited)", "@executable_path/Frameworks", ); - MARKETING_VERSION = 1.1.2; + MARKETING_VERSION = 1.1.3; PRODUCT_BUNDLE_IDENTIFIER = com.thimratv.app; PRODUCT_NAME = "$(TARGET_NAME)"; PROVISIONING_PROFILE_SPECIFIER = ""; @@ -2142,7 +2154,7 @@ "$(inherited)", "@executable_path/Frameworks", ); - MARKETING_VERSION = 1.1.2; + MARKETING_VERSION = 1.1.3; PRODUCT_BUNDLE_IDENTIFIER = com.thimratv.app; PRODUCT_NAME = "$(TARGET_NAME)"; PROVISIONING_PROFILE_SPECIFIER = ""; diff --git a/ThimraTV/Base/Controller/SPTabBarController.swift b/ThimraTV/Base/Controller/SPTabBarController.swift index 46d1759..fc9018e 100644 --- a/ThimraTV/Base/Controller/SPTabBarController.swift +++ b/ThimraTV/Base/Controller/SPTabBarController.swift @@ -20,7 +20,7 @@ class SPTabBarController: UITabBarController { let nav3 = createNavigationController(viewController: SPMyListViewController(), title: "movia_my_list".localized, image: UIImage(named: "tabbar_icon_04"), selectedImage: UIImage(named: "tabbar_icon_04_selected")) - let nav4 = createNavigationController(viewController: SPRewardsViewController(), title: "movia_rewards".localized, image: UIImage(named: "tabbar_icon_04"), selectedImage: UIImage(named: "tabbar_icon_04_selected")) + let nav4 = createNavigationController(viewController: SPRewardsViewController(), title: "movia_rewards".localized, image: UIImage(named: "tabbar_icon_03"), selectedImage: UIImage(named: "tabbar_icon_03_selected")) let nav5 = createNavigationController(viewController: SPMineViewController(), title: "movia_profile".localized, image: UIImage(named: "tabbar_icon_05"), selectedImage: UIImage(named: "tabbar_icon_05_selected")) diff --git a/ThimraTV/Base/Networking/API/SPStatAPI.swift b/ThimraTV/Base/Networking/API/SPStatAPI.swift index 72071b5..b2cae54 100644 --- a/ThimraTV/Base/Networking/API/SPStatAPI.swift +++ b/ThimraTV/Base/Networking/API/SPStatAPI.swift @@ -74,7 +74,7 @@ class SPStatAPI: NSObject { } ///广告统计 - static func requestStatAd(model: SPStatAdModel) { + static func requestStatAd(model: SPStatAdModel, completer: (() -> Void)? = nil) { var param = SPNetworkParameters(path: "/ad/history") param.isToast = false @@ -82,7 +82,7 @@ class SPStatAPI: NSObject { param.parameters = model.toDictionary() SPNetwork.request(parameters: param) { (response: SPNetworkResponse) in - + completer?() } } diff --git a/ThimraTV/Base/WebView/SPWebView.swift b/ThimraTV/Base/WebView/SPWebView.swift index 039d215..fb8635b 100644 --- a/ThimraTV/Base/WebView/SPWebView.swift +++ b/ThimraTV/Base/WebView/SPWebView.swift @@ -17,6 +17,7 @@ class SPWebView: WKWebView { WebMessageOpenFeedbackList, WebMessageOpenFeedbackDetail, WebMessageOpenPhotoPicker, + WebMessageOpenCheckSignIn, ] @@ -62,8 +63,8 @@ class SPWebView: WKWebView { func load(urlStr: String) { guard let url = URL(string: urlStr) else { return } -// var request = URLRequest(url: url, cachePolicy: .reloadIgnoringLocalCacheData, timeoutInterval: 30) - var request = URLRequest(url: url, cachePolicy: .returnCacheDataElseLoad, timeoutInterval: 30) +// let request = URLRequest(url: url, cachePolicy: .reloadIgnoringLocalCacheData, timeoutInterval: 30) + let request = URLRequest(url: url, cachePolicy: .returnCacheDataElseLoad, timeoutInterval: 30) self.load(request) } diff --git a/ThimraTV/Base/WebView/SPWebViewController+ScriptMessage.swift b/ThimraTV/Base/WebView/SPWebViewController+ScriptMessage.swift index 1983768..685bd5a 100644 --- a/ThimraTV/Base/WebView/SPWebViewController+ScriptMessage.swift +++ b/ThimraTV/Base/WebView/SPWebViewController+ScriptMessage.swift @@ -18,6 +18,8 @@ let WebMessageOpenFeedbackList: SPWebViewMessageName = "openFeedbackList" let WebMessageOpenFeedbackDetail: SPWebViewMessageName = "openFeedbackDetail" ///打开相册 let WebMessageOpenPhotoPicker: SPWebViewMessageName = "openPhotoPicker" +///点击签到 +let WebMessageOpenCheckSignIn: SPWebViewMessageName = "openCheckSignIn" extension SPWebViewController { @@ -73,8 +75,13 @@ extension SPWebViewController { } } - - + + } else if name == WebMessageOpenCheckSignIn { //点击点到 + self.needAutoRefresh = false + let manager = SPRewardedAdManager.manager + manager.statScene = .reward + manager.delegate = self + manager.loadAndShowRewardedAd() } @@ -117,3 +124,22 @@ extension SPWebViewController: TZImagePickerControllerDelegate { } } + +//MARK: -------------- SPRewardedAdManagerDelegate -------------- +extension SPWebViewController: SPRewardedAdManagerDelegate { + + func rewardedAdManager(manager: SPRewardedAdManager, didLoadFail error: any Error) { + self.needAutoRefresh = true + } + + func rewardedAdManager(manager: SPRewardedAdManager, didDisplayFail error: any Error) { + self.needAutoRefresh = true + } + + func rewardedAdManagerDidDismiss(manager: SPRewardedAdManager) { + self.needAutoRefresh = true + + let js = "uploadCheckSignIn()" + self.webView.evaluateJavaScript(js) + } +} diff --git a/ThimraTV/Base/WebView/SPWebViewController.swift b/ThimraTV/Base/WebView/SPWebViewController.swift index 1268df4..579028c 100644 --- a/ThimraTV/Base/WebView/SPWebViewController.swift +++ b/ThimraTV/Base/WebView/SPWebViewController.swift @@ -15,6 +15,8 @@ class SPWebViewController: SPViewController { ///自动设置标题 var autoTitle = true + var needAutoRefresh = true + private(set) lazy var webView: SPWebView = { let controller = WKUserContentController() @@ -51,10 +53,7 @@ class SPWebViewController: SPViewController { func load(urlString: String) { let str: String = urlString - guard let url = URL(string: str) else { return } - let request = URLRequest(url: url, timeoutInterval: 30) - - self.webView.load(request) + self.webView.load(urlStr: str) } func reload() { diff --git a/ThimraTV/Class/Mine/Controller/SPMineViewController.swift b/ThimraTV/Class/Mine/Controller/SPMineViewController.swift index 6752e62..f0517a1 100644 --- a/ThimraTV/Class/Mine/Controller/SPMineViewController.swift +++ b/ThimraTV/Class/Mine/Controller/SPMineViewController.swift @@ -118,6 +118,7 @@ extension SPMineViewController { guard SPLoginManager.manager.userInfo?.user_level == .ad else { return } guard needShowRewardedAd else { return } needShowRewardedAd = false + guard SPRewardedAdManager.manager.isEnable else { return } let manager = SPRewardedAdManager.manager manager.statScene = .me diff --git a/ThimraTV/Class/Rewards/Controller/SPRewardsViewController.swift b/ThimraTV/Class/Rewards/Controller/SPRewardsViewController.swift index ed3b7f5..2880e88 100644 --- a/ThimraTV/Class/Rewards/Controller/SPRewardsViewController.swift +++ b/ThimraTV/Class/Rewards/Controller/SPRewardsViewController.swift @@ -16,6 +16,7 @@ class SPRewardsViewController: SPCampaignWebViewController { private var isFirst = true + override func viewDidLoad() { self.urlStr = SPRewardsWebUrl super.viewDidLoad() @@ -54,7 +55,9 @@ class SPRewardsViewController: SPCampaignWebViewController { override func viewDidAppear(_ animated: Bool) { super.viewDidAppear(animated) if !isFirst { - self.reload() + if needAutoRefresh { + self.reload() + } } else { isFirst = false } diff --git a/ThimraTV/Libs/AdManager/AppOpenAd/SPAppOpenAdManager.swift b/ThimraTV/Libs/AdManager/AppOpenAd/SPAppOpenAdManager.swift new file mode 100644 index 0000000..d2e0823 --- /dev/null +++ b/ThimraTV/Libs/AdManager/AppOpenAd/SPAppOpenAdManager.swift @@ -0,0 +1,83 @@ +// +// SPAppOpenAdManager.swift +// ThimraTV +// +// Created by 长沙佳儿 on 2025/7/10. +// + +import UIKit +import GoogleMobileAds + +class SPAppOpenAdManager: NSObject { + + var appOpenAd: AppOpenAd? + var isLoadingAd = false + var isShowingAd = false + + static let shared = SPAppOpenAdManager() + + private func loadAd() async { + // Do not load ad if there is an unused ad or one is already loading. + if isLoadingAd || isAdAvailable() { + return + } + isLoadingAd = true + + do { + appOpenAd = try await AppOpenAd.load(with: "ca-app-pub-3940256099942544/5575463023", request: Request()) + + appOpenAd?.fullScreenContentDelegate = self + } catch { + print("App open ad failed to load with error: \(error.localizedDescription)") + } + isLoadingAd = false + } + + func showAdIfAvailable() { + // If the app open ad is already showing, do not show the ad again. + guard !isShowingAd else { return } + + // If the app open ad is not available yet but is supposed to show, load + // a new ad. + if !isAdAvailable() { + Task { + await loadAd() + } + return + } + + if let ad = appOpenAd { + isShowingAd = true + ad.present(from: nil) + } + } + + private func isAdAvailable() -> Bool { + // Check if ad exists and can be shown. + return appOpenAd != nil + } +} + +extension SPAppOpenAdManager: FullScreenContentDelegate { + func adWillPresentFullScreenContent(_ ad: FullScreenPresentingAd) { + print("App open ad will be presented.") + } + + func adDidDismissFullScreenContent(_ ad: FullScreenPresentingAd) { + appOpenAd = nil + isShowingAd = false + // Reload an ad. + Task { + await loadAd() + } + } + + func ad(_ ad: FullScreenPresentingAd, didFailToPresentFullScreenContentWithError error: Error) { + appOpenAd = nil + isShowingAd = false + // Reload an ad. + Task { + await loadAd() + } + } +} diff --git a/ThimraTV/Libs/AdManager/RewardedAd/SPRewardedAdManager.swift b/ThimraTV/Libs/AdManager/RewardedAd/SPRewardedAdManager.swift index 9b0644f..740cb5f 100644 --- a/ThimraTV/Libs/AdManager/RewardedAd/SPRewardedAdManager.swift +++ b/ThimraTV/Libs/AdManager/RewardedAd/SPRewardedAdManager.swift @@ -36,6 +36,8 @@ class SPRewardedAdManager: NSObject { private var retryCount = 0 ///最大重试次数 private let retryMaxCount = 1 + ///广告激活状态 + private(set) var isEnable = true private(set) var adInfo: SPAdInfo? @@ -47,6 +49,7 @@ class SPRewardedAdManager: NSObject { var statScene: SPStatAdModel.AdScene? var videoInfo: SPVideoInfoModel? + deinit { NotificationCenter.default.removeObserver(self) } @@ -57,23 +60,41 @@ class SPRewardedAdManager: NSObject { } ///加载并展示激励广告 - func loadAndShowRewardedAd() { - isShowLoading = true - isShowToast = true + func loadAndShowRewardedAd(isShowLoading: Bool = true, isShowToast: Bool = true) { + guard isEnable else { + let text = "movia_no_ads_tip".localized + if isShowToast { + SPToast.show(text: text) + } + self.isShowToast = false + self.isShowLoading = false + let error = NSError(domain: text.localized, code: -1) + loadFailHandler(isStat: false, error: error) + return + } - SPHUD.show() + self.isShowLoading = isShowLoading + self.isShowToast = isShowToast - if let adInfo = adInfo {//已有广告,并且加载完成 + if self.isShowLoading { + SPHUD.show() + } + + if let adInfo = adInfo {//已有广告 if adInfo.platform_key == .google { self.admob_loadAndShowRewardedAd(adInfo: adInfo) } } else { + guard !isLoadingRewardedAd else { return } + self.isLoadingRewardedAd = true + SPAdAPI.requestShowAdInfo { [weak self] adInfo in guard let self = self else { return } guard let adInfo = adInfo else { - SPHUD.dismiss() - SPToast.show(text: "movia_no_ads_tip".localized) + let text = "movia_no_ads_tip".localized + let error = NSError(domain: text.localized, code: -1) + loadFailHandler(isStat: false, error: error) return } self.adInfo = adInfo @@ -89,6 +110,7 @@ class SPRewardedAdManager: NSObject { ///预加载一个广告 func preloadRewardedAd() { + guard isEnable else { return } guard !isLoadingRewardedAd else { return } isShowLoading = false isShowToast = false @@ -112,6 +134,8 @@ class SPRewardedAdManager: NSObject { ///重试加载广告 private func retryLoadAd() { + guard isEnable else { return } + guard retryCount < retryMaxCount else { retryCount = 0 retryAttempt = 0 @@ -141,7 +165,7 @@ extension SPRewardedAdManager { } ///广告加载失败 - func loadFailHandler(error: Error) { + func loadFailHandler(isStat: Bool = true, error: Error) { if isShowLoading { SPHUD.dismiss() @@ -151,10 +175,13 @@ extension SPRewardedAdManager { } self.isLoadingRewardedAd = false self.delegate?.rewardedAdManager?(manager: self, didLoadFail: error) - self.requestStatAd(type: "load_failed", errorMsg: error.localizedDescription) + if isStat { + self.requestStatAd(type: "load_failed", errorMsg: error.localizedDescription) + } self.statScene = nil self.videoInfo = nil + self.isEnable = false self.retryLoadAd() } @@ -195,13 +222,16 @@ extension SPRewardedAdManager { } ///广告被关闭 func didDismissHandler() { - self.delegate?.rewardedAdManagerDidDismiss?(manager: self) var seconds = 0 if let adsDate = self.adsDate { seconds = Int(Date().timeIntervalSince(adsDate)) } - self.requestStatAd(type: "close", seconds: seconds, errorMsg: nil) + + self.requestStatAd(type: "close", seconds: seconds, errorMsg: nil) { [weak self] in + guard let self = self else { return } + self.delegate?.rewardedAdManagerDidDismiss?(manager: self) + } self.statScene = nil self.videoInfo = nil @@ -224,7 +254,7 @@ extension SPRewardedAdManager { //MARK: -------------- 统计 -------------- extension SPRewardedAdManager { - private func requestStatAd(type: String, seconds: Int = 0, errorMsg: String?) { + private func requestStatAd(type: String, seconds: Int = 0, errorMsg: String?, completer: (() -> Void)? = nil) { guard let adInfo = adInfo else { return } let model = SPStatAdModel() @@ -237,7 +267,7 @@ extension SPRewardedAdManager { model.short_play_id = self.videoInfo?.short_play_id model.short_play_video_id = self.videoInfo?.short_play_video_id - SPStatAPI.requestStatAd(model: model) + SPStatAPI.requestStatAd(model: model, completer: completer) } diff --git a/ThimraTV/Libs/AdManager/SPStatAdModel.swift b/ThimraTV/Libs/AdManager/SPStatAdModel.swift index a51fee1..ca075b8 100644 --- a/ThimraTV/Libs/AdManager/SPStatAdModel.swift +++ b/ThimraTV/Libs/AdManager/SPStatAdModel.swift @@ -13,6 +13,7 @@ class SPStatAdModel: SPModel, SmartCodable { enum AdScene: String, SmartCaseDefaultable { case detail = "detail" case me = "me" + case reward = "reward" } var type: String? //start click error click show_failed load_failed Interrupt(退到后台) close diff --git a/ThimraTV/Source/Assets.xcassets/TabBar/tabbar_icon_03.imageset/Frame@2x.png b/ThimraTV/Source/Assets.xcassets/TabBar/tabbar_icon_03.imageset/Frame@2x.png index 8d492fa679de5658964c448a93c335c4429821b6..9814033c4053d29c468657fa2839a76bef87aa2e 100644 GIT binary patch literal 958 zcmV;v13~$*9^FbYz#JfiR!W1Vujd^_nK z%d+x9h#cqqmg+vtiJ3^a?x#Fsq6Q#$sG1w-vP1uls@3wD{IQetbedALE3HjAxq0-r?b42NEI?iLM6t4LlN1 z1JjrNhA0CQ5&}zzxJDYvt2$$NCWI=<(kOY-K!Kj_hw@4*oIezknwXhHm`o_rfRvI< zrs58Wc#5cD@N=4ML5S|;Yu_>qggzqUr%)g;=$xQVQ+tVDKye;+L55*2;RGTy-ikoVc9wbKd) zLAh(1W~|qu{%z|2b5|Z+(_~-5w!6DKKaSK8iE&=!{{uVZ#t$l$%EeHNUeQe^tx#GW zB+|FADQJ-^l&a{H-79s@9EcFv>z-G_3o@@CFf)*XDSYV85tYgHk%%;*%!mZqkB|4} z2|fz-db1ST_#*lXJy_5i$|7mQ3)@&&P+NzvY+1~Ml!39p9S6|o8nnUF!C2FNN+iZ2 zBas$FBq)${!g4oyrVHemwtMB?T!Xq^A-DKb-|uiPe!i62(=2v=YmB!4|qZg14(B$FTFz~(O zIM;)Xv7bkex^zmL>pY$mbQ*m8{F9@7=3>)=j6_Bqy*$wc<6y)!dY<>kwu>+6 zRAy84)%yCny|uOZ{qpj1?mXKlsNBZJMp4}b2b!R()KkxEdz0Rq>Y$_N4uY2`qXTo? z(~dz-C0X<_Divp93L%h%DWTtm{%a@=NXgx46D^5zc8CupO7*^_p%(0|&{sF-lw7%( glt#{wA;UAkUx=1#DR8zmpa1{>07*qoM6N<$f;xo5vj6}9 literal 779 zcmV+m1N8ifP)Px%#Ysd#RA@u(S-*?aKotIFcZ)3)EEMfL(MC|Puu!m9(Bk|9LF>l-QO~km!@Ua3M$2r{X_BLXW_et!u+kA3mg_@CBMFwQX4+hfQ37l(Gzn zR{$=U5H!II28DCAn)PlJHgN&|CPZ|x-^XbafHSb0IveE9;5Yo{a~lltuTuX+m?^x zI+5BDl2Y9Ru;dZ{G#C_a)N0n}s6x^dFm&?)XaQIQ_%;!_zm3)`3GfO3WEM-h*1!kP zq5z-U8j)Ji*)Yojc8Jv8tP1FP&Dm-e1-$Kacwu?jtk0jNBecyd7HwNT(^Y-AA4;i} z_~U)Re|)-cbCFhx4#+Zd;cBTQ)-7vv4{xF*H325%Ofb0sDOIdy&ZN2~n4}$ePNc4w zY@8G(2?0Z6m0quOre3f9NQz)s9&f1jAuyh45~(AjV#40Y9s#%+2+|FD@;2i)_xz5QXT`u9dA~n8?Prt+#S<5 z0A3}cuVG2G0+M1htvtDaX;s!VZ|;C;rKW|;9hg>SP4i~nfnQm%lR!a`KOF!7002ov JPDHLkV1fl7UONB) diff --git a/ThimraTV/Source/Assets.xcassets/TabBar/tabbar_icon_03.imageset/Frame@3x.png b/ThimraTV/Source/Assets.xcassets/TabBar/tabbar_icon_03.imageset/Frame@3x.png index 78e9ca5808f1bd1810b94be5a6930f96663a8e69..52ec7b02a597e8006927278f6eb967119ca3cec7 100644 GIT binary patch literal 1329 zcmV-11T2vLq4&B~T(2S;6<7V-W-)^7mjc!~g-XSS%LHi-JLkTwY$*MkCRXQq(wievBgV z4`VFkoDEy8)jM}J?!Q2R6k2olgw}V$pQFk1+_uLJYy3Ffz zT0JO;LPR=0@Bghnw3PCrl#!R^Sn--;{MA*io7SEA9ulWg;my<2(?Hh_b;~G%TaD-^ zXJ_pXPylO-GvlUH7|`oo+@PRGv7%6jr=N-#{Tx`Iu5x^0 z>O4K~G!Vkshq(pKAWJkAXnYgh_Ayyqtf-1z_dOKAS|Uw`=eZToP3ARm5(=+8NtUwU z)vHSGt`bGOnP`QvcTfOE-7OZ#Rg*X2&?s~qD>^~vn=441g0aqE-Y!{$T*>iD>0Bqf zFKaR;0<~VAKy;x<DJPNy?e%PX3S;)ms=$;^f%BU@7FaWaqIW8DK>+z=~vm70G~wB4G$ngPmvjGp0m}zYb97PSc~X zqxgP5F=3eX>Xmve!I!-+I9b)09@G3WzR&e^b23FD6E7tYPA2rq{66*ud&+y|9zN;n zR?-(o9~g6w=4Lqljk&Z^lf5d{_$1tBV1es8ciJ<$!etZmJ4ood{FkhZjMi~aC+M@x zZ>tc+z=~vm70CcAk^xpE1FT2}tR)hy(uFOjhp`OvojY5Tm=~7qWM>&la{6N{0!-4&!B%MuME=5{dR= zs5^n4o}$}r6l$`oAxi9nqjZu5h2yw?DZ45| z&YhK#sVgNHG1*6}F*Mr@SU?$4{3(4KdKQ?Sr9YN#L|b_$<;oe@UeEX9>EkVDt*xeO zrK!oR)BDS|2{vB!uiGz@s}(4K$-X$CMNtjNSXIA4aByKm?0BD0oI5ChQWiXXtI_W9 n@iE-Qf6HO9SS%Kc<-6d2&nEoRUGR-i00000NkvXXu0mjfBF|=a literal 1403 zcmV->1%&#EP)Px)HAzH4RCr$Pn@?yQRUF5^zqb=j6N?9{7tvN!BHDu>c<>-z?7^EzY^o@V_!mK` zg*BSYytf;o!PJeQg28IBicRBLs6AL|sbHm0N@CO&tnI-+J%q$;OtbTTX42Fon@#4; z&SaC>zPY~l`}02Yo!`v7KLmTNNPsM#l?hltAqug8ETDKr#45-t$SNov0jr>R{A>-f z3bG1{M<8hhNhz<&WHOserBW*(9tCg*z*n1RNmBqu0R34elR2cd{#i`(dH#hZUv)S?54&5x8@c;uj#p2|LGk3oYfMe#~ zs8?x5h5MVDHoUYRAsGSkJkMbk?L_P*3}=oYO$EN0`CX+{0Bqe{Mu57yx^9}DE`4*U z-mKbn+Ho=ub#`|Cx@r-saBKv~^SqY<(Fbs5aSWOS^kD$M6OkVlpLy2)Wu` znVEw}jR;4>{Ft^2A;y{cjFj@2sZDu5LqPI70QZ*-XdK|@bGh7?QG>g#y91z)h-hO} z+ba8?26ztUCel=4A7KPUSpW=D+SO~%=ok%hEg(g{GlB#6;qk` zYd-AGCD|^ew18FuY5|4FEtP;;TU#?NEiGGwXt>vL==|8&*oofW-iah1t;@br2`Hb> z-%=|12blRDB2ff*U+_bzl=?AgNT~!QrEFuS&*!I5$Y<7n0b+M^b7Oy!vx{j3RPoIM zpak%t85KzYCz6<9tT#ZjPZ%?g6VZD_7#JEF`e|@*Fmyt0xks}u0nI@Qp!@;^|4q3) z)z+rE1yly4e|q|&+uhy$XH-yE2q2nb#%sBp_kjgefdCOrYmIC!=M^lVr35rHpJL8D z8)ZH@)gOw>)rAV`IM2)jMEF=KH4;@lLH~NLK}P{@C!!zXY;dSIKpLQPfbLUD^;M&o za+_2Fa$WZkBJtJ2!OVRe2LELHhKGlb$N4y1=r@&sf^{(>@%{YjDjyd@w2zLC9xD_I zlSwEi)kQj37ZXD4(3;zbFw8u=QhOmuFsTN#8X)TGU(5okC4rDwsVvg9VY=s79n z{;(ix*&ZwoXwCf4s4t*l?;}RZ6`dma`F{d_I4BspNkR;I=S_DQO>RXmGZ5bab2x%hw1{@LNDcJDDjL z?OaA!_%&%S1>+#nZ<#D983780v5H3#YDp>bu?J&7^N@;JfF1|1rIsU$6D!!HPDEz_ z9%yQcc5o&VpdiWMIFt~g#rORO0r6z?<4|#i8rAmyqgMwU#~Ji}|7_Hm$;g1BrkM8r z7Es6?w16z2cn`T%kX4XXP&@)wLGk$68e|n@6%>zvRZu*B{{d9SD0XwA`cD7=002ov JPDHLkV1kpIh%o>F diff --git a/ThimraTV/Source/Assets.xcassets/TabBar/tabbar_icon_03_selected.imageset/Contents.json b/ThimraTV/Source/Assets.xcassets/TabBar/tabbar_icon_03_selected.imageset/Contents.json index d77ddd3..6aa90f6 100644 --- a/ThimraTV/Source/Assets.xcassets/TabBar/tabbar_icon_03_selected.imageset/Contents.json +++ b/ThimraTV/Source/Assets.xcassets/TabBar/tabbar_icon_03_selected.imageset/Contents.json @@ -5,10 +5,12 @@ "scale" : "1x" }, { + "filename" : "Frame@2x.png", "idiom" : "universal", "scale" : "2x" }, { + "filename" : "Frame@3x.png", "idiom" : "universal", "scale" : "3x" } diff --git a/ThimraTV/Source/Assets.xcassets/TabBar/tabbar_icon_03_selected.imageset/Frame@2x.png b/ThimraTV/Source/Assets.xcassets/TabBar/tabbar_icon_03_selected.imageset/Frame@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..40d6eead0966dbfd8fc17933bcbb91d5b7238f91 GIT binary patch literal 1214 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