diff --git a/Podfile b/Podfile index 4c5ab96..0e96da5 100644 --- a/Podfile +++ b/Podfile @@ -26,7 +26,6 @@ target 'Veloria' do pod 'KTVHTTPCache' #视频缓存 pod 'Kingfisher' #图片加载 pod 'HWPanModal' #底部弹出控制器 - pod "ESTabBarController-swift" pod 'WMZPageController' #分页控制器 pod 'ZFPlayer/AVPlayer' #播放器 pod 'EmptyDataSet-Swift' #空数据页面 diff --git a/Podfile.lock b/Podfile.lock index a37042e..8344377 100644 --- a/Podfile.lock +++ b/Podfile.lock @@ -2,7 +2,6 @@ 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) - KTVHTTPCache (3.0.2): @@ -30,7 +29,6 @@ PODS: DEPENDENCIES: - EmptyDataSet-Swift - - ESTabBarController-swift - HWPanModal - Kingfisher - KTVHTTPCache @@ -49,7 +47,6 @@ SPEC REPOS: - Alamofire - CocoaAsyncSocket - EmptyDataSet-Swift - - ESTabBarController-swift - HWPanModal - Kingfisher - KTVHTTPCache @@ -67,7 +64,6 @@ SPEC CHECKSUMS: Alamofire: 7193b3b92c74a07f85569e1a6c4f4237291e7496 CocoaAsyncSocket: 065fd1e645c7abab64f7a6a2007a48038fdc6a99 EmptyDataSet-Swift: eb382c0c87a2d9c678077385a595cec52da38171 - ESTabBarController-swift: 05593a6ad64700b03c0eb60ff625916370aa4136 HWPanModal: b57a6717d3cdcd666bff44f9dd2a5be9f4d6f5d2 Kingfisher: 0621d0ac0c78fecb19f6dc5303bde2b52abaf2f5 KTVHTTPCache: 5711692cdf9a5ecfe829b1e16577deb3ffe3dc86 @@ -81,6 +77,6 @@ SPEC CHECKSUMS: YYKit: 7cda43304a8dc3696c449041e2cb3107b4e236e7 ZFPlayer: 5cf39e8d9f0c2394a014b0db4767b5b5a6bffe13 -PODFILE CHECKSUM: 5a8b71939b2bf65623c166084b1e01d877b2979d +PODFILE CHECKSUM: e2712ae0c35ebb37af30822c851f06195b8f41d7 COCOAPODS: 1.16.2 diff --git a/Veloria.xcodeproj/project.pbxproj b/Veloria.xcodeproj/project.pbxproj index d6bc0dd..65bd7e6 100644 --- a/Veloria.xcodeproj/project.pbxproj +++ b/Veloria.xcodeproj/project.pbxproj @@ -44,11 +44,9 @@ BF0FA6F42DDC604500C9E5F2 /* VPHUD.swift in Sources */ = {isa = PBXBuildFile; fileRef = BF0FA6F32DDC604500C9E5F2 /* VPHUD.swift */; }; BF0FA6F62DDC616300C9E5F2 /* VPToast.swift in Sources */ = {isa = PBXBuildFile; fileRef = BF0FA6F52DDC616300C9E5F2 /* VPToast.swift */; }; BF0FA6F92DDC64E700C9E5F2 /* VPHomeAPI.swift in Sources */ = {isa = PBXBuildFile; fileRef = BF0FA6F82DDC64E700C9E5F2 /* VPHomeAPI.swift */; }; - BF0FA6FC2DDC657500C9E5F2 /* VPHomeDataModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = BF0FA6FB2DDC657500C9E5F2 /* VPHomeDataModel.swift */; }; BF0FA7002DDC665300C9E5F2 /* VPShortModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = BF0FA6FF2DDC665300C9E5F2 /* VPShortModel.swift */; }; BF0FA7022DDC667C00C9E5F2 /* VPVideoInfoModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = BF0FA7012DDC667C00C9E5F2 /* VPVideoInfoModel.swift */; }; BF0FA7052DDC67AC00C9E5F2 /* VPHomeViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = BF0FA7042DDC67AC00C9E5F2 /* VPHomeViewModel.swift */; }; - BF0FA7072DDC687C00C9E5F2 /* VPHomeDataItem.swift in Sources */ = {isa = PBXBuildFile; fileRef = BF0FA7062DDC687C00C9E5F2 /* VPHomeDataItem.swift */; }; BF0FA70A2DDC69C800C9E5F2 /* VPTableViewCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = BF0FA7092DDC69C800C9E5F2 /* VPTableViewCell.swift */; }; BF0FA70C2DDC6A3800C9E5F2 /* VPHomeBannerContentCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = BF0FA70B2DDC6A3800C9E5F2 /* VPHomeBannerContentCell.swift */; }; BF0FA70E2DDC6ACC00C9E5F2 /* VPHomeItemContentCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = BF0FA70D2DDC6ACC00C9E5F2 /* VPHomeItemContentCell.swift */; }; @@ -136,6 +134,18 @@ BF5E75B82DE46F7100DE9DFE /* VPNetworkReachabilityManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = BF5E75B72DE46F7100DE9DFE /* VPNetworkReachabilityManager.swift */; }; BF5E75BC2DE546AD00DE9DFE /* VPAboutUsCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = BF5E75BB2DE546AD00DE9DFE /* VPAboutUsCell.swift */; }; BF5E75BE2DE54B2800DE9DFE /* VPAboutUsHeaderView.swift in Sources */ = {isa = PBXBuildFile; fileRef = BF5E75BD2DE54B2800DE9DFE /* VPAboutUsHeaderView.swift */; }; + BF5E75C02DE5566200DE9DFE /* VPHomePageControlView.swift in Sources */ = {isa = PBXBuildFile; fileRef = BF5E75BF2DE5566200DE9DFE /* VPHomePageControlView.swift */; }; + BF5E75CB2DE5692D00DE9DFE /* UINavigationController+JXTransition.swift in Sources */ = {isa = PBXBuildFile; fileRef = BF5E75C82DE5692D00DE9DFE /* UINavigationController+JXTransition.swift */; }; + BF5E75CC2DE5692D00DE9DFE /* JXTransitionDefine.swift in Sources */ = {isa = PBXBuildFile; fileRef = BF5E75C52DE5692D00DE9DFE /* JXTransitionDefine.swift */; }; + BF5E75CD2DE5692D00DE9DFE /* JXTransitionDelegateBridge.swift in Sources */ = {isa = PBXBuildFile; fileRef = BF5E75C62DE5692D00DE9DFE /* JXTransitionDelegateBridge.swift */; }; + BF5E75CE2DE5692D00DE9DFE /* JXPushAnimatedTransition.swift in Sources */ = {isa = PBXBuildFile; fileRef = BF5E75C42DE5692D00DE9DFE /* JXPushAnimatedTransition.swift */; }; + BF5E75CF2DE5692D00DE9DFE /* UIViewController+JXTransition.swift in Sources */ = {isa = PBXBuildFile; fileRef = BF5E75C92DE5692D00DE9DFE /* UIViewController+JXTransition.swift */; }; + BF5E75D02DE5692D00DE9DFE /* UIGestureRecognizer+JXTransition.swift in Sources */ = {isa = PBXBuildFile; fileRef = BF5E75C72DE5692D00DE9DFE /* UIGestureRecognizer+JXTransition.swift */; }; + BF5E75D12DE5692D00DE9DFE /* JXPopAnimatedTransition.swift in Sources */ = {isa = PBXBuildFile; fileRef = BF5E75C32DE5692D00DE9DFE /* JXPopAnimatedTransition.swift */; }; + BF5E75D22DE5692D00DE9DFE /* JXNavigationInteractiveTransition.swift in Sources */ = {isa = PBXBuildFile; fileRef = BF5E75C22DE5692D00DE9DFE /* JXNavigationInteractiveTransition.swift */; }; + BF5E75D32DE5692D00DE9DFE /* JXBaseAnimatedTransition.swift in Sources */ = {isa = PBXBuildFile; fileRef = BF5E75C12DE5692D00DE9DFE /* JXBaseAnimatedTransition.swift */; }; + BF5E75D52DE56B2000DE9DFE /* VPHomeCagetoryRecommandContentCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = BF5E75D42DE56B2000DE9DFE /* VPHomeCagetoryRecommandContentCell.swift */; }; + BF5E75DB2DE5B8B700DE9DFE /* VPMarqueeView.swift in Sources */ = {isa = PBXBuildFile; fileRef = BF5E75DA2DE5B8B700DE9DFE /* VPMarqueeView.swift */; }; F939C04AD4003BA127F15C28 /* Pods_Veloria.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 34F57E87E765BF8D72A43DCA /* Pods_Veloria.framework */; }; /* End PBXBuildFile section */ @@ -186,11 +196,9 @@ BF0FA6F32DDC604500C9E5F2 /* VPHUD.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = VPHUD.swift; sourceTree = ""; }; BF0FA6F52DDC616300C9E5F2 /* VPToast.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = VPToast.swift; sourceTree = ""; }; BF0FA6F82DDC64E700C9E5F2 /* VPHomeAPI.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = VPHomeAPI.swift; sourceTree = ""; }; - BF0FA6FB2DDC657500C9E5F2 /* VPHomeDataModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = VPHomeDataModel.swift; sourceTree = ""; }; BF0FA6FF2DDC665300C9E5F2 /* VPShortModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = VPShortModel.swift; sourceTree = ""; }; BF0FA7012DDC667C00C9E5F2 /* VPVideoInfoModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = VPVideoInfoModel.swift; sourceTree = ""; }; BF0FA7042DDC67AC00C9E5F2 /* VPHomeViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = VPHomeViewModel.swift; sourceTree = ""; }; - BF0FA7062DDC687C00C9E5F2 /* VPHomeDataItem.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = VPHomeDataItem.swift; sourceTree = ""; }; BF0FA7092DDC69C800C9E5F2 /* VPTableViewCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = VPTableViewCell.swift; sourceTree = ""; }; BF0FA70B2DDC6A3800C9E5F2 /* VPHomeBannerContentCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = VPHomeBannerContentCell.swift; sourceTree = ""; }; BF0FA70D2DDC6ACC00C9E5F2 /* VPHomeItemContentCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = VPHomeItemContentCell.swift; sourceTree = ""; }; @@ -278,6 +286,18 @@ BF5E75B72DE46F7100DE9DFE /* VPNetworkReachabilityManager.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = VPNetworkReachabilityManager.swift; sourceTree = ""; }; BF5E75BB2DE546AD00DE9DFE /* VPAboutUsCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = VPAboutUsCell.swift; sourceTree = ""; }; BF5E75BD2DE54B2800DE9DFE /* VPAboutUsHeaderView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = VPAboutUsHeaderView.swift; sourceTree = ""; }; + BF5E75BF2DE5566200DE9DFE /* VPHomePageControlView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = VPHomePageControlView.swift; sourceTree = ""; }; + BF5E75C12DE5692D00DE9DFE /* JXBaseAnimatedTransition.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = JXBaseAnimatedTransition.swift; sourceTree = ""; }; + BF5E75C22DE5692D00DE9DFE /* JXNavigationInteractiveTransition.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = JXNavigationInteractiveTransition.swift; sourceTree = ""; }; + BF5E75C32DE5692D00DE9DFE /* JXPopAnimatedTransition.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = JXPopAnimatedTransition.swift; sourceTree = ""; }; + BF5E75C42DE5692D00DE9DFE /* JXPushAnimatedTransition.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = JXPushAnimatedTransition.swift; sourceTree = ""; }; + BF5E75C52DE5692D00DE9DFE /* JXTransitionDefine.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = JXTransitionDefine.swift; sourceTree = ""; }; + BF5E75C62DE5692D00DE9DFE /* JXTransitionDelegateBridge.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = JXTransitionDelegateBridge.swift; sourceTree = ""; }; + BF5E75C72DE5692D00DE9DFE /* UIGestureRecognizer+JXTransition.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "UIGestureRecognizer+JXTransition.swift"; sourceTree = ""; }; + BF5E75C82DE5692D00DE9DFE /* UINavigationController+JXTransition.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "UINavigationController+JXTransition.swift"; sourceTree = ""; }; + BF5E75C92DE5692D00DE9DFE /* UIViewController+JXTransition.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "UIViewController+JXTransition.swift"; sourceTree = ""; }; + BF5E75D42DE56B2000DE9DFE /* VPHomeCagetoryRecommandContentCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = VPHomeCagetoryRecommandContentCell.swift; sourceTree = ""; }; + BF5E75DA2DE5B8B700DE9DFE /* VPMarqueeView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = VPMarqueeView.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 */ @@ -350,6 +370,7 @@ 1B056E352DDAC1DE007EE38D /* Libs */ = { isa = PBXGroup; children = ( + BF5E75D92DE5B89300DE9DFE /* MarqueeView */, BF5E75B42DE46D9500DE9DFE /* Empty */, BF0FA7BF2DE45D4500C9E5F2 /* User */, BF0FA7432DDF025A00C9E5F2 /* Player */, @@ -556,6 +577,7 @@ BF0FA6E82DDC5F6F00C9E5F2 /* Thirdparty */ = { isa = PBXGroup; children = ( + BF5E75CA2DE5692D00DE9DFE /* JXTransition */, BF0FA7932DE16E9300C9E5F2 /* JXTagView */, BF0FA6ED2DDC5F8700C9E5F2 /* JXUUID */, BF0FA7152DDC78FF00C9E5F2 /* ZKCycleScrollView-Swift */, @@ -597,8 +619,6 @@ BF0FA6FA2DDC652000C9E5F2 /* Model */ = { isa = PBXGroup; children = ( - BF0FA6FB2DDC657500C9E5F2 /* VPHomeDataModel.swift */, - BF0FA7062DDC687C00C9E5F2 /* VPHomeDataItem.swift */, BF0FA7112DDC6D2C00C9E5F2 /* VPHomeModuleItem.swift */, BF0FA7332DDEC74500C9E5F2 /* VPCategoryModel.swift */, ); @@ -644,6 +664,7 @@ BF0FA70B2DDC6A3800C9E5F2 /* VPHomeBannerContentCell.swift */, BF0FA7232DDC888F00C9E5F2 /* VPHomeRecommandContentCell.swift */, BF0FA72B2DDD7B7300C9E5F2 /* VPHomeRankingContentCell.swift */, + BF5E75D42DE56B2000DE9DFE /* VPHomeCagetoryRecommandContentCell.swift */, BF0FA7182DDC7F4900C9E5F2 /* VPHomeBannerCell.swift */, BF0FA7292DDC922F00C9E5F2 /* VPHomeRecommandCell.swift */, BF0FA72D2DDD7DD400C9E5F2 /* VPHomeRankingCell.swift */, @@ -657,6 +678,7 @@ BF0FA7882DE161F200C9E5F2 /* VPSearchResultView.swift */, BF0FA78A2DE164C100C9E5F2 /* VPSearchResultCell.swift */, BF0FA7902DE16CBF00C9E5F2 /* VPSearchHistoryView.swift */, + BF5E75BF2DE5566200DE9DFE /* VPHomePageControlView.swift */, ); path = View; sourceTree = ""; @@ -862,6 +884,30 @@ path = Empty; sourceTree = ""; }; + BF5E75CA2DE5692D00DE9DFE /* JXTransition */ = { + isa = PBXGroup; + children = ( + BF5E75C12DE5692D00DE9DFE /* JXBaseAnimatedTransition.swift */, + BF5E75C22DE5692D00DE9DFE /* JXNavigationInteractiveTransition.swift */, + BF5E75C32DE5692D00DE9DFE /* JXPopAnimatedTransition.swift */, + BF5E75C42DE5692D00DE9DFE /* JXPushAnimatedTransition.swift */, + BF5E75C52DE5692D00DE9DFE /* JXTransitionDefine.swift */, + BF5E75C62DE5692D00DE9DFE /* JXTransitionDelegateBridge.swift */, + BF5E75C72DE5692D00DE9DFE /* UIGestureRecognizer+JXTransition.swift */, + BF5E75C82DE5692D00DE9DFE /* UINavigationController+JXTransition.swift */, + BF5E75C92DE5692D00DE9DFE /* UIViewController+JXTransition.swift */, + ); + path = JXTransition; + sourceTree = ""; + }; + BF5E75D92DE5B89300DE9DFE /* MarqueeView */ = { + isa = PBXGroup; + children = ( + BF5E75DA2DE5B8B700DE9DFE /* VPMarqueeView.swift */, + ); + path = MarqueeView; + sourceTree = ""; + }; /* End PBXGroup section */ /* Begin PBXNativeTarget section */ @@ -990,11 +1036,13 @@ BF0FA7B82DE44FCC00C9E5F2 /* VPWebViewController.swift in Sources */, BF0FA72A2DDC922F00C9E5F2 /* VPHomeRecommandCell.swift in Sources */, BF0FA7322DDEBD6400C9E5F2 /* AppDelegate+Config.swift in Sources */, + BF5E75D52DE56B2000DE9DFE /* VPHomeCagetoryRecommandContentCell.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 */, + BF5E75DB2DE5B8B700DE9DFE /* VPMarqueeView.swift in Sources */, BF0FA7C32DE45DE300C9E5F2 /* VPUserAPI.swift in Sources */, BF0FA78B2DE164C100C9E5F2 /* VPSearchResultCell.swift in Sources */, BF0FA71D2DDC807200C9E5F2 /* UIImageView+VPAdd.swift in Sources */, @@ -1031,6 +1079,15 @@ BF0FA7B12DE447EB00C9E5F2 /* VPMeItem.swift in Sources */, 1B056E2C2DDAC0FD007EE38D /* SceneDelegate.swift in Sources */, BF0FA75D2DDF208400C9E5F2 /* VPExplorePlayerControlView.swift in Sources */, + BF5E75CB2DE5692D00DE9DFE /* UINavigationController+JXTransition.swift in Sources */, + BF5E75CC2DE5692D00DE9DFE /* JXTransitionDefine.swift in Sources */, + BF5E75CD2DE5692D00DE9DFE /* JXTransitionDelegateBridge.swift in Sources */, + BF5E75CE2DE5692D00DE9DFE /* JXPushAnimatedTransition.swift in Sources */, + BF5E75CF2DE5692D00DE9DFE /* UIViewController+JXTransition.swift in Sources */, + BF5E75D02DE5692D00DE9DFE /* UIGestureRecognizer+JXTransition.swift in Sources */, + BF5E75D12DE5692D00DE9DFE /* JXPopAnimatedTransition.swift in Sources */, + BF5E75D22DE5692D00DE9DFE /* JXNavigationInteractiveTransition.swift in Sources */, + BF5E75D32DE5692D00DE9DFE /* JXBaseAnimatedTransition.swift in Sources */, 1B056E462DDAC370007EE38D /* UIScreen+VPAdd.swift in Sources */, BF0FA7692DE0502900C9E5F2 /* VPEpisodeCell.swift in Sources */, BF5E75BE2DE54B2800DE9DFE /* VPAboutUsHeaderView.swift in Sources */, @@ -1047,6 +1104,7 @@ BF0FA75F2DDFFDB000C9E5F2 /* VPDetailPlayerViewController.swift in Sources */, BF0FA7732DE0671200C9E5F2 /* VPRateSelectedCell.swift in Sources */, 1B056E4D2DDAC7C1007EE38D /* VPTabBarController.swift in Sources */, + BF5E75C02DE5566200DE9DFE /* VPHomePageControlView.swift in Sources */, BF0FA6DA2DDC5CB600C9E5F2 /* VPLoginManager.swift in Sources */, BF0FA74A2DDF04E200C9E5F2 /* VPPlayerProtocol.swift in Sources */, BF0FA72C2DDD7B7300C9E5F2 /* VPHomeRankingContentCell.swift in Sources */, @@ -1059,7 +1117,6 @@ 1B056E3F2DDAC2DB007EE38D /* VPCryptorService.swift in Sources */, BF0FA7202DDC83AE00C9E5F2 /* JXButton.swift in Sources */, BF0FA7912DE16CBF00C9E5F2 /* VPSearchHistoryView.swift in Sources */, - BF0FA7072DDC687C00C9E5F2 /* VPHomeDataItem.swift in Sources */, BF0FA7992DE1951A00C9E5F2 /* VPMyListViewController.swift in Sources */, BF0FA7452DDF027900C9E5F2 /* VPPlayer.swift in Sources */, BF0FA70E2DDC6ACC00C9E5F2 /* VPHomeItemContentCell.swift in Sources */, @@ -1096,7 +1153,6 @@ 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 */, @@ -1140,7 +1196,7 @@ CLANG_ENABLE_MODULES = YES; CODE_SIGN_STYLE = Automatic; CURRENT_PROJECT_VERSION = 1; - DEVELOPMENT_TEAM = ""; + DEVELOPMENT_TEAM = 394VH538M8; GENERATE_INFOPLIST_FILE = YES; INFOPLIST_FILE = Veloria/Source/Info.plist; INFOPLIST_KEY_UIApplicationSupportsIndirectInputEvents = YES; @@ -1154,7 +1210,7 @@ "@executable_path/Frameworks", ); MARKETING_VERSION = 1.0; - PRODUCT_BUNDLE_IDENTIFIER = com.zeng.VideoPlayer; + PRODUCT_BUNDLE_IDENTIFIER = com.qjwl168.veloria.ios; PRODUCT_NAME = "$(TARGET_NAME)"; SUPPORTED_PLATFORMS = "iphoneos iphonesimulator"; SUPPORTS_MACCATALYST = NO; @@ -1175,7 +1231,7 @@ CLANG_ENABLE_MODULES = YES; CODE_SIGN_STYLE = Automatic; CURRENT_PROJECT_VERSION = 1; - DEVELOPMENT_TEAM = ""; + DEVELOPMENT_TEAM = 394VH538M8; GENERATE_INFOPLIST_FILE = YES; INFOPLIST_FILE = Veloria/Source/Info.plist; INFOPLIST_KEY_UIApplicationSupportsIndirectInputEvents = YES; @@ -1189,7 +1245,7 @@ "@executable_path/Frameworks", ); MARKETING_VERSION = 1.0; - PRODUCT_BUNDLE_IDENTIFIER = com.zeng.VideoPlayer; + PRODUCT_BUNDLE_IDENTIFIER = com.qjwl168.veloria.ios; PRODUCT_NAME = "$(TARGET_NAME)"; SUPPORTED_PLATFORMS = "iphoneos iphonesimulator"; SUPPORTS_MACCATALYST = NO; diff --git a/Veloria/Base/Controller/VPNavigationController.swift b/Veloria/Base/Controller/VPNavigationController.swift index cc991d8..162c6b3 100644 --- a/Veloria/Base/Controller/VPNavigationController.swift +++ b/Veloria/Base/Controller/VPNavigationController.swift @@ -11,8 +11,7 @@ class VPNavigationController: UINavigationController { override func viewDidLoad() { super.viewDidLoad() - -// self.interactivePopGestureRecognizer?.delegate = self + self.jx_transitionAwake() } override func pushViewController(_ viewController: UIViewController, animated: Bool) { diff --git a/Veloria/Base/Networking/Base/VPURLPath.swift b/Veloria/Base/Networking/Base/VPURLPath.swift index bb77794..66f4ad1 100644 --- a/Veloria/Base/Networking/Base/VPURLPath.swift +++ b/Veloria/Base/Networking/Base/VPURLPath.swift @@ -17,8 +17,8 @@ let VPCampaignWebURL = "https://campaign.qjwl168.com" let VPBaseURL = "https://api-qjwl168.qjwl168.com" let VPURLPathPrefix = "/velo" -let VPWebBaseURL = "https://www.thimratv.com" -let VPCampaignWebURL = "https://campaign.moviatv.com" +let VPWebBaseURL = "https://www.qjwl168.com" +let VPCampaignWebURL = "https://campaign.qjwl168.com" #endif ///用户协议 @@ -43,4 +43,4 @@ let kVPFeedBackListWebUrl = VPCampaignWebURL + "/pages/leave/list" ///反馈详情 let kVPFeedBackDetailWebUrl = VPCampaignWebURL + "/pages/leave/detail" ///活动页面 -let kVPRewardsWebUrl = VPCampaignWebURL +let kVPRewardsWebUrl = VPCampaignWebURL + "/pages/reward/theme4" diff --git a/Veloria/Base/View/TabBar/VPTabBarItemContentView.swift b/Veloria/Base/View/TabBar/VPTabBarItemContentView.swift index edc728a..c579caf 100644 --- a/Veloria/Base/View/TabBar/VPTabBarItemContentView.swift +++ b/Veloria/Base/View/TabBar/VPTabBarItemContentView.swift @@ -6,7 +6,6 @@ // import UIKit -import ESTabBarController_swift class VPTabBarItemContentView: UIView { diff --git a/Veloria/Class/Home/Controller/VPHomePageViewController.swift b/Veloria/Class/Home/Controller/VPHomePageViewController.swift index 71c2193..82149f3 100644 --- a/Veloria/Class/Home/Controller/VPHomePageViewController.swift +++ b/Veloria/Class/Home/Controller/VPHomePageViewController.swift @@ -64,13 +64,13 @@ class VPHomePageViewController: VPViewController { let height = UIScreen.height - y let pageView = WMZPageView(frame: CGRect(x: 0, y: y, width: width, height: height), param: pageParam, parentReponder: self) pageView.param = pageParam -// pageView.downSc?.delegate = self pageView.downSc?.dataSource = self pageView.downSc?.isScrollEnabled = true pageView.downSc?.separatorStyle = .none pageView.downSc?.register(VPHomeItemContentCell.self, forCellReuseIdentifier: "cell") pageView.downSc?.register(VPHomeBannerContentCell.self, forCellReuseIdentifier: VPHomeBannerContentCell.moduleKey.rawValue) pageView.downSc?.register(VPHomeRecommandContentCell.self, forCellReuseIdentifier: VPHomeRecommandContentCell.moduleKey.rawValue) + pageView.downSc?.register(VPHomeCagetoryRecommandContentCell.self, forCellReuseIdentifier: VPHomeCagetoryRecommandContentCell.moduleKey.rawValue) pageView.downSc?.register(VPHomeRankingContentCell.self, forCellReuseIdentifier: VPHomeRankingContentCell.moduleKey.rawValue) pageView.downSc?.vp_addRefreshHeader(block: { [weak self] in self?.handleHeaderRefresh(nil) @@ -146,6 +146,7 @@ class VPHomePageViewController: VPViewController { } else { self.pageView.downSc?.vp_endHeaderRefreshing() } + self.requestHomeData() } @@ -246,9 +247,13 @@ extension VPHomePageViewController { guard let self = self else { return } if let list = list { self.viewModel.oldModuleList = list - self.pageParam.wTitleArr = self.viewModel.categoryTitleList - self.pageView.updateMenuData() - self.setupPageView() + if self.viewModel.needUpdateCategory { + self.viewModel.needUpdateCategory = false + self.pageParam.wTitleArr = self.viewModel.categoryTitleList + self.pageView.updateMenuData() + self.setupPageView() + } + self.searchButton.marqueeArr = self.viewModel.marqueeArr self.pageView.downSc?.reloadData() } diff --git a/Veloria/Class/Home/Controller/VPSearchViewController.swift b/Veloria/Class/Home/Controller/VPSearchViewController.swift index cf304f0..b41c08a 100644 --- a/Veloria/Class/Home/Controller/VPSearchViewController.swift +++ b/Veloria/Class/Home/Controller/VPSearchViewController.swift @@ -21,6 +21,7 @@ class VPSearchViewController: VPViewController { private lazy var textView: VPSearchInputView = { let view = VPSearchInputView() + view.textField.delegate = self view.textDidChange = { [weak self] text in self?.textDidChange(text: text) } @@ -45,12 +46,20 @@ class VPSearchViewController: VPViewController { vp_setupUI() vp_addAction() + + let tap = UITapGestureRecognizer(target: self, action: #selector(handleScreen)) + self.view.addGestureRecognizer(tap) + } override func viewWillAppear(_ animated: Bool) { super.viewWillAppear(animated) self.navigationController?.setNavigationBarHidden(true, animated: true) } + + @objc private func handleScreen() { + VPAppTool.keyWindow?.endEditing(true) + } } @@ -109,3 +118,13 @@ extension VPSearchViewController { } } } + +//MARK: -------------- UITextFieldDelegate -------------- +extension VPSearchViewController: UITextFieldDelegate { + func textFieldShouldReturn(_ textField: UITextField) -> Bool { + self.viewModel.addHistory(text: textField.text ?? "") + VPAppTool.keyWindow?.endEditing(true) + + return true + } +} diff --git a/Veloria/Class/Home/Model/VPHomeDataItem.swift b/Veloria/Class/Home/Model/VPHomeDataItem.swift deleted file mode 100644 index 3987ea6..0000000 --- a/Veloria/Class/Home/Model/VPHomeDataItem.swift +++ /dev/null @@ -1,20 +0,0 @@ -// -// VPHomeDataItem.swift -// Veloria -// -// Created by Veloria on 2025/5/20. -// - -import UIKit - -class VPHomeDataItem: VPModel { - enum ItemType: String { - case banner - } - - - var type: ItemType = .banner - var list: [VPShortModel]? - - -} diff --git a/Veloria/Class/Home/Model/VPHomeDataModel.swift b/Veloria/Class/Home/Model/VPHomeDataModel.swift deleted file mode 100644 index 9b70723..0000000 --- a/Veloria/Class/Home/Model/VPHomeDataModel.swift +++ /dev/null @@ -1,27 +0,0 @@ -// -// VPHomeDataModel.swift -// Veloria -// -// Created by Veloria on 2025/5/20. -// - -import UIKit -import SmartCodable - -class VPHomeDataModel: VPModel, SmartCodable { - - - var bannerData: [VPShortModel]? - ///首页九宫格数据 - var nineSquare: VPNineSquareModel? - ///新剧列表 - var manualNewestRecommand: [VPShortModel]? - ///热门排行 - var hotData: [VPShortModel]? -} - -class VPNineSquareModel: VPModel, SmartCodable { - - var list: [VPShortModel]? - var title: String? -} diff --git a/Veloria/Class/Home/Model/VPHomeModuleItem.swift b/Veloria/Class/Home/Model/VPHomeModuleItem.swift index 8c571a9..04ba290 100644 --- a/Veloria/Class/Home/Model/VPHomeModuleItem.swift +++ b/Veloria/Class/Home/Model/VPHomeModuleItem.swift @@ -13,8 +13,12 @@ class VPHomeModuleItem: VPModel, SmartCodable { enum ModuleKey: String, SmartCaseDefaultable { case banner = "home_banner" case v3_recommand = "home_v3_recommand" + ///分类推荐 + case cagetory_recommand = "home_cagetory_recommand" case week_ranking = "week_ranking" case category_navigation = "category_navigation" + ///跑马灯 + case marquee = "marquee" } @@ -41,6 +45,7 @@ class VPHomeModuleItem: VPModel, SmartCodable { dataList = list } else if let list = data["shortPlayList"] as? [[String : Any]] { + self.title = data["category_name"] as? String dataList = list } diff --git a/Veloria/Class/Home/View/VPHomeBannerContentCell.swift b/Veloria/Class/Home/View/VPHomeBannerContentCell.swift index e1119b7..f60621b 100644 --- a/Veloria/Class/Home/View/VPHomeBannerContentCell.swift +++ b/Veloria/Class/Home/View/VPHomeBannerContentCell.swift @@ -15,6 +15,7 @@ class VPHomeBannerContentCell: VPHomeItemContentCell { override var item: VPHomeModuleItem? { didSet { + pageControl.count = item?.list?.count ?? 0 bannerView.reloadData() } } @@ -26,9 +27,18 @@ class VPHomeBannerContentCell: VPHomeItemContentCell { view.hidesPageControl = true view.layer.cornerRadius = 10 view.layer.masksToBounds = true + view.loadCompletion = { [weak self] in + guard let self = self else { return } + self.pageControl.currentIndex = self.bannerView.currentIdx + } view.register(VPHomeBannerCell.self, forCellWithReuseIdentifier: "cell") return view }() + + private lazy var pageControl: VPHomePageControlView = { + let view = VPHomePageControlView() + return view + }() override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) { super.init(style: style, reuseIdentifier: reuseIdentifier) @@ -46,6 +56,7 @@ extension VPHomeBannerContentCell { private func vp_setupUI() { containerView.addSubview(bannerView) + bannerView.addSubview(pageControl) bannerView.snp.makeConstraints { make in make.left.equalToSuperview().offset(15) @@ -54,6 +65,11 @@ extension VPHomeBannerContentCell { make.bottom.equalToSuperview() make.height.equalTo(182) } + + pageControl.snp.makeConstraints { make in + make.bottom.equalToSuperview().offset(-10) + make.right.equalToSuperview().offset(-10) + } } @@ -72,6 +88,10 @@ extension VPHomeBannerContentCell: ZKCycleScrollViewDataSource, ZKCycleScrollVie return cell } + func cycleScrollView(_ cycleScrollView: ZKCycleScrollView, didScrollFromIndex fromIndex: Int, toIndex: Int) { + pageControl.currentIndex = toIndex + } + func cycleScrollView(_ cycleScrollView: ZKCycleScrollView, didSelectItemAt index: Int) { guard let model = self.item?.list?[index] else { return } diff --git a/Veloria/Class/Home/View/VPHomeCagetoryRecommandContentCell.swift b/Veloria/Class/Home/View/VPHomeCagetoryRecommandContentCell.swift new file mode 100644 index 0000000..775aa67 --- /dev/null +++ b/Veloria/Class/Home/View/VPHomeCagetoryRecommandContentCell.swift @@ -0,0 +1,18 @@ +// +// VPHomeCagetoryRecommandContentCell.swift +// Veloria +// +// Created by 湖南秦九 on 2025/5/27. +// + +import UIKit + +class VPHomeCagetoryRecommandContentCell: VPHomeRecommandContentCell { + + override class var moduleKey: VPHomeModuleItem.ModuleKey { + return .cagetory_recommand + } + + + +} diff --git a/Veloria/Class/Home/View/VPHomePageControlView.swift b/Veloria/Class/Home/View/VPHomePageControlView.swift new file mode 100644 index 0000000..071857f --- /dev/null +++ b/Veloria/Class/Home/View/VPHomePageControlView.swift @@ -0,0 +1,90 @@ +// +// VPHomePageControlView.swift +// Veloria +// +// Created by 湖南秦九 on 2025/5/27. +// + +import UIKit + +class VPHomePageControlView: UIView { + + var currentIndex: Int = 0 { + didSet { + if count == 0 { return } + if currentIndex >= count { + currentIndex = 0 + return + } + + for view in self.stackView.arrangedSubviews { + if let view = view as? UIButton { + view.isSelected = view.tag == currentIndex + } + } + + } + } + + var count = 0 { + didSet { + self.stackView.removeAllArrangedSubview() + + for i in 0.. UIButton { + var config = UIButton.Configuration.plain() + config.contentInsets = .zero + + let button = UIButton(configuration: config) + button.configurationUpdateHandler = { [weak self] button in + guard let _ = self else { return } + if button.isSelected { + button.backgroundColor = .color7C174F() + button.layer.borderWidth = 0 + } else { + button.backgroundColor = .clear + button.layer.borderWidth = 1 + } + } + button.layer.cornerRadius = 3 + button.layer.masksToBounds = true + button.layer.borderColor = UIColor.colorFFFFFF(alpha: 0.35).cgColor + button.snp.makeConstraints { make in + make.width.height.equalTo(6) + } + + return button + } + +} diff --git a/Veloria/Class/Home/View/VPHomeRankingContentCell.swift b/Veloria/Class/Home/View/VPHomeRankingContentCell.swift index b64ec12..dd2d390 100644 --- a/Veloria/Class/Home/View/VPHomeRankingContentCell.swift +++ b/Veloria/Class/Home/View/VPHomeRankingContentCell.swift @@ -15,6 +15,12 @@ class VPHomeRankingContentCell: VPHomeItemContentCell { override var item: VPHomeModuleItem? { didSet { + let list = item?.list ?? [] + if list.count > 3, list.count % 3 != 0 { + var newCount = list.count / 3 + newCount = newCount * 3 + item?.list = Array(list.prefix(upTo: newCount)) + } collectionView.reloadData() } } diff --git a/Veloria/Class/Home/View/VPHomeRecommandContentCell.swift b/Veloria/Class/Home/View/VPHomeRecommandContentCell.swift index 225dc63..a058546 100644 --- a/Veloria/Class/Home/View/VPHomeRecommandContentCell.swift +++ b/Veloria/Class/Home/View/VPHomeRecommandContentCell.swift @@ -20,6 +20,11 @@ class VPHomeRecommandContentCell: VPHomeItemContentCell { } } + private lazy var iconImageView: UIImageView = { + let imageView = UIImageView(image: UIImage(named: "hot_icon_03")) + return imageView + }() + private lazy var titleLabel: UILabel = { let label = UILabel() label.font = .fontMedium(ofSize: 15) @@ -63,11 +68,29 @@ extension VPHomeRecommandContentCell { containerView.addSubview(titleLabel) containerView.addSubview(collectionView) - titleLabel.snp.makeConstraints { make in - make.left.equalToSuperview().offset(15) - make.top.equalToSuperview() + if Self.moduleKey == .v3_recommand { + + containerView.addSubview(iconImageView) + iconImageView.snp.makeConstraints { make in + make.left.equalToSuperview().offset(15) + make.top.equalToSuperview() + } + + titleLabel.snp.makeConstraints { make in + make.left.equalToSuperview().offset(38) + make.centerY.equalTo(iconImageView) + } + } else { + titleLabel.snp.makeConstraints { make in + make.left.equalToSuperview().offset(15) +// make.centerY.equalTo(iconImageView) + make.top.equalToSuperview() + } } + + + collectionView.snp.makeConstraints { make in make.left.right.equalToSuperview() make.bottom.equalToSuperview() diff --git a/Veloria/Class/Home/View/VPHomeSearchButton.swift b/Veloria/Class/Home/View/VPHomeSearchButton.swift index 00fea78..b2a0b30 100644 --- a/Veloria/Class/Home/View/VPHomeSearchButton.swift +++ b/Veloria/Class/Home/View/VPHomeSearchButton.swift @@ -9,11 +9,27 @@ import UIKit class VPHomeSearchButton: UIControl { + var marqueeArr: [VPShortModel] = [] { + didSet { + marqueeView.reloadData() + } + } + + private lazy var currentIndex = 0 + private lazy var iconImageView: UIImageView = { let imageView = UIImageView(image: UIImage(named: "search_icon_01")) return imageView }() + + private lazy var marqueeView: VPMarqueeView = { + let view = VPMarqueeView() + view.dataSource = self + view.start() + return view + }() + private lazy var textLabel: UILabel = { let label = UILabel() label.font = .fontRegular(ofSize: 14) @@ -46,7 +62,7 @@ extension VPHomeSearchButton { addSubview(iconImageView) - addSubview(textLabel) + addSubview(marqueeView) iconImageView.snp.makeConstraints { make in @@ -54,10 +70,32 @@ extension VPHomeSearchButton { make.left.equalToSuperview().offset(10) } - textLabel.snp.makeConstraints { make in - make.centerY.equalToSuperview() + marqueeView.snp.makeConstraints { make in make.left.equalTo(iconImageView.snp.right).offset(6) + make.top.bottom.equalToSuperview() + make.right.equalToSuperview().offset(-10) } } } + +extension VPHomeSearchButton: VPMarqueeViewDataSource { + func numberOfItems(_ marqueeView: VPMarqueeView) -> Int { + return marqueeArr.count == 0 ? 1 : marqueeArr.count + } + + func marqueeView(_ marqueeView: VPMarqueeView, cellForItemAt index: Int) -> NSAttributedString { + var text: String + if marqueeArr.count == 0 { + text = "kSearchPlaceholderText1".localized + } else { + text = marqueeArr[index].name ?? "" + } + + let string = NSMutableAttributedString(string: text) + string.font = .fontRegular(ofSize: 14) + string.color = .colorFFFFFF(alpha: 0.3) + + return string + } +} diff --git a/Veloria/Class/Home/View/VPSearchHistoryView.swift b/Veloria/Class/Home/View/VPSearchHistoryView.swift index 982e415..7f738c9 100644 --- a/Veloria/Class/Home/View/VPSearchHistoryView.swift +++ b/Veloria/Class/Home/View/VPSearchHistoryView.swift @@ -78,7 +78,7 @@ extension VPSearchHistoryView { titleLabel.snp.makeConstraints { make in make.left.equalToSuperview().offset(15) - make.top.equalToSuperview().offset(20) + make.top.equalToSuperview().offset(0) } deleteButton.snp.makeConstraints { make in @@ -90,7 +90,7 @@ extension VPSearchHistoryView { tagView.snp.makeConstraints { make in make.left.right.equalToSuperview() - make.top.equalToSuperview().offset(48) + make.top.equalToSuperview().offset(28) make.bottom.equalToSuperview() } } diff --git a/Veloria/Class/Home/View/VPSearchInputView.swift b/Veloria/Class/Home/View/VPSearchInputView.swift index 280bb41..6e30763 100644 --- a/Veloria/Class/Home/View/VPSearchInputView.swift +++ b/Veloria/Class/Home/View/VPSearchInputView.swift @@ -25,9 +25,10 @@ class VPSearchInputView: UIView { return imageView }() - private lazy var textField: VPTextField = { + private(set) lazy var textField: VPTextField = { let textField = VPTextField() textField.font = .fontRegular(ofSize: 14) + textField.returnKeyType = .search textField.vp_placeholder = "kSearchPlaceholderText2".localized textField.vp_placeholderFont = textField.font textField.textDidChange = { [weak self] text in diff --git a/Veloria/Class/Home/View/VPSearchRecommendedContentView.swift b/Veloria/Class/Home/View/VPSearchRecommendedContentView.swift index 1b1181e..8e80d90 100644 --- a/Veloria/Class/Home/View/VPSearchRecommendedContentView.swift +++ b/Veloria/Class/Home/View/VPSearchRecommendedContentView.swift @@ -88,6 +88,7 @@ class VPSearchRecommendedContentView: VPGradientView { collectionView.dataSource = self collectionView.showsVerticalScrollIndicator = false collectionView.register(VPSearchRecommendedCell.self, forCellWithReuseIdentifier: "cell") + collectionView.keyboardDismissMode = .onDrag return collectionView }() diff --git a/Veloria/Class/Home/View/VPSearchRecommendedView.swift b/Veloria/Class/Home/View/VPSearchRecommendedView.swift index fda69e0..fc777f3 100644 --- a/Veloria/Class/Home/View/VPSearchRecommendedView.swift +++ b/Veloria/Class/Home/View/VPSearchRecommendedView.swift @@ -90,7 +90,7 @@ extension VPSearchRecommendedView { make.left.equalToSuperview().offset(15) make.right.equalToSuperview().offset(-15) make.top.equalToSuperview() - make.height.equalTo(self).offset(-(30 + UIScreen.tabbarSafeBottomMargin)) + make.height.equalTo(self).offset(-(30 + UIScreen.tabbarSafeBottomMargin + 10)) } } diff --git a/Veloria/Class/Home/View/VPSearchResultView.swift b/Veloria/Class/Home/View/VPSearchResultView.swift index a0980f8..55d5124 100644 --- a/Veloria/Class/Home/View/VPSearchResultView.swift +++ b/Veloria/Class/Home/View/VPSearchResultView.swift @@ -36,6 +36,8 @@ class VPSearchResultView: UIView { collectionView.delegate = self collectionView.dataSource = self collectionView.register(VPSearchResultCell.self, forCellWithReuseIdentifier: "cell") + collectionView.vp_addNormalEmpty(image: UIImage(named: "empty_image_02")) + collectionView.keyboardDismissMode = .onDrag return collectionView }() diff --git a/Veloria/Class/Home/ViewModel/VPHomeViewModel.swift b/Veloria/Class/Home/ViewModel/VPHomeViewModel.swift index 2c52150..da32db5 100644 --- a/Veloria/Class/Home/ViewModel/VPHomeViewModel.swift +++ b/Veloria/Class/Home/ViewModel/VPHomeViewModel.swift @@ -19,10 +19,16 @@ class VPHomeViewModel: VPModel { ///筛选后的数据 private(set) lazy var newModuleList: [VPHomeModuleItem] = [] + + ///需要更新分类数据 + var needUpdateCategory = true ///分类列表 private(set) lazy var categoryList: [VPCategoryModel] = [] private(set) lazy var categoryTitleList: [String] = [] + ///跑马灯数据 + private(set) lazy var marqueeArr: [VPShortModel] = [] + ///筛选模版数据 private func filterModuleData() { @@ -33,20 +39,24 @@ class VPHomeViewModel: VPModel { if key == .banner { newModuleList.insert($0, at: 0) - } else if key == .category_navigation { - categoryList.removeAll() - categoryTitleList.removeAll() - - let allCategory = VPCategoryModel() - allCategory.category_name = "All".localized - allCategory.category_id = "0" - categoryList.append(allCategory) - categoryList += ($0.categoryList ?? []) - - categoryList.forEach { model in - categoryTitleList.append(model.category_name ?? "") + } else if key == .category_navigation { //分类数据 + if needUpdateCategory { + categoryList.removeAll() + categoryTitleList.removeAll() + + let allCategory = VPCategoryModel() + allCategory.category_name = "All".localized + allCategory.category_id = "0" + categoryList.append(allCategory) + categoryList += ($0.categoryList ?? []) + + categoryList.forEach { model in + categoryTitleList.append(model.category_name ?? "") + } } + } else if key == .marquee { //跑马灯数据 + marqueeArr = $0.list ?? [] } else { newModuleList.append($0) } diff --git a/Veloria/Class/MyList/Controller/VPCollectListViewController.swift b/Veloria/Class/MyList/Controller/VPCollectListViewController.swift index e6b21fa..ba1e8aa 100644 --- a/Veloria/Class/MyList/Controller/VPCollectListViewController.swift +++ b/Veloria/Class/MyList/Controller/VPCollectListViewController.swift @@ -64,7 +64,8 @@ class VPCollectListViewController: VPViewController { private lazy var dataArr: [VPShortModel] = [] private var page: Int = 1 - + ///更新节点,当节点大于1时,下次进入页面会更新列表 + private var updateNode = 0 private lazy var allSelectedButton: UIButton = { var config = UIButton.Configuration.plain() @@ -117,9 +118,14 @@ class VPCollectListViewController: VPViewController { return collectionView }() + deinit { + NotificationCenter.default.removeObserver(self) + } + override func viewDidLoad() { super.viewDidLoad() - + NotificationCenter.default.addObserver(self, selector: #selector(updateShortCollectStateNotification), name: VPVideoAPI.updateShortCollectStateNotification, object: nil) + self.bgImageView.isHidden = true self.view.backgroundColor = .clear @@ -128,6 +134,14 @@ class VPCollectListViewController: VPViewController { requestDataArr(page: 1, completer: nil) } + override func viewDidAppear(_ animated: Bool) { + super.viewDidAppear(animated) + if updateNode > 0 { + updateNode = 0 + requestDataArr(page: 1, completer: nil) + } + } + override func handleHeaderRefresh(_ completer: (() -> Void)?) { requestDataArr(page: 1) { [weak self] in self?.collectionView.vp_endHeaderRefreshing() @@ -220,6 +234,15 @@ extension VPCollectListViewController: UICollectionViewDelegate, UICollectionVie } +extension VPCollectListViewController { + + @objc private func updateShortCollectStateNotification() { + if !self.isDidAppear { + updateNode += 1 + } + } +} + extension VPCollectListViewController { private func requestDataArr(page: Int, completer: (() -> Void)?) { diff --git a/Veloria/Class/Player/Model/VPShortModel.swift b/Veloria/Class/Player/Model/VPShortModel.swift index 6e2398d..1fedf60 100644 --- a/Veloria/Class/Player/Model/VPShortModel.swift +++ b/Veloria/Class/Player/Model/VPShortModel.swift @@ -47,7 +47,8 @@ class VPShortModel: VPModel, SmartCodable { static func mappingForKey() -> [SmartKeyTransformer]? { return [ - CodingKeys.vp_description <--- ["description"] + CodingKeys.vp_description <--- ["description"], + CodingKeys.name <--- ["short_video_title", "name"] ] } } diff --git a/Veloria/Libs/MarqueeView/VPMarqueeView.swift b/Veloria/Libs/MarqueeView/VPMarqueeView.swift new file mode 100644 index 0000000..64f959e --- /dev/null +++ b/Veloria/Libs/MarqueeView/VPMarqueeView.swift @@ -0,0 +1,131 @@ +// +// VPMarqueeView.swift +// Veloria +// +// Created by 湖南秦九 on 2025/5/27. +// + +import UIKit + +protocol VPMarqueeViewDataSource: NSObjectProtocol { + + /// MARK: - 多少条数据 + func numberOfItems(_ marqueeView:VPMarqueeView) -> Int + /// MARK: - 每条的attributedString + func marqueeView(_ marqueeView:VPMarqueeView, cellForItemAt index:Int) -> NSAttributedString +} + +class VPMarqueeView: UIView { + + weak var dataSource: VPMarqueeViewDataSource? + + + private var timer: Timer? + + private var totalCount = 0 + + private var currentIndex = 0 + + private var isFirstLayout = true + + private lazy var scrollView: UIScrollView = { + let scrollView = UIScrollView() + scrollView.delegate = self + scrollView.contentInsetAdjustmentBehavior = .never + return scrollView + }() + + private lazy var oneLabel: UILabel = { + let label = UILabel() + return label + }() + + private lazy var twoLabel: UILabel = { + let label = UILabel() + return label + }() + + override init(frame: CGRect) { + super.init(frame: frame) + self.isUserInteractionEnabled = false + addSubview(scrollView) + scrollView.addSubview(oneLabel) + scrollView.addSubview(twoLabel) + + } + + override func layoutSubviews() { + super.layoutSubviews() + scrollView.frame = self.bounds + oneLabel.frame = self.bounds + twoLabel.frame = .init(x: 0, y: self.bounds.height, width: self.bounds.width, height: self.bounds.height) + scrollView.contentSize = CGSize(width: self.bounds.width, height: self.bounds.height * 2) + + if isFirstLayout { + isFirstLayout = false + reloadData() + } + + } + + required init?(coder: NSCoder) { + fatalError("init(coder:) has not been implemented") + } + + func reloadData() { + totalCount = self.dataSource?.numberOfItems(self) ?? 0 + _setData() + } + + func start() { + if self.timer == nil { + self.timer = Timer.scheduledTimer(timeInterval: 4, target: YYWeakProxy(target: self), selector: #selector(handleTimer), userInfo: nil, repeats: true) + } + } + + + +} + +extension VPMarqueeView { + + ///设置数据 + private func _setData() { + guard totalCount > 0 else { return } + let nextIndex = getNextIndex() + + oneLabel.attributedText = self.dataSource?.marqueeView(self, cellForItemAt: currentIndex) + twoLabel.attributedText = self.dataSource?.marqueeView(self, cellForItemAt: nextIndex) + + } + + @objc private func handleTimer() { + self.scrollView.setContentOffset(.init(x: 0, y: self.bounds.height), animated: true) + } + + private func getNextIndex() -> Int { + guard totalCount > 0 else { return 0 } + var nextIndex = currentIndex + 1 + if nextIndex >= totalCount { + nextIndex = 0 + } + return nextIndex + } + +} + +//MARK: UIScrollViewDelegate +extension VPMarqueeView: UIScrollViewDelegate { + + func scrollViewDidEndScrollingAnimation(_ scrollView: UIScrollView) { + guard totalCount > 0 else { return } + let nextIndex = getNextIndex() + + currentIndex = nextIndex + _setData() + self.scrollView.contentOffset = .zero + } + +} + + diff --git a/Veloria/Libs/User/VPUserInfo.swift b/Veloria/Libs/User/VPUserInfo.swift index 3063299..32a5c8a 100644 --- a/Veloria/Libs/User/VPUserInfo.swift +++ b/Veloria/Libs/User/VPUserInfo.swift @@ -45,23 +45,24 @@ class VPUserInfo: VPModel, SmartCodable, NSSecureCoding { 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") + coder.encode(id, forKey: "id") + coder.encode(customer_id, forKey: "customer_id") + coder.encode(is_tourist, forKey: "is_tourist") + coder.encode(is_vip, forKey: "is_vip") + coder.encode(avator, forKey: "avator") + coder.encode(family_name, forKey: "family_name") + coder.encode(giving_name, forKey: "giving_name") } 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 + id = coder.decodeObject(of: NSString.self, forKey: "id") as? String + customer_id = coder.decodeObject(of: NSString.self, forKey: "customer_id") as? String + is_tourist = coder.decodeObject(of: NSNumber.self, forKey: "is_tourist")?.boolValue + is_vip = coder.decodeObject(of: NSNumber.self, forKey: "is_vip")?.boolValue + avator = coder.decodeObject(of: NSString.self, forKey: "avator") as? String + family_name = coder.decodeObject(of: NSString.self, forKey: "family_name") as? String + giving_name = coder.decodeObject(of: NSString.self, forKey: "giving_name") as? String } } diff --git a/Veloria/Source/Assets.xcassets/icon/hot_icon_03.imageset/Contents.json b/Veloria/Source/Assets.xcassets/icon/hot_icon_03.imageset/Contents.json new file mode 100644 index 0000000..5c4d3b1 --- /dev/null +++ b/Veloria/Source/Assets.xcassets/icon/hot_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/hot_icon_03.imageset/Frame@2x.png b/Veloria/Source/Assets.xcassets/icon/hot_icon_03.imageset/Frame@2x.png new file mode 100644 index 0000000..923c1ac Binary files /dev/null and b/Veloria/Source/Assets.xcassets/icon/hot_icon_03.imageset/Frame@2x.png differ diff --git a/Veloria/Source/Assets.xcassets/icon/hot_icon_03.imageset/Frame@3x.png b/Veloria/Source/Assets.xcassets/icon/hot_icon_03.imageset/Frame@3x.png new file mode 100644 index 0000000..a316eb7 Binary files /dev/null and b/Veloria/Source/Assets.xcassets/icon/hot_icon_03.imageset/Frame@3x.png differ diff --git a/Veloria/Source/Assets.xcassets/image/empty_image_02.imageset/Contents.json b/Veloria/Source/Assets.xcassets/image/empty_image_02.imageset/Contents.json new file mode 100644 index 0000000..7416d0a --- /dev/null +++ b/Veloria/Source/Assets.xcassets/image/empty_image_02.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_02.imageset/缺省页-搜索不到-切图图层@2x.png b/Veloria/Source/Assets.xcassets/image/empty_image_02.imageset/缺省页-搜索不到-切图图层@2x.png new file mode 100644 index 0000000..67f58a5 Binary files /dev/null and b/Veloria/Source/Assets.xcassets/image/empty_image_02.imageset/缺省页-搜索不到-切图图层@2x.png differ diff --git a/Veloria/Source/Assets.xcassets/image/empty_image_02.imageset/缺省页-搜索不到-切图图层@3x.png b/Veloria/Source/Assets.xcassets/image/empty_image_02.imageset/缺省页-搜索不到-切图图层@3x.png new file mode 100644 index 0000000..aa1cbf5 Binary files /dev/null and b/Veloria/Source/Assets.xcassets/image/empty_image_02.imageset/缺省页-搜索不到-切图图层@3x.png differ diff --git a/Veloria/Source/Assets.xcassets/launchScreen/Contents.json b/Veloria/Source/Assets.xcassets/launchScreen/Contents.json new file mode 100644 index 0000000..73c0059 --- /dev/null +++ b/Veloria/Source/Assets.xcassets/launchScreen/Contents.json @@ -0,0 +1,6 @@ +{ + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/Veloria/Source/Assets.xcassets/launchScreen/launch_screen_bg.imageset/Contents.json b/Veloria/Source/Assets.xcassets/launchScreen/launch_screen_bg.imageset/Contents.json new file mode 100644 index 0000000..36577cc --- /dev/null +++ b/Veloria/Source/Assets.xcassets/launchScreen/launch_screen_bg.imageset/Contents.json @@ -0,0 +1,22 @@ +{ + "images" : [ + { + "idiom" : "universal", + "scale" : "1x" + }, + { + "filename" : "bg@2x.png", + "idiom" : "universal", + "scale" : "2x" + }, + { + "filename" : "bg@3x.png", + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/Veloria/Source/Assets.xcassets/launchScreen/launch_screen_bg.imageset/bg@2x.png b/Veloria/Source/Assets.xcassets/launchScreen/launch_screen_bg.imageset/bg@2x.png new file mode 100644 index 0000000..52f58d9 Binary files /dev/null and b/Veloria/Source/Assets.xcassets/launchScreen/launch_screen_bg.imageset/bg@2x.png differ diff --git a/Veloria/Source/Assets.xcassets/launchScreen/launch_screen_bg.imageset/bg@3x.png b/Veloria/Source/Assets.xcassets/launchScreen/launch_screen_bg.imageset/bg@3x.png new file mode 100644 index 0000000..5ab0f27 Binary files /dev/null and b/Veloria/Source/Assets.xcassets/launchScreen/launch_screen_bg.imageset/bg@3x.png differ diff --git a/Veloria/Source/Assets.xcassets/launchScreen/launch_screen_logo_01.imageset/Contents.json b/Veloria/Source/Assets.xcassets/launchScreen/launch_screen_logo_01.imageset/Contents.json new file mode 100644 index 0000000..6d2a9fe --- /dev/null +++ b/Veloria/Source/Assets.xcassets/launchScreen/launch_screen_logo_01.imageset/Contents.json @@ -0,0 +1,22 @@ +{ + "images" : [ + { + "idiom" : "universal", + "scale" : "1x" + }, + { + "filename" : "logo 8@2x.png", + "idiom" : "universal", + "scale" : "2x" + }, + { + "filename" : "logo 8@3x.png", + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/Veloria/Source/Assets.xcassets/launchScreen/launch_screen_logo_01.imageset/logo 8@2x.png b/Veloria/Source/Assets.xcassets/launchScreen/launch_screen_logo_01.imageset/logo 8@2x.png new file mode 100644 index 0000000..928ae1c Binary files /dev/null and b/Veloria/Source/Assets.xcassets/launchScreen/launch_screen_logo_01.imageset/logo 8@2x.png differ diff --git a/Veloria/Source/Assets.xcassets/launchScreen/launch_screen_logo_01.imageset/logo 8@3x.png b/Veloria/Source/Assets.xcassets/launchScreen/launch_screen_logo_01.imageset/logo 8@3x.png new file mode 100644 index 0000000..4f95fc5 Binary files /dev/null and b/Veloria/Source/Assets.xcassets/launchScreen/launch_screen_logo_01.imageset/logo 8@3x.png differ diff --git a/Veloria/Source/Assets.xcassets/launchScreen/launch_screen_logo_02.imageset/Contents.json b/Veloria/Source/Assets.xcassets/launchScreen/launch_screen_logo_02.imageset/Contents.json new file mode 100644 index 0000000..7657533 --- /dev/null +++ b/Veloria/Source/Assets.xcassets/launchScreen/launch_screen_logo_02.imageset/Contents.json @@ -0,0 +1,22 @@ +{ + "images" : [ + { + "idiom" : "universal", + "scale" : "1x" + }, + { + "filename" : "Veloria-白 2@2x.png", + "idiom" : "universal", + "scale" : "2x" + }, + { + "filename" : "Veloria-白 2@3x.png", + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/Veloria/Source/Assets.xcassets/launchScreen/launch_screen_logo_02.imageset/Veloria-白 2@2x.png b/Veloria/Source/Assets.xcassets/launchScreen/launch_screen_logo_02.imageset/Veloria-白 2@2x.png new file mode 100644 index 0000000..71eefa5 Binary files /dev/null and b/Veloria/Source/Assets.xcassets/launchScreen/launch_screen_logo_02.imageset/Veloria-白 2@2x.png differ diff --git a/Veloria/Source/Assets.xcassets/launchScreen/launch_screen_logo_02.imageset/Veloria-白 2@3x.png b/Veloria/Source/Assets.xcassets/launchScreen/launch_screen_logo_02.imageset/Veloria-白 2@3x.png new file mode 100644 index 0000000..f410cd0 Binary files /dev/null and b/Veloria/Source/Assets.xcassets/launchScreen/launch_screen_logo_02.imageset/Veloria-白 2@3x.png differ diff --git a/Veloria/Source/Base.lproj/LaunchScreen.storyboard b/Veloria/Source/Base.lproj/LaunchScreen.storyboard index 865e932..ce6b5e2 100644 --- a/Veloria/Source/Base.lproj/LaunchScreen.storyboard +++ b/Veloria/Source/Base.lproj/LaunchScreen.storyboard @@ -1,7 +1,9 @@ - - + + + - + + @@ -11,10 +13,31 @@ - + - + + + + + + + + + + + + + + + + + + + + + + @@ -22,4 +45,9 @@ + + + + + diff --git a/Veloria/Thirdparty/JXTransition/JXBaseAnimatedTransition.swift b/Veloria/Thirdparty/JXTransition/JXBaseAnimatedTransition.swift new file mode 100644 index 0000000..7d64349 --- /dev/null +++ b/Veloria/Thirdparty/JXTransition/JXBaseAnimatedTransition.swift @@ -0,0 +1,86 @@ +// +// JXBaseAnimatedTransition.swift +// Test +// +// Created by 曾觉新 on 2022/10/10. +// + +import UIKit + +class JXBaseAnimatedTransition: NSObject { + + open var isHideTabBar = false + + open var transitionContext: UIViewControllerContextTransitioning? + open weak var containerView: UIView? + open weak var fromViewController: UIViewController? + open weak var toViewController: UIViewController? + + open var contentView: UIView? + +// open var isScale = false +// open var shadowView: UIView! +// open var isHideTabBar = false +// open var contentView: UIView? + + + open func getCapture(with view: UIView) -> UIImage? { + UIGraphicsBeginImageContextWithOptions(view.bounds.size, view.isOpaque, 0) + view.drawHierarchy(in: view.bounds, afterScreenUpdates: false) + let image = UIGraphicsGetImageFromCurrentImageContext() + UIGraphicsEndImageContext() + return image + } +} + +extension JXBaseAnimatedTransition: UIViewControllerAnimatedTransitioning { + func transitionDuration(using transitionContext: UIViewControllerContextTransitioning?) -> TimeInterval { + return TimeInterval(UINavigationController.hideShowBarDuration) + } + + func animateTransition(using transitionContext: UIViewControllerContextTransitioning) { + let containerView = transitionContext.containerView + + let fromVC = transitionContext.viewController(forKey: .from) + let toVC = transitionContext.viewController(forKey: .to) + + self.containerView = containerView + self.fromViewController = fromVC + self.toViewController = toVC + self.transitionContext = transitionContext + + animateTransition() + } + + + @objc open func animateTransition() { + // SubClass Implementation + } + + public func completeTransition() { + guard let transitionContext = self.transitionContext else { return } + transitionContext.completeTransition(!transitionContext.transitionWasCancelled) + } + + public func animationDuration() -> TimeInterval { + return self.transitionDuration(using: self.transitionContext) + } + +} + + +extension UIViewController { + fileprivate struct AssociatedKeys { + static var defCaptureImage: Int? + } + + public var jx_captureImage: UIImage? { + get { + guard let obj = objc_getAssociatedObject(self, &AssociatedKeys.defCaptureImage) else { return nil } + return obj as? UIImage + } + set { + objc_setAssociatedObject(self, &AssociatedKeys.defCaptureImage, newValue, .OBJC_ASSOCIATION_RETAIN_NONATOMIC) + } + } +} diff --git a/Veloria/Thirdparty/JXTransition/JXNavigationInteractiveTransition.swift b/Veloria/Thirdparty/JXTransition/JXNavigationInteractiveTransition.swift new file mode 100644 index 0000000..eee2aab --- /dev/null +++ b/Veloria/Thirdparty/JXTransition/JXNavigationInteractiveTransition.swift @@ -0,0 +1,202 @@ +// +// JXNavigationInteractiveTransition.swift +// Test +// +// Created by 曾觉新 on 2022/10/10. +// + +import UIKit + +class JXNavigationInteractiveTransition: NSObject { + + + var interactionController: UIPercentDrivenInteractiveTransition? + + var isGesturePush = false + + weak var navigationController: UINavigationController! + weak var visibleVC: UIViewController? + +} + +extension JXNavigationInteractiveTransition { + + @objc func panGestureRecognizerAction(_ sender: UIPanGestureRecognizer) { + guard let view = sender.view else { return } + + + var progress = sender.translation(in: view).x / UIScreen.main.bounds.width + let velocity = sender.velocity(in: sender.view) + + + // 在手势开始的时候判断是push操作还是pop操作 + if sender.state == .began { + isGesturePush = velocity.x < 0 ? true : false + visibleVC = self.navigationController.visibleViewController + } + + if isGesturePush { + progress = -progress + } + + progress = min(1, max(0, progress)) +// bcLog(message: progress) + + switch sender.state { + case .began: + if self.isGesturePush { + if let visibleVC = self.visibleVC { + if visibleVC.jx_pushDelegate != nil { + self.interactionController = UIPercentDrivenInteractiveTransition() + visibleVC.jx_pushDelegate?.pushToNextViewController?() + self.pushScrollBegan() + } + } + } else { + self.interactionController = UIPercentDrivenInteractiveTransition() + self.navigationController.popViewController(animated: true) + self.popScrollBegan() + } + + case .changed: + self.interactionController?.update(progress) + + if self.isGesturePush { + self.pushScrollUpdate(progress: progress) + } else { + self.popScrollUpdate(progress: progress) + } + + default: + + var pushFinished: Bool = false + + var finishProgress = 0.5 + if self.isGesturePush { + finishProgress = 0.3 + } + + if progress > finishProgress { + pushFinished = true + self.interactionController?.finish() + } else { + pushFinished = false + self.interactionController?.cancel() + } + + if self.isGesturePush { + pushScrollEnded(finished: pushFinished) + } else { + popScrollEnded(finished: pushFinished) + } + + self.interactionController = nil + } + + } + + func pushScrollBegan() { + if let visibleVC = self.visibleVC { + visibleVC.jx_pushDelegate?.viewControllerPushScrollBegan?() + } + } + + func pushScrollUpdate(progress: CGFloat) { + if let visibleVC = self.visibleVC { + visibleVC.jx_pushDelegate?.viewControllerPushScrollUpdate?(progress: progress) + } + } + + func pushScrollEnded(finished: Bool) { + if let visibleVC = self.visibleVC { + visibleVC.jx_pushDelegate?.viewControllerPushScrollEnded?(finished: finished) + } + } + + func popScrollBegan() { + if let visibleVC = self.visibleVC { + visibleVC.jx_popDelegate?.viewControllerPopScrollBegan?() + } + } + + func popScrollUpdate(progress: CGFloat) { + if let visibleVC = self.visibleVC { + visibleVC.jx_popDelegate?.viewControllerPopScrollUpdate?(progress: progress) + } + } + + func popScrollEnded(finished: Bool) { + if let visibleVC = self.visibleVC { + visibleVC.jx_popDelegate?.viewControllerPopScrollEnded?(finished: finished) + } + } + +} + +extension JXNavigationInteractiveTransition: UIGestureRecognizerDelegate { + + func gestureRecognizerShouldBegin(_ gestureRecognizer: UIGestureRecognizer) -> Bool { +// ydLog(message: "滑动========\(gestureRecognizer.jxTag ?? "")") + guard let jxTag = gestureRecognizer.jxTag else { return true } + + // 忽略导航控制器正在做转场动画 + if self.navigationController.jx_isTransitioning == true { return false } + + // 如果没有visibleViewController,不作处理 + guard let visibleVC = self.navigationController.visibleViewController else { return true } + + //页面禁止了手势 + if visibleVC.jx_popGestureType == .disabled { return false } + + if let _ = gestureRecognizer as? UIScreenEdgePanGestureRecognizer { + if visibleVC.jx_popGestureType == .fullScreen { return false } //当前是全屏手势直接返回 + // 修复边缘侧滑返回失效的bug + if self.navigationController.viewControllers.count <= 1 { return false } +// ydLog(message: "滑动========这里是边缘手势返回") + return true + + } else if let panGesture = gestureRecognizer as? UIPanGestureRecognizer { //全屏滑动手势处理 + // 根据transition判断是左滑还是右滑 + let transition = panGesture.translation(in: gestureRecognizer.view) + if transition.x == 0 { return false } + + if jxTag == "pop" { + if visibleVC.jx_popGestureType == .edge { return false } + if transition.x <= 0 { return false } //左滑直接返回 + if self.navigationController.viewControllers.count <= 1 { return false } + if visibleVC.jx_popDelegate?.viewControllerPopShouldScrollBegan?() == false { return false } + visibleVC.jx_popDelegate?.viewControllerPopScrollBegan?() +// ydLog(message: "滑动========这里是pop滑动") + return true + } else if jxTag == "push" { + if transition.x >= 0 { return false } //右滑直接返回 + if visibleVC.jx_pushDelegate == nil { return false } +// ydLog(message: "滑动========这里是push滑动") + return true + } + } + + return true + } +} + +extension JXNavigationInteractiveTransition: UINavigationControllerDelegate { + + + func navigationController(_ navigationController: UINavigationController, animationControllerFor operation: UINavigationController.Operation, from fromVC: UIViewController, to toVC: UIViewController) -> UIViewControllerAnimatedTransitioning? { + if interactionController != nil, operation == .pop { + return JXPopAnimatedTransition() + } else if interactionController != nil, operation == .push { + return JXPushAnimatedTransition() + } + return nil + } + + ///处理交互式转场 + func navigationController(_ navigationController: UINavigationController, interactionControllerFor animationController: UIViewControllerAnimatedTransitioning) -> UIViewControllerInteractiveTransitioning? { + if animationController.isKind(of: JXBaseAnimatedTransition.self) { + return interactionController + } + return nil + } +} diff --git a/Veloria/Thirdparty/JXTransition/JXPopAnimatedTransition.swift b/Veloria/Thirdparty/JXTransition/JXPopAnimatedTransition.swift new file mode 100644 index 0000000..b0f0f74 --- /dev/null +++ b/Veloria/Thirdparty/JXTransition/JXPopAnimatedTransition.swift @@ -0,0 +1,72 @@ +// +// JXPopAnimatedTransition.swift +// Test +// +// Created by 曾觉新 on 2022/10/10. +// + +import UIKit + +class JXPopAnimatedTransition: JXBaseAnimatedTransition { + + override func animateTransition() { + guard let fromView = self.fromViewController?.view else { return } + + var toView = self.toViewController?.view + + if toView == nil { return } + + self.containerView?.insertSubview(toView!, belowSubview: fromView) + + let size = self.containerView?.bounds.size ?? .zero + + self.isHideTabBar = (self.toViewController?.tabBarController != nil) && (self.fromViewController?.hidesBottomBarWhenPushed == true) && (self.toViewController?.jx_captureImage != nil) + + if self.isHideTabBar { + let captureView = UIImageView(image: self.toViewController?.jx_captureImage!) + + captureView.frame = CGRect(x: 0, y: 0, width: size.width, height: size.height) + self.containerView?.insertSubview(captureView, belowSubview: fromView) + toView = captureView + self.toViewController?.view.isHidden = true + self.toViewController?.tabBarController?.tabBar.isHidden = true + } + self.contentView = toView + + + fromView.frame = CGRect(x: 0, y: 0, width: size.width, height: size.height) + toView!.frame = CGRect(x: -(0.3 * size.width), y: 0, width: size.width, height: size.height) + + fromView.layer.shadowColor = UIColor.black.cgColor + fromView.layer.shadowOpacity = 0.15 + fromView.layer.shadowRadius = 3.0 + + UIView.animate(withDuration: animationDuration(), delay: 0, options: .curveEaseInOut) { + + fromView.frame = CGRect(x: size.width, y: 0, width: size.width, height: size.height) + + if #available(iOS 11.0, *) { + toView!.frame = CGRect(x: 0, y: 0, width: size.width, height: size.height) + }else { + toView!.transform = .identity + } + + } completion: { finish in + + if self.isHideTabBar { + if self.contentView != nil { + self.contentView?.removeFromSuperview() + self.contentView = nil + } + self.toViewController?.view.isHidden = false + if self.toViewController?.navigationController?.children.count == 1 { + self.toViewController?.tabBarController?.tabBar.isHidden = false + } + } + + self.completeTransition() + } + } + + +} diff --git a/Veloria/Thirdparty/JXTransition/JXPushAnimatedTransition.swift b/Veloria/Thirdparty/JXTransition/JXPushAnimatedTransition.swift new file mode 100644 index 0000000..24fd9ee --- /dev/null +++ b/Veloria/Thirdparty/JXTransition/JXPushAnimatedTransition.swift @@ -0,0 +1,79 @@ +// +// JXPushAnimatedTransition.swift +// Test +// +// Created by 曾觉新 on 2022/10/10. +// + +import UIKit + +class JXPushAnimatedTransition: JXBaseAnimatedTransition { + + + override func animateTransition() { + guard let toView = self.toViewController?.view else { return } + + var fromView = self.fromViewController?.view + + let size = self.containerView?.bounds.size ?? .zero + + // 解决UITabBarController左滑push时的显示问题 + self.isHideTabBar = (self.fromViewController?.tabBarController != nil) && (self.toViewController?.hidesBottomBarWhenPushed == true) + + + if self.isHideTabBar { + // 获取fromViewController的截图 + let view: UIView? + if self.fromViewController?.view.window != nil { + view = self.fromViewController?.view.window + }else { + view = self.fromViewController?.view + } + + if view != nil { + let captureImage = self.getCapture(with: view!) + let captureView = UIImageView(image: captureImage) + captureView.frame = CGRect(x: 0, y: 0, width: size.width, height: size.height) + containerView?.addSubview(captureView) + fromView = captureView + self.fromViewController?.jx_captureImage = captureImage + self.fromViewController?.view.isHidden = true + self.fromViewController?.tabBarController?.tabBar.isHidden = true + } + } + self.contentView = fromView + + + self.containerView?.addSubview(toView) + + + toView.frame = CGRect(x: size.width, y: 0, width: size.width, height: size.height) + + toView.layer.shadowColor = UIColor.black.cgColor + toView.layer.shadowOpacity = 0.15 + toView.layer.shadowRadius = 3.0 + + + UIView.animate(withDuration: transitionDuration(using: transitionContext), delay: 0, options: .curveEaseInOut) { + + fromView?.frame = CGRect(x: -(0.3 * size.width), y: 0, width: size.width, height: size.height) + toView.frame = CGRect(x: 0, y: 0, width: size.width, height: size.height) + + } completion: { finish in + if self.isHideTabBar { + if self.contentView != nil { + self.contentView!.removeFromSuperview() + self.contentView = nil + } + self.fromViewController?.view.isHidden = false + + if self.fromViewController?.navigationController?.children.count == 1 { + self.fromViewController?.tabBarController?.tabBar.isHidden = false + } + } + + + self.completeTransition() + } + } +} diff --git a/Veloria/Thirdparty/JXTransition/JXTransitionDefine.swift b/Veloria/Thirdparty/JXTransition/JXTransitionDefine.swift new file mode 100644 index 0000000..6889415 --- /dev/null +++ b/Veloria/Thirdparty/JXTransition/JXTransitionDefine.swift @@ -0,0 +1,47 @@ +// +// JXTransitionDefine.swift +// Test +// +// Created by 曾觉新 on 2022/10/11. +// + +import UIKit + +public func jx_swizzled_instanceMethod(_ prefix: String, oldClass: Swift.AnyClass!, oldSelector: String, newClass: Swift.AnyClass) { + let newSelector = prefix + "_" + oldSelector; + + let originalSelector = NSSelectorFromString(oldSelector) + let swizzledSelector = NSSelectorFromString(newSelector) + + let originalMethod = class_getInstanceMethod(oldClass, originalSelector) + let swizzledMethod = class_getInstanceMethod(newClass, swizzledSelector) + + let isAdd = class_addMethod(oldClass, originalSelector, method_getImplementation(swizzledMethod!), method_getTypeEncoding(swizzledMethod!)) + + if isAdd { + class_replaceMethod(newClass, swizzledSelector, method_getImplementation(originalMethod!), method_getTypeEncoding(originalMethod!)) + }else { + method_exchangeImplementations(originalMethod!, swizzledMethod!) + } +} + + +// MARK: - Swizzling会改变全局状态,所以用DispatchQueue.once来确保无论多少线程都只会被执行一次 +extension DispatchQueue { + private static var onceTracker = [String]() + // Executes a block of code, associated with a unique token, only once. The code is thread safe and will only execute the code once even in the presence of multithreaded calls. + public class func once(token: String, block: () -> Void) { + // 保证被 objc_sync_enter 和 objc_sync_exit 包裹的代码可以有序同步地执行 + objc_sync_enter(self) + defer { // 作用域结束后执行defer中的代码 + objc_sync_exit(self) + } + + if onceTracker.contains(token) { + return + } + + onceTracker.append(token) + block() + } +} diff --git a/Veloria/Thirdparty/JXTransition/JXTransitionDelegateBridge.swift b/Veloria/Thirdparty/JXTransition/JXTransitionDelegateBridge.swift new file mode 100644 index 0000000..a938e4e --- /dev/null +++ b/Veloria/Thirdparty/JXTransition/JXTransitionDelegateBridge.swift @@ -0,0 +1,16 @@ +// +// JXTransitionDelegateBridge.swift +// Test +// +// Created by 曾觉新 on 2022/10/10. +// + +import UIKit + +class JXTransitionDelegateBridge: NSObject { + + weak var jx_pushDelegate: JXViewControllerPushDelegate? + + weak var jx_popDelegate: JXViewControllerPopDelegate? + +} diff --git a/Veloria/Thirdparty/JXTransition/UIGestureRecognizer+JXTransition.swift b/Veloria/Thirdparty/JXTransition/UIGestureRecognizer+JXTransition.swift new file mode 100644 index 0000000..0a49233 --- /dev/null +++ b/Veloria/Thirdparty/JXTransition/UIGestureRecognizer+JXTransition.swift @@ -0,0 +1,25 @@ +// +// UIGestureRecognizer+JXTransition.swift +// YDLive +// +// Created by 曾觉新 on 2022/11/29. +// + +import UIKit + +extension UIGestureRecognizer { + + fileprivate struct AssociatedKeys { + static var jxTag: Int? + } + + var jxTag: String? { + get { + guard let obj = objc_getAssociatedObject(self, &AssociatedKeys.jxTag) as? String else { return nil } + return obj + } + set { + objc_setAssociatedObject(self, &AssociatedKeys.jxTag, newValue, .OBJC_ASSOCIATION_RETAIN_NONATOMIC) + } + } +} diff --git a/Veloria/Thirdparty/JXTransition/UINavigationController+JXTransition.swift b/Veloria/Thirdparty/JXTransition/UINavigationController+JXTransition.swift new file mode 100644 index 0000000..e02c4cf --- /dev/null +++ b/Veloria/Thirdparty/JXTransition/UINavigationController+JXTransition.swift @@ -0,0 +1,130 @@ +// +// UINavigationController+JXTransition.swift +// Test +// +// Created by 曾觉新 on 2022/10/10. +// + +import UIKit + + +extension UINavigationController { + + /** + 承载手势的视图 + */ + private var gestureView: UIView? { + return self.interactivePopGestureRecognizer?.view + } + /** + 激活转场动画 + */ + func jx_transitionAwake() { +// UIViewController.jxTransitionAwake() + + self.delegate = self.interactiveTransition + self.interactivePopGestureRecognizer?.isEnabled = false + + self.gestureView?.addGestureRecognizer(pushGesture) + self.gestureView?.addGestureRecognizer(popGesture) + self.gestureView?.addGestureRecognizer(edgePopGesture) + } + + + +} + + +extension UINavigationController { + fileprivate struct AssociatedKeys { + static var screenPanGesture: Int? + static var panGesture: Int? + static var panPushGesture: Int? + static var transition: Int? + } + + var interactiveTransition: JXNavigationInteractiveTransition { + get { + var transition = objc_getAssociatedObject(self, &AssociatedKeys.transition) as? JXNavigationInteractiveTransition + if transition == nil { + transition = JXNavigationInteractiveTransition() + transition?.navigationController = self + + objc_setAssociatedObject(self, &AssociatedKeys.transition, transition, .OBJC_ASSOCIATION_RETAIN_NONATOMIC) + } + return transition! + } + } + + /** + 边缘滑动手势 + */ + var edgePopGesture: UIScreenEdgePanGestureRecognizer { + get { + var panGesture = objc_getAssociatedObject(self, &AssociatedKeys.screenPanGesture) as? UIScreenEdgePanGestureRecognizer + if panGesture == nil { + panGesture = UIScreenEdgePanGestureRecognizer(target: self.systemTarget, action: self.systemAction) + panGesture?.jxTag = "edgePop" + panGesture?.edges = .left + panGesture?.delegate = self.interactiveTransition + + objc_setAssociatedObject(self, &AssociatedKeys.screenPanGesture, panGesture, .OBJC_ASSOCIATION_RETAIN_NONATOMIC) + } + return panGesture! + } + } + + /** + 全屏返回手势 + */ + var popGesture: UIPanGestureRecognizer { + get { + var panGesture = objc_getAssociatedObject(self, &AssociatedKeys.panGesture) as? UIPanGestureRecognizer + if panGesture == nil { + panGesture = UIPanGestureRecognizer(target: self.systemTarget, action: self.systemAction) + panGesture?.jxTag = "pop" + panGesture?.maximumNumberOfTouches = 1 + panGesture?.delegate = self.interactiveTransition + objc_setAssociatedObject(self, &AssociatedKeys.panGesture, panGesture, .OBJC_ASSOCIATION_RETAIN_NONATOMIC) + } + return panGesture! + } + } + + /** + 全屏push手势 + */ + var pushGesture: UIPanGestureRecognizer { + get { + var panGesture = objc_getAssociatedObject(self, &AssociatedKeys.panPushGesture) as? UIPanGestureRecognizer + if panGesture == nil { + panGesture = UIPanGestureRecognizer(target: self.interactiveTransition, action: #selector(self.interactiveTransition.panGestureRecognizerAction(_:))) + panGesture?.jxTag = "push" + panGesture?.maximumNumberOfTouches = 1 + panGesture?.delegate = self.interactiveTransition + objc_setAssociatedObject(self, &AssociatedKeys.panPushGesture, panGesture, .OBJC_ASSOCIATION_RETAIN_NONATOMIC) + } + return panGesture! + } + } + + + + var systemTarget: Any? { + get { + let internalTargets = self.interactivePopGestureRecognizer?.value(forKey: "targets") as? [AnyObject] + let internamTarget = internalTargets?.first?.value(forKey: "target") + return internamTarget + } + } + var systemAction: Selector { + return NSSelectorFromString("handleNavigationTransition:") + } + + /** + 是否正在做转场动画 + */ + var jx_isTransitioning: Bool? { + return value(forKey: "_isTransitioning") as? Bool + } +} diff --git a/Veloria/Thirdparty/JXTransition/UIViewController+JXTransition.swift b/Veloria/Thirdparty/JXTransition/UIViewController+JXTransition.swift new file mode 100644 index 0000000..5a3eef8 --- /dev/null +++ b/Veloria/Thirdparty/JXTransition/UIViewController+JXTransition.swift @@ -0,0 +1,127 @@ +// +// UIViewController+JXTransition.swift +// Test +// +// Created by 曾觉新 on 2022/10/10. +// + +import UIKit + +// 左滑push代理 +@objc public protocol JXViewControllerPushDelegate: NSObjectProtocol { + /// 左滑push,在这里创建将要push的控制器 + @objc optional func pushToNextViewController() + + /// push手势滑动开始 + @objc optional func viewControllerPushScrollBegan() + + /// push手势滑动进度更新 + /// - Parameter progress: 进度(0-1) + @objc optional func viewControllerPushScrollUpdate(progress: CGFloat) + + /// push手势滑动结束 + /// - Parameter finished: 是否完成push操作(true:push成功 false:push取消) + @objc optional func viewControllerPushScrollEnded(finished: Bool) +} + +// 右滑pop代理 +@objc public protocol JXViewControllerPopDelegate: NSObjectProtocol { + + @objc optional func viewControllerPopShouldScrollBegan() -> Bool + + /// pop手势滑动开始 + @objc optional func viewControllerPopScrollBegan() + + /// pop手势滑动进度更新 + /// - Parameter progress: 进度(0-1) + @objc optional func viewControllerPopScrollUpdate(progress: CGFloat) + + /// pop手势滑动结束 + /// - Parameter finished: 是否完成pop操作(true:pop成功 false:pop取消) + @objc optional func viewControllerPopScrollEnded(finished: Bool) +} + +extension UIViewController { + +// // MARK: - 重新系统方法 +// private static let onceToken = UUID().uuidString +// @objc public static func jxTransitionAwake() { +// DispatchQueue.once(token: onceToken) { +// let oriSels = ["viewDidAppear:",] +// for oriSel in oriSels { +// jx_swizzled_instanceMethod("jxGesture", oldClass: self, oldSelector: oriSel, newClass: self) +// } +// } +// } +// +// @objc func jxGesture_viewDidAppear(_ animated: Bool) { +// jxGesture_viewDidAppear(animated) +// } +} + +extension UIViewController { + enum GestureTransitionType: Int { + ///全屏手势 + case fullScreen + ///边缘手势 + case edge + ///禁用手势 + case disabled + + } + + fileprivate struct AssociatedKeys { + static var jxDelegateBridge: Int? + static var jx_gestureType: Int? + } + + /** + 手势类型 + */ + var jx_popGestureType: GestureTransitionType { + get { + guard let obj = objc_getAssociatedObject(self, &AssociatedKeys.jx_gestureType) as? GestureTransitionType else { return .fullScreen } + return obj + } + set { + objc_setAssociatedObject(self, &AssociatedKeys.jx_gestureType, newValue, .OBJC_ASSOCIATION_RETAIN_NONATOMIC) + } + } + + + /** + 代理桥接 + */ + fileprivate var jx_delegateBridge: JXTransitionDelegateBridge { + get { + var bridge = objc_getAssociatedObject(self, &AssociatedKeys.jxDelegateBridge) as? JXTransitionDelegateBridge + if bridge == nil { + bridge = JXTransitionDelegateBridge() + objc_setAssociatedObject(self, &AssociatedKeys.jxDelegateBridge, bridge, .OBJC_ASSOCIATION_RETAIN_NONATOMIC) + } + return bridge! + } + } + + var jx_pushDelegate: JXViewControllerPushDelegate? { + get { + return jx_delegateBridge.jx_pushDelegate + } + set { + jx_delegateBridge.jx_pushDelegate = newValue + } + } + + var jx_popDelegate: JXViewControllerPopDelegate? { + get { + return jx_delegateBridge.jx_popDelegate + } + set { + jx_delegateBridge.jx_popDelegate = newValue + } + } + +} + + +