Commit 350e7cac by suolong

限时表演UI

parent 186fb7b0
Showing with 1540 additions and 37 deletions
...@@ -52,8 +52,6 @@ ...@@ -52,8 +52,6 @@
004773262F5C281300E46A79 /* liveRoom_newComer_gift_animate.webp in Resources */ = {isa = PBXBuildFile; fileRef = 004773252F5C281300E46A79 /* liveRoom_newComer_gift_animate.webp */; }; 004773262F5C281300E46A79 /* liveRoom_newComer_gift_animate.webp in Resources */ = {isa = PBXBuildFile; fileRef = 004773252F5C281300E46A79 /* liveRoom_newComer_gift_animate.webp */; };
004773382F5E7E7800E46A79 /* FUSGetSuccessRecommendResultModel.h in Headers */ = {isa = PBXBuildFile; fileRef = 004773362F5E7E7800E46A79 /* FUSGetSuccessRecommendResultModel.h */; }; 004773382F5E7E7800E46A79 /* FUSGetSuccessRecommendResultModel.h in Headers */ = {isa = PBXBuildFile; fileRef = 004773362F5E7E7800E46A79 /* FUSGetSuccessRecommendResultModel.h */; };
004773392F5E7E7800E46A79 /* FUSGetSuccessRecommendResultModel.m in Sources */ = {isa = PBXBuildFile; fileRef = 004773372F5E7E7800E46A79 /* FUSGetSuccessRecommendResultModel.m */; }; 004773392F5E7E7800E46A79 /* FUSGetSuccessRecommendResultModel.m in Sources */ = {isa = PBXBuildFile; fileRef = 004773372F5E7E7800E46A79 /* FUSGetSuccessRecommendResultModel.m */; };
00F1A6022F60C11000B81234 /* FUSTicketShowCollectTicketToggleResultModel.h in Headers */ = {isa = PBXBuildFile; fileRef = 00F1A6002F60C11000B81234 /* FUSTicketShowCollectTicketToggleResultModel.h */; };
00F1A6032F60C11000B81234 /* FUSTicketShowCollectTicketToggleResultModel.m in Sources */ = {isa = PBXBuildFile; fileRef = 00F1A6012F60C11000B81234 /* FUSTicketShowCollectTicketToggleResultModel.m */; };
004773412F5EBADE00E46A79 /* FUSNewUserSevenDayCheckInControl.swift in Sources */ = {isa = PBXBuildFile; fileRef = 004773402F5EBADE00E46A79 /* FUSNewUserSevenDayCheckInControl.swift */; }; 004773412F5EBADE00E46A79 /* FUSNewUserSevenDayCheckInControl.swift in Sources */ = {isa = PBXBuildFile; fileRef = 004773402F5EBADE00E46A79 /* FUSNewUserSevenDayCheckInControl.swift */; };
0089F9552D1979A900714CE3 /* FUSRegalValueUpgradeView.xib in Resources */ = {isa = PBXBuildFile; fileRef = 0089FD702D13F3460030DAA7 /* FUSRegalValueUpgradeView.xib */; }; 0089F9552D1979A900714CE3 /* FUSRegalValueUpgradeView.xib in Resources */ = {isa = PBXBuildFile; fileRef = 0089FD702D13F3460030DAA7 /* FUSRegalValueUpgradeView.xib */; };
0089FD732D13F3460030DAA7 /* FUSLiveParcelGiftAndPropsCollectionViewCell.h in Headers */ = {isa = PBXBuildFile; fileRef = 0089FD612D13F3460030DAA7 /* FUSLiveParcelGiftAndPropsCollectionViewCell.h */; }; 0089FD732D13F3460030DAA7 /* FUSLiveParcelGiftAndPropsCollectionViewCell.h in Headers */ = {isa = PBXBuildFile; fileRef = 0089FD612D13F3460030DAA7 /* FUSLiveParcelGiftAndPropsCollectionViewCell.h */; };
...@@ -1332,6 +1330,8 @@ ...@@ -1332,6 +1330,8 @@
BECF744D2D30C76A00F5ABBC /* FUSLiveBeforeReadyModel.m in Sources */ = {isa = PBXBuildFile; fileRef = BECF744B2D30C76A00F5ABBC /* FUSLiveBeforeReadyModel.m */; }; BECF744D2D30C76A00F5ABBC /* FUSLiveBeforeReadyModel.m in Sources */ = {isa = PBXBuildFile; fileRef = BECF744B2D30C76A00F5ABBC /* FUSLiveBeforeReadyModel.m */; };
BECF74502D30C7BF00F5ABBC /* FUSBeforeLiveCondModel.h in Headers */ = {isa = PBXBuildFile; fileRef = BECF744E2D30C7BF00F5ABBC /* FUSBeforeLiveCondModel.h */; }; BECF74502D30C7BF00F5ABBC /* FUSBeforeLiveCondModel.h in Headers */ = {isa = PBXBuildFile; fileRef = BECF744E2D30C7BF00F5ABBC /* FUSBeforeLiveCondModel.h */; };
BECF74512D30C7BF00F5ABBC /* FUSBeforeLiveCondModel.m in Sources */ = {isa = PBXBuildFile; fileRef = BECF744F2D30C7BF00F5ABBC /* FUSBeforeLiveCondModel.m */; }; BECF74512D30C7BF00F5ABBC /* FUSBeforeLiveCondModel.m in Sources */ = {isa = PBXBuildFile; fileRef = BECF744F2D30C7BF00F5ABBC /* FUSBeforeLiveCondModel.m */; };
00F7FF402F9A200100AAAA01 /* FUSTicketShowCollectTicketToggleResultModel.h in Headers */ = {isa = PBXBuildFile; fileRef = 00F7FF3E2F9A200100AAAA01 /* FUSTicketShowCollectTicketToggleResultModel.h */; };
00F7FF412F9A200100AAAA02 /* FUSTicketShowCollectTicketToggleResultModel.m in Sources */ = {isa = PBXBuildFile; fileRef = 00F7FF3F2F9A200100AAAA02 /* FUSTicketShowCollectTicketToggleResultModel.m */; };
BED6554A2C5B6BF300668116 /* FUSShowRoomRouter.h in Headers */ = {isa = PBXBuildFile; fileRef = BED655482C5B6BF300668116 /* FUSShowRoomRouter.h */; }; BED6554A2C5B6BF300668116 /* FUSShowRoomRouter.h in Headers */ = {isa = PBXBuildFile; fileRef = BED655482C5B6BF300668116 /* FUSShowRoomRouter.h */; };
BED6554B2C5B6BF300668116 /* FUSShowRoomRouter.m in Sources */ = {isa = PBXBuildFile; fileRef = BED655492C5B6BF300668116 /* FUSShowRoomRouter.m */; }; BED6554B2C5B6BF300668116 /* FUSShowRoomRouter.m in Sources */ = {isa = PBXBuildFile; fileRef = BED655492C5B6BF300668116 /* FUSShowRoomRouter.m */; };
BED658692C5B745E00668116 /* FUSZhaixinRecommendedViewController.h in Headers */ = {isa = PBXBuildFile; fileRef = BED655552C5B745D00668116 /* FUSZhaixinRecommendedViewController.h */; }; BED658692C5B745E00668116 /* FUSZhaixinRecommendedViewController.h in Headers */ = {isa = PBXBuildFile; fileRef = BED655552C5B745D00668116 /* FUSZhaixinRecommendedViewController.h */; };
...@@ -1457,6 +1457,14 @@ ...@@ -1457,6 +1457,14 @@
BEA1B2C62F7A111100ABCDEF /* FUSLiveRoomThemePopView.m in Sources */ = {isa = PBXBuildFile; fileRef = BEA1B2C42F7A111100ABCDEF /* FUSLiveRoomThemePopView.m */; }; BEA1B2C62F7A111100ABCDEF /* FUSLiveRoomThemePopView.m in Sources */ = {isa = PBXBuildFile; fileRef = BEA1B2C42F7A111100ABCDEF /* FUSLiveRoomThemePopView.m */; };
BEF6C0BB2F0A1D3A0033D4E5 /* FUSLiveShowTimeCollectFrostedView.h in Headers */ = {isa = PBXBuildFile; fileRef = BEF6C0B92F0A1D3A0033D4E5 /* FUSLiveShowTimeCollectFrostedView.h */; }; BEF6C0BB2F0A1D3A0033D4E5 /* FUSLiveShowTimeCollectFrostedView.h in Headers */ = {isa = PBXBuildFile; fileRef = BEF6C0B92F0A1D3A0033D4E5 /* FUSLiveShowTimeCollectFrostedView.h */; };
BEF6C0BC2F0A1D3A0033D4E5 /* FUSLiveShowTimeCollectFrostedView.m in Sources */ = {isa = PBXBuildFile; fileRef = BEF6C0BA2F0A1D3A0033D4E5 /* FUSLiveShowTimeCollectFrostedView.m */; }; BEF6C0BC2F0A1D3A0033D4E5 /* FUSLiveShowTimeCollectFrostedView.m in Sources */ = {isa = PBXBuildFile; fileRef = BEF6C0BA2F0A1D3A0033D4E5 /* FUSLiveShowTimeCollectFrostedView.m */; };
00F7FF202F9A100100AAAA01 /* FUSLiveShowTimeTicketActionPopView.h in Headers */ = {isa = PBXBuildFile; fileRef = 00F7FF102F9A100100AAAA01 /* FUSLiveShowTimeTicketActionPopView.h */; };
00F7FF212F9A100100AAAA02 /* FUSLiveShowTimeTicketActionPopView.m in Sources */ = {isa = PBXBuildFile; fileRef = 00F7FF112F9A100100AAAA02 /* FUSLiveShowTimeTicketActionPopView.m */; };
00F7FF222F9A100100AAAA03 /* FUSLiveShowTimeTicketContributionCell.h in Headers */ = {isa = PBXBuildFile; fileRef = 00F7FF122F9A100100AAAA03 /* FUSLiveShowTimeTicketContributionCell.h */; };
00F7FF232F9A100100AAAA04 /* FUSLiveShowTimeTicketContributionCell.m in Sources */ = {isa = PBXBuildFile; fileRef = 00F7FF132F9A100100AAAA04 /* FUSLiveShowTimeTicketContributionCell.m */; };
00F7FF242F9A100100AAAA05 /* FUSLiveShowTimeTicketContributionListView.h in Headers */ = {isa = PBXBuildFile; fileRef = 00F7FF142F9A100100AAAA05 /* FUSLiveShowTimeTicketContributionListView.h */; };
00F7FF252F9A100100AAAA06 /* FUSLiveShowTimeTicketContributionListView.m in Sources */ = {isa = PBXBuildFile; fileRef = 00F7FF152F9A100100AAAA06 /* FUSLiveShowTimeTicketContributionListView.m */; };
00F7FF262F9A100100AAAA07 /* FUSLiveShowTimeTicketNoticeView.h in Headers */ = {isa = PBXBuildFile; fileRef = 00F7FF162F9A100100AAAA07 /* FUSLiveShowTimeTicketNoticeView.h */; };
00F7FF272F9A100100AAAA08 /* FUSLiveShowTimeTicketNoticeView.m in Sources */ = {isa = PBXBuildFile; fileRef = 00F7FF172F9A100100AAAA08 /* FUSLiveShowTimeTicketNoticeView.m */; };
BED658F52C5B745E00668116 /* FUSLiveBottomToolView.h in Headers */ = {isa = PBXBuildFile; fileRef = BED655F22C5B745D00668116 /* FUSLiveBottomToolView.h */; }; BED658F52C5B745E00668116 /* FUSLiveBottomToolView.h in Headers */ = {isa = PBXBuildFile; fileRef = BED655F22C5B745D00668116 /* FUSLiveBottomToolView.h */; };
BED658F62C5B745E00668116 /* FUSLiveBottomToolView.m in Sources */ = {isa = PBXBuildFile; fileRef = BED655F32C5B745D00668116 /* FUSLiveBottomToolView.m */; }; BED658F62C5B745E00668116 /* FUSLiveBottomToolView.m in Sources */ = {isa = PBXBuildFile; fileRef = BED655F32C5B745D00668116 /* FUSLiveBottomToolView.m */; };
BED658F72C5B745E00668116 /* FUSLiveChatFastInputCell.h in Headers */ = {isa = PBXBuildFile; fileRef = BED655F42C5B745D00668116 /* FUSLiveChatFastInputCell.h */; }; BED658F72C5B745E00668116 /* FUSLiveChatFastInputCell.h in Headers */ = {isa = PBXBuildFile; fileRef = BED655F42C5B745D00668116 /* FUSLiveChatFastInputCell.h */; };
...@@ -2442,8 +2450,6 @@ ...@@ -2442,8 +2450,6 @@
004773252F5C281300E46A79 /* liveRoom_newComer_gift_animate.webp */ = {isa = PBXFileReference; lastKnownFileType = file; path = liveRoom_newComer_gift_animate.webp; sourceTree = "<group>"; }; 004773252F5C281300E46A79 /* liveRoom_newComer_gift_animate.webp */ = {isa = PBXFileReference; lastKnownFileType = file; path = liveRoom_newComer_gift_animate.webp; sourceTree = "<group>"; };
004773362F5E7E7800E46A79 /* FUSGetSuccessRecommendResultModel.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = FUSGetSuccessRecommendResultModel.h; sourceTree = "<group>"; }; 004773362F5E7E7800E46A79 /* FUSGetSuccessRecommendResultModel.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = FUSGetSuccessRecommendResultModel.h; sourceTree = "<group>"; };
004773372F5E7E7800E46A79 /* FUSGetSuccessRecommendResultModel.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = FUSGetSuccessRecommendResultModel.m; sourceTree = "<group>"; }; 004773372F5E7E7800E46A79 /* FUSGetSuccessRecommendResultModel.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = FUSGetSuccessRecommendResultModel.m; sourceTree = "<group>"; };
00F1A6002F60C11000B81234 /* FUSTicketShowCollectTicketToggleResultModel.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = FUSTicketShowCollectTicketToggleResultModel.h; sourceTree = "<group>"; };
00F1A6012F60C11000B81234 /* FUSTicketShowCollectTicketToggleResultModel.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = FUSTicketShowCollectTicketToggleResultModel.m; sourceTree = "<group>"; };
004773402F5EBADE00E46A79 /* FUSNewUserSevenDayCheckInControl.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FUSNewUserSevenDayCheckInControl.swift; sourceTree = "<group>"; }; 004773402F5EBADE00E46A79 /* FUSNewUserSevenDayCheckInControl.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FUSNewUserSevenDayCheckInControl.swift; sourceTree = "<group>"; };
0089FD4A2D13F3460030DAA7 /* FUSGiftNumSelectView.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = FUSGiftNumSelectView.h; sourceTree = "<group>"; }; 0089FD4A2D13F3460030DAA7 /* FUSGiftNumSelectView.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = FUSGiftNumSelectView.h; sourceTree = "<group>"; };
0089FD4B2D13F3460030DAA7 /* FUSGiftNumSelectView.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = FUSGiftNumSelectView.m; sourceTree = "<group>"; }; 0089FD4B2D13F3460030DAA7 /* FUSGiftNumSelectView.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = FUSGiftNumSelectView.m; sourceTree = "<group>"; };
...@@ -3727,6 +3733,8 @@ ...@@ -3727,6 +3733,8 @@
BECF744B2D30C76A00F5ABBC /* FUSLiveBeforeReadyModel.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = FUSLiveBeforeReadyModel.m; sourceTree = "<group>"; }; BECF744B2D30C76A00F5ABBC /* FUSLiveBeforeReadyModel.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = FUSLiveBeforeReadyModel.m; sourceTree = "<group>"; };
BECF744E2D30C7BF00F5ABBC /* FUSBeforeLiveCondModel.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = FUSBeforeLiveCondModel.h; sourceTree = "<group>"; }; BECF744E2D30C7BF00F5ABBC /* FUSBeforeLiveCondModel.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = FUSBeforeLiveCondModel.h; sourceTree = "<group>"; };
BECF744F2D30C7BF00F5ABBC /* FUSBeforeLiveCondModel.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = FUSBeforeLiveCondModel.m; sourceTree = "<group>"; }; BECF744F2D30C7BF00F5ABBC /* FUSBeforeLiveCondModel.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = FUSBeforeLiveCondModel.m; sourceTree = "<group>"; };
00F7FF3E2F9A200100AAAA01 /* FUSTicketShowCollectTicketToggleResultModel.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = FUSTicketShowCollectTicketToggleResultModel.h; sourceTree = "<group>"; };
00F7FF3F2F9A200100AAAA02 /* FUSTicketShowCollectTicketToggleResultModel.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = FUSTicketShowCollectTicketToggleResultModel.m; sourceTree = "<group>"; };
BED655472C5B6BA300668116 /* FUSShowRoomPrefixHeader.pch */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = FUSShowRoomPrefixHeader.pch; sourceTree = "<group>"; }; BED655472C5B6BA300668116 /* FUSShowRoomPrefixHeader.pch */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = FUSShowRoomPrefixHeader.pch; sourceTree = "<group>"; };
BED655482C5B6BF300668116 /* FUSShowRoomRouter.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = FUSShowRoomRouter.h; sourceTree = "<group>"; }; BED655482C5B6BF300668116 /* FUSShowRoomRouter.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = FUSShowRoomRouter.h; sourceTree = "<group>"; };
BED655492C5B6BF300668116 /* FUSShowRoomRouter.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = FUSShowRoomRouter.m; sourceTree = "<group>"; }; BED655492C5B6BF300668116 /* FUSShowRoomRouter.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = FUSShowRoomRouter.m; sourceTree = "<group>"; };
...@@ -3864,6 +3872,14 @@ ...@@ -3864,6 +3872,14 @@
BEA1B2C42F7A111100ABCDEF /* FUSLiveRoomThemePopView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = FUSLiveRoomThemePopView.m; sourceTree = "<group>"; }; BEA1B2C42F7A111100ABCDEF /* FUSLiveRoomThemePopView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = FUSLiveRoomThemePopView.m; sourceTree = "<group>"; };
BEF6C0B92F0A1D3A0033D4E5 /* FUSLiveShowTimeCollectFrostedView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FUSLiveShowTimeCollectFrostedView.h; sourceTree = "<group>"; }; BEF6C0B92F0A1D3A0033D4E5 /* FUSLiveShowTimeCollectFrostedView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FUSLiveShowTimeCollectFrostedView.h; sourceTree = "<group>"; };
BEF6C0BA2F0A1D3A0033D4E5 /* FUSLiveShowTimeCollectFrostedView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = FUSLiveShowTimeCollectFrostedView.m; sourceTree = "<group>"; }; BEF6C0BA2F0A1D3A0033D4E5 /* FUSLiveShowTimeCollectFrostedView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = FUSLiveShowTimeCollectFrostedView.m; sourceTree = "<group>"; };
00F7FF102F9A100100AAAA01 /* FUSLiveShowTimeTicketActionPopView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FUSLiveShowTimeTicketActionPopView.h; sourceTree = "<group>"; };
00F7FF112F9A100100AAAA02 /* FUSLiveShowTimeTicketActionPopView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = FUSLiveShowTimeTicketActionPopView.m; sourceTree = "<group>"; };
00F7FF122F9A100100AAAA03 /* FUSLiveShowTimeTicketContributionCell.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FUSLiveShowTimeTicketContributionCell.h; sourceTree = "<group>"; };
00F7FF132F9A100100AAAA04 /* FUSLiveShowTimeTicketContributionCell.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = FUSLiveShowTimeTicketContributionCell.m; sourceTree = "<group>"; };
00F7FF142F9A100100AAAA05 /* FUSLiveShowTimeTicketContributionListView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FUSLiveShowTimeTicketContributionListView.h; sourceTree = "<group>"; };
00F7FF152F9A100100AAAA06 /* FUSLiveShowTimeTicketContributionListView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = FUSLiveShowTimeTicketContributionListView.m; sourceTree = "<group>"; };
00F7FF162F9A100100AAAA07 /* FUSLiveShowTimeTicketNoticeView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FUSLiveShowTimeTicketNoticeView.h; sourceTree = "<group>"; };
00F7FF172F9A100100AAAA08 /* FUSLiveShowTimeTicketNoticeView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = FUSLiveShowTimeTicketNoticeView.m; sourceTree = "<group>"; };
BED655F22C5B745D00668116 /* FUSLiveBottomToolView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FUSLiveBottomToolView.h; sourceTree = "<group>"; }; BED655F22C5B745D00668116 /* FUSLiveBottomToolView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FUSLiveBottomToolView.h; sourceTree = "<group>"; };
BED655F32C5B745D00668116 /* FUSLiveBottomToolView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = FUSLiveBottomToolView.m; sourceTree = "<group>"; }; BED655F32C5B745D00668116 /* FUSLiveBottomToolView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = FUSLiveBottomToolView.m; sourceTree = "<group>"; };
BED655F42C5B745D00668116 /* FUSLiveChatFastInputCell.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FUSLiveChatFastInputCell.h; sourceTree = "<group>"; }; BED655F42C5B745D00668116 /* FUSLiveChatFastInputCell.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FUSLiveChatFastInputCell.h; sourceTree = "<group>"; };
...@@ -6692,12 +6708,12 @@ ...@@ -6692,12 +6708,12 @@
BECF744B2D30C76A00F5ABBC /* FUSLiveBeforeReadyModel.m */, BECF744B2D30C76A00F5ABBC /* FUSLiveBeforeReadyModel.m */,
BECF744E2D30C7BF00F5ABBC /* FUSBeforeLiveCondModel.h */, BECF744E2D30C7BF00F5ABBC /* FUSBeforeLiveCondModel.h */,
BECF744F2D30C7BF00F5ABBC /* FUSBeforeLiveCondModel.m */, BECF744F2D30C7BF00F5ABBC /* FUSBeforeLiveCondModel.m */,
00F7FF3E2F9A200100AAAA01 /* FUSTicketShowCollectTicketToggleResultModel.h */,
00F7FF3F2F9A200100AAAA02 /* FUSTicketShowCollectTicketToggleResultModel.m */,
00E6CD8F2F52FA3900B63797 /* FUSLiveChatTableClickTypeRangeModel.h */, 00E6CD8F2F52FA3900B63797 /* FUSLiveChatTableClickTypeRangeModel.h */,
00E6CD902F52FA3900B63797 /* FUSLiveChatTableClickTypeRangeModel.m */, 00E6CD902F52FA3900B63797 /* FUSLiveChatTableClickTypeRangeModel.m */,
004773362F5E7E7800E46A79 /* FUSGetSuccessRecommendResultModel.h */, 004773362F5E7E7800E46A79 /* FUSGetSuccessRecommendResultModel.h */,
004773372F5E7E7800E46A79 /* FUSGetSuccessRecommendResultModel.m */, 004773372F5E7E7800E46A79 /* FUSGetSuccessRecommendResultModel.m */,
00F1A6002F60C11000B81234 /* FUSTicketShowCollectTicketToggleResultModel.h */,
00F1A6012F60C11000B81234 /* FUSTicketShowCollectTicketToggleResultModel.m */,
); );
path = Model; path = Model;
sourceTree = "<group>"; sourceTree = "<group>";
...@@ -6898,10 +6914,26 @@ ...@@ -6898,10 +6914,26 @@
BED656112C5B745D00668116 /* FUSRoomShareView.m */, BED656112C5B745D00668116 /* FUSRoomShareView.m */,
00E6CB0C2F4D523000B63797 /* FUSLiveGameListViewHeader.swift */, 00E6CB0C2F4D523000B63797 /* FUSLiveGameListViewHeader.swift */,
00E6CE1F2F56F5F200B63797 /* FUSLiveBottomToolWebpButton.swift */, 00E6CE1F2F56F5F200B63797 /* FUSLiveBottomToolWebpButton.swift */,
00F7FF302F9A100100AAAA01 /* FUSLiveShowTimeTicketActionPop */,
); );
path = ChatInputView; path = ChatInputView;
sourceTree = "<group>"; sourceTree = "<group>";
}; };
00F7FF302F9A100100AAAA01 /* FUSLiveShowTimeTicketActionPop */ = {
isa = PBXGroup;
children = (
00F7FF102F9A100100AAAA01 /* FUSLiveShowTimeTicketActionPopView.h */,
00F7FF112F9A100100AAAA02 /* FUSLiveShowTimeTicketActionPopView.m */,
00F7FF122F9A100100AAAA03 /* FUSLiveShowTimeTicketContributionCell.h */,
00F7FF132F9A100100AAAA04 /* FUSLiveShowTimeTicketContributionCell.m */,
00F7FF142F9A100100AAAA05 /* FUSLiveShowTimeTicketContributionListView.h */,
00F7FF152F9A100100AAAA06 /* FUSLiveShowTimeTicketContributionListView.m */,
00F7FF162F9A100100AAAA07 /* FUSLiveShowTimeTicketNoticeView.h */,
00F7FF172F9A100100AAAA08 /* FUSLiveShowTimeTicketNoticeView.m */,
);
name = FUSLiveShowTimeTicketActionPop;
sourceTree = "<group>";
};
BED6561B2C5B745D00668116 /* ChatTableView */ = { BED6561B2C5B745D00668116 /* ChatTableView */ = {
isa = PBXGroup; isa = PBXGroup;
children = ( children = (
...@@ -8723,6 +8755,10 @@ ...@@ -8723,6 +8755,10 @@
BEF6C0A72F0A1B2C0033D4E5 /* FUSLiveShowTimePopView.h in Headers */, BEF6C0A72F0A1B2C0033D4E5 /* FUSLiveShowTimePopView.h in Headers */,
BEA1B2C52F7A111100ABCDEF /* FUSLiveRoomThemePopView.h in Headers */, BEA1B2C52F7A111100ABCDEF /* FUSLiveRoomThemePopView.h in Headers */,
BEF6C0BB2F0A1D3A0033D4E5 /* FUSLiveShowTimeCollectFrostedView.h in Headers */, BEF6C0BB2F0A1D3A0033D4E5 /* FUSLiveShowTimeCollectFrostedView.h in Headers */,
00F7FF202F9A100100AAAA01 /* FUSLiveShowTimeTicketActionPopView.h in Headers */,
00F7FF222F9A100100AAAA03 /* FUSLiveShowTimeTicketContributionCell.h in Headers */,
00F7FF242F9A100100AAAA05 /* FUSLiveShowTimeTicketContributionListView.h in Headers */,
00F7FF262F9A100100AAAA07 /* FUSLiveShowTimeTicketNoticeView.h in Headers */,
00B28CBA2D2FC4E10008476B /* FUSLiveEndLiveAssesModel.h in Headers */, 00B28CBA2D2FC4E10008476B /* FUSLiveEndLiveAssesModel.h in Headers */,
BE189DDF2C733B460008418B /* FSRRoomManagerViewController.h in Headers */, BE189DDF2C733B460008418B /* FSRRoomManagerViewController.h in Headers */,
BED65A442C5B745F00668116 /* FUSLiveBoxDetailSettingView.h in Headers */, BED65A442C5B745F00668116 /* FUSLiveBoxDetailSettingView.h in Headers */,
...@@ -8885,6 +8921,7 @@ ...@@ -8885,6 +8921,7 @@
BED6598B2C5B745E00668116 /* FUSLiveDewIncreaseView.h in Headers */, BED6598B2C5B745E00668116 /* FUSLiveDewIncreaseView.h in Headers */,
BED658B92C5B745E00668116 /* FUSHalfWebViewCollectionViewCell.h in Headers */, BED658B92C5B745E00668116 /* FUSHalfWebViewCollectionViewCell.h in Headers */,
BECF744C2D30C76A00F5ABBC /* FUSLiveBeforeReadyModel.h in Headers */, BECF744C2D30C76A00F5ABBC /* FUSLiveBeforeReadyModel.h in Headers */,
00F7FF402F9A200100AAAA01 /* FUSTicketShowCollectTicketToggleResultModel.h in Headers */,
BED65AB62C5B745F00668116 /* FUSHomePageViewController.h in Headers */, BED65AB62C5B745F00668116 /* FUSHomePageViewController.h in Headers */,
00E6CD922F52FA3900B63797 /* FUSLiveChatTableClickTypeRangeModel.h in Headers */, 00E6CD922F52FA3900B63797 /* FUSLiveChatTableClickTypeRangeModel.h in Headers */,
BED6591D2C5B745E00668116 /* FUSBulletMessageBaseView.h in Headers */, BED6591D2C5B745E00668116 /* FUSBulletMessageBaseView.h in Headers */,
...@@ -9002,7 +9039,6 @@ ...@@ -9002,7 +9039,6 @@
00A3AB702CB665EA007646E1 /* FUSLiveQuickChatSetCell.h in Headers */, 00A3AB702CB665EA007646E1 /* FUSLiveQuickChatSetCell.h in Headers */,
BED65A3B2C5B745F00668116 /* FUSTreasureBoxOptionModel.h in Headers */, BED65A3B2C5B745F00668116 /* FUSTreasureBoxOptionModel.h in Headers */,
004773382F5E7E7800E46A79 /* FUSGetSuccessRecommendResultModel.h in Headers */, 004773382F5E7E7800E46A79 /* FUSGetSuccessRecommendResultModel.h in Headers */,
00F1A6022F60C11000B81234 /* FUSTicketShowCollectTicketToggleResultModel.h in Headers */,
BED65AC62C5B745F00668116 /* FUSBroadcastModel.h in Headers */, BED65AC62C5B745F00668116 /* FUSBroadcastModel.h in Headers */,
BED65B042C5B746000668116 /* FUSBaoFangTagView.h in Headers */, BED65B042C5B746000668116 /* FUSBaoFangTagView.h in Headers */,
BE189E132C733B460008418B /* FSREffectdictGiftShowRoomRoomGuarderView.h in Headers */, BE189E132C733B460008418B /* FSREffectdictGiftShowRoomRoomGuarderView.h in Headers */,
...@@ -10802,6 +10838,10 @@ ...@@ -10802,6 +10838,10 @@
BEF6C0A82F0A1B2C0033D4E5 /* FUSLiveShowTimePopView.m in Sources */, BEF6C0A82F0A1B2C0033D4E5 /* FUSLiveShowTimePopView.m in Sources */,
BEA1B2C62F7A111100ABCDEF /* FUSLiveRoomThemePopView.m in Sources */, BEA1B2C62F7A111100ABCDEF /* FUSLiveRoomThemePopView.m in Sources */,
BEF6C0BC2F0A1D3A0033D4E5 /* FUSLiveShowTimeCollectFrostedView.m in Sources */, BEF6C0BC2F0A1D3A0033D4E5 /* FUSLiveShowTimeCollectFrostedView.m in Sources */,
00F7FF212F9A100100AAAA02 /* FUSLiveShowTimeTicketActionPopView.m in Sources */,
00F7FF232F9A100100AAAA04 /* FUSLiveShowTimeTicketContributionCell.m in Sources */,
00F7FF252F9A100100AAAA06 /* FUSLiveShowTimeTicketContributionListView.m in Sources */,
00F7FF272F9A100100AAAA08 /* FUSLiveShowTimeTicketNoticeView.m in Sources */,
BED6599E2C5B745F00668116 /* FUSLinkMicItemView.m in Sources */, BED6599E2C5B745F00668116 /* FUSLinkMicItemView.m in Sources */,
BED658802C5B745E00668116 /* FUSLivePropsModel.m in Sources */, BED658802C5B745E00668116 /* FUSLivePropsModel.m in Sources */,
BE189DB82C733B460008418B /* FSRRoomManagerShowRoomModel.m in Sources */, BE189DB82C733B460008418B /* FSRRoomManagerShowRoomModel.m in Sources */,
...@@ -10946,6 +10986,7 @@ ...@@ -10946,6 +10986,7 @@
00BA21412D155E69000CC4C9 /* FUSLiveAgreementConfirmSectionView.m in Sources */, 00BA21412D155E69000CC4C9 /* FUSLiveAgreementConfirmSectionView.m in Sources */,
00BA21422D155E69000CC4C9 /* FUSIncomeAgreementAlertView.m in Sources */, 00BA21422D155E69000CC4C9 /* FUSIncomeAgreementAlertView.m in Sources */,
BECF744D2D30C76A00F5ABBC /* FUSLiveBeforeReadyModel.m in Sources */, BECF744D2D30C76A00F5ABBC /* FUSLiveBeforeReadyModel.m in Sources */,
00F7FF412F9A200100AAAA02 /* FUSTicketShowCollectTicketToggleResultModel.m in Sources */,
BE189E2C2C733B460008418B /* FSRLivedictRoomManagerShowRoomView.m in Sources */, BE189E2C2C733B460008418B /* FSRLivedictRoomManagerShowRoomView.m in Sources */,
BE189E162C733B460008418B /* FSREnterdictActiveMotorEffectView.m in Sources */, BE189E162C733B460008418B /* FSREnterdictActiveMotorEffectView.m in Sources */,
BED658FA2C5B745E00668116 /* FUSLiveChatFastInputView.m in Sources */, BED658FA2C5B745E00668116 /* FUSLiveChatFastInputView.m in Sources */,
...@@ -10975,7 +11016,6 @@ ...@@ -10975,7 +11016,6 @@
BED659C62C5B745F00668116 /* FUSLiveScrollView.m in Sources */, BED659C62C5B745F00668116 /* FUSLiveScrollView.m in Sources */,
BECF743F2D2FBC4500F5ABBC /* FUSLiveBitrateModel.swift in Sources */, BECF743F2D2FBC4500F5ABBC /* FUSLiveBitrateModel.swift in Sources */,
004773392F5E7E7800E46A79 /* FUSGetSuccessRecommendResultModel.m in Sources */, 004773392F5E7E7800E46A79 /* FUSGetSuccessRecommendResultModel.m in Sources */,
00F1A6032F60C11000B81234 /* FUSTicketShowCollectTicketToggleResultModel.m in Sources */,
BED6590F2C5B745E00668116 /* FUSLiveShareView.m in Sources */, BED6590F2C5B745E00668116 /* FUSLiveShareView.m in Sources */,
BE189DC02C733B460008418B /* FSRActiveMotorEffectViewController.m in Sources */, BE189DC02C733B460008418B /* FSRActiveMotorEffectViewController.m in Sources */,
BEB504702D2E8C2E00EA6E6F /* FUSLiveThemeModel+FUSRequest.m in Sources */, BEB504702D2E8C2E00EA6E6F /* FUSLiveThemeModel+FUSRequest.m in Sources */,
{
"images" : [
{
"filename" : "live_room_runBK.png",
"idiom" : "universal",
"scale" : "1x"
},
{
"filename" : "live_room_runBK@2x.png",
"idiom" : "universal",
"scale" : "2x"
},
{
"filename" : "live_room_runBK@3x.png",
"idiom" : "universal",
"scale" : "3x"
}
],
"info" : {
"author" : "xcode",
"version" : 1
}
}
{
"images" : [
{
"filename" : "live_room_ticket.png",
"idiom" : "universal",
"scale" : "1x"
},
{
"filename" : "live_room_ticket@2x.png",
"idiom" : "universal",
"scale" : "2x"
},
{
"filename" : "live_room_ticket@3x.png",
"idiom" : "universal",
"scale" : "3x"
}
],
"info" : {
"author" : "xcode",
"version" : 1
}
}
...@@ -31,10 +31,12 @@ ...@@ -31,10 +31,12 @@
#import "FUSLiveShowTimePopView.h" #import "FUSLiveShowTimePopView.h"
#import "FUSLiveShowTimeCollectFrostedView.h" #import "FUSLiveShowTimeCollectFrostedView.h"
#import "FUSLiveRoomThemePopView.h" #import "FUSLiveRoomThemePopView.h"
#import "FUSLiveShowTimeTicketActionPopView.h"
#import "FUSLiveFunctionLayerView.h" #import "FUSLiveFunctionLayerView.h"
#import <FUSFoundation/FUSFoundation-Swift.h> #import <FUSFoundation/FUSFoundation-Swift.h>
#import <FUSCommon/FUSCommon-Swift.h> #import <FUSCommon/FUSCommon-Swift.h>
#import "FUSShowRoomModule/FUSShowRoomModule-Swift.h"
@interface FUSLiveChatInputHelper () @interface FUSLiveChatInputHelper ()
...@@ -51,10 +53,24 @@ ...@@ -51,10 +53,24 @@
// 限时表演集票磨砂条:由工具栏点击触发创建,用于后续 socket 刷新进度/新票 // 限时表演集票磨砂条:由工具栏点击触发创建,用于后续 socket 刷新进度/新票
@property (nonatomic, strong) FUSLiveShowTimeCollectFrostedView *showTimeFrostedView; @property (nonatomic, strong) FUSLiveShowTimeCollectFrostedView *showTimeFrostedView;
/// 限时表演集票回合 ID(用于接口请求与回合一致性校验)
@property (nonatomic, copy) NSString *showTimeRoundId; @property (nonatomic, copy) NSString *showTimeRoundId;
/// 最新一次接口/推送同步到的已集票数(用于进度计算与“新票数”兜底)
@property (nonatomic, assign) NSInteger showTimeLastFinalTicketNum; @property (nonatomic, assign) NSInteger showTimeLastFinalTicketNum;
/// 弹窗右上角倒计时剩余秒数(外部传入,弹窗内部保持自减)
@property (nonatomic, assign) NSInteger showTimeCountdownRemainSeconds;
/// 本轮目标票数(用于已集票数展示与“还差 N 张”计算)
@property (nonatomic, assign) NSInteger showTimeTargetTicketNum;
/// 当前阶段状态(0:集票中 1:待表演 2:表演中 9999:已结束)
@property (nonatomic, assign) NSInteger showTimeStageStatus;
/// 抢当 MVP 需要购买的票数(兜底按 mvpUserNum + 1 计算)
@property (nonatomic, assign) NSInteger showTimeMvpNeedTicketCount;
@end @end
@implementation FUSLiveChatInputHelper @implementation FUSLiveChatInputHelper
...@@ -69,6 +85,10 @@ ...@@ -69,6 +85,10 @@
_chatInputView.delegate = self; _chatInputView.delegate = self;
_isBeautyFace = YES; _isBeautyFace = YES;
_showTimeLastFinalTicketNum = -1; _showTimeLastFinalTicketNum = -1;
_showTimeCountdownRemainSeconds = -1;
_showTimeTargetTicketNum = -1;
_showTimeStageStatus = -1;
_showTimeMvpNeedTicketCount = -1;
[self registerReceiptNotification]; [self registerReceiptNotification];
...@@ -77,6 +97,35 @@ ...@@ -77,6 +97,35 @@
return self; return self;
} }
- (void)fus_presentShowTimeTicketActionPopupFromBar:(FUSLiveShowTimeCollectFrostedView *)bar {
UIView *containerView = [[FUSLiveHelper shareInstance].currentFunctionView fus_viewWithLayer:FUSLiveFunctionLayerManualPopView];
if (!containerView) {
containerView = [UIViewController fus_topViewController].view;
}
if (!containerView) return;
FUSLiveShowTimeTicketActionEntryType entryType = FUSLiveShowTimeTicketActionEntryTypeBuy;
if ([bar.actionTitle isEqualToString:[NSString fus_localString:@"抢当MVP"]]) {
entryType = FUSLiveShowTimeTicketActionEntryTypeGrabMVP;
}
FUSLiveShowTimeTicketActionPopView *popView = [FUSLiveShowTimeTicketActionPopView fus_showOnView:containerView entryType:entryType];
popView.mainActionTitle = (self.showTimeStageStatus == 2 ? [NSString fus_localString:@"支持主播"] : [NSString fus_localString:@"进入限时表演"]);
[popView fus_updateStageStatus:self.showTimeStageStatus];
[popView fus_updateCountdownRemainingSeconds:self.showTimeCountdownRemainSeconds];
[popView fus_updateCollectedTicketCount:self.showTimeLastFinalTicketNum targetTicketCount:self.showTimeTargetTicketNum];
NSInteger remaining = -1;
if (self.showTimeTargetTicketNum > 0 && self.showTimeLastFinalTicketNum >= 0) {
remaining = MAX(0, self.showTimeTargetTicketNum - self.showTimeLastFinalTicketNum);
}
[popView fus_updateRemainingTicketCount:remaining mvpNeedTicketCount:self.showTimeMvpNeedTicketCount];
popView.confirmHandler = ^(FUSLiveShowTimeTicketPurchaseOption option) {
[FUSDialogView fus_showDialog:[NSString fus_localString:@"购票接口未接入"]];
};
}
#pragma mark - Getter #pragma mark - Getter
#pragma mark - Notification #pragma mark - Notification
// 注册消息回执通知 // 注册消息回执通知
...@@ -154,20 +203,9 @@ ...@@ -154,20 +203,9 @@
FUSTicketShowCollectTicketToggleResultModel *model = [FUSTicketShowCollectTicketToggleResultModel fus_modelWithDict:payload]; FUSTicketShowCollectTicketToggleResultModel *model = [FUSTicketShowCollectTicketToggleResultModel fus_modelWithDict:payload];
dispatch_async(dispatch_get_main_queue(), ^{ dispatch_async(dispatch_get_main_queue(), ^{
// 优先复用已有磨砂条所在容器;否则按直播间层级兜底找一个合适的展示层 UIView *onView = self.showTimeFrostedView.superview ?: [[FUSLiveHelper shareInstance].currentFunctionView fus_viewWithLayer:FUSLiveFunctionLayerFunctionButtons];
UIView *onView = self.showTimeFrostedView.superview; if (!onView) onView = [UIViewController fus_topViewController].view;
if (!onView) { if (!onView) return;
onView = [[FUSLiveHelper shareInstance].currentFunctionView fus_viewWithLayer:FUSLiveFunctionLayerFunctionButtons];
}
if (!onView) {
onView = [FUSLiveHelper shareInstance].currentLiveVCView;
}
if (!onView) {
onView = [UIViewController fus_topViewController].view;
}
if (!onView) {
return;
}
FUSLiveShowTimeCollectFrostedView *bar = [FUSLiveShowTimeCollectFrostedView fus_showOnView:onView]; FUSLiveShowTimeCollectFrostedView *bar = [FUSLiveShowTimeCollectFrostedView fus_showOnView:onView];
self.showTimeFrostedView = bar; self.showTimeFrostedView = bar;
...@@ -178,6 +216,7 @@ ...@@ -178,6 +216,7 @@
NSString *incomingRoundId = (model.stageData.roundId.length > 0 ? model.stageData.roundId : model.roundId); NSString *incomingRoundId = (model.stageData.roundId.length > 0 ? model.stageData.roundId : model.roundId);
self.showTimeRoundId = (incomingRoundId.length > 0 ? incomingRoundId : @""); self.showTimeRoundId = (incomingRoundId.length > 0 ? incomingRoundId : @"");
NSInteger stageStatus = (model.stageData ? model.stageData.showStatus : model.showStatus); NSInteger stageStatus = (model.stageData ? model.stageData.showStatus : model.showStatus);
self.showTimeStageStatus = stageStatus;
if (FUSLiveHelper.shareInstance.liveType == FUSLiveTypeAnchor) { if (FUSLiveHelper.shareInstance.liveType == FUSLiveTypeAnchor) {
bar.displayMode = FUSLiveShowTimeCollectFrostedDisplayModeAnchor; bar.displayMode = FUSLiveShowTimeCollectFrostedDisplayModeAnchor;
...@@ -234,12 +273,13 @@ ...@@ -234,12 +273,13 @@
if (!strongSelf) { if (!strongSelf) {
return; return;
} }
[FUSDialogView fus_showDialog:[NSString fus_localString:@"购票接口未接入"]]; [strongSelf fus_presentShowTimeTicketActionPopupFromBar:bar];
}; };
} }
NSInteger target = MAX(0, model.targetTicketNum); NSInteger target = MAX(0, model.targetTicketNum);
NSInteger finalNum = MAX(0, model.finalTicketNum); NSInteger finalNum = MAX(0, model.finalTicketNum);
self.showTimeTargetTicketNum = target;
NSInteger remaining = MAX(0, target - finalNum); NSInteger remaining = MAX(0, target - finalNum);
CGFloat progress = (target > 0 ? ((CGFloat)finalNum / (CGFloat)target) : 0); CGFloat progress = (target > 0 ? ((CGFloat)finalNum / (CGFloat)target) : 0);
NSString *remainingText = [NSString stringWithFormat:[NSString fus_localString:@"还差 %zd 张!"], (NSInteger)remaining]; NSString *remainingText = [NSString stringWithFormat:[NSString fus_localString:@"还差 %zd 张!"], (NSInteger)remaining];
...@@ -251,6 +291,12 @@ ...@@ -251,6 +291,12 @@
} }
self.showTimeLastFinalTicketNum = finalNum; self.showTimeLastFinalTicketNum = finalNum;
NSInteger mvpNeed = -1;
if (model.mvpInfo && [NSString stringWithObject:model.mvpInfo.mvpUserId].length > 0) {
mvpNeed = MAX(0, (NSInteger)model.mvpInfo.mvpUserNum + 1);
}
self.showTimeMvpNeedTicketCount = mvpNeed;
FUSOnlineUserModel *giftUser = model.buyUser; FUSOnlineUserModel *giftUser = model.buyUser;
if (!giftUser) { if (!giftUser) {
NSDictionary *giftUserDict = nil; NSDictionary *giftUserDict = nil;
...@@ -282,6 +328,7 @@ ...@@ -282,6 +328,7 @@
if (durationMs > 0 && remainMs >= 0 && remainMs <= durationMs) { if (durationMs > 0 && remainMs >= 0 && remainMs <= durationMs) {
remainSeconds = (NSInteger)llround(((NSTimeInterval)remainMs) / 1000.0); remainSeconds = (NSInteger)llround(((NSTimeInterval)remainMs) / 1000.0);
} }
self.showTimeCountdownRemainSeconds = remainSeconds;
[bar fus_updateAudienceWithState:showState [bar fus_updateAudienceWithState:showState
themeText:themeText themeText:themeText
progress:progress progress:progress
...@@ -1069,19 +1116,8 @@ ...@@ -1069,19 +1116,8 @@
return; return;
} }
UIView *onView = self.showTimeFrostedView.superview; UIView *onView = [[FUSLiveHelper shareInstance].currentFunctionView fus_viewWithLayer:FUSLiveFunctionLayerFunctionButtons];
if (!onView) {
onView = [[FUSLiveHelper shareInstance].currentFunctionView fus_viewWithLayer:FUSLiveFunctionLayerFunctionButtons];
}
if (!onView) {
onView = [FUSLiveHelper shareInstance].currentLiveVCView;
}
if (!onView) {
onView = [UIViewController fus_topViewController].view;
}
if (!onView) {
return;
}
FUSLiveShowTimeCollectFrostedView *bar = [FUSLiveShowTimeCollectFrostedView fus_showOnView:onView]; FUSLiveShowTimeCollectFrostedView *bar = [FUSLiveShowTimeCollectFrostedView fus_showOnView:onView];
self.showTimeFrostedView = bar; self.showTimeFrostedView = bar;
...@@ -1090,12 +1126,17 @@ ...@@ -1090,12 +1126,17 @@
bar.stageStatus = 0; bar.stageStatus = 0;
bar.actionTitle = [NSString fus_localString:@"购票支持"]; bar.actionTitle = [NSString fus_localString:@"购票支持"];
__weak typeof(self) weakSelf = self; __weak typeof(self) weakSelf = self;
__weak typeof(bar) weakBar = bar;
bar.actionHandler = ^{ bar.actionHandler = ^{
__strong typeof(weakSelf) strongSelf = weakSelf; __strong typeof(weakSelf) strongSelf = weakSelf;
if (!strongSelf) { if (!strongSelf) {
return; return;
} }
[FUSDialogView fus_showDialog:[NSString fus_localString:@"购票接口未接入"]]; __strong typeof(weakBar) strongBar = weakBar;
if (!strongBar) {
return;
}
[strongSelf fus_presentShowTimeTicketActionPopupFromBar:strongBar];
}; };
NSString *themeText = (![NSString isNull:roomInfoModel.introduce] ? roomInfoModel.introduce : [NSString fus_localString:@"限时表演"]); NSString *themeText = (![NSString isNull:roomInfoModel.introduce] ? roomInfoModel.introduce : [NSString fus_localString:@"限时表演"]);
...@@ -1139,6 +1180,7 @@ ...@@ -1139,6 +1180,7 @@
[strongSelf fus_destroyShowTimeFrostedIfNeeded]; [strongSelf fus_destroyShowTimeFrostedIfNeeded];
return; return;
} }
strongSelf.showTimeStageStatus = stageStatus;
NSString *incomingRoundId = (model.stageData.roundId.length > 0 ? model.stageData.roundId : model.roundId); NSString *incomingRoundId = (model.stageData.roundId.length > 0 ? model.stageData.roundId : model.roundId);
strongSelf.showTimeRoundId = (incomingRoundId.length > 0 ? incomingRoundId : @""); strongSelf.showTimeRoundId = (incomingRoundId.length > 0 ? incomingRoundId : @"");
...@@ -1146,6 +1188,13 @@ ...@@ -1146,6 +1188,13 @@
NSInteger target = MAX(0, model.targetTicketNum); NSInteger target = MAX(0, model.targetTicketNum);
NSInteger finalNum = MAX(0, model.finalTicketNum); NSInteger finalNum = MAX(0, model.finalTicketNum);
strongSelf.showTimeLastFinalTicketNum = finalNum; strongSelf.showTimeLastFinalTicketNum = finalNum;
strongSelf.showTimeTargetTicketNum = target;
NSInteger mvpNeed = -1;
if (model.mvpInfo && [NSString stringWithObject:model.mvpInfo.mvpUserId].length > 0) {
mvpNeed = MAX(0, (NSInteger)model.mvpInfo.mvpUserNum + 1);
}
strongSelf.showTimeMvpNeedTicketCount = mvpNeed;
if (target <= 0) { if (target <= 0) {
return; return;
...@@ -1173,6 +1222,7 @@ ...@@ -1173,6 +1222,7 @@
if (durationMs > 0 && remainMs >= 0 && remainMs <= durationMs) { if (durationMs > 0 && remainMs >= 0 && remainMs <= durationMs) {
remainSeconds = (NSInteger)llround(((NSTimeInterval)remainMs) / 1000.0); remainSeconds = (NSInteger)llround(((NSTimeInterval)remainMs) / 1000.0);
} }
strongSelf.showTimeCountdownRemainSeconds = remainSeconds;
FUSLiveShowTimeCollectFrostedState showState = (finalNum >= target ? FUSLiveShowTimeCollectFrostedStateCompleted : FUSLiveShowTimeCollectFrostedStateStarted); FUSLiveShowTimeCollectFrostedState showState = (finalNum >= target ? FUSLiveShowTimeCollectFrostedStateCompleted : FUSLiveShowTimeCollectFrostedStateStarted);
[currentBar fus_updateAudienceWithState:showState [currentBar fus_updateAudienceWithState:showState
......
#import <UIKit/UIKit.h>
NS_ASSUME_NONNULL_BEGIN
/// “限时表演”观众端:购票入口弹窗(从底部上滑展示)
@interface FUSLiveShowTimeTicketActionPopView : UIView
/// 弹窗入口类型(用于默认选中项/顶部标识态)
typedef NS_ENUM(NSInteger, FUSLiveShowTimeTicketActionEntryType) {
/// 从“购票选秀/购票支持”入口进入
FUSLiveShowTimeTicketActionEntryTypeBuy = 1,
/// 从“抢当MVP”入口进入
FUSLiveShowTimeTicketActionEntryTypeGrabMVP = 2,
};
/// 购票选项
typedef NS_ENUM(NSInteger, FUSLiveShowTimeTicketPurchaseOption) {
/// 选择 1 张票
FUSLiveShowTimeTicketPurchaseOptionOneTicket = 0,
/// 补全所有票
FUSLiveShowTimeTicketPurchaseOptionFillAllTickets = 1,
/// 购买“抢当 MVP 所需”的票数
FUSLiveShowTimeTicketPurchaseOptionMVPRequiredTickets = 2,
};
/// 在指定容器上展示弹窗
/// @param onView 承载弹窗的父视图
/// @param entryType 入口类型(用于默认选中项/顶部标识态)
+ (instancetype)fus_showOnView:(UIView *)onView entryType:(FUSLiveShowTimeTicketActionEntryType)entryType;
/// 当前入口类型(外部只读,便于埋点/判断)
@property (nonatomic, assign, readonly) FUSLiveShowTimeTicketActionEntryType entryType;
/// 当前选中的购票选项
@property (nonatomic, assign) FUSLiveShowTimeTicketPurchaseOption selectedOption;
/// 更新底部主按钮文案(例如“确认购买”“支持主播”)
@property (nonatomic, copy, nullable) NSString *mainActionTitle;
/// 点击底部主按钮回调(由外部决定具体业务行为)
/// @param option 当前选中的购票选项
@property (nonatomic, copy, nullable) void (^confirmHandler)(FUSLiveShowTimeTicketPurchaseOption option);
/// 更新“补全所有票/抢当MVP所需”的票数显示
/// @param remainingTicketCount 还差多少张票(<0 表示未知,不展示)
/// @param mvpNeedTicketCount 抢当MVP需要多少张票(<0 表示未知,不展示)
- (void)fus_updateRemainingTicketCount:(NSInteger)remainingTicketCount
mvpNeedTicketCount:(NSInteger)mvpNeedTicketCount;
/// 更新“票的贡献”列表数据
/// @param contributionList 元素建议包含:nickname/face/ticketCount(字段缺失会兜底空展示)
- (void)fus_updateContributionList:(NSArray<NSDictionary *> *)contributionList;
/// 更新顶部“已集票数”显示
/// @param currentTicketCount 已集票数(<0 表示未知)
/// @param targetTicketCount 目标票数(<=0 表示未知)
- (void)fus_updateCollectedTicketCount:(NSInteger)currentTicketCount
targetTicketCount:(NSInteger)targetTicketCount;
/// 更新阶段状态(用于展示“精彩限时表演中”等样式)
/// @param stageStatus 0:集票中 1:待表演 2:表演中 9999:已结束
- (void)fus_updateStageStatus:(NSInteger)stageStatus;
/// 更新右上角倒计时
/// @param remainingSeconds 剩余秒数;<0 表示不展示倒计时
- (void)fus_updateCountdownRemainingSeconds:(NSInteger)remainingSeconds;
/// 主动关闭弹窗(会带动画并移除)
- (void)fus_dismiss;
@end
NS_ASSUME_NONNULL_END
#import "FUSLiveShowTimeTicketActionPopView.h"
#import <FUSCommon/FUSCommon.h>
#import <FUSFoundation/FUSFoundation.h>
#import <Masonry/Masonry.h>
#import "FUSShowRoomCenterBunble.h"
#import "FUSLiveShowTimeTicketContributionListView.h"
#import "FUSLiveShowTimeTicketNoticeView.h"
@interface FUSLiveShowTimeTicketOptionCardView : UIControl
/// 选择框卡片容器(负责圆角/描边的选中态展示)
@property (nonatomic, strong) UIView *cardView;
/// 票券图标(资源:live_room_ticket)
@property (nonatomic, strong) UIImageView *ticketImageView;
/// 票数文本(示例:x1 / x10)
@property (nonatomic, strong) UILabel *countLabel;
/// 价格前置小圆点(视觉分隔)
@property (nonatomic, strong) UIView *priceDotView;
/// 价格文本(示例:100)
@property (nonatomic, strong) UILabel *priceLabel;
/// 价格区域容器(用于让小圆点与价格文本整体居中)
@property (nonatomic, strong) UIView *priceContainerView;
/// 贴附标签按钮(示例:直接开始/抢当MVP,背景:live_room_runBK)
@property (nonatomic, strong) UIButton *tagButton;
@end
@implementation FUSLiveShowTimeTicketOptionCardView
- (instancetype)initWithFrame:(CGRect)frame {
self = [super initWithFrame:frame];
if (!self) {
return nil;
}
self.backgroundColor = UIColor.clearColor;
self.cardView = [[UIView alloc] initWithFrame:CGRectZero];
self.cardView.backgroundColor = UIColor.whiteColor;
self.cardView.layer.cornerRadius = 10;
self.cardView.layer.masksToBounds = YES;
self.cardView.layer.borderWidth = 1;
self.cardView.layer.borderColor = [UIColor colorWithHex:@"#E6E8EB"].CGColor;
self.cardView.userInteractionEnabled = NO;
[self addSubview:self.cardView];
self.ticketImageView = [[UIImageView alloc] initWithFrame:CGRectZero];
self.ticketImageView.contentMode = UIViewContentModeScaleAspectFit;
self.ticketImageView.image = [FUSShowRoomCenterBunble imageNamed:@"live_room_ticket"];
[self.cardView addSubview:self.ticketImageView];
self.countLabel = [[UILabel alloc] initWithFrame:CGRectZero];
self.countLabel.font = [UIFont fus_themeFont:12];
self.countLabel.textColor = [UIColor colorWithHex:@"#9AA0A6"];
self.countLabel.textAlignment = NSTextAlignmentCenter;
self.countLabel.text = @"x--";
[self.cardView addSubview:self.countLabel];
self.priceDotView = [[UIView alloc] initWithFrame:CGRectZero];
self.priceDotView.backgroundColor = [UIColor colorWithHex:@"#52DDE2"];
self.priceDotView.layer.cornerRadius = 3;
self.priceDotView.layer.masksToBounds = YES;
[self.cardView addSubview:self.priceDotView];
self.priceLabel = [[UILabel alloc] initWithFrame:CGRectZero];
self.priceLabel.font = [UIFont fus_themeBoldFont:12];
self.priceLabel.textColor = [UIColor colorWithHex:@"#1F1F1F"];
self.priceLabel.text = @"100";
[self.cardView addSubview:self.priceLabel];
self.priceContainerView = [[UIView alloc] initWithFrame:CGRectZero];
self.priceContainerView.backgroundColor = UIColor.clearColor;
[self.cardView addSubview:self.priceContainerView];
[self.priceContainerView addSubview:self.priceDotView];
[self.priceContainerView addSubview:self.priceLabel];
self.tagButton = [UIButton buttonWithType:UIButtonTypeCustom];
self.tagButton.hidden = YES;
self.tagButton.userInteractionEnabled = NO;
[self.tagButton setBackgroundImage:[FUSShowRoomCenterBunble imageNamed:@"live_room_runBK"] forState:UIControlStateNormal];
[self.tagButton setTitleColor:UIColor.blackColor forState:UIControlStateNormal];
self.tagButton.titleLabel.font = [UIFont fus_themeBoldFont:11];
[self addSubview:self.tagButton];
[self.cardView mas_makeConstraints:^(MASConstraintMaker *make) {
make.edges.equalTo(self);
}];
[self.ticketImageView mas_makeConstraints:^(MASConstraintMaker *make) {
make.top.equalTo(self.cardView).offset(12);
make.centerX.equalTo(self.cardView);
make.width.mas_equalTo(56);
make.height.mas_equalTo(44);
}];
[self.countLabel mas_makeConstraints:^(MASConstraintMaker *make) {
make.top.equalTo(self.ticketImageView.mas_bottom).offset(4);
make.left.right.equalTo(self.cardView);
make.height.mas_equalTo(16);
}];
[self.priceContainerView mas_makeConstraints:^(MASConstraintMaker *make) {
make.top.equalTo(self.countLabel.mas_bottom).offset(6);
make.centerX.equalTo(self.cardView);
make.height.mas_equalTo(16);
make.width.equalTo(self.priceLabel.mas_width).offset(10);
}];
[self.priceDotView mas_makeConstraints:^(MASConstraintMaker *make) {
make.left.equalTo(self.priceContainerView);
make.centerY.equalTo(self.priceContainerView);
make.width.height.mas_equalTo(6);
}];
[self.priceLabel mas_makeConstraints:^(MASConstraintMaker *make) {
make.left.equalTo(self.priceDotView.mas_right).offset(4);
make.right.equalTo(self.priceContainerView);
make.centerY.equalTo(self.priceContainerView);
make.height.mas_equalTo(16);
}];
[self.tagButton mas_makeConstraints:^(MASConstraintMaker *make) {
make.centerX.equalTo(self);
make.centerY.equalTo(self.cardView.mas_bottom);
make.width.mas_equalTo(57);
make.height.mas_equalTo(24);
}];
return self;
}
- (void)setSelected:(BOOL)selected {
[super setSelected:selected];
self.cardView.layer.borderWidth = (selected ? 1.5 : 1);
self.cardView.layer.borderColor = (selected ? [UIColor colorWithHex:@"#52DDE2"].CGColor : [UIColor colorWithHex:@"#E6E8EB"].CGColor);
}
- (void)fus_setupCountText:(NSString *)countText priceText:(NSString *)priceText tagText:(nullable NSString *)tagText {
self.countLabel.text = (countText.length > 0 ? countText : @"x--");
self.priceLabel.text = (priceText.length > 0 ? priceText : @"");
if (tagText.length > 0) {
self.tagButton.hidden = NO;
[self.tagButton setTitle:tagText forState:UIControlStateNormal];
} else {
self.tagButton.hidden = YES;
[self.tagButton setTitle:@"" forState:UIControlStateNormal];
}
[self setNeedsLayout];
}
@end
@interface FUSLiveShowTimeTicketOptionGroupView : UIView
@property (nonatomic, strong) FUSLiveShowTimeTicketOptionCardView *oneTicketOptionView;
@property (nonatomic, strong) FUSLiveShowTimeTicketOptionCardView *fillAllOptionView;
@property (nonatomic, strong) FUSLiveShowTimeTicketOptionCardView *mvpNeedOptionView;
@property (nonatomic, copy) void (^selectHandler)(FUSLiveShowTimeTicketPurchaseOption option);
- (void)fus_setSelectedOption:(FUSLiveShowTimeTicketPurchaseOption)option;
- (void)fus_updateRemainingTicketCount:(NSInteger)remainingTicketCount mvpNeedTicketCount:(NSInteger)mvpNeedTicketCount stageStatus:(NSInteger)stageStatus;
@end
@implementation FUSLiveShowTimeTicketOptionGroupView
- (instancetype)initWithFrame:(CGRect)frame {
self = [super initWithFrame:frame];
if (!self) {
return nil;
}
self.backgroundColor = UIColor.whiteColor;
self.oneTicketOptionView = [[FUSLiveShowTimeTicketOptionCardView alloc] initWithFrame:CGRectZero];
self.oneTicketOptionView.tag = FUSLiveShowTimeTicketPurchaseOptionOneTicket;
[self.oneTicketOptionView addTarget:self action:@selector(fus_onSelectOption:) forControlEvents:UIControlEventTouchUpInside];
[self addSubview:self.oneTicketOptionView];
self.fillAllOptionView = [[FUSLiveShowTimeTicketOptionCardView alloc] initWithFrame:CGRectZero];
self.fillAllOptionView.tag = FUSLiveShowTimeTicketPurchaseOptionFillAllTickets;
[self.fillAllOptionView addTarget:self action:@selector(fus_onSelectOption:) forControlEvents:UIControlEventTouchUpInside];
[self addSubview:self.fillAllOptionView];
self.mvpNeedOptionView = [[FUSLiveShowTimeTicketOptionCardView alloc] initWithFrame:CGRectZero];
self.mvpNeedOptionView.tag = FUSLiveShowTimeTicketPurchaseOptionMVPRequiredTickets;
[self.mvpNeedOptionView addTarget:self action:@selector(fus_onSelectOption:) forControlEvents:UIControlEventTouchUpInside];
[self addSubview:self.mvpNeedOptionView];
[self.oneTicketOptionView mas_makeConstraints:^(MASConstraintMaker *make) {
make.left.top.bottom.equalTo(self);
}];
[self.fillAllOptionView mas_makeConstraints:^(MASConstraintMaker *make) {
make.left.equalTo(self.oneTicketOptionView.mas_right).offset(12);
make.top.bottom.equalTo(self);
make.width.equalTo(self.oneTicketOptionView);
}];
[self.mvpNeedOptionView mas_makeConstraints:^(MASConstraintMaker *make) {
make.left.equalTo(self.fillAllOptionView.mas_right).offset(12);
make.right.top.bottom.equalTo(self);
make.width.equalTo(self.oneTicketOptionView);
}];
return self;
}
- (void)fus_onSelectOption:(UIControl *)sender {
if (![sender isKindOfClass:FUSLiveShowTimeTicketOptionCardView.class]) {
return;
}
if (self.selectHandler) {
self.selectHandler((FUSLiveShowTimeTicketPurchaseOption)sender.tag);
}
}
- (void)fus_setSelectedOption:(FUSLiveShowTimeTicketPurchaseOption)option {
self.oneTicketOptionView.selected = (option == FUSLiveShowTimeTicketPurchaseOptionOneTicket);
self.fillAllOptionView.selected = (option == FUSLiveShowTimeTicketPurchaseOptionFillAllTickets);
self.mvpNeedOptionView.selected = (option == FUSLiveShowTimeTicketPurchaseOptionMVPRequiredTickets);
}
- (void)fus_updateRemainingTicketCount:(NSInteger)remainingTicketCount mvpNeedTicketCount:(NSInteger)mvpNeedTicketCount stageStatus:(NSInteger)stageStatus {
[self.oneTicketOptionView fus_setupCountText:@"x1" priceText:@"100" tagText:nil];
NSString *fillCountText = (remainingTicketCount >= 0 ? [NSString stringWithFormat:@"x%zd", (NSInteger)MAX(0, remainingTicketCount)] : @"x--");
NSString *fillTag = (stageStatus == 2 ? @"黑票票力" : [NSString fus_localString:@"直接开始"]);
[self.fillAllOptionView fus_setupCountText:fillCountText priceText:@"100" tagText:fillTag];
NSString *mvpCountText = (mvpNeedTicketCount >= 0 ? [NSString stringWithFormat:@"x%zd", (NSInteger)MAX(0, mvpNeedTicketCount)] : @"x--");
[self.mvpNeedOptionView fus_setupCountText:mvpCountText priceText:@"100" tagText:[NSString fus_localString:@"抢当MVP"]];
}
@end
@interface FUSLiveShowTimeTicketActionPopView () <UIScrollViewDelegate>
/// 背景遮罩(点击空白处关闭)
@property (nonatomic, strong) UIButton *bgBtn;
/// 内容容器(从底部滑入)
@property (nonatomic, strong) UIView *contentView;
/// 内容容器底部约束(用于入场/退场动画)
@property (nonatomic, strong) MASConstraint *contentBottomConstraint;
/// 顶部:已集票数
@property (nonatomic, strong) UILabel *collectedLabel;
/// 右上角倒计时
@property (nonatomic, strong) UIImageView *countdownIconView;
@property (nonatomic, strong) UILabel *countdownLabel;
@property (nonatomic, assign) NSInteger countdownRemainingSeconds;
@property (nonatomic, strong) dispatch_source_t countdownTimer;
/// 购票选项区域
@property (nonatomic, strong) UIView *optionContainerView;
@property (nonatomic, strong) FUSLiveShowTimeTicketOptionGroupView *optionGroupView;
/// 下方分栏(居中二等分,不可左右滑动)
@property (nonatomic, strong) UIView *tabContainerView;
@property (nonatomic, strong) UIButton *contributionTabBtn;
@property (nonatomic, strong) UIButton *noticeTabBtn;
@property (nonatomic, strong) UIView *tabIndicatorView;
/// 分栏指示器 centerX 约束(便于动画更新)
@property (nonatomic, strong) MASConstraint *tabIndicatorCenterXConstraint;
@property (nonatomic, strong) UIScrollView *pageScrollView;
@property (nonatomic, strong) FUSLiveShowTimeTicketContributionListView *contributionListView;
@property (nonatomic, strong) FUSLiveShowTimeTicketNoticeView *noticeView;
@property (nonatomic, assign) NSInteger currentTabIndex;
/// 底部持有张数栏
@property (nonatomic, strong) UIView *bottomCountContainerView;
@property (nonatomic, strong) UIView *bottomDividerView;
@property (nonatomic, strong) UILabel *ownedPrefixLabel;
@property (nonatomic, strong) UILabel *ownedValueLabel;
@property (nonatomic, strong) UILabel *mvpBadgeLabel;
@property (nonatomic, strong) UILabel *mvpOwnedPrefixLabel;
@property (nonatomic, strong) UILabel *mvpOwnedValueLabel;
/// 主按钮
@property (nonatomic, strong) UIButton *confirmBtn;
@property (nonatomic, assign) NSInteger remainingTicketCount;
@property (nonatomic, assign) NSInteger mvpNeedTicketCount;
@property (nonatomic, assign) NSInteger collectedCurrentTicketNum;
@property (nonatomic, assign) NSInteger collectedTargetTicketNum;
@property (nonatomic, assign) NSInteger stageStatus;
@property (nonatomic, assign) NSInteger ownedTicketCount;
@property (nonatomic, assign) NSInteger mvpOwnedTicketCount;
@property (nonatomic, strong) MASConstraint *headerLabelHeightConstraint;
@end
@implementation FUSLiveShowTimeTicketActionPopView
+ (instancetype)fus_showOnView:(UIView *)onView entryType:(FUSLiveShowTimeTicketActionEntryType)entryType {
if (!onView) {
return nil;
}
FUSLiveShowTimeTicketActionPopView *view = [[FUSLiveShowTimeTicketActionPopView alloc] initWithFrame:CGRectZero entryType:entryType];
[onView addSubview:view];
[view mas_makeConstraints:^(MASConstraintMaker *make) {
make.edges.equalTo(onView);
}];
[view fus_show];
return view;
}
- (instancetype)initWithFrame:(CGRect)frame entryType:(FUSLiveShowTimeTicketActionEntryType)entryType {
self = [super initWithFrame:frame];
if (!self) {
return nil;
}
_entryType = entryType;
self.remainingTicketCount = -1;
self.mvpNeedTicketCount = -1;
self.countdownRemainingSeconds = -1;
self.collectedCurrentTicketNum = -1;
self.collectedTargetTicketNum = -1;
self.stageStatus = -1;
self.ownedTicketCount = -1;
self.mvpOwnedTicketCount = -1;
self.currentTabIndex = 0;
self.bgBtn = [UIButton buttonWithType:UIButtonTypeCustom];
self.bgBtn.backgroundColor = [UIColor colorWithWhite:0 alpha:0.35];
[self.bgBtn addTarget:self action:@selector(fus_dismiss) forControlEvents:UIControlEventTouchUpInside];
[self addSubview:self.bgBtn];
CGFloat safeBottom = UIView.fus_SafeBottom;
CGFloat maxContentH = MIN(550, UIView.fus_screenH * 0.85);
CGFloat contentH = maxContentH + safeBottom;
self.contentView = [[UIView alloc] initWithFrame:CGRectZero];
self.contentView.backgroundColor = UIColor.whiteColor;
self.contentView.layer.cornerRadius = 16;
self.contentView.layer.masksToBounds = YES;
if (@available(iOS 11.0, *)) {
self.contentView.layer.maskedCorners = kCALayerMinXMinYCorner | kCALayerMaxXMinYCorner;
}
[self addSubview:self.contentView];
CGFloat padding = 24;
self.collectedLabel = [[UILabel alloc] initWithFrame:CGRectZero];
self.collectedLabel.font = [UIFont fus_themeFont:12];
self.collectedLabel.textColor = [UIColor colorWithHex:@"#9AA0A6"];
self.collectedLabel.text = [NSString fus_localString:@"已集票数:--/--"];
[self.contentView addSubview:self.collectedLabel];
CGFloat iconW = 14;
self.countdownIconView = [[UIImageView alloc] initWithFrame:CGRectZero];
self.countdownIconView.contentMode = UIViewContentModeScaleAspectFit;
self.countdownIconView.image = [FUSShowRoomCenterBunble imageNamed:@"Live_bottom_countdown"];
self.countdownIconView.hidden = YES;
[self.contentView addSubview:self.countdownIconView];
self.countdownLabel = [[UILabel alloc] initWithFrame:CGRectZero];
self.countdownLabel.hidden = YES;
self.countdownLabel.font = [UIFont fus_themeBoldFont:12];
self.countdownLabel.textColor = [UIColor colorWithHex:@"#1F1F1F"];
self.countdownLabel.textAlignment = NSTextAlignmentLeft;
self.countdownLabel.text = @"";
[self.contentView addSubview:self.countdownLabel];
CGFloat optionH = 125;
CGFloat optionSidePadding = 12;
self.optionContainerView = [[UIView alloc] initWithFrame:CGRectZero];
self.optionContainerView.backgroundColor = UIColor.whiteColor;
[self.contentView addSubview:self.optionContainerView];
self.optionGroupView = [[FUSLiveShowTimeTicketOptionGroupView alloc] initWithFrame:CGRectZero];
__weak typeof(self) weakSelf = self;
self.optionGroupView.selectHandler = ^(FUSLiveShowTimeTicketPurchaseOption option) {
__strong typeof(weakSelf) strongSelf = weakSelf;
if (!strongSelf) {
return;
}
strongSelf.selectedOption = option;
[strongSelf fus_applyOptionSelectedUI];
};
[self.optionContainerView addSubview:self.optionGroupView];
CGFloat confirmH = 40;
self.confirmBtn = [UIButton buttonWithType:UIButtonTypeCustom];
self.confirmBtn.backgroundColor = [UIColor colorWithHex:@"#52DDE2"];
self.confirmBtn.layer.cornerRadius = confirmH / 2.0;
self.confirmBtn.layer.masksToBounds = YES;
[self.confirmBtn setTitle:[NSString fus_localString:@"进入限时表演"] forState:UIControlStateNormal];
[self.confirmBtn setTitleColor:UIColor.blackColor forState:UIControlStateNormal];
self.confirmBtn.titleLabel.font = [UIFont fus_themeBoldFont:15];
[self.confirmBtn addTarget:self action:@selector(fus_onClickConfirm) forControlEvents:UIControlEventTouchUpInside];
[self.contentView addSubview:self.confirmBtn];
self.tabContainerView = [[UIView alloc] initWithFrame:CGRectZero];
self.tabContainerView.backgroundColor = UIColor.whiteColor;
[self.contentView addSubview:self.tabContainerView];
self.contributionTabBtn = [UIButton buttonWithType:UIButtonTypeCustom];
[self.contributionTabBtn setTitle:[NSString fus_localString:@"票的贡献"] forState:UIControlStateNormal];
[self.contributionTabBtn setTitleColor:[UIColor colorWithHex:@"#1F1F1F"] forState:UIControlStateNormal];
self.contributionTabBtn.titleLabel.font = [UIFont fus_themeBoldFont:14];
[self.contributionTabBtn addTarget:self action:@selector(fus_onTapTab:) forControlEvents:UIControlEventTouchUpInside];
self.contributionTabBtn.tag = 0;
[self.tabContainerView addSubview:self.contributionTabBtn];
self.noticeTabBtn = [UIButton buttonWithType:UIButtonTypeCustom];
[self.noticeTabBtn setTitle:[NSString fus_localString:@"活动须知"] forState:UIControlStateNormal];
[self.noticeTabBtn setTitleColor:[UIColor colorWithHex:@"#9AA0A6"] forState:UIControlStateNormal];
self.noticeTabBtn.titleLabel.font = [UIFont fus_themeFont:14];
[self.noticeTabBtn addTarget:self action:@selector(fus_onTapTab:) forControlEvents:UIControlEventTouchUpInside];
self.noticeTabBtn.tag = 1;
[self.tabContainerView addSubview:self.noticeTabBtn];
self.tabIndicatorView = [[UIView alloc] initWithFrame:CGRectZero];
self.tabIndicatorView.backgroundColor = [UIColor colorWithHex:@"#1F1F1F"];
self.tabIndicatorView.layer.cornerRadius = 1;
self.tabIndicatorView.layer.masksToBounds = YES;
[self.tabContainerView addSubview:self.tabIndicatorView];
self.pageScrollView = [[UIScrollView alloc] initWithFrame:CGRectZero];
self.pageScrollView.showsVerticalScrollIndicator = NO;
self.pageScrollView.showsHorizontalScrollIndicator = NO;
self.pageScrollView.pagingEnabled = YES;
self.pageScrollView.bounces = NO;
self.pageScrollView.delegate = self;
[self.contentView addSubview:self.pageScrollView];
self.contributionListView = [[FUSLiveShowTimeTicketContributionListView alloc] initWithFrame:CGRectZero];
[self.pageScrollView addSubview:self.contributionListView];
self.noticeView = [[FUSLiveShowTimeTicketNoticeView alloc] initWithFrame:CGRectZero];
self.noticeView.noticeText = @"本活動由主播個人主辦,詳細活動辦法與內容請洽詢主播。\n集票達成或未達成主播自願表演,本活動才算成立;若集票未達成且主播不願意表演";
[self.pageScrollView addSubview:self.noticeView];
self.bottomCountContainerView = [[UIView alloc] initWithFrame:CGRectZero];
self.bottomCountContainerView.backgroundColor = [UIColor colorWithHex:@"#EDEDED"];
self.bottomCountContainerView.layer.cornerRadius = 12;
self.bottomCountContainerView.layer.masksToBounds = YES;
if (@available(iOS 11.0, *)) {
self.bottomCountContainerView.layer.maskedCorners = kCALayerMinXMinYCorner | kCALayerMaxXMinYCorner;
}
[self.contentView addSubview:self.bottomCountContainerView];
UIView *bottomCountTopContentView = [[UIView alloc] initWithFrame:CGRectZero];
bottomCountTopContentView.backgroundColor = UIColor.clearColor;
[self.bottomCountContainerView addSubview:bottomCountTopContentView];
UIView *bottomCenterSplitView = [[UIView alloc] initWithFrame:CGRectZero];
bottomCenterSplitView.backgroundColor = [UIColor colorWithHex:@"#D8D8D8"];
[bottomCountTopContentView addSubview:bottomCenterSplitView];
UIView *bottomLeftHalfView = [[UIView alloc] initWithFrame:CGRectZero];
bottomLeftHalfView.backgroundColor = UIColor.clearColor;
[bottomCountTopContentView addSubview:bottomLeftHalfView];
UIView *bottomRightHalfView = [[UIView alloc] initWithFrame:CGRectZero];
bottomRightHalfView.backgroundColor = UIColor.clearColor;
[bottomCountTopContentView addSubview:bottomRightHalfView];
UIView *bottomLeftContentView = [[UIView alloc] initWithFrame:CGRectZero];
bottomLeftContentView.backgroundColor = UIColor.clearColor;
[bottomLeftHalfView addSubview:bottomLeftContentView];
UIView *bottomRightContentView = [[UIView alloc] initWithFrame:CGRectZero];
bottomRightContentView.backgroundColor = UIColor.clearColor;
[bottomRightHalfView addSubview:bottomRightContentView];
self.bottomDividerView = [[UIView alloc] initWithFrame:CGRectZero];
self.bottomDividerView.backgroundColor = [UIColor colorWithHex:@"#F0F1F3"];
[bottomCountTopContentView addSubview:self.bottomDividerView];
self.ownedPrefixLabel = [[UILabel alloc] initWithFrame:CGRectZero];
self.ownedPrefixLabel.font = [UIFont fus_themeFont:12];
self.ownedPrefixLabel.textColor = [UIColor colorWithHex:@"#9AA0A6"];
self.ownedPrefixLabel.text = [NSString fus_localString:@"你持有张数"];
[bottomLeftContentView addSubview:self.ownedPrefixLabel];
self.ownedValueLabel = [[UILabel alloc] initWithFrame:CGRectZero];
self.ownedValueLabel.font = [UIFont fus_themeBoldFont:12];
self.ownedValueLabel.textColor = [UIColor colorWithHex:@"#52DDE2"];
self.ownedValueLabel.text = @"--";
[bottomLeftContentView addSubview:self.ownedValueLabel];
self.mvpBadgeLabel = [[UILabel alloc] initWithFrame:CGRectZero];
self.mvpBadgeLabel.textAlignment = NSTextAlignmentCenter;
self.mvpBadgeLabel.font = [UIFont fus_themeBoldFont:10];
self.mvpBadgeLabel.textColor = UIColor.blackColor;
self.mvpBadgeLabel.backgroundColor = [UIColor colorWithHex:@"#52DDE2"];
self.mvpBadgeLabel.text = @"MVP";
self.mvpBadgeLabel.layer.cornerRadius = 8;
self.mvpBadgeLabel.layer.masksToBounds = YES;
[bottomRightContentView addSubview:self.mvpBadgeLabel];
self.mvpOwnedPrefixLabel = [[UILabel alloc] initWithFrame:CGRectZero];
self.mvpOwnedPrefixLabel.font = [UIFont fus_themeFont:12];
self.mvpOwnedPrefixLabel.textColor = [UIColor colorWithHex:@"#9AA0A6"];
self.mvpOwnedPrefixLabel.text = [NSString fus_localString:@"MVP持有张数"];
[bottomRightContentView addSubview:self.mvpOwnedPrefixLabel];
self.mvpOwnedValueLabel = [[UILabel alloc] initWithFrame:CGRectZero];
self.mvpOwnedValueLabel.font = [UIFont fus_themeBoldFont:12];
self.mvpOwnedValueLabel.textColor = [UIColor colorWithHex:@"#52DDE2"];
self.mvpOwnedValueLabel.text = @"--";
[bottomRightContentView addSubview:self.mvpOwnedValueLabel];
[self.bgBtn mas_makeConstraints:^(MASConstraintMaker *make) {
make.edges.equalTo(self);
}];
[self.contentView mas_makeConstraints:^(MASConstraintMaker *make) {
make.left.right.equalTo(self);
make.height.mas_equalTo(contentH);
self.contentBottomConstraint = make.bottom.equalTo(self).offset(contentH);
}];
[self.collectedLabel mas_makeConstraints:^(MASConstraintMaker *make) {
make.top.equalTo(self.contentView).offset(20);
make.centerX.equalTo(self.contentView);
self.headerLabelHeightConstraint = make.height.mas_equalTo(18);
make.left.greaterThanOrEqualTo(self.contentView).offset(padding);
make.right.lessThanOrEqualTo(self.countdownIconView.mas_left).offset(-8);
}];
[self.countdownLabel mas_makeConstraints:^(MASConstraintMaker *make) {
make.right.equalTo(self.contentView).offset(-12);
make.centerY.equalTo(self.collectedLabel);
make.height.mas_equalTo(18);
}];
[self.countdownLabel setContentCompressionResistancePriority:UILayoutPriorityRequired forAxis:UILayoutConstraintAxisHorizontal];
[self.countdownLabel setContentHuggingPriority:UILayoutPriorityRequired forAxis:UILayoutConstraintAxisHorizontal];
[self.countdownIconView mas_makeConstraints:^(MASConstraintMaker *make) {
make.right.equalTo(self.countdownLabel.mas_left).offset(-4);
make.centerY.equalTo(self.countdownLabel);
make.width.height.mas_equalTo(iconW);
}];
[self.optionContainerView mas_makeConstraints:^(MASConstraintMaker *make) {
make.top.equalTo(self.collectedLabel.mas_bottom).offset(14);
make.left.equalTo(self.contentView).offset(optionSidePadding);
make.right.equalTo(self.contentView).offset(-optionSidePadding);
make.height.mas_equalTo(optionH);
}];
[self.optionGroupView mas_makeConstraints:^(MASConstraintMaker *make) {
make.edges.equalTo(self.optionContainerView);
}];
[self.confirmBtn mas_makeConstraints:^(MASConstraintMaker *make) {
make.top.equalTo(self.optionContainerView.mas_bottom).offset(24);
make.left.equalTo(self.contentView).offset(padding);
make.right.equalTo(self.contentView).offset(-padding);
make.height.mas_equalTo(confirmH);
}];
[self.tabContainerView mas_makeConstraints:^(MASConstraintMaker *make) {
make.top.equalTo(self.confirmBtn.mas_bottom).offset(10);
make.left.right.equalTo(self.contentView);
make.height.mas_equalTo(44);
}];
[self.contributionTabBtn mas_makeConstraints:^(MASConstraintMaker *make) {
make.left.top.bottom.equalTo(self.tabContainerView);
make.width.equalTo(self.tabContainerView).multipliedBy(0.5);
}];
[self.noticeTabBtn mas_makeConstraints:^(MASConstraintMaker *make) {
make.right.top.bottom.equalTo(self.tabContainerView);
make.width.equalTo(self.tabContainerView).multipliedBy(0.5);
}];
[self.tabIndicatorView mas_makeConstraints:^(MASConstraintMaker *make) {
make.bottom.equalTo(self.tabContainerView).offset(-12);
make.height.mas_equalTo(2);
make.width.mas_equalTo(14);
self.tabIndicatorCenterXConstraint = make.centerX.equalTo(self.contributionTabBtn);
}];
[self.bottomCountContainerView mas_makeConstraints:^(MASConstraintMaker *make) {
make.left.right.equalTo(self.contentView);
make.bottom.equalTo(self.contentView);
make.height.mas_equalTo(45 + safeBottom);
}];
[bottomCountTopContentView mas_makeConstraints:^(MASConstraintMaker *make) {
make.left.right.top.equalTo(self.bottomCountContainerView);
make.height.mas_equalTo(45);
}];
[self.bottomDividerView mas_makeConstraints:^(MASConstraintMaker *make) {
make.left.right.top.equalTo(bottomCountTopContentView);
make.height.mas_equalTo(0.5);
}];
[bottomCenterSplitView mas_makeConstraints:^(MASConstraintMaker *make) {
make.centerX.equalTo(bottomCountTopContentView);
make.centerY.equalTo(bottomCountTopContentView);
make.width.mas_equalTo(0.5);
make.height.mas_equalTo(16);
}];
[bottomLeftHalfView mas_makeConstraints:^(MASConstraintMaker *make) {
make.left.top.bottom.equalTo(bottomCountTopContentView);
make.right.equalTo(bottomCenterSplitView.mas_left);
}];
[bottomRightHalfView mas_makeConstraints:^(MASConstraintMaker *make) {
make.right.top.bottom.equalTo(bottomCountTopContentView);
make.left.equalTo(bottomCenterSplitView.mas_right);
}];
[bottomLeftContentView mas_makeConstraints:^(MASConstraintMaker *make) {
make.center.equalTo(bottomLeftHalfView);
}];
[bottomRightContentView mas_makeConstraints:^(MASConstraintMaker *make) {
make.center.equalTo(bottomRightHalfView);
}];
[self.ownedPrefixLabel mas_makeConstraints:^(MASConstraintMaker *make) {
make.left.equalTo(bottomLeftContentView);
make.centerY.equalTo(bottomLeftContentView);
}];
[self.ownedValueLabel mas_makeConstraints:^(MASConstraintMaker *make) {
make.left.equalTo(self.ownedPrefixLabel.mas_right).offset(6);
make.centerY.equalTo(bottomLeftContentView);
make.right.equalTo(bottomLeftContentView);
}];
[self.mvpBadgeLabel mas_makeConstraints:^(MASConstraintMaker *make) {
make.left.equalTo(bottomRightContentView);
make.centerY.equalTo(bottomRightContentView);
make.width.mas_equalTo(34);
make.height.mas_equalTo(16);
}];
[self.mvpOwnedPrefixLabel mas_makeConstraints:^(MASConstraintMaker *make) {
make.left.equalTo(self.mvpBadgeLabel.mas_right).offset(6);
make.centerY.equalTo(bottomRightContentView);
}];
[self.mvpOwnedValueLabel mas_makeConstraints:^(MASConstraintMaker *make) {
make.left.equalTo(self.mvpOwnedPrefixLabel.mas_right).offset(6);
make.centerY.equalTo(bottomRightContentView);
make.right.equalTo(bottomRightContentView);
}];
[self.pageScrollView mas_makeConstraints:^(MASConstraintMaker *make) {
make.left.right.equalTo(self.contentView);
make.top.equalTo(self.tabContainerView.mas_bottom);
make.bottom.equalTo(self.bottomCountContainerView.mas_top);
}];
[self.contributionListView mas_makeConstraints:^(MASConstraintMaker *make) {
make.top.bottom.left.equalTo(self.pageScrollView);
make.width.equalTo(self.pageScrollView);
make.height.equalTo(self.pageScrollView);
}];
[self.noticeView mas_makeConstraints:^(MASConstraintMaker *make) {
make.top.bottom.equalTo(self.pageScrollView);
make.left.equalTo(self.contributionListView.mas_right);
make.width.equalTo(self.pageScrollView);
make.height.equalTo(self.pageScrollView);
make.right.equalTo(self.pageScrollView);
}];
[self fus_applyEntryTypeDefaultSelection];
[self fus_applyCountsToOptionViews];
[self fus_applyBottomCountsUI];
[self fus_applyHeaderUI];
return self;
}
/// 弹窗从底部滑入
- (void)fus_show {
[self.superview layoutIfNeeded];
[self.contentBottomConstraint setOffset:0];
[UIView animateWithDuration:0.3 animations:^{
[self.superview layoutIfNeeded];
}];
}
/// 关闭弹窗并移除
- (void)fus_dismiss {
[self fus_stopCountdownTimer];
CGFloat safeBottom = UIView.fus_SafeBottom;
CGFloat maxContentH = MIN(550, UIView.fus_screenH * 0.85);
CGFloat contentH = maxContentH + safeBottom;
[self.contentBottomConstraint setOffset:contentH];
[UIView animateWithDuration:0.25 animations:^{
self.bgBtn.alpha = 0;
[self layoutIfNeeded];
} completion:^(BOOL finished) {
[self removeFromSuperview];
}];
}
- (void)dealloc {
[self fus_stopCountdownTimer];
}
- (void)setMainActionTitle:(NSString *)mainActionTitle {
_mainActionTitle = [mainActionTitle copy];
NSString *title = (_mainActionTitle.length > 0 ? _mainActionTitle : [NSString fus_localString:@"进入限时表演"]);
[self.confirmBtn setTitle:title forState:UIControlStateNormal];
}
- (void)setSelectedOption:(FUSLiveShowTimeTicketPurchaseOption)selectedOption {
_selectedOption = selectedOption;
[self fus_applyOptionSelectedUI];
}
- (void)fus_updateRemainingTicketCount:(NSInteger)remainingTicketCount
mvpNeedTicketCount:(NSInteger)mvpNeedTicketCount {
self.remainingTicketCount = remainingTicketCount;
self.mvpNeedTicketCount = mvpNeedTicketCount;
[self fus_applyCountsToOptionViews];
}
- (void)fus_updateOwnedTicketCount:(NSInteger)ownedTicketCount
mvpOwnedTicketCount:(NSInteger)mvpOwnedTicketCount {
self.ownedTicketCount = ownedTicketCount;
self.mvpOwnedTicketCount = mvpOwnedTicketCount;
[self fus_applyBottomCountsUI];
}
- (void)fus_updateContributionList:(NSArray<NSDictionary *> *)contributionList {
self.contributionListView.contributionList = (contributionList ?: @[]);
}
- (void)fus_updateCollectedTicketCount:(NSInteger)currentTicketCount targetTicketCount:(NSInteger)targetTicketCount {
self.collectedCurrentTicketNum = currentTicketCount;
self.collectedTargetTicketNum = targetTicketCount;
[self fus_applyHeaderUI];
}
- (void)fus_updateStageStatus:(NSInteger)stageStatus {
self.stageStatus = stageStatus;
if (stageStatus == 2 && self.mainActionTitle.length <= 0) {
self.mainActionTitle = [NSString fus_localString:@"支持主播"];
}
[self fus_applyCountsToOptionViews];
[self fus_applyHeaderUI];
}
- (void)fus_updateCountdownRemainingSeconds:(NSInteger)remainingSeconds {
self.countdownRemainingSeconds = remainingSeconds;
if (remainingSeconds < 0) {
self.countdownLabel.hidden = YES;
self.countdownIconView.hidden = YES;
self.countdownLabel.text = @"";
[self fus_stopCountdownTimer];
return;
}
self.countdownLabel.hidden = NO;
self.countdownIconView.hidden = NO;
[self fus_startCountdownTimerIfNeeded];
[self fus_refreshCountdownText];
}
- (void)fus_applyHeaderUI {
if (self.stageStatus == 2) {
self.collectedLabel.attributedText = nil;
self.collectedLabel.font = [UIFont fus_themeBoldFont:16];
self.collectedLabel.textColor = [UIColor colorWithHex:@"#111111"];
self.collectedLabel.textAlignment = NSTextAlignmentCenter;
self.collectedLabel.text = [NSString fus_localString:@"精彩限时表演中"];
[self.headerLabelHeightConstraint setOffset:22];
return;
}
NSInteger current = self.collectedCurrentTicketNum;
NSInteger target = self.collectedTargetTicketNum;
NSString *prefix = [NSString fus_localString:@"已集票数:"];
NSString *currentStr = (current >= 0 ? [NSString stringWithFormat:@"%zd", (NSInteger)current] : @"--");
NSString *targetStr = (target > 0 ? [NSString stringWithFormat:@"%zd", (NSInteger)target] : @"--");
NSString *full = [NSString stringWithFormat:@"%@%@/%@", prefix, currentStr, targetStr];
NSMutableAttributedString *att = [[NSMutableAttributedString alloc] initWithString:full attributes:@{
NSFontAttributeName: [UIFont fus_themeBoldFont:16],
NSForegroundColorAttributeName: [UIColor colorWithHex:@"#111111"]
}];
if (current >= 0 && currentStr.length > 0) {
NSRange currentRange = NSMakeRange(MIN(prefix.length, full.length), MIN(currentStr.length, MAX(0, full.length - prefix.length)));
if (currentRange.location + currentRange.length <= full.length) {
[att addAttribute:NSForegroundColorAttributeName value:[UIColor colorWithHex:@"#00F7FF"] range:currentRange];
}
}
self.collectedLabel.textAlignment = NSTextAlignmentCenter;
self.collectedLabel.attributedText = att;
[self.headerLabelHeightConstraint setOffset:22];
}
- (void)fus_applyEntryTypeDefaultSelection {
if (self.entryType == FUSLiveShowTimeTicketActionEntryTypeGrabMVP) {
self.selectedOption = FUSLiveShowTimeTicketPurchaseOptionMVPRequiredTickets;
} else {
self.selectedOption = FUSLiveShowTimeTicketPurchaseOptionOneTicket;
}
}
- (void)fus_applyOptionSelectedUI {
[self.optionGroupView fus_setSelectedOption:self.selectedOption];
}
- (void)fus_applyCountsToOptionViews {
[self.optionGroupView fus_updateRemainingTicketCount:self.remainingTicketCount mvpNeedTicketCount:self.mvpNeedTicketCount stageStatus:self.stageStatus];
}
- (void)fus_onSelectOption:(UIControl *)sender {
if (![sender isKindOfClass:FUSLiveShowTimeTicketOptionCardView.class]) {
return;
}
self.selectedOption = (FUSLiveShowTimeTicketPurchaseOption)sender.tag;
[self fus_applyOptionSelectedUI];
}
- (void)fus_onClickConfirm {
if (self.confirmHandler) {
self.confirmHandler(self.selectedOption);
}
[self fus_dismiss];
}
#pragma mark - 分栏
- (void)fus_onTapTab:(UIButton *)sender {
NSInteger index = sender.tag;
CGFloat width = CGRectGetWidth(self.pageScrollView.bounds);
if (width <= 0) {
[self layoutIfNeeded];
width = CGRectGetWidth(self.pageScrollView.bounds);
}
[self.pageScrollView setContentOffset:CGPointMake(index * width, 0) animated:YES];
}
- (void)fus_applyTabSelectedIndex:(NSInteger)index {
BOOL showNotice = (index == 1);
if (showNotice) {
[self.noticeTabBtn setTitleColor:[UIColor colorWithHex:@"#1F1F1F"] forState:UIControlStateNormal];
self.noticeTabBtn.titleLabel.font = [UIFont fus_themeBoldFont:14];
[self.contributionTabBtn setTitleColor:[UIColor colorWithHex:@"#9AA0A6"] forState:UIControlStateNormal];
self.contributionTabBtn.titleLabel.font = [UIFont fus_themeFont:14];
} else {
[self.contributionTabBtn setTitleColor:[UIColor colorWithHex:@"#1F1F1F"] forState:UIControlStateNormal];
self.contributionTabBtn.titleLabel.font = [UIFont fus_themeBoldFont:14];
[self.noticeTabBtn setTitleColor:[UIColor colorWithHex:@"#9AA0A6"] forState:UIControlStateNormal];
self.noticeTabBtn.titleLabel.font = [UIFont fus_themeFont:14];
}
[self.tabIndicatorCenterXConstraint uninstall];
[self.tabIndicatorView mas_updateConstraints:^(MASConstraintMaker *make) {
self.tabIndicatorCenterXConstraint = make.centerX.equalTo(showNotice ? self.noticeTabBtn : self.contributionTabBtn);
}];
[self layoutIfNeeded];
[UIView animateWithDuration:0.2 animations:^{
[self layoutIfNeeded];
}];
}
#pragma mark - UIScrollViewDelegate
- (void)scrollViewDidEndDecelerating:(UIScrollView *)scrollView {
[self fus_syncTabIndexFromScrollView:scrollView];
}
- (void)scrollViewDidEndScrollingAnimation:(UIScrollView *)scrollView {
[self fus_syncTabIndexFromScrollView:scrollView];
}
- (void)fus_syncTabIndexFromScrollView:(UIScrollView *)scrollView {
CGFloat width = CGRectGetWidth(scrollView.bounds);
if (width <= 0) {
return;
}
NSInteger page = (NSInteger)((scrollView.contentOffset.x + width * 0.5) / width);
page = MAX(0, MIN(1, page));
if (page == self.currentTabIndex) {
return;
}
self.currentTabIndex = page;
[self fus_applyTabSelectedIndex:page];
}
- (void)fus_applyBottomCountsUI {
self.ownedValueLabel.text = (self.ownedTicketCount >= 0 ? [NSString stringWithFormat:@"%zd", (NSInteger)MAX(0, self.ownedTicketCount)] : @"--");
self.mvpOwnedValueLabel.text = (self.mvpOwnedTicketCount >= 0 ? [NSString stringWithFormat:@"%zd", (NSInteger)MAX(0, self.mvpOwnedTicketCount)] : @"--");
}
#pragma mark - 倒计时
- (void)fus_startCountdownTimerIfNeeded {
if (self.countdownRemainingSeconds < 0) {
[self fus_stopCountdownTimer];
return;
}
if (self.countdownTimer) {
return;
}
__weak typeof(self) weakSelf = self;
dispatch_queue_t queue = dispatch_get_main_queue();
dispatch_source_t timer = dispatch_source_create(DISPATCH_SOURCE_TYPE_TIMER, 0, 0, queue);
self.countdownTimer = timer;
dispatch_source_set_timer(timer, DISPATCH_TIME_NOW, (uint64_t)(1.0 * NSEC_PER_SEC), (uint64_t)(0.05 * NSEC_PER_SEC));
dispatch_source_set_event_handler(timer, ^{
__strong typeof(weakSelf) strongSelf = weakSelf;
if (!strongSelf) {
return;
}
if (strongSelf.countdownRemainingSeconds <= 0) {
[strongSelf fus_refreshCountdownText];
[strongSelf fus_stopCountdownTimer];
return;
}
strongSelf.countdownRemainingSeconds = MAX(0, strongSelf.countdownRemainingSeconds - 1);
[strongSelf fus_refreshCountdownText];
});
dispatch_resume(timer);
}
- (void)fus_stopCountdownTimer {
if (self.countdownTimer) {
dispatch_source_cancel(self.countdownTimer);
self.countdownTimer = nil;
}
}
- (void)fus_refreshCountdownText {
if (self.countdownRemainingSeconds < 0) {
self.countdownLabel.text = @"";
return;
}
NSInteger remain = MAX(0, self.countdownRemainingSeconds);
NSInteger minutes = remain / 60;
NSInteger seconds = remain % 60;
self.countdownLabel.text = [NSString stringWithFormat:@"%02zd:%02zd", (NSInteger)minutes, (NSInteger)seconds];
}
@end
#import <UIKit/UIKit.h>
NS_ASSUME_NONNULL_BEGIN
/// “限时表演-票的贡献”列表 cell
@interface FUSLiveShowTimeTicketContributionCell : UITableViewCell
/// 刷新贡献数据
/// @param face 头像 URL(可为空)
/// @param nickname 昵称(可为空)
/// @param ticketCount 票数
/// @param isMVP 是否为 MVP(控制左侧 MVP 标签展示)
- (void)fus_setupWithFace:(NSString *)face
nickname:(NSString *)nickname
ticketCount:(NSInteger)ticketCount
isMVP:(BOOL)isMVP;
@end
NS_ASSUME_NONNULL_END
#import "FUSLiveShowTimeTicketContributionCell.h"
#import <FUSCommon/FUSCommon.h>
#import <FUSFoundation/FUSFoundation.h>
#import <Masonry/Masonry.h>
#import "FUSShowRoomCenterBunble.h"
@implementation FUSLiveShowTimeTicketContributionCell {
/// 头像(圆形裁切)
UIImageView *_faceImageView;
/// 昵称
UILabel *_nicknameLabel;
/// MVP 标签(仅 MVP 用户展示)
UILabel *_mvpTagLabel;
/// 票券图标
UIImageView *_ticketIconView;
/// 票数
UILabel *_countLabel;
/// 底部分割线
UIView *_dividerView;
/// MVP 标签宽度约束(用于 show/hide 时收缩宽度)
MASConstraint *_mvpWidthConstraint;
}
- (instancetype)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier {
self = [super initWithStyle:style reuseIdentifier:reuseIdentifier];
if (!self) {
return nil;
}
self.contentView.backgroundColor = UIColor.whiteColor;
self.backgroundColor = UIColor.whiteColor;
self.selectionStyle = UITableViewCellSelectionStyleNone;
_faceImageView = [[UIImageView alloc] initWithFrame:CGRectZero];
_faceImageView.contentMode = UIViewContentModeScaleAspectFill;
_faceImageView.layer.cornerRadius = 16;
_faceImageView.layer.masksToBounds = YES;
[self.contentView addSubview:_faceImageView];
_nicknameLabel = [[UILabel alloc] initWithFrame:CGRectZero];
_nicknameLabel.font = [UIFont fus_themeFont:14];
_nicknameLabel.textColor = [UIColor colorWithHex:@"#1F1F1F"];
[self.contentView addSubview:_nicknameLabel];
_mvpTagLabel = [[UILabel alloc] initWithFrame:CGRectZero];
_mvpTagLabel.hidden = YES;
_mvpTagLabel.textAlignment = NSTextAlignmentCenter;
_mvpTagLabel.font = [UIFont fus_themeBoldFont:9];
_mvpTagLabel.textColor = UIColor.blackColor;
_mvpTagLabel.backgroundColor = [UIColor colorWithHex:@"#52DDE2"];
_mvpTagLabel.text = @"MVP";
_mvpTagLabel.layer.cornerRadius = 7;
_mvpTagLabel.layer.masksToBounds = YES;
[self.contentView addSubview:_mvpTagLabel];
_countLabel = [[UILabel alloc] initWithFrame:CGRectZero];
_countLabel.font = [UIFont fus_themeBoldFont:14];
_countLabel.textColor = [UIColor colorWithHex:@"#1F1F1F"];
_countLabel.textAlignment = NSTextAlignmentRight;
[self.contentView addSubview:_countLabel];
_ticketIconView = [[UIImageView alloc] initWithFrame:CGRectZero];
_ticketIconView.image = [FUSShowRoomCenterBunble imageNamed:@"live_room_ticket"];
_ticketIconView.contentMode = UIViewContentModeScaleAspectFit;
[self.contentView addSubview:_ticketIconView];
_dividerView = [[UIView alloc] initWithFrame:CGRectZero];
_dividerView.backgroundColor = [UIColor colorWithHex:@"#F0F1F3"];
[self.contentView addSubview:_dividerView];
[_faceImageView mas_makeConstraints:^(MASConstraintMaker *make) {
make.left.equalTo(self.contentView).offset(16);
make.centerY.equalTo(self.contentView);
make.width.height.mas_equalTo(32);
}];
[_ticketIconView mas_makeConstraints:^(MASConstraintMaker *make) {
make.right.equalTo(self.contentView).offset(-16);
make.centerY.equalTo(self.contentView);
make.width.height.mas_equalTo(14);
}];
[_countLabel mas_makeConstraints:^(MASConstraintMaker *make) {
make.right.equalTo(_ticketIconView.mas_left).offset(-6);
make.top.bottom.equalTo(self.contentView);
make.width.mas_equalTo(70);
}];
[_mvpTagLabel mas_makeConstraints:^(MASConstraintMaker *make) {
make.left.equalTo(_faceImageView.mas_right).offset(10);
make.centerY.equalTo(self.contentView);
make.height.mas_equalTo(14);
_mvpWidthConstraint = make.width.mas_equalTo(0);
}];
[_nicknameLabel mas_makeConstraints:^(MASConstraintMaker *make) {
make.left.equalTo(_faceImageView.mas_right).offset(10);
make.right.equalTo(_countLabel.mas_left).offset(-10);
make.top.bottom.equalTo(self.contentView);
}];
[_dividerView mas_makeConstraints:^(MASConstraintMaker *make) {
make.left.equalTo(self.contentView).offset(16);
make.right.equalTo(self.contentView).offset(-16);
make.bottom.equalTo(self.contentView);
make.height.mas_equalTo(0.5);
}];
return self;
}
- (void)prepareForReuse {
[super prepareForReuse];
/// 复用时清理展示内容,避免旧数据闪现
_faceImageView.image = nil;
_nicknameLabel.text = @"";
_countLabel.text = @"";
_mvpTagLabel.hidden = YES;
}
- (void)fus_setupWithFace:(NSString *)face nickname:(NSString *)nickname ticketCount:(NSInteger)ticketCount isMVP:(BOOL)isMVP {
/// 头像优先加载网络图,兜底默认头像
if (![NSString isNull:face]) {
[_faceImageView setWebImageWithSubURLString:face placeholder:UIImage.fus_defaultIcon];
} else {
_faceImageView.image = UIImage.fus_defaultIcon;
}
/// 票数与 MVP 标签受服务端数据影响,统一做兜底,避免异常值导致 UI 抖动
_nicknameLabel.text = (nickname.length > 0 ? nickname : @"");
_countLabel.text = [NSString stringWithFormat:@"%zd", (NSInteger)MAX(0, ticketCount)];
_mvpTagLabel.hidden = !isMVP;
[_mvpWidthConstraint uninstall];
[_mvpTagLabel mas_updateConstraints:^(MASConstraintMaker *make) {
_mvpWidthConstraint = make.width.mas_equalTo(isMVP ? 34 : 0);
}];
[_nicknameLabel mas_remakeConstraints:^(MASConstraintMaker *make) {
make.left.equalTo(isMVP ? _mvpTagLabel.mas_right : _faceImageView.mas_right).offset(isMVP ? 6 : 10);
make.right.equalTo(_countLabel.mas_left).offset(-10);
make.top.bottom.equalTo(self.contentView);
}];
}
@end
#import <UIKit/UIKit.h>
NS_ASSUME_NONNULL_BEGIN
/// “限时表演-票的贡献”列表 View(内部为 UITableView,支持滚动)
@interface FUSLiveShowTimeTicketContributionListView : UIView
/// 票的贡献列表数据源(元素建议包含:nickname/face/ticketCount/isMVP)
@property (nonatomic, copy) NSArray<NSDictionary *> *contributionList;
@end
NS_ASSUME_NONNULL_END
#import "FUSLiveShowTimeTicketContributionListView.h"
#import <FUSCommon/FUSCommon.h>
#import <FUSFoundation/FUSFoundation.h>
#import <Masonry/Masonry.h>
#import "FUSLiveShowTimeTicketContributionCell.h"
@interface FUSLiveShowTimeTicketContributionListView () <UITableViewDelegate, UITableViewDataSource>
/// 承载贡献列表的 tableView(复用 cell,避免频繁创建视图)
@property (nonatomic, strong) UITableView *tableView;
@end
@implementation FUSLiveShowTimeTicketContributionListView
- (instancetype)initWithFrame:(CGRect)frame {
self = [super initWithFrame:frame];
if (!self) {
return nil;
}
/// 外部可能异步下发,先给一个空数组避免 nil 分支判断
_contributionList = @[];
self.backgroundColor = UIColor.whiteColor;
self.tableView = [[UITableView alloc] initWithFrame:CGRectZero style:UITableViewStylePlain];
self.tableView.delegate = self;
self.tableView.dataSource = self;
self.tableView.separatorStyle = UITableViewCellSeparatorStyleNone;
self.tableView.backgroundColor = UIColor.whiteColor;
self.tableView.rowHeight = 52;
[self.tableView registerClass:FUSLiveShowTimeTicketContributionCell.class forCellReuseIdentifier:NSStringFromClass(FUSLiveShowTimeTicketContributionCell.class)];
[self addSubview:self.tableView];
[self.tableView mas_makeConstraints:^(MASConstraintMaker *make) {
make.edges.equalTo(self);
}];
return self;
}
- (void)setContributionList:(NSArray<NSDictionary *> *)contributionList {
/// copy 保证外部可变数组传入时不会被后续修改影响 UI 展示
_contributionList = [contributionList copy] ?: @[];
[self.tableView reloadData];
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
return self.contributionList.count;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
FUSLiveShowTimeTicketContributionCell *cell = [tableView dequeueReusableCellWithIdentifier:NSStringFromClass(FUSLiveShowTimeTicketContributionCell.class) forIndexPath:indexPath];
NSDictionary *item = nil;
if (indexPath.row < self.contributionList.count) {
item = self.contributionList[indexPath.row];
}
id nicknameValue = item[@"nickname"];
NSString *nickname = ([nicknameValue isKindOfClass:NSString.class] ? (NSString *)nicknameValue : @"");
id faceValue = item[@"face"];
NSString *face = ([faceValue isKindOfClass:NSString.class] ? (NSString *)faceValue : @"");
NSInteger ticketCount = 0;
id countValue = item[@"ticketCount"];
if ([countValue isKindOfClass:NSNumber.class]) {
ticketCount = [(NSNumber *)countValue integerValue];
} else if ([countValue isKindOfClass:NSString.class]) {
ticketCount = [(NSString *)countValue integerValue];
}
BOOL isMVP = NO;
id isMVPValue = item[@"isMVP"];
if ([isMVPValue isKindOfClass:NSNumber.class]) {
isMVP = ([(NSNumber *)isMVPValue integerValue] == 1);
} else if ([isMVPValue isKindOfClass:NSString.class]) {
isMVP = ([(NSString *)isMVPValue integerValue] == 1);
}
[cell fus_setupWithFace:face nickname:nickname ticketCount:ticketCount isMVP:isMVP];
return cell;
}
@end
#import <UIKit/UIKit.h>
NS_ASSUME_NONNULL_BEGIN
/// “限时表演-活动须知”View(内部为 UITextView,支持长文滚动)
@interface FUSLiveShowTimeTicketNoticeView : UIView
/// 活动须知文本内容(内部使用 UITextView 支持长文滚动展示)
@property (nonatomic, copy) NSString *noticeText;
@end
NS_ASSUME_NONNULL_END
#import "FUSLiveShowTimeTicketNoticeView.h"
#import <FUSCommon/FUSCommon.h>
#import <FUSFoundation/FUSFoundation.h>
#import <Masonry/Masonry.h>
@interface FUSLiveShowTimeTicketNoticeView ()
/// 须知正文(长文可滚动,避免超出一屏)
@property (nonatomic, strong) UITextView *textView;
@end
@implementation FUSLiveShowTimeTicketNoticeView
- (instancetype)initWithFrame:(CGRect)frame {
self = [super initWithFrame:frame];
if (!self) {
return nil;
}
/// 外部可异步下发文本,先给默认值避免 nil
_noticeText = @"";
self.backgroundColor = UIColor.whiteColor;
self.textView = [[UITextView alloc] initWithFrame:CGRectZero];
self.textView.editable = NO;
self.textView.scrollEnabled = YES;
self.textView.showsVerticalScrollIndicator = NO;
self.textView.textContainerInset = UIEdgeInsetsZero;
self.textView.textContainer.lineFragmentPadding = 0;
self.textView.font = [UIFont fus_themeFont:14];
self.textView.textColor = [UIColor colorWithHex:@"#666666"];
self.textView.backgroundColor = UIColor.clearColor;
[self addSubview:self.textView];
[self.textView mas_makeConstraints:^(MASConstraintMaker *make) {
make.top.equalTo(self).offset(16);
make.left.equalTo(self).offset(16);
make.right.equalTo(self).offset(-16);
make.bottom.equalTo(self).offset(-16);
}];
return self;
}
- (void)setNoticeText:(NSString *)noticeText {
/// copy 保证外部可变字符串不会影响已渲染内容
_noticeText = [noticeText copy] ?: @"";
self.textView.text = _noticeText;
}
@end
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or sign in to comment