diff --git a/Podfile b/Podfile index ac19a15..4c5ab96 100644 --- a/Podfile +++ b/Podfile @@ -16,17 +16,20 @@ target 'Veloria' do use_frameworks! + pod 'SVProgressHUD' #HUD pod 'Moya' #网络框架 - pod 'SnapKit' #布局 pod 'SmartCodable' #数据解析 pod 'YYKit' #工具类 pod 'MJRefresh' #刷新控件 + pod 'SnapKit' #布局 pod 'Toast' #吐司提示 - pod 'ZFPlayer/AVPlayer' #播放器 pod 'KTVHTTPCache' #视频缓存 - pod 'HWPanModal' #底部弹出控制器 pod 'Kingfisher' #图片加载 + pod 'HWPanModal' #底部弹出控制器 pod "ESTabBarController-swift" pod 'WMZPageController' #分页控制器 - + pod 'ZFPlayer/AVPlayer' #播放器 + pod 'EmptyDataSet-Swift' #空数据页面 + + end diff --git a/Podfile.lock b/Podfile.lock index 38ae34b..a37042e 100644 --- a/Podfile.lock +++ b/Podfile.lock @@ -1,6 +1,7 @@ PODS: - Alamofire (5.10.2) - CocoaAsyncSocket (7.6.5) + - EmptyDataSet-Swift (5.0.0) - ESTabBarController-swift (2.8.0) - HWPanModal (0.9.9) - Kingfisher (8.3.2) @@ -15,6 +16,9 @@ PODS: - SmartCodable/Core (= 5.0.9) - SmartCodable/Core (5.0.9) - SnapKit (5.7.1) + - SVProgressHUD (2.3.1): + - SVProgressHUD/Core (= 2.3.1) + - SVProgressHUD/Core (2.3.1) - Toast (4.1.1) - WMZPageController (1.5.5) - YYKit (1.0.9): @@ -25,6 +29,7 @@ PODS: - ZFPlayer/Core (4.1.4) DEPENDENCIES: + - EmptyDataSet-Swift - ESTabBarController-swift - HWPanModal - Kingfisher @@ -33,6 +38,7 @@ DEPENDENCIES: - Moya - SmartCodable - SnapKit + - SVProgressHUD - Toast - WMZPageController - YYKit @@ -42,6 +48,7 @@ SPEC REPOS: trunk: - Alamofire - CocoaAsyncSocket + - EmptyDataSet-Swift - ESTabBarController-swift - HWPanModal - Kingfisher @@ -50,6 +57,7 @@ SPEC REPOS: - Moya - SmartCodable - SnapKit + - SVProgressHUD - Toast - WMZPageController - YYKit @@ -58,6 +66,7 @@ SPEC REPOS: SPEC CHECKSUMS: Alamofire: 7193b3b92c74a07f85569e1a6c4f4237291e7496 CocoaAsyncSocket: 065fd1e645c7abab64f7a6a2007a48038fdc6a99 + EmptyDataSet-Swift: eb382c0c87a2d9c678077385a595cec52da38171 ESTabBarController-swift: 05593a6ad64700b03c0eb60ff625916370aa4136 HWPanModal: b57a6717d3cdcd666bff44f9dd2a5be9f4d6f5d2 Kingfisher: 0621d0ac0c78fecb19f6dc5303bde2b52abaf2f5 @@ -66,11 +75,12 @@ SPEC CHECKSUMS: Moya: 138f0573e53411fb3dc17016add0b748dfbd78ee SmartCodable: 68b3598438181a938eed8ee5623e58ef3e3ea443 SnapKit: d612e99e678a2d3b95bf60b0705ed0a35c03484a + SVProgressHUD: 4837c74bdfe2e51e8821c397825996a8d7de6e22 Toast: 1f5ea13423a1e6674c4abdac5be53587ae481c4e WMZPageController: 87dd82d1e3528cd362de19b9a74fd6890d6e1906 YYKit: 7cda43304a8dc3696c449041e2cb3107b4e236e7 ZFPlayer: 5cf39e8d9f0c2394a014b0db4767b5b5a6bffe13 -PODFILE CHECKSUM: e5cac55fd92698becba7d142dc17ec724cd6313f +PODFILE CHECKSUM: 5a8b71939b2bf65623c166084b1e01d877b2979d COCOAPODS: 1.16.2 diff --git a/Veloria.xcodeproj/project.pbxproj b/Veloria.xcodeproj/project.pbxproj index e05b1da..8a35188 100644 --- a/Veloria.xcodeproj/project.pbxproj +++ b/Veloria.xcodeproj/project.pbxproj @@ -119,6 +119,21 @@ BF0FA7A12DE1AA5100C9E5F2 /* VPTableView.swift in Sources */ = {isa = PBXBuildFile; fileRef = BF0FA7A02DE1AA5100C9E5F2 /* VPTableView.swift */; }; BF0FA7A32DE1AB1800C9E5F2 /* VPWatchHistoryCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = BF0FA7A22DE1AB1800C9E5F2 /* VPWatchHistoryCell.swift */; }; BF0FA7A52DE4384100C9E5F2 /* AttributedString+VPAdd.swift in Sources */ = {isa = PBXBuildFile; fileRef = BF0FA7A42DE4384100C9E5F2 /* AttributedString+VPAdd.swift */; }; + BF0FA7AF2DE443E000C9E5F2 /* VPMeViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = BF0FA7AE2DE443E000C9E5F2 /* VPMeViewController.swift */; }; + BF0FA7B12DE447EB00C9E5F2 /* VPMeItem.swift in Sources */ = {isa = PBXBuildFile; fileRef = BF0FA7B02DE447EB00C9E5F2 /* VPMeItem.swift */; }; + BF0FA7B32DE447FE00C9E5F2 /* VPMeCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = BF0FA7B22DE447FE00C9E5F2 /* VPMeCell.swift */; }; + BF0FA7B62DE44E8000C9E5F2 /* VPWebView.swift in Sources */ = {isa = PBXBuildFile; fileRef = BF0FA7B52DE44E8000C9E5F2 /* VPWebView.swift */; }; + BF0FA7B82DE44FCC00C9E5F2 /* VPWebViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = BF0FA7B72DE44FCC00C9E5F2 /* VPWebViewController.swift */; }; + BF0FA7BA2DE451B900C9E5F2 /* UINavigationBar+VPAdd.swift in Sources */ = {isa = PBXBuildFile; fileRef = BF0FA7B92DE451B000C9E5F2 /* UINavigationBar+VPAdd.swift */; }; + BF0FA7BC2DE4563300C9E5F2 /* VPMeUserInfoCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = BF0FA7BB2DE4563300C9E5F2 /* VPMeUserInfoCell.swift */; }; + BF0FA7BE2DE4592A00C9E5F2 /* UserDefaults+VPAdd.swift in Sources */ = {isa = PBXBuildFile; fileRef = BF0FA7BD2DE4591B00C9E5F2 /* UserDefaults+VPAdd.swift */; }; + BF0FA7C12DE45D5D00C9E5F2 /* VPUserInfo.swift in Sources */ = {isa = PBXBuildFile; fileRef = BF0FA7C02DE45D5D00C9E5F2 /* VPUserInfo.swift */; }; + BF0FA7C32DE45DE300C9E5F2 /* VPUserAPI.swift in Sources */ = {isa = PBXBuildFile; fileRef = BF0FA7C22DE45DE300C9E5F2 /* VPUserAPI.swift */; }; + BF5E75AF2DE4632200DE9DFE /* VPAboutUsViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = BF5E75AE2DE4632200DE9DFE /* VPAboutUsViewController.swift */; }; + BF5E75B12DE4656600DE9DFE /* VPCampaignWebViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = BF5E75B02DE4656600DE9DFE /* VPCampaignWebViewController.swift */; }; + BF5E75B32DE465EC00DE9DFE /* Dictionary+SPAdd.swift in Sources */ = {isa = PBXBuildFile; fileRef = BF5E75B22DE465EA00DE9DFE /* Dictionary+SPAdd.swift */; }; + BF5E75B62DE46DB600DE9DFE /* UIScrollView+Empty.swift in Sources */ = {isa = PBXBuildFile; fileRef = BF5E75B52DE46DB600DE9DFE /* UIScrollView+Empty.swift */; }; + BF5E75B82DE46F7100DE9DFE /* VPNetworkReachabilityManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = BF5E75B72DE46F7100DE9DFE /* VPNetworkReachabilityManager.swift */; }; F939C04AD4003BA127F15C28 /* Pods_Veloria.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 34F57E87E765BF8D72A43DCA /* Pods_Veloria.framework */; }; /* End PBXBuildFile section */ @@ -244,6 +259,21 @@ BF0FA7A02DE1AA5100C9E5F2 /* VPTableView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = VPTableView.swift; sourceTree = ""; }; BF0FA7A22DE1AB1800C9E5F2 /* VPWatchHistoryCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = VPWatchHistoryCell.swift; sourceTree = ""; }; BF0FA7A42DE4384100C9E5F2 /* AttributedString+VPAdd.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "AttributedString+VPAdd.swift"; sourceTree = ""; }; + BF0FA7AE2DE443E000C9E5F2 /* VPMeViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = VPMeViewController.swift; sourceTree = ""; }; + BF0FA7B02DE447EB00C9E5F2 /* VPMeItem.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = VPMeItem.swift; sourceTree = ""; }; + BF0FA7B22DE447FE00C9E5F2 /* VPMeCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = VPMeCell.swift; sourceTree = ""; }; + BF0FA7B52DE44E8000C9E5F2 /* VPWebView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = VPWebView.swift; sourceTree = ""; }; + BF0FA7B72DE44FCC00C9E5F2 /* VPWebViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = VPWebViewController.swift; sourceTree = ""; }; + BF0FA7B92DE451B000C9E5F2 /* UINavigationBar+VPAdd.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "UINavigationBar+VPAdd.swift"; sourceTree = ""; }; + BF0FA7BB2DE4563300C9E5F2 /* VPMeUserInfoCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = VPMeUserInfoCell.swift; sourceTree = ""; }; + BF0FA7BD2DE4591B00C9E5F2 /* UserDefaults+VPAdd.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "UserDefaults+VPAdd.swift"; sourceTree = ""; }; + BF0FA7C02DE45D5D00C9E5F2 /* VPUserInfo.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = VPUserInfo.swift; sourceTree = ""; }; + BF0FA7C22DE45DE300C9E5F2 /* VPUserAPI.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = VPUserAPI.swift; sourceTree = ""; }; + BF5E75AE2DE4632200DE9DFE /* VPAboutUsViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = VPAboutUsViewController.swift; sourceTree = ""; }; + BF5E75B02DE4656600DE9DFE /* VPCampaignWebViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = VPCampaignWebViewController.swift; sourceTree = ""; }; + BF5E75B22DE465EA00DE9DFE /* Dictionary+SPAdd.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Dictionary+SPAdd.swift"; sourceTree = ""; }; + BF5E75B52DE46DB600DE9DFE /* UIScrollView+Empty.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "UIScrollView+Empty.swift"; sourceTree = ""; }; + BF5E75B72DE46F7100DE9DFE /* VPNetworkReachabilityManager.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = VPNetworkReachabilityManager.swift; sourceTree = ""; }; E0BDA3570E00C90877E45AA0 /* Pods-VideoPlayer.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-VideoPlayer.debug.xcconfig"; path = "Target Support Files/Pods-VideoPlayer/Pods-VideoPlayer.debug.xcconfig"; sourceTree = ""; }; /* End PBXFileReference section */ @@ -316,6 +346,8 @@ 1B056E352DDAC1DE007EE38D /* Libs */ = { isa = PBXGroup; children = ( + BF5E75B42DE46D9500DE9DFE /* Empty */, + BF0FA7BF2DE45D4500C9E5F2 /* User */, BF0FA7432DDF025A00C9E5F2 /* Player */, BF0FA6F22DDC603200C9E5F2 /* HUD */, BF0FA6D82DDC5C8200C9E5F2 /* Login */, @@ -328,6 +360,7 @@ 1B056E362DDAC1E8007EE38D /* Class */ = { isa = PBXGroup; children = ( + BF0FA7A62DE4437F00C9E5F2 /* Me */, BF0FA7952DE1948A00C9E5F2 /* MyList */, 1B056E522DDACBF4007EE38D /* Home */, BF0FA7422DDF024400C9E5F2 /* Explore */, @@ -344,6 +377,7 @@ 1B056E3A2DDAC21E007EE38D /* Model */, 1B056E422DDAC32C007EE38D /* Extension */, 1B056E3C2DDAC23D007EE38D /* Define */, + BF0FA7B42DE44E5100C9E5F2 /* WebView */, 1B056E3B2DDAC22D007EE38D /* Networking */, ); path = Base; @@ -410,6 +444,7 @@ BF0FA6D42DDC5B5D00C9E5F2 /* VPApi.swift */, BF0FA6D62DDC5BE100C9E5F2 /* VPURLPath.swift */, BF0FA6F02DDC600200C9E5F2 /* VPNetwork.swift */, + BF5E75B72DE46F7100DE9DFE /* VPNetworkReachabilityManager.swift */, ); path = Base; sourceTree = ""; @@ -417,6 +452,9 @@ 1B056E422DDAC32C007EE38D /* Extension */ = { isa = PBXGroup; children = ( + BF5E75B22DE465EA00DE9DFE /* Dictionary+SPAdd.swift */, + BF0FA7BD2DE4591B00C9E5F2 /* UserDefaults+VPAdd.swift */, + BF0FA7B92DE451B000C9E5F2 /* UINavigationBar+VPAdd.swift */, 1B056E432DDAC355007EE38D /* UIDevice+VPAdd.swift */, 1B056E452DDAC370007EE38D /* UIScreen+VPAdd.swift */, 1B056E5A2DDACD80007EE38D /* UIColor+VPAdd.swift */, @@ -547,6 +585,7 @@ children = ( BF0FA6F82DDC64E700C9E5F2 /* VPHomeAPI.swift */, BF0FA73C2DDED2D000C9E5F2 /* VPVideoAPI.swift */, + BF0FA7C22DE45DE300C9E5F2 /* VPUserAPI.swift */, ); path = API; sourceTree = ""; @@ -755,6 +794,68 @@ path = View; sourceTree = ""; }; + BF0FA7A62DE4437F00C9E5F2 /* Me */ = { + isa = PBXGroup; + children = ( + BF0FA7A72DE4438600C9E5F2 /* Controller */, + BF0FA7AC2DE443AE00C9E5F2 /* View */, + BF0FA7AD2DE443B700C9E5F2 /* Model */, + ); + path = Me; + sourceTree = ""; + }; + BF0FA7A72DE4438600C9E5F2 /* Controller */ = { + isa = PBXGroup; + children = ( + BF0FA7AE2DE443E000C9E5F2 /* VPMeViewController.swift */, + BF5E75AE2DE4632200DE9DFE /* VPAboutUsViewController.swift */, + BF5E75B02DE4656600DE9DFE /* VPCampaignWebViewController.swift */, + ); + path = Controller; + sourceTree = ""; + }; + BF0FA7AC2DE443AE00C9E5F2 /* View */ = { + isa = PBXGroup; + children = ( + BF0FA7B22DE447FE00C9E5F2 /* VPMeCell.swift */, + BF0FA7BB2DE4563300C9E5F2 /* VPMeUserInfoCell.swift */, + ); + path = View; + sourceTree = ""; + }; + BF0FA7AD2DE443B700C9E5F2 /* Model */ = { + isa = PBXGroup; + children = ( + BF0FA7B02DE447EB00C9E5F2 /* VPMeItem.swift */, + ); + path = Model; + sourceTree = ""; + }; + BF0FA7B42DE44E5100C9E5F2 /* WebView */ = { + isa = PBXGroup; + children = ( + BF0FA7B52DE44E8000C9E5F2 /* VPWebView.swift */, + BF0FA7B72DE44FCC00C9E5F2 /* VPWebViewController.swift */, + ); + path = WebView; + sourceTree = ""; + }; + BF0FA7BF2DE45D4500C9E5F2 /* User */ = { + isa = PBXGroup; + children = ( + BF0FA7C02DE45D5D00C9E5F2 /* VPUserInfo.swift */, + ); + path = User; + sourceTree = ""; + }; + BF5E75B42DE46D9500DE9DFE /* Empty */ = { + isa = PBXGroup; + children = ( + BF5E75B52DE46DB600DE9DFE /* UIScrollView+Empty.swift */, + ); + path = Empty; + sourceTree = ""; + }; /* End PBXGroup section */ /* Begin PBXNativeTarget section */ @@ -877,13 +978,18 @@ 1B056E742DDB2DD7007EE38D /* UIView+VPAdd.swift in Sources */, BF0FA6F12DDC600200C9E5F2 /* VPNetwork.swift in Sources */, BF0FA7502DDF0A9900C9E5F2 /* VPVideoPlayerCell.swift in Sources */, + BF5E75B62DE46DB600DE9DFE /* UIScrollView+Empty.swift in Sources */, 1B056E572DDACC6B007EE38D /* VPHomePageViewController.swift in Sources */, + BF0FA7BC2DE4563300C9E5F2 /* VPMeUserInfoCell.swift in Sources */, + BF0FA7B82DE44FCC00C9E5F2 /* VPWebViewController.swift in Sources */, BF0FA72A2DDC922F00C9E5F2 /* VPHomeRecommandCell.swift in Sources */, BF0FA7322DDEBD6400C9E5F2 /* AppDelegate+Config.swift in Sources */, + BF0FA7B32DE447FE00C9E5F2 /* VPMeCell.swift in Sources */, BF0FA6DF2DDC5E4D00C9E5F2 /* String+VPAdd.swift in Sources */, BF0FA7002DDC665300C9E5F2 /* VPShortModel.swift in Sources */, 1B056E7B2DDB37BA007EE38D /* VPGradientView.swift in Sources */, BF0FA7262DDC8F7600C9E5F2 /* VPCollectionView.swift in Sources */, + BF0FA7C32DE45DE300C9E5F2 /* VPUserAPI.swift in Sources */, BF0FA78B2DE164C100C9E5F2 /* VPSearchResultCell.swift in Sources */, BF0FA71D2DDC807200C9E5F2 /* UIImageView+VPAdd.swift in Sources */, BF0FA6DC2DDC5CD700C9E5F2 /* VPTokenModel.swift in Sources */, @@ -916,12 +1022,15 @@ BF0FA7522DDF134700C9E5F2 /* VPVideoPlayerControlView.swift in Sources */, BF0FA7852DE1561D00C9E5F2 /* VPSearchRecommendedCell.swift in Sources */, BF0FA7832DE1533E00C9E5F2 /* VPGradientLabel.swift in Sources */, + BF0FA7B12DE447EB00C9E5F2 /* VPMeItem.swift in Sources */, 1B056E2C2DDAC0FD007EE38D /* SceneDelegate.swift in Sources */, BF0FA75D2DDF208400C9E5F2 /* VPExplorePlayerControlView.swift in Sources */, 1B056E462DDAC370007EE38D /* UIScreen+VPAdd.swift in Sources */, BF0FA7692DE0502900C9E5F2 /* VPEpisodeCell.swift in Sources */, BF0FA73D2DDED2D000C9E5F2 /* VPVideoAPI.swift in Sources */, BF0FA6EE2DDC5F8700C9E5F2 /* JXUUID.m in Sources */, + BF5E75B12DE4656600DE9DFE /* VPCampaignWebViewController.swift in Sources */, + BF0FA7BA2DE451B900C9E5F2 /* UINavigationBar+VPAdd.swift in Sources */, BF0FA77D2DE078D400C9E5F2 /* VPSearchRecommendedView.swift in Sources */, BF0FA7812DE150F700C9E5F2 /* VPSearchRecommendedContentView.swift in Sources */, BF0FA7872DE1601200C9E5F2 /* VPTextField.swift in Sources */, @@ -933,6 +1042,7 @@ BF0FA6DA2DDC5CB600C9E5F2 /* VPLoginManager.swift in Sources */, BF0FA74A2DDF04E200C9E5F2 /* VPPlayerProtocol.swift in Sources */, BF0FA72C2DDD7B7300C9E5F2 /* VPHomeRankingContentCell.swift in Sources */, + BF0FA7AF2DE443E000C9E5F2 /* VPMeViewController.swift in Sources */, BF0FA7942DE16E9300C9E5F2 /* JXTagView.swift in Sources */, BF0FA7A52DE4384100C9E5F2 /* AttributedString+VPAdd.swift in Sources */, BF0FA7652DE00A0E00C9E5F2 /* VPDetailPlayerControlView.swift in Sources */, @@ -951,11 +1061,13 @@ BF0FA79D2DE198C600C9E5F2 /* VPWatchHistoryViewController.swift in Sources */, 1B056E6A2DDAD0BF007EE38D /* VPLocalizedManager.swift in Sources */, BF0FA7242DDC888F00C9E5F2 /* VPHomeRecommandContentCell.swift in Sources */, + BF5E75AF2DE4632200DE9DFE /* VPAboutUsViewController.swift in Sources */, BF0FA78F2DE16B2A00C9E5F2 /* VPUserDefaultsKey.swift in Sources */, BF0FA7192DDC7F4900C9E5F2 /* VPHomeBannerCell.swift in Sources */, BF0FA7712DE062EB00C9E5F2 /* VPVideoRateModel.swift in Sources */, BF0FA7022DDC667C00C9E5F2 /* VPVideoInfoModel.swift in Sources */, BF0FA77B2DE0788A00C9E5F2 /* UIStackView+VPAdd.swift in Sources */, + BF0FA7BE2DE4592A00C9E5F2 /* UserDefaults+VPAdd.swift in Sources */, BF0FA76F2DE062A700C9E5F2 /* VPRateSelectedView.swift in Sources */, BF0FA7772DE0735800C9E5F2 /* VPSearchInputView.swift in Sources */, BF0FA7892DE161F200C9E5F2 /* VPSearchResultView.swift in Sources */, @@ -969,13 +1081,17 @@ BF0FA73F2DDEF26E00C9E5F2 /* VPHomeSearchButton.swift in Sources */, 1B056E512DDACBE5007EE38D /* VPViewController.swift in Sources */, BF0FA7122DDC6D2C00C9E5F2 /* VPHomeModuleItem.swift in Sources */, + BF5E75B32DE465EC00DE9DFE /* Dictionary+SPAdd.swift in Sources */, BF0FA7162DDC78FF00C9E5F2 /* ZKCycleScrollViewFlowLayout.swift in Sources */, BF0FA7172DDC78FF00C9E5F2 /* ZKCycleScrollView.swift in Sources */, BF0FA7612DDFFE7100C9E5F2 /* VPVideoDetailModel.swift in Sources */, + BF5E75B82DE46F7100DE9DFE /* VPNetworkReachabilityManager.swift in Sources */, BF0FA6D52DDC5B5D00C9E5F2 /* VPApi.swift in Sources */, + BF0FA7C12DE45D5D00C9E5F2 /* VPUserInfo.swift in Sources */, BF0FA6FC2DDC657500C9E5F2 /* VPHomeDataModel.swift in Sources */, BF0FA7392DDECF8900C9E5F2 /* VPHomeListViewController.swift in Sources */, BF0FA6F62DDC616300C9E5F2 /* VPToast.swift in Sources */, + BF0FA7B62DE44E8000C9E5F2 /* VPWebView.swift in Sources */, 1B056E492DDAC3DF007EE38D /* VPAppTool.swift in Sources */, BF0FA74E2DDF067E00C9E5F2 /* VPVideoPlayViewModel.swift in Sources */, BF0FA75B2DDF206000C9E5F2 /* VPExplorePlayerCell.swift in Sources */, diff --git a/Veloria/AppDelegate/AppDelegate+Config.swift b/Veloria/AppDelegate/AppDelegate+Config.swift index 38bc9e2..2481478 100644 --- a/Veloria/AppDelegate/AppDelegate+Config.swift +++ b/Veloria/AppDelegate/AppDelegate+Config.swift @@ -12,6 +12,8 @@ extension AppDelegate { func appConfig() { UIButton.vp_bt_Awake() UIView.vp_Awake() + + VPToast.config() } } diff --git a/Veloria/AppDelegate/AppDelegate.swift b/Veloria/AppDelegate/AppDelegate.swift index 045c7af..6aef8d6 100644 --- a/Veloria/AppDelegate/AppDelegate.swift +++ b/Veloria/AppDelegate/AppDelegate.swift @@ -15,6 +15,11 @@ class AppDelegate: UIResponder, UIApplicationDelegate { func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool { appConfig() + ///开启网络监控 + VPNetworkReachabilityManager.manager.startMonitoring() + NotificationCenter.default.addObserver(self, selector: #selector(reachabilityDidChangeNotification), name: VPNetworkReachabilityManager.reachabilityDidChangeNotification, object: nil) + + VPLoginManager.manager.updateUserInfo(completer: nil) return true } @@ -36,3 +41,13 @@ class AppDelegate: UIResponder, UIApplicationDelegate { } +extension AppDelegate { + + @objc private func reachabilityDidChangeNotification() { + if VPNetworkReachabilityManager.manager.isReachable == true { + VPLoginManager.manager.updateUserInfo(completer: nil) + } + } + +} + diff --git a/Veloria/Base/Controller/VPTabBarController.swift b/Veloria/Base/Controller/VPTabBarController.swift index 82c56fd..8dce1ae 100644 --- a/Veloria/Base/Controller/VPTabBarController.swift +++ b/Veloria/Base/Controller/VPTabBarController.swift @@ -6,7 +6,6 @@ // import UIKit -import ESTabBarController_swift class VPTabBarController: UITabBarController { @@ -53,7 +52,6 @@ class VPTabBarController: UITabBarController { view.backgroundColor = .color000000() -// ESTabBarController vp_setup() self.tabBar.isTranslucent = true @@ -89,7 +87,7 @@ extension VPTabBarController { let nav1 = createNavigationController(viewController: VPHomePageViewController(), title: "Home".localized, image: UIImage(named: "tabbar_icon_01"), selectedImage: UIImage(named: "tabbar_icon_01_selected")) let nav2 = createNavigationController(viewController: VPExploreViewController(), title: "Explore".localized, image: UIImage(named: "tabbar_icon_02"), selectedImage: UIImage(named: "tabbar_icon_02_selected")) let nav3 = createNavigationController(viewController: VPMyListViewController(), title: "My List".localized, image: UIImage(named: "tabbar_icon_03"), selectedImage: UIImage(named: "tabbar_icon_03_selected")) - let nav4 = createNavigationController(viewController: VPHomePageViewController(), title: "Home".localized, image: UIImage(named: "tabbar_icon_04"), selectedImage: UIImage(named: "tabbar_icon_04_selected")) + let nav4 = createNavigationController(viewController: VPMeViewController(), title: "Me".localized, image: UIImage(named: "tabbar_icon_04"), selectedImage: UIImage(named: "tabbar_icon_04_selected")) viewControllers = [nav1, nav2, nav3, nav4] @@ -97,13 +95,6 @@ extension VPTabBarController { private func createNavigationController(viewController: UIViewController, title: String?, image: UIImage?, selectedImage: UIImage?) -> UINavigationController { -// let tabBarContentView = VPTabBarItemContentView() -// let tabBarItem = ESTabBarItem(tabBarContentView, title: title, image: image, selectedImage: selectedImage) -// -// tabBarItem.contentView?.renderingMode = .alwaysOriginal -// tabBarItem.contentView?.textColor = .colorFFFFFF() -// tabBarItem.contentView?.highlightTextColor = .colorFFFFFF() -// tabBarItem.contentView?.titleLabel.font = .fontRegular(ofSize: 13) let tabBarItem = VPTabBarItem() tabBarItem.title = title @@ -111,7 +102,6 @@ extension VPTabBarController { tabBarItem.selectedImage = selectedImage let nav = VPNavigationController(rootViewController: viewController) -// nav.tabBarItem.title = title nav.tabBarItem = tabBarItem return nav } @@ -124,11 +114,6 @@ extension VPTabBarController { guard let idx = tabBar.items?.firstIndex(of: item) else { return; } -// if idx == tabBar.items!.count - 1, ESTabBarController.isShowingMore(self) { -// ignoreNextSelection = true -// selectedViewController = moreNavigationController -// return; -// } if let vc = viewControllers?[idx] { ignoreNextSelection = true selectedIndex = idx @@ -149,3 +134,24 @@ extension VPTabBarController { } } + + +extension VPTabBarController { + func openHistoryPage() { + + var index: Int? + var viewController: VPMyListViewController? + self.viewControllers?.enumerated().forEach({ + guard let nav = $1 as? UINavigationController else { return } + if let vc = nav.viewControllers.first as? VPMyListViewController { + index = $0 + viewController = vc + } + + }) + if let index = index { + self.selectedIndex = index + viewController?.showHistoryPage() + } + } +} diff --git a/Veloria/Base/Controller/VPViewController.swift b/Veloria/Base/Controller/VPViewController.swift index 842f2df..288f1d5 100644 --- a/Veloria/Base/Controller/VPViewController.swift +++ b/Veloria/Base/Controller/VPViewController.swift @@ -92,3 +92,40 @@ extension VPViewController { } } } + +extension UIViewController { + ///设置导航默认样式 + func setNavigationNormalStyle(backgroundColor: UIColor = .clear, + isTranslucent: Bool = true, + prefersLargeTitles: Bool = false) + { + self.setNavigationBackgroundColor(color: backgroundColor, isTranslucent: isTranslucent) + self.setNavigationTitleStyle() + self.navigationController?.navigationBar.prefersLargeTitles = prefersLargeTitles + } + + ///设置导航背景色 + func setNavigationBackgroundColor(color: UIColor?, isTranslucent: Bool = false) { + guard let nav = navigationController else { return } + if nav.visibleViewController == self { + nav.navigationBar.vp_setBackgroundColor(backgroundColor: color) + nav.navigationBar.vp_setTranslucent(isTranslucent: isTranslucent) + } + } + + ///设置标题样式 + func setNavigationTitleStyle(color: UIColor? = nil, font: UIFont? = nil) { + guard let nav = navigationController else { return } + if nav.visibleViewController == self { + //标题样式 + var titleTextAttributes = UINavigationBar.vp_normalTitleTextAttributes + if let color = color { + titleTextAttributes[NSAttributedString.Key.foregroundColor] = color + } + if let font = font { + titleTextAttributes[NSAttributedString.Key.font] = font + } + nav.navigationBar.vp_setTitleTextAttributes(titleTextAttributes: titleTextAttributes) + } + } +} diff --git a/Veloria/Base/Define/VPUserDefaultsKey.swift b/Veloria/Base/Define/VPUserDefaultsKey.swift index d700329..bbfb6b8 100644 --- a/Veloria/Base/Define/VPUserDefaultsKey.swift +++ b/Veloria/Base/Define/VPUserDefaultsKey.swift @@ -9,3 +9,9 @@ import UIKit ///搜索记录 let kVPSearchHistoryDefaultsKey = "kVPSearchHistoryDefaultsKey" + +///登录token +let kVPLoginTokenDefaultsKey = "kVPLoginTokenDefaultsKey" + +///用户信息 +let kVPLoginUserInfoDefaultsKey = "kSPLoginUserInfoDefaultsKey" diff --git a/Veloria/Base/Extension/Dictionary+SPAdd.swift b/Veloria/Base/Extension/Dictionary+SPAdd.swift new file mode 100644 index 0000000..7e644c5 --- /dev/null +++ b/Veloria/Base/Extension/Dictionary+SPAdd.swift @@ -0,0 +1,23 @@ +// +// Dictionary+SPAdd.swift +// Veloria +// +// Created by 湖南秦九 on 2025/5/26. +// + +import UIKit + +extension Dictionary { + + func toJsonString() -> String? { + do { + let data = try JSONSerialization.data(withJSONObject: self) + let jsonStr = String(data: data, encoding: .utf8) + return jsonStr + } catch { + + } + return nil + } + +} diff --git a/Veloria/Base/Extension/UIColor+VPAdd.swift b/Veloria/Base/Extension/UIColor+VPAdd.swift index 7b42232..eea58c0 100644 --- a/Veloria/Base/Extension/UIColor+VPAdd.swift +++ b/Veloria/Base/Extension/UIColor+VPAdd.swift @@ -97,4 +97,8 @@ extension UIColor { static func colorD87675(alpha: CGFloat = 1) -> UIColor { return UIColor(rgb: 0xD87675, alpha: alpha) } + + static func colorB5B5B5(alpha: CGFloat = 1) -> UIColor { + return UIColor(rgb: 0xB5B5B5, alpha: alpha) + } } diff --git a/Veloria/Base/Extension/UINavigationBar+VPAdd.swift b/Veloria/Base/Extension/UINavigationBar+VPAdd.swift new file mode 100644 index 0000000..09d47f3 --- /dev/null +++ b/Veloria/Base/Extension/UINavigationBar+VPAdd.swift @@ -0,0 +1,88 @@ +// +// UINavigationBar+VPAdd.swift +// Veloria +// +// Created by 湖南秦九 on 2025/5/26. +// + +import UIKit + +extension UINavigationBar { + + static let vp_normalTitleFont = UIFont.fontBold(ofSize: 16) + static var vp_normalTitleColor: UIColor { + get { + return .colorFFFFFF() + } + } + + /** + 默认标题样式 + */ + static var vp_normalTitleTextAttributes: [NSAttributedString.Key : Any] { + get { + return [ + NSAttributedString.Key.font : vp_normalTitleFont, + NSAttributedString.Key.foregroundColor : vp_normalTitleColor + ] + } + } + + /** + 默认背景色 + */ + static var vp_normalBackgroundColor: UIColor { + get { + return .black + } + } + + @available(iOS 13.0, *) + static let navBarAppearance: UINavigationBarAppearance = { + let navBarAppearance = UINavigationBarAppearance() + navBarAppearance.configureWithOpaqueBackground() + // 背景色 + navBarAppearance.backgroundColor = vp_normalBackgroundColor + // 去掉半透明效果 + navBarAppearance.backgroundEffect = nil + // 去除导航栏阴影(如果不设置clear,导航栏底下会有一条阴影线) + navBarAppearance.shadowColor = UIColor.clear + // 字体颜色 + navBarAppearance.titleTextAttributes = vp_normalTitleTextAttributes + + return navBarAppearance + }() + + + func vp_setTranslucent(isTranslucent: Bool) { + self.isTranslucent = isTranslucent + } + + func vp_setBackgroundColor(backgroundColor: UIColor?) { + if #available(iOS 15.0, *) { + UINavigationBar.navBarAppearance.backgroundColor = backgroundColor + self.standardAppearance = UINavigationBar.navBarAppearance + self.scrollEdgeAppearance = UINavigationBar.navBarAppearance + } + + if let backgroundColor = backgroundColor { + self.setBackgroundImage(UIImage(color: backgroundColor), for: .default) + } else { + self.setBackgroundImage(UIImage(), for: .default) + } + } + + func vp_setTitleTextAttributes(titleTextAttributes: [NSAttributedString.Key : Any]?) { + + if #available(iOS 15.0, *) { + if let titleTextAttributes = titleTextAttributes { + UINavigationBar.navBarAppearance.titleTextAttributes = titleTextAttributes + } + self.scrollEdgeAppearance = UINavigationBar.navBarAppearance + self.standardAppearance = UINavigationBar.navBarAppearance + } else { + + self.titleTextAttributes = titleTextAttributes + } + } +} diff --git a/Veloria/Base/Extension/UserDefaults+VPAdd.swift b/Veloria/Base/Extension/UserDefaults+VPAdd.swift new file mode 100644 index 0000000..8184157 --- /dev/null +++ b/Veloria/Base/Extension/UserDefaults+VPAdd.swift @@ -0,0 +1,45 @@ +// +// UserDefaults+VPAdd.swift +// Veloria +// +// Created by 湖南秦九 on 2025/5/26. +// + +import Foundation + + +extension UserDefaults { + + static func vp_setObject(_ obj: NSSecureCoding?, forKey key: String) { + let defaults = UserDefaults.standard + + guard let obj = obj else { + defaults.removeObject(forKey: key) + return + } + + do { + let data = try NSKeyedArchiver.archivedData(withRootObject: obj, requiringSecureCoding: true) + defaults.set(data, forKey: key) + } catch { + print("Error archiving object: \(error)") + } + } + + static func vp_object(forKey key: String, as type: T.Type) -> T? { + let defaults = UserDefaults.standard + + guard let data = defaults.data(forKey: key) else { + return nil + } + + do { + let object = try NSKeyedUnarchiver.unarchivedObject(ofClass: type, from: data) + return object + } catch { + print("Error unarchiving object: \(error)") + return nil + } + } + +} diff --git a/Veloria/Base/Networking/API/VPHomeAPI.swift b/Veloria/Base/Networking/API/VPHomeAPI.swift index a5cc769..c86ef59 100644 --- a/Veloria/Base/Networking/API/VPHomeAPI.swift +++ b/Veloria/Base/Networking/API/VPHomeAPI.swift @@ -13,7 +13,7 @@ class VPHomeAPI: NSObject { static func requestHomeData(completer: ((_ list: [VPHomeModuleItem]?) -> Void)?) { var param = VPNetworkParameters(path: "/home/all-modules") param.method = .get - + param.isToast = true VPNetwork.request(parameters: param) { (response: VPNetworkResponse>) in completer?(response.data?.list) diff --git a/Veloria/Base/Networking/API/VPUserAPI.swift b/Veloria/Base/Networking/API/VPUserAPI.swift new file mode 100644 index 0000000..a740cd4 --- /dev/null +++ b/Veloria/Base/Networking/API/VPUserAPI.swift @@ -0,0 +1,22 @@ +// +// VPUserAPI.swift +// Veloria +// +// Created by 湖南秦九 on 2025/5/26. +// + +import UIKit + +class VPUserAPI: NSObject { + + ///获取用户信息 + static func requestUserInfo(completer: ((_ userInfo: VPUserInfo?) -> Void)?) { + + var param = VPNetworkParameters(path: "/customer/info") + param.method = .get + + VPNetwork.request(parameters: param) { (response: VPNetworkResponse) in + completer?(response.data) + } + } +} diff --git a/Veloria/Base/Networking/Base/VPNetworkReachabilityManager.swift b/Veloria/Base/Networking/Base/VPNetworkReachabilityManager.swift new file mode 100644 index 0000000..9045755 --- /dev/null +++ b/Veloria/Base/Networking/Base/VPNetworkReachabilityManager.swift @@ -0,0 +1,60 @@ +// +// VPNetworkReachabilityManager.swift +// Veloria +// +// Created by 湖南秦九 on 2025/5/26. +// + +import UIKit +import Network + +class VPNetworkReachabilityManager { + + static let manager = VPNetworkReachabilityManager() + + ///是否有网 + var isReachable: Bool? + + + private let monitor = NWPathMonitor() + private let queue = DispatchQueue(label: "NetworkMonitorQueue") + + func startMonitoring() { + + monitor.pathUpdateHandler = { [weak self] path in + guard let self = self else { return } + if path.status == .satisfied { + if self.isReachable == false { + self.isReachable = true + DispatchQueue.main.async { + NotificationCenter.default.post(name: VPNetworkReachabilityManager.reachabilityDidChangeNotification, object: nil) + } + } else { + self.isReachable = true + } + + } else { + if self.isReachable == true { + self.isReachable = false + DispatchQueue.main.async { + NotificationCenter.default.post(name: VPNetworkReachabilityManager.reachabilityDidChangeNotification, object: nil) + } + } else { + self.isReachable = false + } + } + } + + monitor.start(queue: queue) + } + + func stopMonitoring() { + monitor.cancel() + } + +} + +extension VPNetworkReachabilityManager { + ///网络发生变化 + @objc static let reachabilityDidChangeNotification = NSNotification.Name(rawValue: "VPNetworkReachabilityManager.reachabilityDidChangeNotification") +} diff --git a/Veloria/Base/Networking/Base/VPURLPath.swift b/Veloria/Base/Networking/Base/VPURLPath.swift index b3dc47f..1dc617d 100644 --- a/Veloria/Base/Networking/Base/VPURLPath.swift +++ b/Veloria/Base/Networking/Base/VPURLPath.swift @@ -22,25 +22,25 @@ let VPCampaignWebURL = "https://campaign.moviatv.com" #endif ///用户协议 -let VPUserAgreementWebUrl = VPWebBaseURL + "/user_policy" +let kVPUserAgreementWebUrl = VPWebBaseURL + "/user_policy" ///隐私协议 -let VPPrivacyPolicyWebUrl = VPWebBaseURL + "/private" +let kVPPrivacyPolicyWebUrl = VPWebBaseURL + "/private" ///儿童个人信息保护规则 -let VPInformationProtectionWebUrl = VPWebBaseURL + "/information_protection" +let kVPInformationProtectionWebUrl = VPWebBaseURL + "/information_protection" ///第三方共享清单 -let VPInformationSharingWebUrl = VPWebBaseURL + "/information_sharing" +let kVPInformationSharingWebUrl = VPWebBaseURL + "/information_sharing" ///收集个人信息明示清单 -let VPPersoInforDisclosureWebUrl = VPWebBaseURL + "/persoInfor_disclosure" +let kVPPersoInforDisclosureWebUrl = VPWebBaseURL + "/persoInfor_disclosure" ///全国青少年互联网文明公约 -let VPCivizatioConventionWebUrl = VPWebBaseURL + "/civizatio_convention" +let kVPCivizatioConventionWebUrl = VPWebBaseURL + "/civizatio_convention" ///会员服务协议 -let VPMemberShipAgreement = VPWebBaseURL + "/member_ship_agreement" +let kVPMemberShipAgreement = VPWebBaseURL + "/member_ship_agreement" ///反馈首页 -let VPFeedBackHomeWebUrl = VPCampaignWebURL + "/pages/leave/index" +let kVPFeedBackHomeWebUrl = VPCampaignWebURL + "/pages/leave/index" ///反馈列表 -let VPFeedBackListWebUrl = VPCampaignWebURL + "/pages/leave/list" +let kVPFeedBackListWebUrl = VPCampaignWebURL + "/pages/leave/list" ///反馈详情 -let VPFeedBackDetailWebUrl = VPCampaignWebURL + "/pages/leave/detail" +let kVPFeedBackDetailWebUrl = VPCampaignWebURL + "/pages/leave/detail" ///活动页面 -let VPRewardsWebUrl = VPCampaignWebURL +let kVPRewardsWebUrl = VPCampaignWebURL diff --git a/Veloria/Base/View/VPTableView.swift b/Veloria/Base/View/VPTableView.swift index 33641df..d2549a8 100644 --- a/Veloria/Base/View/VPTableView.swift +++ b/Veloria/Base/View/VPTableView.swift @@ -39,11 +39,9 @@ class VPTableView: UITableView { } get { var margins = super.layoutMargins - if #available(iOS 13.0, *) { - if self.style == .insetGrouped { - margins.left = self.safeAreaInsets.left + insetGroupedMargins - margins.right = self.safeAreaInsets.right + insetGroupedMargins - } + if self.style == .insetGrouped { + margins.left = self.safeAreaInsets.left + insetGroupedMargins + margins.right = self.safeAreaInsets.right + insetGroupedMargins } return margins } diff --git a/Veloria/Base/View/VPTableViewCell.swift b/Veloria/Base/View/VPTableViewCell.swift index 66aea11..da19e57 100644 --- a/Veloria/Base/View/VPTableViewCell.swift +++ b/Veloria/Base/View/VPTableViewCell.swift @@ -9,6 +9,11 @@ import UIKit class VPTableViewCell: UITableViewCell { + private(set) lazy var indicatorImageView: UIImageView = { + let imageView = UIImageView(image: UIImage(named: "arrow_right_icon_02")) + return imageView + }() + override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) { super.init(style: style, reuseIdentifier: reuseIdentifier) diff --git a/Veloria/Base/WebView/VPWebView.swift b/Veloria/Base/WebView/VPWebView.swift new file mode 100644 index 0000000..601f225 --- /dev/null +++ b/Veloria/Base/WebView/VPWebView.swift @@ -0,0 +1,197 @@ +// +// VPWebView.swift +// Veloria +// +// Created by 湖南秦九 on 2025/5/26. +// + +import UIKit +@preconcurrency import WebKit + +//MARK:-------------- VPWebViewDelegate -------------- +@objc protocol VPWebViewDelegate: NSObjectProtocol { + + @objc optional func webView(_ webView: VPWebView, shouldStartLoadWith navigationAction: WKNavigationAction) -> Bool + + @objc optional func webViewDidStartLoad(_ webView: VPWebView) + + @objc optional func webViewDidFinishLoad(_ webView: VPWebView) + + @objc optional func webView(_ webView: VPWebView, didFailLoadWithError error: Error) + + ///进度 + @objc optional func webView(webView: VPWebView, didChangeProgress progress: CGFloat) + ///标题 + @objc optional func webView(webView: VPWebView, didChangeTitle title: String) + + ///web交互用 + @objc optional func userContentController(_ userContentController: WKUserContentController, didReceive message: WKScriptMessage) + +} + +class VPWebView: WKWebView { + + weak var delegate: VPWebViewDelegate? + +// private(set) var scriptMessageHandlerArray: [SPWebViewMessageName] = [ +// WebMessageAPP, +// WebMessageOpenFeedbackList, +// WebMessageOpenFeedbackDetail, +// WebMessageOpenPhotoPicker, +// ] + + + deinit { + + self.removeObserver(self, forKeyPath: "estimatedProgress") + self.removeObserver(self, forKeyPath: "title") + + } + + override init(frame: CGRect, configuration: WKWebViewConfiguration) { + super.init(frame: frame, configuration: configuration) +// addScriptMessageHandler() + _setupInit() + } + required init?(coder: NSCoder) { + fatalError("init(coder:) has not been implemented") + } + private func _setupInit() { + + self.isOpaque = false + self.uiDelegate = self + self.navigationDelegate = self + self.addObserver(self, forKeyPath: "estimatedProgress", options: .new, context: nil) + self.addObserver(self, forKeyPath: "title", options: .new, context: nil) + + } + + override func observeValue(forKeyPath keyPath: String?, of object: Any?, change: [NSKeyValueChangeKey : Any]?, context: UnsafeMutableRawPointer?) { + if object as? VPWebView == self { + if keyPath == "estimatedProgress", let progress = change?[NSKeyValueChangeKey.newKey] as? CGFloat { + self.delegate?.webView?(webView: self, didChangeProgress: progress) + } else if keyPath == "title", let title = change?[NSKeyValueChangeKey.newKey] as? String { + self.delegate?.webView?(webView: self, didChangeTitle: title) + } + } + } + + func load(urlStr: String) { + guard let url = URL(string: urlStr) else { return } + var request = URLRequest(url: url, cachePolicy: .reloadIgnoringLocalCacheData, timeoutInterval: 30) + self.load(request) + } + +// func removeScriptMessageHandler() { +// self.scriptMessageHandlerArray.forEach{ +// configuration.userContentController.removeScriptMessageHandler(forName: $0) +// } +// } +// func addScriptMessageHandler() { +// self.scriptMessageHandlerArray.forEach{ +// configuration.userContentController.add(YYWeakProxy(target: self) as! WKScriptMessageHandler, name: $0) +// } +// } + + +} + +//MARK:-------------- WKUIDelegate -------------- +extension VPWebView: WKUIDelegate { + + func webView(_ webView: WKWebView, runJavaScriptAlertPanelWithMessage message: String, initiatedByFrame frame: WKFrameInfo, completionHandler: @escaping () -> Void) { + let alertController = UIAlertController(title: "提示", message: message, preferredStyle: .alert) + alertController.addAction(UIAlertAction(title: "确认", style: .default, handler: { (action) in + completionHandler() + })) + self.viewController?.present(alertController, animated: true, completion: nil) + } + + func webView(_ webView: WKWebView, runJavaScriptConfirmPanelWithMessage message: String, initiatedByFrame frame: WKFrameInfo, completionHandler: @escaping (Bool) -> Void) { + let alertController = UIAlertController(title: "提示", message: message, preferredStyle: .alert) + alertController.addAction(UIAlertAction(title: "取消", style: .cancel, handler: { (action) in + completionHandler(false) + })) + alertController.addAction(UIAlertAction(title: "确认", style: .default, handler: { (action) in + completionHandler(true) + })) + self.viewController?.present(alertController, animated: true, completion: nil) + } + + func webView(_ webView: WKWebView, runJavaScriptTextInputPanelWithPrompt prompt: String, defaultText: String?, initiatedByFrame frame: WKFrameInfo, completionHandler: @escaping (String?) -> Void) { + let alertController = UIAlertController(title: prompt, message: "", preferredStyle: .alert) + alertController.addTextField { (textField) in + textField.text = defaultText + } + alertController.addAction(UIAlertAction(title: "完成", style: .default, handler: { (action) in + completionHandler(alertController.textFields?.first?.text) + })) + self.viewController?.present(alertController, animated: true, completion: nil) + } +} + +//MARK:-------------- WKNavigationDelegate -------------- +extension VPWebView: WKNavigationDelegate { + + func webView(_ webView: WKWebView, decidePolicyFor navigationResponse: WKNavigationResponse, decisionHandler: @escaping (WKNavigationResponsePolicy) -> Void) { + + decisionHandler(.allow); + } + + func webView(_ webView: WKWebView, decidePolicyFor navigationAction: WKNavigationAction, decisionHandler: @escaping (WKNavigationActionPolicy) -> Void) { + vpLog(message: navigationAction.request.url) + + if let url = navigationAction.request.url, + url.scheme != "http", + url.scheme != "https" + { + UIApplication.shared.open(url) + decisionHandler(.cancel) + return + } + + //防止抓包 +// if JXRequestHttpProxy.isIntercept() { +// decisionHandler(.cancel) +// return +// } + + + if let result = self.delegate?.webView?(self, shouldStartLoadWith: navigationAction) { + if result { + decisionHandler(.allow) + } else { + decisionHandler(.cancel) + } + } else { + decisionHandler(.allow) + } + } + + func webView(_ webView: WKWebView, didStartProvisionalNavigation navigation: WKNavigation!) { + self.delegate?.webViewDidStartLoad?(self) + } + + func webView(_ webView: WKWebView, didFinish navigation: WKNavigation!) { + self.delegate?.webViewDidFinishLoad?(self) + } + + func webView(_ webView: WKWebView, didFail navigation: WKNavigation!, withError error: Error) { + self.delegate?.webView?(self, didFailLoadWithError: error) + } + + func webView(_ webView: WKWebView, didFailProvisionalNavigation navigation: WKNavigation!, withError error: Error) { + self.delegate?.webView?(self, didFailLoadWithError: error) + } + + +} + +//MARK:-------------- WKScriptMessageHandler -------------- +extension VPWebView: WKScriptMessageHandler { + + func userContentController(_ userContentController: WKUserContentController, didReceive message: WKScriptMessage) { + self.delegate?.userContentController?(userContentController, didReceive: message) + } + +} diff --git a/Veloria/Base/WebView/VPWebViewController.swift b/Veloria/Base/WebView/VPWebViewController.swift new file mode 100644 index 0000000..c2d375d --- /dev/null +++ b/Veloria/Base/WebView/VPWebViewController.swift @@ -0,0 +1,99 @@ +// +// VPWebViewController.swift +// Veloria +// +// Created by 湖南秦九 on 2025/5/26. +// + +import UIKit +import WebKit + +class VPWebViewController: VPViewController { + + var urlStr: String? + + ///自动设置标题 + var autoTitle = true + + private(set) lazy var webView: VPWebView = { + let controller = WKUserContentController() + + let config = WKWebViewConfiguration() + config.userContentController = controller + config.preferences.javaScriptEnabled = true + /** 默认是不能通过JS自动打开窗口的,必须通过用户交互才能打开 */ + config.preferences.javaScriptCanOpenWindowsAutomatically = true + let webView = VPWebView(frame: self.view.bounds, configuration: config) + webView.delegate = self + return webView + }() + + override func viewDidLoad() { + super.viewDidLoad() + + + _setupUI() + + if let url = urlStr { + self.load(urlString: url) + } + } + + override func viewWillAppear(_ animated: Bool) { + super.viewWillAppear(animated) + self.navigationController?.setNavigationBarHidden(false, animated: true) + self.setNavigationNormalStyle() + } + + 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) + } + + func reload() { + self.webView.reload() + } + +} + +extension VPWebViewController { + + private func _setupUI() { + self.view.addSubview(webView) + + self.webView.snp.makeConstraints { make in + make.left.equalToSuperview().offset(0) + make.right.equalToSuperview().offset(0) + make.top.equalToSuperview().offset(UIScreen.navBarHeight) + make.bottom.equalToSuperview().offset(0) + } + } + +} + +//MARK: -------------- VPWebViewDelegate -------------- +extension VPWebViewController: VPWebViewDelegate { + + func webView(webView: VPWebView, didChangeTitle title: String) { + if autoTitle { + self.title = title + } + } + + func webView(_ webView: VPWebView, didFailLoadWithError error: any Error) { + vpLog(message: error) + } + + func webViewDidFinishLoad(_ webView: VPWebView) { + vpLog(message: "网页加载完成") + + } + + func userContentController(_ userContentController: WKUserContentController, didReceive message: WKScriptMessage) { +// _webViewUserContentController(didReceive: message) + } +} diff --git a/Veloria/Class/Home/Controller/VPHomePageViewController.swift b/Veloria/Class/Home/Controller/VPHomePageViewController.swift index 4718eff..71c2193 100644 --- a/Veloria/Class/Home/Controller/VPHomePageViewController.swift +++ b/Veloria/Class/Home/Controller/VPHomePageViewController.swift @@ -118,17 +118,19 @@ class VPHomePageViewController: VPViewController { private lazy var historyButton: UIButton = { let button = UIButton(type: .custom) button.setImage(UIImage(named: "history_icon_01"), for: .normal) + button.addTarget(self, action: #selector(handleHistoryButton), for: .touchUpInside) return button }() override func viewDidLoad() { super.viewDidLoad() + NotificationCenter.default.addObserver(self, selector: #selector(reachabilityDidChangeNotification), name: VPNetworkReachabilityManager.reachabilityDidChangeNotification, object: nil) requestHomeData() - setupPageView() vp_setupUI() + } override func viewWillAppear(_ animated: Bool) { @@ -172,6 +174,21 @@ class VPHomePageViewController: VPViewController { self.navigationController?.pushViewController(vc, animated: true) } + @objc private func handleHistoryButton() { + (VPAppTool.rootViewController as? VPTabBarController)?.openHistoryPage() + } + +} + +extension VPHomePageViewController { + @objc private func reachabilityDidChangeNotification() { + if VPNetworkReachabilityManager.manager.isReachable == true { + if self.viewModel.oldModuleList == nil { + requestHomeData() + } + } + + } } extension VPHomePageViewController { @@ -199,8 +216,6 @@ extension VPHomePageViewController { make.width.height.equalTo(40) make.centerY.equalTo(searchButton) } - - } } diff --git a/Veloria/Class/Home/Model/VPHomeModuleItem.swift b/Veloria/Class/Home/Model/VPHomeModuleItem.swift index 06f2f71..8c571a9 100644 --- a/Veloria/Class/Home/Model/VPHomeModuleItem.swift +++ b/Veloria/Class/Home/Model/VPHomeModuleItem.swift @@ -35,8 +35,19 @@ class VPHomeModuleItem: VPModel, SmartCodable { self.list = [VPShortModel].deserialize(from: data) } } else if let data = data as? [String : Any] { - title = data["title"] as? String - list = [VPShortModel].deserialize(from: data["list"] as? [[String : Any]]) + var dataList: [[String : Any]]? + if let list = data["list"] as? [[String : Any]] { + self.title = data["title"] as? String + dataList = list + + } else if let list = data["shortPlayList"] as? [[String : Any]] { + dataList = list + } + + if let dataList = dataList { + self.list = [VPShortModel].deserialize(from: dataList) + } + } } diff --git a/Veloria/Class/Me/Controller/VPAboutUsViewController.swift b/Veloria/Class/Me/Controller/VPAboutUsViewController.swift new file mode 100644 index 0000000..039e520 --- /dev/null +++ b/Veloria/Class/Me/Controller/VPAboutUsViewController.swift @@ -0,0 +1,25 @@ +// +// VPAboutUsViewController.swift +// Veloria +// +// Created by 湖南秦九 on 2025/5/26. +// + +import UIKit + +class VPAboutUsViewController: VPViewController { + + override func viewDidLoad() { + super.viewDidLoad() + self.title = "About Us".localized + + } + + override func viewWillAppear(_ animated: Bool) { + super.viewWillAppear(animated) + self.navigationController?.setNavigationBarHidden(false, animated: true) + setNavigationNormalStyle() + } + + +} diff --git a/Veloria/Class/Me/Controller/VPCampaignWebViewController.swift b/Veloria/Class/Me/Controller/VPCampaignWebViewController.swift new file mode 100644 index 0000000..e89f07d --- /dev/null +++ b/Veloria/Class/Me/Controller/VPCampaignWebViewController.swift @@ -0,0 +1,83 @@ +// +// VPCampaignWebViewController.swift +// Veloria +// +// Created by 湖南秦九 on 2025/5/26. +// + +import UIKit + +class VPCampaignWebViewController: VPWebViewController { + + var id: String? + + ///重试次数 + private var receiveDataCount = 0 + + override func viewDidLoad() { + super.viewDidLoad() + autoTitle = false + if urlStr == kVPFeedBackListWebUrl { + self.title = "Feedback History".localized + } else if urlStr == kVPFeedBackHomeWebUrl { + self.title = "Feedback".localized + } else if urlStr == kVPFeedBackDetailWebUrl { + self.title = "Feedback Details".localized + } else if urlStr == kVPRewardsWebUrl { + self.title = "Rewards".localized + } + + self.webView.scrollView.vp_addRefreshHeader { [weak self] in + self?.handleHeaderRefresh(nil) + } + + } + + override func handleHeaderRefresh(_ completer: (() -> Void)?) { + self.reload() + self.webView.scrollView.vp_endHeaderRefreshing() + } + + + override func webViewDidFinishLoad(_ webView: VPWebView) { + super.webViewDidFinishLoad(webView) + receiveDataCount = 0 + receiveDataFromNative() + } + +} + +extension VPCampaignWebViewController { + ///设置登录信息 + func receiveDataFromNative() { + receiveDataCount += 1 + if receiveDataCount > 10 { return } + + DispatchQueue.main.asyncAfter(deadline: .now() + 0.5) { [weak self] in + guard let self = self else { return } + var dic = [ + "token" : VPLoginManager.manager.token?.token ?? "", + "time_zone" : String.timeZone(), + "lang" : VPLocalizedManager.shared.currentLocalizedKey, + "type" : "ios", + "theme" : "theme_1", + ] + if let id = id { + dic["id"] = id + } + + + if let json = dic.toJsonString() { + let js = "receiveDataFromNative(\(json))" + self.webView.evaluateJavaScript(js) { [weak self] _, error in + guard let self = self else { return } + if error != nil { + self.receiveDataFromNative() + } + } + } + } + + } + +} diff --git a/Veloria/Class/Me/Controller/VPMeViewController.swift b/Veloria/Class/Me/Controller/VPMeViewController.swift new file mode 100644 index 0000000..2fc66d2 --- /dev/null +++ b/Veloria/Class/Me/Controller/VPMeViewController.swift @@ -0,0 +1,152 @@ +// +// VPMeViewController.swift +// Veloria +// +// Created by 湖南秦九 on 2025/5/26. +// + +import UIKit + +class VPMeViewController: VPViewController { + + private lazy var dataArr: [[VPMeItem]] = { + let arr = [ + [ + VPMeItem(cellKey: .userInfo), + ], + [ + VPMeItem(icon: UIImage(named: "me_item_icon_01"), title: "Privacy Policy".localized, type: .privacyPolicy, cellKey: .normal), + VPMeItem(icon: UIImage(named: "me_item_icon_02"), title: "User Agreement".localized, type: .userAgreement, cellKey: .normal), +// VPMeItem(icon: UIImage(named: "me_item_icon_04"), title: "Help Center".localized, type: .feedback, cellKey: .normal), + VPMeItem(icon: UIImage(named: "me_item_icon_03"), title: "About Us".localized, type: .aboutUs, cellKey: .normal), + ] + ] + return arr + }() + + + + private lazy var tableView: VPTableView = { + let tableView = VPTableView(frame: .zero, style: .insetGrouped) + tableView.delegate = self + tableView.dataSource = self + tableView.separatorStyle = .none + tableView.vp_addRefreshHeader { [weak self] in + self?.handleHeaderRefresh(nil) + } + tableView.register(VPMeCell.self, forCellReuseIdentifier: VPMeItem.CellKey.normal.rawValue) + tableView.register(VPMeUserInfoCell.self, forCellReuseIdentifier: VPMeItem.CellKey.userInfo.rawValue) + return tableView + }() + + override func viewDidLoad() { + super.viewDidLoad() + + vp_setupUI() + + requestUserInfo() + } + + override func viewWillAppear(_ animated: Bool) { + super.viewWillAppear(animated) + self.navigationController?.setNavigationBarHidden(true, animated: true) + + } + + override func viewDidAppear(_ animated: Bool) { + if hasViewDidAppear { + requestUserInfo() + } + super.viewDidAppear(animated) + } + + override func handleHeaderRefresh(_ completer: (() -> Void)?) { + self.requestUserInfo() + } + +} + +extension VPMeViewController { + + private func vp_setupUI() { + view.addSubview(tableView) + + tableView.snp.makeConstraints { make in + make.left.right.bottom.equalToSuperview() + make.top.equalTo(UIScreen.statusBarHeight) + } + } + +} + +//MARK: -------------- UITableViewDelegate UITableViewDataSource -------------- +extension VPMeViewController: UITableViewDelegate, UITableViewDataSource { + + func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { + let item = self.dataArr[indexPath.section][indexPath.row] + let cell = tableView.dequeueReusableCell(withIdentifier: item.cellKey?.rawValue ?? VPMeItem.CellKey.normal.rawValue, for: indexPath) + if let cell = cell as? VPMeCell { + cell.item = item + } else if let cell = cell as? VPMeUserInfoCell { + cell.userInfo = VPLoginManager.manager.userInfo + } + + return cell + } + + func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { + return self.dataArr[section].count + } + + func numberOfSections(in tableView: UITableView) -> Int { + return self.dataArr.count + } + + func tableView(_ tableView: UITableView, heightForHeaderInSection section: Int) -> CGFloat { + if section == 0 { + return 0.1 + } else { + return 14 + } + } + + func tableView(_ tableView: UITableView, heightForFooterInSection section: Int) -> CGFloat { + return 0.1 + } + + func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) { + let item = dataArr[indexPath.section][indexPath.row] + + switch item.type { + case .privacyPolicy: + let vc = VPWebViewController() + vc.urlStr = kVPPrivacyPolicyWebUrl + self.navigationController?.pushViewController(vc, animated: true) + + case .userAgreement: + let vc = VPWebViewController() + vc.urlStr = kVPUserAgreementWebUrl + self.navigationController?.pushViewController(vc, animated: true) + + case .aboutUs: + let vc = VPAboutUsViewController() + self.navigationController?.pushViewController(vc, animated: true) + + default: + break + } + + } + +} + +extension VPMeViewController { + + + ///获取用户信息 + private func requestUserInfo() { + VPLoginManager.manager.updateUserInfo { [weak self] in + self?.tableView.reloadData() + } + } +} diff --git a/Veloria/Class/Me/Model/VPMeItem.swift b/Veloria/Class/Me/Model/VPMeItem.swift new file mode 100644 index 0000000..40a5f6b --- /dev/null +++ b/Veloria/Class/Me/Model/VPMeItem.swift @@ -0,0 +1,27 @@ +// +// VPMeItem.swift +// Veloria +// +// Created by 湖南秦九 on 2025/5/26. +// + +import UIKit + +struct VPMeItem { + enum ItemType { + case privacyPolicy + case userAgreement + case aboutUs + case feedback + } + + enum CellKey: String { + case normal + case userInfo + } + + var icon: UIImage? + var title: String? + var type: ItemType? + var cellKey: CellKey? +} diff --git a/Veloria/Class/Me/View/VPMeCell.swift b/Veloria/Class/Me/View/VPMeCell.swift new file mode 100644 index 0000000..2b75b52 --- /dev/null +++ b/Veloria/Class/Me/View/VPMeCell.swift @@ -0,0 +1,69 @@ +// +// VPMeCell.swift +// Veloria +// +// Created by 湖南秦九 on 2025/5/26. +// + +import UIKit + +class VPMeCell: VPTableViewCell { + + var item: VPMeItem? { + didSet { + titleLabel.text = item?.title + iconImageView.image = item?.icon + } + } + + private lazy var iconImageView: UIImageView = { + let imageView = UIImageView() + return imageView + }() + + private lazy var titleLabel: UILabel = { + let label = UILabel() + label.font = .fontRegular(ofSize: 14) + label.textColor = .colorFFFFFF() + return label + }() + + + + override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) { + super.init(style: style, reuseIdentifier: reuseIdentifier) + contentView.backgroundColor = .colorFFFFFF(alpha: 0.1) + vp_setupUI() + } + + @MainActor required init?(coder: NSCoder) { + fatalError("init(coder:) has not been implemented") + } +} + +extension VPMeCell { + + private func vp_setupUI() { + contentView.addSubview(iconImageView) + contentView.addSubview(titleLabel) + contentView.addSubview(indicatorImageView) + + iconImageView.snp.makeConstraints { make in + make.centerY.equalToSuperview() + make.left.equalToSuperview().offset(10) + make.width.height.equalTo(20) + make.top.equalToSuperview().offset(18) + } + + titleLabel.snp.makeConstraints { make in + make.centerY.equalToSuperview() + make.left.equalToSuperview().offset(39) + } + + indicatorImageView.snp.makeConstraints { make in + make.centerY.equalToSuperview() + make.right.equalToSuperview().offset(-10) + } + } + +} diff --git a/Veloria/Class/Me/View/VPMeUserInfoCell.swift b/Veloria/Class/Me/View/VPMeUserInfoCell.swift new file mode 100644 index 0000000..409a73a --- /dev/null +++ b/Veloria/Class/Me/View/VPMeUserInfoCell.swift @@ -0,0 +1,89 @@ +// +// VPMeUserInfoCell.swift +// Veloria +// +// Created by 湖南秦九 on 2025/5/26. +// + +import UIKit + +class VPMeUserInfoCell: VPTableViewCell { + + + var userInfo: VPUserInfo? { + didSet { + avatarImageView.vp_setImage(url: userInfo?.avator, placeholder: UIImage(named: "avatar_placeholder_icon_01")) + + if let name = userInfo?.family_name, name.count > 0 { + nicknameLabel.text = name + } else { + nicknameLabel.text = "Visitor".localized + } + + idLabel.text = "ID \(userInfo?.customer_id ?? "")" + } + } + + private lazy var avatarImageView: VPImageView = { + let imageView = VPImageView() + imageView.layer.cornerRadius = 22 + imageView.layer.masksToBounds = true + imageView.layer.borderWidth = 1 + imageView.layer.borderColor = UIColor.colorFFFFFF().cgColor + return imageView + }() + + private lazy var nicknameLabel: UILabel = { + let label = UILabel() + label.font = .fontBold(ofSize: 16) + label.textColor = .colorFFFFFF() + return label + }() + + private lazy var idLabel: UILabel = { + let label = UILabel() + label.font = .fontRegular(ofSize: 12) + label.textColor = .colorB5B5B5() + return label + }() + + override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) { + super.init(style: style, reuseIdentifier: reuseIdentifier) + + bc_setupUI() + } + + @MainActor required init?(coder: NSCoder) { + fatalError("init(coder:) has not been implemented") + } + +} + +extension VPMeUserInfoCell { + + private func bc_setupUI() { + contentView.addSubview(avatarImageView) + contentView.addSubview(nicknameLabel) + contentView.addSubview(idLabel) + + avatarImageView.snp.makeConstraints { make in + make.left.equalToSuperview() + make.bottom.equalToSuperview() + make.width.height.equalTo(44) + make.top.equalToSuperview().offset(36) + } + + nicknameLabel.snp.makeConstraints { make in + make.top.equalTo(avatarImageView).offset(3) + make.left.equalTo(avatarImageView.snp.right).offset(10) + make.right.lessThanOrEqualToSuperview().offset(-170) + } + + idLabel.snp.makeConstraints { make in + make.left.equalTo(nicknameLabel) + make.bottom.equalTo(avatarImageView).offset(-3) + } + + } + +} diff --git a/Veloria/Class/MyList/Controller/VPCollectListViewController.swift b/Veloria/Class/MyList/Controller/VPCollectListViewController.swift index d93e8db..e6b21fa 100644 --- a/Veloria/Class/MyList/Controller/VPCollectListViewController.swift +++ b/Veloria/Class/MyList/Controller/VPCollectListViewController.swift @@ -14,14 +14,18 @@ class VPCollectListViewController: VPViewController { didSet { allSelectedButton.isHidden = editState == .normal if editState == .normal { - collectionView.snp.updateConstraints { make in - make.top.equalToSuperview().offset(0) + if collectionView.superview != nil { + collectionView.snp.updateConstraints { make in + make.top.equalToSuperview().offset(0) + } } isAllSelected = false allSelectedButton.isSelected = false } else { - collectionView.snp.updateConstraints { make in - make.top.equalToSuperview().offset(30) + if collectionView.superview != nil { + collectionView.snp.updateConstraints { make in + make.top.equalToSuperview().offset(30) + } } } @@ -101,6 +105,7 @@ class VPCollectListViewController: VPViewController { collectionView.delegate = self collectionView.dataSource = self collectionView.contentInset = .init(top: 5, left: 0, bottom: 0, right: 0) + collectionView.vp_addNormalEmpty() collectionView.vp_addRefreshHeader(insetTop: collectionView.top) { [weak self] in self?.handleHeaderRefresh(nil) } @@ -146,7 +151,7 @@ class VPCollectListViewController: VPViewController { if count > 0 { requestCancelCollect() } else { - VPToast.show(text: "kToastText1") + VPToast.show(text: "kToastText1".localized) } } } diff --git a/Veloria/Class/MyList/Controller/VPMyListViewController.swift b/Veloria/Class/MyList/Controller/VPMyListViewController.swift index bbebbf4..777f3da 100644 --- a/Veloria/Class/MyList/Controller/VPMyListViewController.swift +++ b/Veloria/Class/MyList/Controller/VPMyListViewController.swift @@ -76,7 +76,7 @@ class VPMyListViewController: VPViewController { return param }() - private lazy var pageView: WMZPageView = { + private(set) lazy var pageView: WMZPageView = { let y = UIScreen.statusBarHeight + 10 let height = UIScreen.height - y - UIScreen.customTabBarHeight @@ -120,6 +120,7 @@ class VPMyListViewController: VPViewController { super.viewDidLoad() vp_setupUI() +// pageView.selectMenu(with: 1) } override func viewWillAppear(_ animated: Bool) { @@ -131,6 +132,12 @@ class VPMyListViewController: VPViewController { super.viewDidDisappear(animated) self.editState = .normal } + + func showHistoryPage() { + DispatchQueue.main.asyncAfter(deadline: .now() + 0.1) { [weak self] in + self?.pageView.selectMenu(with: 1) + } + } } diff --git a/Veloria/Class/MyList/Controller/VPWatchHistoryViewController.swift b/Veloria/Class/MyList/Controller/VPWatchHistoryViewController.swift index f720fe2..5688b37 100644 --- a/Veloria/Class/MyList/Controller/VPWatchHistoryViewController.swift +++ b/Veloria/Class/MyList/Controller/VPWatchHistoryViewController.swift @@ -20,6 +20,7 @@ class VPWatchHistoryViewController: VPViewController { tableView.dataSource = self tableView.separatorStyle = .none tableView.rowHeight = 118 + tableView.vp_addNormalEmpty() tableView.vp_addRefreshHeader { [weak self] in self?.handleHeaderRefresh(nil) } diff --git a/Veloria/Class/Player/View/VPVideoPlayerCell.swift b/Veloria/Class/Player/View/VPVideoPlayerCell.swift index 74ceefc..0b5916c 100644 --- a/Veloria/Class/Player/View/VPVideoPlayerCell.swift +++ b/Veloria/Class/Player/View/VPVideoPlayerCell.swift @@ -194,9 +194,7 @@ extension VPVideoPlayerCell: VPPlayerDelegate { } func vp_player(_ player: VPPlayer, playStateDidChanged state: VPPlayer.PlayState) { - if state == .playing { - self.coverImageView.isHidden = true - } + updateCoverShowState() } func vp_player(_ player: VPPlayer, loadStateDidChange state: VPPlayer.LoadState) { @@ -205,10 +203,19 @@ extension VPVideoPlayerCell: VPPlayerDelegate { } else { self.controlView.isLoading = false } + updateCoverShowState() } func vp_playerReadyToPlay(_ player: VPPlayer) { self.seekToTime(toTime: (videoInfo?.play_seconds ?? 0) / 1000) } + private func updateCoverShowState() { + let loadState = self.player.loadState + let playState = self.player.playState + if isCurrent && (loadState == .playable || loadState == .playthroughOK) && (playState == .playing) { + self.coverImageView.isHidden = true + } + } + } diff --git a/Veloria/Libs/Empty/UIScrollView+Empty.swift b/Veloria/Libs/Empty/UIScrollView+Empty.swift new file mode 100644 index 0000000..dcfd3c7 --- /dev/null +++ b/Veloria/Libs/Empty/UIScrollView+Empty.swift @@ -0,0 +1,20 @@ +// +// UIScrollView+Empty.swift +// Veloria +// +// Created by 湖南秦九 on 2025/5/26. +// + +import UIKit +import EmptyDataSet_Swift + +extension UIScrollView { + func vp_addNormalEmpty(image: UIImage? = UIImage(named: "empty_image_01"), title: String? = nil, titleColor: UIColor? = nil) { + + self.emptyDataSetView { view in + view.image(image) + .isScrollAllowed(true) + .verticalOffset(-100) + } + } +} diff --git a/Veloria/Libs/HUD/VPHUD.swift b/Veloria/Libs/HUD/VPHUD.swift index d4b7967..fc3ffa6 100644 --- a/Veloria/Libs/HUD/VPHUD.swift +++ b/Veloria/Libs/HUD/VPHUD.swift @@ -8,16 +8,13 @@ import UIKit class VPHUD: NSObject { - static func config() { -// SVProgressHUD.setDefaultMaskType(.clear) - } static func show() { -// SVProgressHUD.setDefaultMaskType(.clear) -// SVProgressHUD.show() + SVProgressHUD.setDefaultMaskType(.clear) + SVProgressHUD.show() } static func dismiss() { -// SVProgressHUD.dismiss() + SVProgressHUD.dismiss() } } diff --git a/Veloria/Libs/HUD/VPToast.swift b/Veloria/Libs/HUD/VPToast.swift index 9bda3ed..c460f02 100644 --- a/Veloria/Libs/HUD/VPToast.swift +++ b/Veloria/Libs/HUD/VPToast.swift @@ -17,6 +17,6 @@ class VPToast: NSObject { static func show(text: String?) { guard let text = text else { return } -// SPAPPTool.getKeyWindow()?.makeToast(text) + VPAppTool.keyWindow?.makeToast(text) } } diff --git a/Veloria/Libs/Login/VPLoginManager.swift b/Veloria/Libs/Login/VPLoginManager.swift index 5e0b8c6..674f7ee 100644 --- a/Veloria/Libs/Login/VPLoginManager.swift +++ b/Veloria/Libs/Login/VPLoginManager.swift @@ -13,13 +13,35 @@ class VPLoginManager: NSObject { static let manager = VPLoginManager() private(set) var token: VPTokenModel? + private(set) var userInfo: VPUserInfo? ///是否正在刷新token private(set) var isRefreshingToken = false + override init() { + super.init() + token = UserDefaults.vp_object(forKey: kVPLoginTokenDefaultsKey, as: VPTokenModel.self) + userInfo = UserDefaults.vp_object(forKey: kVPLoginUserInfoDefaultsKey, as: VPUserInfo.self) + } + func setLoginToken(token: VPTokenModel?) { self.token = token -// UserDefaults.jx_setObject(token, forKey: kSPLoginTokenDefaultsKey) + UserDefaults.vp_setObject(token, forKey: kVPLoginTokenDefaultsKey) + } + + + ///更新用户信息 + func updateUserInfo(completer: (() -> Void)?) { + + VPUserAPI.requestUserInfo { [weak self] userInfo in + guard let self = self else { return } + if let userInfo = userInfo { + self.userInfo = userInfo + UserDefaults.vp_setObject(userInfo, forKey: kVPLoginUserInfoDefaultsKey) + } + completer?() + } + } } diff --git a/Veloria/Libs/User/VPUserInfo.swift b/Veloria/Libs/User/VPUserInfo.swift new file mode 100644 index 0000000..3063299 --- /dev/null +++ b/Veloria/Libs/User/VPUserInfo.swift @@ -0,0 +1,67 @@ +// +// VPUserInfo.swift +// Veloria +// +// Created by 湖南秦九 on 2025/5/26. +// + +import UIKit +import SmartCodable + +class VPUserInfo: VPModel, SmartCodable, NSSecureCoding { + + var id: String? + var customer_id: String? + var is_guide_vip: String? + ///是否为游客登录 + var is_tourist: Bool? + var family_name: String? + var giving_name: String? + var vip_end_time: TimeInterval? + var third_access_id: String? + var is_vip: Bool? + var coin_left_total: Int? + var send_coin_left_total: Int? + var vip_type: String? + var email: String? + var third_access_platform: String? + var ip_address: String? + var country_code: String? + var user_level: String? + var avator: String? + var sign_in_status: String? + var registered_days: String? + var ln: String? + var country: String? + + + required init() { } + + static var supportsSecureCoding: Bool { + get { + return true + } + } + + + func encode(with coder: NSCoder) { +// coder.encode(id, forKey: "id") +// coder.encode(phone, forKey: "phone") +// coder.encode(userToken, forKey: "userToken") +// coder.encode(ipAddress, forKey: "ipAddress") +// coder.encode(audioNum, forKey: "audioNum") +// coder.encode(audioSeconds, forKey: "audioSeconds") + } + + required init?(coder: NSCoder) { + super.init() + +// id = coder.decodeObject(of: NSString.self, forKey: "id") as? String +// phone = coder.decodeObject(of: NSString.self, forKey: "phone") as? String +// userToken = coder.decodeObject(of: NSString.self, forKey: "userToken") as? String +// ipAddress = coder.decodeObject(of: NSString.self, forKey: "ipAddress") as? String +// audioNum = coder.decodeObject(of: NSNumber.self, forKey: "audioNum")?.intValue +// audioSeconds = coder.decodeObject(of: NSNumber.self, forKey: "audioSeconds")?.intValue + } + +} diff --git a/Veloria/Source/Assets.xcassets/icon/arrow_left_icon_01.imageset/Contents.json b/Veloria/Source/Assets.xcassets/icon/arrow_left_icon_01.imageset/Contents.json index cf16d81..0389380 100644 --- a/Veloria/Source/Assets.xcassets/icon/arrow_left_icon_01.imageset/Contents.json +++ b/Veloria/Source/Assets.xcassets/icon/arrow_left_icon_01.imageset/Contents.json @@ -18,5 +18,8 @@ "info" : { "author" : "xcode", "version" : 1 + }, + "properties" : { + "template-rendering-intent" : "original" } } diff --git a/Veloria/Source/Assets.xcassets/icon/arrow_right_icon_02.imageset/Contents.json b/Veloria/Source/Assets.xcassets/icon/arrow_right_icon_02.imageset/Contents.json new file mode 100644 index 0000000..5c4d3b1 --- /dev/null +++ b/Veloria/Source/Assets.xcassets/icon/arrow_right_icon_02.imageset/Contents.json @@ -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 + } +} diff --git a/Veloria/Source/Assets.xcassets/icon/arrow_right_icon_02.imageset/Frame@2x.png b/Veloria/Source/Assets.xcassets/icon/arrow_right_icon_02.imageset/Frame@2x.png new file mode 100644 index 0000000..51a75e5 Binary files /dev/null and b/Veloria/Source/Assets.xcassets/icon/arrow_right_icon_02.imageset/Frame@2x.png differ diff --git a/Veloria/Source/Assets.xcassets/icon/arrow_right_icon_02.imageset/Frame@3x.png b/Veloria/Source/Assets.xcassets/icon/arrow_right_icon_02.imageset/Frame@3x.png new file mode 100644 index 0000000..c36518f Binary files /dev/null and b/Veloria/Source/Assets.xcassets/icon/arrow_right_icon_02.imageset/Frame@3x.png differ diff --git a/Veloria/Source/Assets.xcassets/icon/avatar_placeholder_icon_01.imageset/Contents.json b/Veloria/Source/Assets.xcassets/icon/avatar_placeholder_icon_01.imageset/Contents.json new file mode 100644 index 0000000..a74d531 --- /dev/null +++ b/Veloria/Source/Assets.xcassets/icon/avatar_placeholder_icon_01.imageset/Contents.json @@ -0,0 +1,22 @@ +{ + "images" : [ + { + "idiom" : "universal", + "scale" : "1x" + }, + { + "filename" : "头像@2x.png", + "idiom" : "universal", + "scale" : "2x" + }, + { + "filename" : "头像@3x.png", + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/Veloria/Source/Assets.xcassets/icon/avatar_placeholder_icon_01.imageset/头像@2x.png b/Veloria/Source/Assets.xcassets/icon/avatar_placeholder_icon_01.imageset/头像@2x.png new file mode 100644 index 0000000..979d53c Binary files /dev/null and b/Veloria/Source/Assets.xcassets/icon/avatar_placeholder_icon_01.imageset/头像@2x.png differ diff --git a/Veloria/Source/Assets.xcassets/icon/avatar_placeholder_icon_01.imageset/头像@3x.png b/Veloria/Source/Assets.xcassets/icon/avatar_placeholder_icon_01.imageset/头像@3x.png new file mode 100644 index 0000000..c127c33 Binary files /dev/null and b/Veloria/Source/Assets.xcassets/icon/avatar_placeholder_icon_01.imageset/头像@3x.png differ diff --git a/Veloria/Source/Assets.xcassets/icon/me_item_icon_01.imageset/Contents.json b/Veloria/Source/Assets.xcassets/icon/me_item_icon_01.imageset/Contents.json new file mode 100644 index 0000000..5c4d3b1 --- /dev/null +++ b/Veloria/Source/Assets.xcassets/icon/me_item_icon_01.imageset/Contents.json @@ -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 + } +} diff --git a/Veloria/Source/Assets.xcassets/icon/me_item_icon_01.imageset/Frame@2x.png b/Veloria/Source/Assets.xcassets/icon/me_item_icon_01.imageset/Frame@2x.png new file mode 100644 index 0000000..51f0730 Binary files /dev/null and b/Veloria/Source/Assets.xcassets/icon/me_item_icon_01.imageset/Frame@2x.png differ diff --git a/Veloria/Source/Assets.xcassets/icon/me_item_icon_01.imageset/Frame@3x.png b/Veloria/Source/Assets.xcassets/icon/me_item_icon_01.imageset/Frame@3x.png new file mode 100644 index 0000000..bea1ab8 Binary files /dev/null and b/Veloria/Source/Assets.xcassets/icon/me_item_icon_01.imageset/Frame@3x.png differ diff --git a/Veloria/Source/Assets.xcassets/icon/me_item_icon_02.imageset/Contents.json b/Veloria/Source/Assets.xcassets/icon/me_item_icon_02.imageset/Contents.json new file mode 100644 index 0000000..5c4d3b1 --- /dev/null +++ b/Veloria/Source/Assets.xcassets/icon/me_item_icon_02.imageset/Contents.json @@ -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 + } +} diff --git a/Veloria/Source/Assets.xcassets/icon/me_item_icon_02.imageset/Frame@2x.png b/Veloria/Source/Assets.xcassets/icon/me_item_icon_02.imageset/Frame@2x.png new file mode 100644 index 0000000..d9dc7a3 Binary files /dev/null and b/Veloria/Source/Assets.xcassets/icon/me_item_icon_02.imageset/Frame@2x.png differ diff --git a/Veloria/Source/Assets.xcassets/icon/me_item_icon_02.imageset/Frame@3x.png b/Veloria/Source/Assets.xcassets/icon/me_item_icon_02.imageset/Frame@3x.png new file mode 100644 index 0000000..9ca7638 Binary files /dev/null and b/Veloria/Source/Assets.xcassets/icon/me_item_icon_02.imageset/Frame@3x.png differ diff --git a/Veloria/Source/Assets.xcassets/icon/me_item_icon_03.imageset/Contents.json b/Veloria/Source/Assets.xcassets/icon/me_item_icon_03.imageset/Contents.json new file mode 100644 index 0000000..5c4d3b1 --- /dev/null +++ b/Veloria/Source/Assets.xcassets/icon/me_item_icon_03.imageset/Contents.json @@ -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 + } +} diff --git a/Veloria/Source/Assets.xcassets/icon/me_item_icon_03.imageset/Frame@2x.png b/Veloria/Source/Assets.xcassets/icon/me_item_icon_03.imageset/Frame@2x.png new file mode 100644 index 0000000..a275110 Binary files /dev/null and b/Veloria/Source/Assets.xcassets/icon/me_item_icon_03.imageset/Frame@2x.png differ diff --git a/Veloria/Source/Assets.xcassets/icon/me_item_icon_03.imageset/Frame@3x.png b/Veloria/Source/Assets.xcassets/icon/me_item_icon_03.imageset/Frame@3x.png new file mode 100644 index 0000000..85e3ebc Binary files /dev/null and b/Veloria/Source/Assets.xcassets/icon/me_item_icon_03.imageset/Frame@3x.png differ diff --git a/Veloria/Source/Assets.xcassets/icon/me_item_icon_04.imageset/Contents.json b/Veloria/Source/Assets.xcassets/icon/me_item_icon_04.imageset/Contents.json new file mode 100644 index 0000000..5c4d3b1 --- /dev/null +++ b/Veloria/Source/Assets.xcassets/icon/me_item_icon_04.imageset/Contents.json @@ -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 + } +} diff --git a/Veloria/Source/Assets.xcassets/icon/me_item_icon_04.imageset/Frame@2x.png b/Veloria/Source/Assets.xcassets/icon/me_item_icon_04.imageset/Frame@2x.png new file mode 100644 index 0000000..0b6f375 Binary files /dev/null and b/Veloria/Source/Assets.xcassets/icon/me_item_icon_04.imageset/Frame@2x.png differ diff --git a/Veloria/Source/Assets.xcassets/icon/me_item_icon_04.imageset/Frame@3x.png b/Veloria/Source/Assets.xcassets/icon/me_item_icon_04.imageset/Frame@3x.png new file mode 100644 index 0000000..b6f944e Binary files /dev/null and b/Veloria/Source/Assets.xcassets/icon/me_item_icon_04.imageset/Frame@3x.png differ diff --git a/Veloria/Source/Assets.xcassets/image/empty_image_01.imageset/Contents.json b/Veloria/Source/Assets.xcassets/image/empty_image_01.imageset/Contents.json new file mode 100644 index 0000000..68072d5 --- /dev/null +++ b/Veloria/Source/Assets.xcassets/image/empty_image_01.imageset/Contents.json @@ -0,0 +1,22 @@ +{ + "images" : [ + { + "idiom" : "universal", + "scale" : "1x" + }, + { + "filename" : "缺省页-内容为空-切图图层@2x.png", + "idiom" : "universal", + "scale" : "2x" + }, + { + "filename" : "缺省页-内容为空-切图图层@3x.png", + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/Veloria/Source/Assets.xcassets/image/empty_image_01.imageset/缺省页-内容为空-切图图层@2x.png b/Veloria/Source/Assets.xcassets/image/empty_image_01.imageset/缺省页-内容为空-切图图层@2x.png new file mode 100644 index 0000000..ca16553 Binary files /dev/null and b/Veloria/Source/Assets.xcassets/image/empty_image_01.imageset/缺省页-内容为空-切图图层@2x.png differ diff --git a/Veloria/Source/Assets.xcassets/image/empty_image_01.imageset/缺省页-内容为空-切图图层@3x.png b/Veloria/Source/Assets.xcassets/image/empty_image_01.imageset/缺省页-内容为空-切图图层@3x.png new file mode 100644 index 0000000..f11751d Binary files /dev/null and b/Veloria/Source/Assets.xcassets/image/empty_image_01.imageset/缺省页-内容为空-切图图层@3x.png differ diff --git a/Veloria/Source/Veloria-Bridging-Header.h b/Veloria/Source/Veloria-Bridging-Header.h index 00efc57..643ef40 100644 --- a/Veloria/Source/Veloria-Bridging-Header.h +++ b/Veloria/Source/Veloria-Bridging-Header.h @@ -10,3 +10,4 @@ #import #import #import +#import diff --git a/Veloria/Source/en.lproj/Localizable.strings b/Veloria/Source/en.lproj/Localizable.strings index b77a96a..8957777 100644 --- a/Veloria/Source/en.lproj/Localizable.strings +++ b/Veloria/Source/en.lproj/Localizable.strings @@ -7,6 +7,7 @@ */ "Home" = "Home"; +"Me" = "Me"; "All" = "All"; "Drama Champions" = "Drama Champions"; "Explore" = "Explore"; @@ -20,6 +21,15 @@ "My List" = "My List"; "History" = "History"; "Select All" = "Select All"; +"Privacy Policy" = "Privacy Policy"; +"User Agreement" = "User Agreement"; +"About Us" = "About Us"; +"Visitor" = "Visitor"; +"Help Center" = "Help Center"; +"Feedback History" = "Feedback History"; +"Feedback" = "Feedback"; +"Feedback Details" = "Feedback Details"; +"Rewards" = "Rewards"; "kHomeTitleText" = "10,000+ addictive shorts await!";