Skip to content
Toggle navigation
P
Projects
G
Groups
S
Snippets
Help
pidan
/
FuSiLive
This project
Loading...
Sign in
Toggle navigation
Go to a project
Project
Repository
Issues
0
Merge Requests
0
Pipelines
Wiki
Snippets
Members
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Commit
e4e310c5
authored
Mar 02, 2026
by
ludi
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
完成来自相关的逻辑
parent
37a5ffd0
Show whitespace changes
Inline
Side-by-side
Showing
20 changed files
with
787 additions
and
148 deletions
DevelopmentPods/FUSCommon/FUSCommon/Classes/Common/Other/JJCollectionViewRoundFlowLayout_Swift/JJCollectionViewRoundFlowLayout+Alignment_Swift.swift
DevelopmentPods/FUSFoundation/FUSFoundation/Classes/FUSFoundation/Tools/FormatContent/FUSFormatContentHelper.h
DevelopmentPods/FUSFoundation/FUSFoundation/Classes/FUSFoundation/Tools/FormatContent/FUSFormatContentHelper.m
Modules/FUSShowRoomModule/FUSShowRoomModule.xcodeproj/project.pbxproj
Modules/FUSShowRoomModule/FUSShowRoomModule/Features/NewLive/Main/Controller/FUSLiveMainViewController.m
Modules/FUSShowRoomModule/FUSShowRoomModule/Features/NewLive/Main/Model/FUSLiveChatModel.h
Modules/FUSShowRoomModule/FUSShowRoomModule/Features/NewLive/Main/Model/FUSLiveChatTableClickTypeRangeModel.h
Modules/FUSShowRoomModule/FUSShowRoomModule/Features/NewLive/Main/Model/FUSLiveChatTableClickTypeRangeModel.m
Modules/FUSShowRoomModule/FUSShowRoomModule/Features/NewLive/Main/Other/FunctionViewHelper/FUSLiveChatDataSourceHelper.h
Modules/FUSShowRoomModule/FUSShowRoomModule/Features/NewLive/Main/Other/FunctionViewHelper/FUSLiveChatDataSourceHelper.m
Modules/FUSShowRoomModule/FUSShowRoomModule/Features/NewLive/Main/View/FunctionView/ChatTableView/FUSLiveChatTableView.h
Modules/FUSShowRoomModule/FUSShowRoomModule/Features/NewLive/Main/View/FunctionView/ChatTableView/FUSLiveChatTableView.m
Modules/FUSShowRoomModule/FUSShowRoomModule/Features/NewLive/Main/View/FunctionView/ChatTableView/FUSLiveChatTableViewCell.h
Modules/FUSShowRoomModule/FUSShowRoomModule/Features/NewLive/Main/View/FunctionView/ChatTableView/FUSLiveChatTableViewCell.m
Modules/FUSShowRoomModule/FUSShowRoomModule/Features/NewLive/Main/View/FunctionView/FUSLiveFunctionView.m
Modules/FUSShowRoomModule/FUSShowRoomModule/Features/NewLive/Main/View/FunctionView/PK/FUSPKNew/FUSView/FUSPKContentView/SubViews/UserContributeView/FFPKUserContributeListView.swift
Modules/FUSShowRoomModule/FUSShowRoomModule/Features/NewLive/Main/View/FunctionView/PK/FUSPKNew/FUSView/FUSPKControlView/FFPKControlPKModeView.swift
Modules/FUSShowRoomModule/FUSShowRoomModule/Features/NewLive/Main/View/FunctionView/PK/FUSPKNew/FUSView/FUSPKControlView/FFPKControlSettingView.swift
Modules/FUSShowRoomModule/FUSShowRoomModule/Features/NewLive/Main/View/FunctionView/PK/FUSPKNew/FUSView/FUSPKControlView/ViewModel/FFPKControlDataHelper.swift
Modules/FUSShowRoomModule/FUSShowRoomModule/Others/FUSShowRoomUDKeyStore.swift
DevelopmentPods/FUSCommon/FUSCommon/Classes/Common/Other/JJCollectionViewRoundFlowLayout_Swift/JJCollectionViewRoundFlowLayout+Alignment_Swift.swift
View file @
e4e310c5
...
...
@@ -123,7 +123,9 @@ extension JJCollectionViewRoundFlowLayout_Swift{
useWidth
+=
attr
.
bounds
.
size
.
width
;
}
let
firstLeft
=
(
layout
.
collectionView
!.
bounds
.
size
.
width
-
useWidth
-
(
JJCollectionViewFlowLayoutUtils_Swift
.
evaluatedMinimumInteritemSpacingForSectionWithCollectionLayout
(
layout
,
atIndex
:
theSection
)
*
CGFloat
(
layoutAttributesAttrs
.
count
)))
/
2.0
;
let
spacingCount
=
max
(
0
,
layoutAttributesAttrs
.
count
-
1
)
let
totalSpacing
=
JJCollectionViewFlowLayoutUtils_Swift
.
evaluatedMinimumInteritemSpacingForSectionWithCollectionLayout
(
layout
,
atIndex
:
theSection
)
*
CGFloat
(
spacingCount
)
let
firstLeft
=
(
layout
.
collectionView
!.
bounds
.
size
.
width
-
useWidth
-
totalSpacing
)
/
2.0
;
for
attr
in
layoutAttributesAttrs
{
if
attr
.
representedElementKind
!=
nil
{
...
...
DevelopmentPods/FUSFoundation/FUSFoundation/Classes/FUSFoundation/Tools/FormatContent/FUSFormatContentHelper.h
View file @
e4e310c5
...
...
@@ -41,6 +41,16 @@ NS_ASSUME_NONNULL_BEGIN
defaultColor
:(
UIColor
*
)
defaultColor
imageSize
:(
CGSize
)
imageSize
;
/// 创建一个通用公屏指令按钮,比如来自xxx公屏消息的那个黑色圆角
/// @param title 标题
/// @param font 字体
/// @param textColor 字体颜色
/// @param backgroundColor 背景颜色
+
(
NSMutableAttributedString
*
)
fus_createAttributedStringOrderBtn
:(
NSString
*
)
title
font
:(
UIFont
*
)
font
textColor
:(
UIColor
*
)
textColor
backgroundColor
:(
UIColor
*
)
backgroundColor
;
/// 获取dictionary里面的HTML Content字段,如果有多语言的文案,则匹配多语言的文案
+
(
NSString
*
)
fus_getContentFromDict
:(
NSDictionary
*
)
dict
;
...
...
DevelopmentPods/FUSFoundation/FUSFoundation/Classes/FUSFoundation/Tools/FormatContent/FUSFormatContentHelper.m
View file @
e4e310c5
...
...
@@ -251,6 +251,34 @@
return
[[
NSMutableAttributedString
alloc
]
initWithString
:
@""
];
}
+
(
NSMutableAttributedString
*
)
fus_createAttributedStringOrderBtn
:
(
NSString
*
)
title
font
:
(
UIFont
*
)
font
textColor
:
(
UIColor
*
)
textColor
backgroundColor
:
(
UIColor
*
)
backgroundColor
{
UIView
*
btnView
=
[[
UIView
alloc
]
init
];
btnView
.
backgroundColor
=
backgroundColor
;
UILabel
*
patTitleLabel
=
[[
UILabel
alloc
]
init
];
patTitleLabel
.
font
=
[
UIFont
fus_themeFont
:
font
.
pointSize
-
4
];
patTitleLabel
.
textColor
=
textColor
;
patTitleLabel
.
text
=
title
;
[
patTitleLabel
sizeToFit
];
patTitleLabel
.
x
=
6
;
patTitleLabel
.
centerY
=
(
font
.
pointSize
+
2
)
/
2
;
[
btnView
addSubview
:
patTitleLabel
];
btnView
.
height
=
font
.
pointSize
+
2
;
btnView
.
width
=
CGRectGetMaxX
(
patTitleLabel
.
frame
)
+
6
;
btnView
.
layer
.
cornerRadius
=
btnView
.
height
/
2
;
UIView
*
btnBgView
=
[[
UIView
alloc
]
init
];
btnBgView
.
userInteractionEnabled
=
NO
;
btnBgView
.
frame
=
btnView
.
bounds
;
btnBgView
.
width
=
btnView
.
width
;
btnBgView
.
height
=
btnView
.
height
+
4
;
[
btnBgView
addSubview
:
btnView
];
btnView
.
center
=
btnBgView
.
center
;
return
[
NSAttributedString
attachmentStringWithContent
:
btnBgView
contentMode
:
UIViewContentModeScaleAspectFit
attachmentSize
:
btnBgView
.
size
alignToFont
:
font
alignment
:
YYTextVerticalAlignmentCenter
];
}
// 根据 string 创建一个可变的可变富文本
+
(
NSMutableAttributedString
*
)
fus_createAttributedStringForString
:
(
NSString
*
)
string
font
:
(
UIFont
*
)
font
{
...
...
Modules/FUSShowRoomModule/FUSShowRoomModule.xcodeproj/project.pbxproj
View file @
e4e310c5
...
...
@@ -601,6 +601,9 @@
00E6CB382F4EB07D00B63797
/* FUSShowRoomSocket.swift in Sources */
=
{
isa
=
PBXBuildFile
;
fileRef
=
00E6CB372F4EB07D00B63797
/* FUSShowRoomSocket.swift */
;
};
00E6CB3B2F4F0BC400B63797
/* FUSLiveOCToSwiftHelper.m in Sources */
=
{
isa
=
PBXBuildFile
;
fileRef
=
00E6CB3A2F4F0BC400B63797
/* FUSLiveOCToSwiftHelper.m */
;
};
00E6CB3C2F4F0BC400B63797
/* FUSLiveOCToSwiftHelper.h in Headers */
=
{
isa
=
PBXBuildFile
;
fileRef
=
00E6CB392F4F0BC400B63797
/* FUSLiveOCToSwiftHelper.h */
;
};
00E6CD8E2F52EDF600B63797
/* FUSShowRoomUDKeyStore.swift in Sources */
=
{
isa
=
PBXBuildFile
;
fileRef
=
00E6CD8D2F52EDF600B63797
/* FUSShowRoomUDKeyStore.swift */
;
};
00E6CD912F52FA3900B63797
/* FUSLiveChatTableClickTypeRangeModel.m in Sources */
=
{
isa
=
PBXBuildFile
;
fileRef
=
00E6CD902F52FA3900B63797
/* FUSLiveChatTableClickTypeRangeModel.m */
;
};
00E6CD922F52FA3900B63797
/* FUSLiveChatTableClickTypeRangeModel.h in Headers */
=
{
isa
=
PBXBuildFile
;
fileRef
=
00E6CD8F2F52FA3900B63797
/* FUSLiveChatTableClickTypeRangeModel.h */
;
};
3E261EA32F2C5F680008C0C0
/* FUSByteHelper.h in Headers */
=
{
isa
=
PBXBuildFile
;
fileRef
=
3E261EA12F2C5F680008C0C0
/* FUSByteHelper.h */
;
};
3E261EA42F2C5F680008C0C0
/* FUSByteHelper.m in Sources */
=
{
isa
=
PBXBuildFile
;
fileRef
=
3E261EA22F2C5F680008C0C0
/* FUSByteHelper.m */
;
};
3E261EA72F2C5FAB0008C0C0
/* FUSLinkMicMediator.h in Headers */
=
{
isa
=
PBXBuildFile
;
fileRef
=
3E261EA52F2C5FAB0008C0C0
/* FUSLinkMicMediator.h */
;
};
...
...
@@ -2465,6 +2468,9 @@
00E6CB372F4EB07D00B63797
/* FUSShowRoomSocket.swift */
=
{
isa
=
PBXFileReference
;
lastKnownFileType
=
sourcecode.swift
;
path
=
FUSShowRoomSocket.swift
;
sourceTree
=
"<group>"
;
};
00E6CB392F4F0BC400B63797
/* FUSLiveOCToSwiftHelper.h */
=
{
isa
=
PBXFileReference
;
lastKnownFileType
=
sourcecode.c.h
;
path
=
FUSLiveOCToSwiftHelper.h
;
sourceTree
=
"<group>"
;
};
00E6CB3A2F4F0BC400B63797
/* FUSLiveOCToSwiftHelper.m */
=
{
isa
=
PBXFileReference
;
lastKnownFileType
=
sourcecode.c.objc
;
path
=
FUSLiveOCToSwiftHelper.m
;
sourceTree
=
"<group>"
;
};
00E6CD8D2F52EDF600B63797
/* FUSShowRoomUDKeyStore.swift */
=
{
isa
=
PBXFileReference
;
lastKnownFileType
=
sourcecode.swift
;
path
=
FUSShowRoomUDKeyStore.swift
;
sourceTree
=
"<group>"
;
};
00E6CD8F2F52FA3900B63797
/* FUSLiveChatTableClickTypeRangeModel.h */
=
{
isa
=
PBXFileReference
;
lastKnownFileType
=
sourcecode.c.h
;
path
=
FUSLiveChatTableClickTypeRangeModel.h
;
sourceTree
=
"<group>"
;
};
00E6CD902F52FA3900B63797
/* FUSLiveChatTableClickTypeRangeModel.m */
=
{
isa
=
PBXFileReference
;
lastKnownFileType
=
sourcecode.c.objc
;
path
=
FUSLiveChatTableClickTypeRangeModel.m
;
sourceTree
=
"<group>"
;
};
3E261EA12F2C5F680008C0C0
/* FUSByteHelper.h */
=
{
isa
=
PBXFileReference
;
lastKnownFileType
=
sourcecode.c.h
;
path
=
FUSByteHelper.h
;
sourceTree
=
"<group>"
;
};
3E261EA22F2C5F680008C0C0
/* FUSByteHelper.m */
=
{
isa
=
PBXFileReference
;
lastKnownFileType
=
sourcecode.c.objc
;
path
=
FUSByteHelper.m
;
sourceTree
=
"<group>"
;
};
3E261EA52F2C5FAB0008C0C0
/* FUSLinkMicMediator.h */
=
{
isa
=
PBXFileReference
;
lastKnownFileType
=
sourcecode.c.h
;
path
=
FUSLinkMicMediator.h
;
sourceTree
=
"<group>"
;
};
...
...
@@ -5018,6 +5024,8 @@
BECF744B2D30C76A00F5ABBC
/* FUSLiveBeforeReadyModel.m */
,
BECF744E2D30C7BF00F5ABBC
/* FUSBeforeLiveCondModel.h */
,
BECF744F2D30C7BF00F5ABBC
/* FUSBeforeLiveCondModel.m */
,
00E6CD8F2F52FA3900B63797
/* FUSLiveChatTableClickTypeRangeModel.h */
,
00E6CD902F52FA3900B63797
/* FUSLiveChatTableClickTypeRangeModel.m */
,
);
path
=
Model
;
sourceTree
=
"<group>"
;
...
...
@@ -6202,6 +6210,7 @@
00E6CB372F4EB07D00B63797
/* FUSShowRoomSocket.swift */
,
00E6CB392F4F0BC400B63797
/* FUSLiveOCToSwiftHelper.h */
,
00E6CB3A2F4F0BC400B63797
/* FUSLiveOCToSwiftHelper.m */
,
00E6CD8D2F52EDF600B63797
/* FUSShowRoomUDKeyStore.swift */
,
);
path
=
Others
;
sourceTree
=
"<group>"
;
...
...
@@ -7173,6 +7182,7 @@
BED658B92C5B745E00668116
/* FUSHalfWebViewCollectionViewCell.h in Headers */
,
BECF744C2D30C76A00F5ABBC
/* FUSLiveBeforeReadyModel.h in Headers */
,
BED65AB62C5B745F00668116
/* FUSHomePageViewController.h in Headers */
,
00E6CD922F52FA3900B63797
/* FUSLiveChatTableClickTypeRangeModel.h in Headers */
,
BED6591D2C5B745E00668116
/* FUSBulletMessageBaseView.h in Headers */
,
00BD44202D1EAA740099A96F
/* FUSCarEnterView.h in Headers */
,
BE189DC72C733B460008418B
/* FSREnterEffectRoomGuarderViewController.h in Headers */
,
...
...
@@ -8482,10 +8492,14 @@
inputFileListPaths
=
(
"${PODS_ROOT}/Target Support Files/Pods-FUSShowRoomModule/Pods-FUSShowRoomModule-resources-${CONFIGURATION}-input-files.xcfilelist"
,
);
inputPaths
=
(
);
name
=
"[CP] Copy Pods Resources"
;
outputFileListPaths
=
(
"${PODS_ROOT}/Target Support Files/Pods-FUSShowRoomModule/Pods-FUSShowRoomModule-resources-${CONFIGURATION}-output-files.xcfilelist"
,
);
outputPaths
=
(
);
runOnlyForDeploymentPostprocessing
=
0
;
shellPath
=
/bin/sh
;
shellScript
=
"\"${PODS_ROOT}/Target Support Files/Pods-FUSShowRoomModule/Pods-FUSShowRoomModule-resources.sh\"\n"
;
...
...
@@ -8869,6 +8883,7 @@
00A84DC42CA41D0C000A3BED
/* FUSPatAudiencePromptAlertView.m in Sources */
,
0089FD832D13F3460030DAA7
/* FUSLiveExchangeDiamondCollectionViewCell.swift in Sources */
,
0089FD842D13F3460030DAA7
/* FUSLiveGiftView.m in Sources */
,
00E6CD8E2F52EDF600B63797
/* FUSShowRoomUDKeyStore.swift in Sources */
,
0089FD852D13F3460030DAA7
/* FUSRegalValueUpgradeView.m in Sources */
,
0089FD862D13F3460030DAA7
/* FUSGiftSelectedNumberBtnView.m in Sources */
,
0089FD872D13F3460030DAA7
/* FUSLiveGiftCollectionViewCell.m in Sources */
,
...
...
@@ -9000,6 +9015,7 @@
BE189E282C733B460008418B
/* FSRLivedictGiftView.m in Sources */
,
BED65AB72C5B745F00668116
/* FUSHomePageViewController.m in Sources */
,
BE189DE82C733B460008418B
/* FSRActiveMotorEffectTableViewCell.m in Sources */
,
00E6CD912F52FA3900B63797
/* FUSLiveChatTableClickTypeRangeModel.m in Sources */
,
BED65A972C5B745F00668116
/* FUSLiveManagerViewController.m in Sources */
,
BED658AD2C5B745E00668116
/* FUSVideoEndedViewBottomCell.m in Sources */
,
BED659162C5B745E00668116
/* FUSLiveChatCharacterHyperlinkTableViewCell.m in Sources */
,
...
...
Modules/FUSShowRoomModule/FUSShowRoomModule/Features/NewLive/Main/Controller/FUSLiveMainViewController.m
View file @
e4e310c5
...
...
@@ -466,21 +466,21 @@ typedef NS_ENUM(NSInteger, FUSStreamState) {
_streamView
=
[[
FUSLiveStreamView
alloc
]
initPushViewWithFrame
:
self
.
contentView
.
bounds
pushConfig
:
FUSLiveHelper
.
shareInstance
.
livePushConfig
];
[
FUSLiveHelper
shareInstance
].
liveRoomType
=
FUSRoomTypeLive
;
__weak
typeof
(
self
)
weakSelf
=
self
;
//
_streamView.pushView.captureHelper.sessionErrorHandler = ^(NSInteger errorCode) {
//
// [weakSelf ff
showLiveLoadingViewWithType:liveLoadingDismiss];
_streamView
.
pushView
.
captureHelper
.
sessionErrorHandler
=
^
(
NSInteger
errorCode
)
{
[
weakSelf
fus_
showLiveLoadingViewWithType
:
liveLoadingDismiss
];
// [BFModule(StatisticService) logEventWithReqtype:FFUserBehaviorEvent.broadcaststop];
// [FF
AlertView showAlertWithTitle:nil message:[NSString fus_localString:@"发生错误,请重新开播"] cancelButtonTitle:[NSString fus_localString:@"重新开播"] otherButtonTitles:nil clickBlock:^(NSInteger buttonIndex) {
//
[weakSelf initPushPrepareView];
//
[weakSelf.liveFunctionView removeFromSuperview];
//
}];
//
};
[
FUS
AlertView
showAlertWithTitle
:
nil
message
:[
NSString
fus_localString
:
@"发生错误,请重新开播"
]
cancelButtonTitle
:
[
NSString
fus_localString
:
@"重新开播"
]
otherButtonTitles
:
nil
clickBlock
:^
(
NSInteger
buttonIndex
)
{
[
weakSelf
initPushPrepareView
];
[
weakSelf
.
liveFunctionView
removeFromSuperview
];
}];
};
//
// ludy直播推流质量
//
_streamView.pushView.captureHelper.networkQualityCallback = ^(FUSLiveCoreNetworkQuality networkQuality) {
//
// [FUSLiveHelper shareInstance
].oc_pushStreamNetworkQuality = networkQuality;
//
};
// ludy直播推流质量
_streamView
.
pushView
.
captureHelper
.
networkQualityCallback
=
^
(
FUSLiveCoreNetworkQuality
networkQuality
)
{
[
FUSSwiftLiveHelper
shared
].
oc_pushStreamNetworkQuality
=
networkQuality
;
};
if
([
NSUserDefaults
fus_readCurrentUserObjectWithKey
:
FUSLiveUDKeys
.
fus_UD_KEY_liveMirrorOpened
])
{
...
...
@@ -609,11 +609,14 @@ typedef NS_ENUM(NSInteger, FUSStreamState) {
}];
// self.playView.playerVideoFrameCallBackHandler = ^(NSString *uid, CVPixelBufferRef videoFrame) {
// if (weakSelf.pipController && [uid isEqualToString:weakSelf.playView.mainUID]) {
// [weakSelf.pipController enqueuePixelBuffer:videoFrame];
// }
// };
self
.
playView
.
playerVideoFrameCallBackHandler
=
^
(
NSString
*
uid
,
CVPixelBufferRef
videoFrame
)
{
if
(
weakSelf
.
pipController
&&
[
uid
isEqualToString
:
weakSelf
.
playView
.
mainUID
])
{
if
(
weakSelf
.
pipController
.
state
!=
VELPictureInPictureStateRunning
)
{
return
;
}
[
weakSelf
.
pipController
enqueuePixelBuffer
:
videoFrame
];
}
};
return
;
}
...
...
Modules/FUSShowRoomModule/FUSShowRoomModule/Features/NewLive/Main/Model/FUSLiveChatModel.h
View file @
e4e310c5
...
...
@@ -31,6 +31,9 @@ typedef NS_ENUM(NSInteger,FUSLiveChatModelClickType) {
@property
(
nonatomic
,
copy
)
NSString
*
realUid
;
//正式 uid
@property
(
nonatomic
,
copy
)
NSString
*
sex
;
//发送人性别
@property
(
nonatomic
,
copy
)
NSString
*
nickname
;
//发送人名称
@property
(
nonatomic
,
copy
)
NSString
*
sendUid
;
//发送人UID
@property
(
nonatomic
,
copy
)
NSString
*
sendNickName
;
//发送人名称
@property
(
nonatomic
,
copy
)
NSString
*
face
;
//头像
@property
(
nonatomic
,
copy
)
NSString
*
toUid
;
//@用户ID、如果是弹幕的话,就是跳转到的直播间的ID
@property
(
nonatomic
,
copy
)
NSString
*
toNickName
;
//@用户昵称、如果是弹幕的话,就是跳转到的直播间的昵称
...
...
Modules/FUSShowRoomModule/FUSShowRoomModule/Features/NewLive/Main/Model/FUSLiveChatTableClickTypeRangeModel.h
0 → 100644
View file @
e4e310c5
//
// FUSLiveChatTableClickTypeRangeModel.h
// FUSShowRoomModule
//
// Created by aaa on 2026/2/28.
//
#import <Foundation/Foundation.h>
NS_ASSUME_NONNULL_BEGIN
/// 点击事件分类
typedef
enum
:
NSUInteger
{
/// 文案
FUSLiveChatDataClickTypeContent
=
0
,
/// 昵称
FUSLiveChatDataClickTypeNickname
,
/// 拍一拍
FUSLiveChatDataClickTypePatAudience
,
/// 其他命令
FUSLiveChatDataClickTypeOrder
,
/// 来自
FUSLiveChatDataClickTypeComefrom
,
}
FUSLiveChatDataClickType
;
@interface
FUSLiveChatTableClickTypeRangeModel
:
NSObject
/// 昵称的范围
@property
(
nonatomic
,
assign
)
NSRange
nicknameRange
;
/// 拍一拍的范围
@property
(
nonatomic
,
assign
)
NSRange
patAudienceRange
;
/// 指令按钮的范围
@property
(
nonatomic
,
assign
)
NSRange
orderBtnRange
;
/// 来自按钮范围
@property
(
nonatomic
,
assign
)
NSRange
comefromRange
;
@end
NS_ASSUME_NONNULL_END
Modules/FUSShowRoomModule/FUSShowRoomModule/Features/NewLive/Main/Model/FUSLiveChatTableClickTypeRangeModel.m
0 → 100644
View file @
e4e310c5
//
// FUSLiveChatTableClickTypeRangeModel.m
// FUSShowRoomModule
//
// Created by aaa on 2026/2/28.
//
#import "FUSLiveChatTableClickTypeRangeModel.h"
@implementation
FUSLiveChatTableClickTypeRangeModel
@end
Modules/FUSShowRoomModule/FUSShowRoomModule/Features/NewLive/Main/Other/FunctionViewHelper/FUSLiveChatDataSourceHelper.h
View file @
e4e310c5
...
...
@@ -200,6 +200,9 @@
/// 取出撩一撩的范围
-
(
NSRange
)
patAudienceRangeForModelID
:(
NSString
*
)
modelId
;
/// 取出来自按钮的范围
-
(
NSRange
)
comfromBtnRangeForModelID
:(
NSString
*
)
modelId
;
/**
取出解析好的富文本
...
...
Modules/FUSShowRoomModule/FUSShowRoomModule/Features/NewLive/Main/Other/FunctionViewHelper/FUSLiveChatDataSourceHelper.m
View file @
e4e310c5
...
...
@@ -31,6 +31,7 @@
#import <YYKit/YYKit.h>
#import "NSMutableAttributedString+colorfulText.h"
#import "FUSLiveChatTableClickTypeRangeModel.h"
#define FUS_LIVE_FONT(fontSize) [UIFont fus_themeMediumFont:fontSize]
...
...
@@ -62,6 +63,9 @@
/// 拍一拍按钮的范围
@property
(
nonatomic
,
strong
)
NSMutableDictionary
*
patAudienceRangeDict
;
/// 来自按钮的范围
@property
(
nonatomic
,
strong
)
NSMutableDictionary
*
comefromRangeDict
;
#pragma mark - Property:Other
/**
等级字典
...
...
@@ -104,6 +108,11 @@
// 计时器期间刷新的消息
@property
(
nonatomic
,
strong
)
NSMutableArray
*
waitForRefreshDataList
;
/// tableView的宽度
@property
(
nonatomic
,
assign
)
CGFloat
tableViewWidth
;
@property
(
nonatomic
,
strong
)
NSOperationQueue
*
chatParseQueue
;
@end
@implementation
FUSLiveChatDataSourceHelper
...
...
@@ -123,6 +132,17 @@
self
.
tableView
=
tableView
;
self
.
tableView
=
tableView
;
self
.
chatParseQueue
=
[[
NSOperationQueue
alloc
]
init
];
self
.
chatParseQueue
.
name
=
@"com.fusiya.liveroom.chatParseQueue"
;
self
.
chatParseQueue
.
maxConcurrentOperationCount
=
6
;
MJWeakSelf
self
.
tableViewWidth
=
tableView
.
width
;
self
.
tableView
.
tableViewWidthDidChangedHandler
=
^
(
CGFloat
tableViewWidth
)
{
weakSelf
.
tableViewWidth
=
tableViewWidth
;
};
[
self
fus_registerSocketNotification
];
// 获取等级字典
...
...
@@ -187,6 +207,7 @@
// NSRange nicknameRange;
NSRange
patAudienceRange
=
NSMakeRange
(
NSNotFound
,
0
);;
// NSRange orderBtnRange;
NSRange
comefromRange
=
NSMakeRange
(
0
,
0
);
//
// if (self.nicknameRangeDict[model.ID]) {
// nicknameRange = [self.nicknameRangeDict[model.ID] rangeValue];
...
...
@@ -199,15 +220,31 @@
// orderBtnRange = [self.orderBtnRangeDict[model.ID] rangeValue];
// }
if
(
self
.
comefromRangeDict
[
model
.
ID
])
{
comefromRange
=
[
self
.
comefromRangeDict
[
model
.
ID
]
rangeValue
];
}
[
self
removeModel
:
lastModel
];
[
self
.
dataSource
addObject
:
model
];
// 如果是直接替换,但是cell大小不同的话,那么还是要刷新tableView。因为高度可能改变
if
(
lastWidth
!=
width
||
lastHeight
!=
height
)
{
if
(
height
>
lastHeight
+
4
||
[
model
.
type
isEqualToString
:
@"-19994"
]
)
{
[
addedRefreshList
addObject
:
model
];
}
else
{
if
([
lastCell
respondsToSelector
:
@selector
(
fus_changeCellToModel
:
attributedString
:
patAudienceRange
:
height
:
width
:
completionHandler
:
)])
{
// if ([lastCell respondsToSelector:@selector(fus_changeCellToModel:attributedString:patAudienceRange:height:width:completionHandler:)]) {
//
// [lastCell fus_changeCellToModel:model attributedString:attr patAudienceRange:patAudienceRange height:height width:width completionHandler:^(FUSLiveChatModel *oldModel) {
// }];
// }
if
([
lastCell
respondsToSelector
:
@selector
(
fus_changeCellToModel
:
attributedString
:
rangeModel
:
height
:
width
:
completionHandler
:
)])
{
FUSLiveChatTableClickTypeRangeModel
*
rangeModel
=
[[
FUSLiveChatTableClickTypeRangeModel
alloc
]
init
];
// rangeModel.nicknameRange = nicknameRange;
rangeModel
.
patAudienceRange
=
patAudienceRange
;
// rangeModel.orderBtnRange = orderBtnRange;
rangeModel
.
comefromRange
=
comefromRange
;
[
lastCell
fus_changeCellToModel
:
model
attributedString
:
attr
rangeModel
:
rangeModel
height
:
height
width
:
width
completionHandler
:^
(
FUSLiveChatModel
*
oldModel
)
{
[
lastCell
fus_changeCellToModel
:
model
attributedString
:
attr
patAudienceRange
:
patAudienceRange
height
:
height
width
:
width
completionHandler
:^
(
FUSLiveChatModel
*
oldModel
)
{
}];
}
}
...
...
@@ -330,6 +367,13 @@
return
_patAudienceRangeDict
;
}
-
(
NSMutableDictionary
*
)
comefromRangeDict
{
if
(
!
_comefromRangeDict
)
{
_comefromRangeDict
=
[
NSMutableDictionary
dictionary
];
}
return
_comefromRangeDict
;
}
#pragma mark - method
#pragma mark -- 添加
// 添加 model
...
...
@@ -390,11 +434,13 @@
model
.
cellCacheWidth
=
width
;
model
.
cellCacheHeight
=
height
;
[
self
.
waitForRefreshDataList
addObject
:
model
];
dispatch_async_on_main_queue
(
^
{
[
weakSelf
.
waitForRefreshDataList
addObject
:
model
];
if
(
complete
)
{
complete
();
}
});
});
}];
}
...
...
@@ -403,20 +449,30 @@
if
(
!
completed
)
{
return
;
}
dispatch_async
(
dispatch_get_main_queue
(),
^
{
CGFloat
width
=
self
.
tableView
.
width
;
dispatch_async
(
dispatch_get_global_queue
(
0
,
0
),
^
{
CGRect
rect
;
@try
{
YYTextLayout
*
layout
=
[
YYTextLayout
layoutWithContainerSize
:
CGSizeMake
(
w
idth
-
(
4
*
CELL_LEADING_SPACE
),
CGFLOAT_MAX
)
text
:
attr
];
YYTextLayout
*
layout
=
[
YYTextLayout
layoutWithContainerSize
:
CGSizeMake
(
self
.
tableViewW
idth
-
(
4
*
CELL_LEADING_SPACE
),
CGFLOAT_MAX
)
text
:
attr
];
rect
=
layout
.
textBoundingRect
;
}
@catch
(
NSException
*
exception
)
{
rect
=
CGRectMake
(
0
,
0
,
w
idth
-
(
4
*
CELL_LEADING_SPACE
),
40
);
rect
=
CGRectMake
(
0
,
0
,
self
.
tableViewW
idth
-
(
4
*
CELL_LEADING_SPACE
),
40
);
}
@finally
{
completed
(
rect
);
}
});
});
// dispatch_async(dispatch_get_main_queue(), ^{
// CGFloat width = self.tableView.width;
// dispatch_async(dispatch_get_global_queue(0, 0), ^{
// CGRect rect;
// @try {
// YYTextLayout *layout = [YYTextLayout layoutWithContainerSize:CGSizeMake(width - (4 * CELL_LEADING_SPACE), CGFLOAT_MAX) text:attr];
// rect = layout.textBoundingRect;
// } @catch (NSException *exception) {
// rect = CGRectMake(0, 0, width - (4 * CELL_LEADING_SPACE), 40);
// } @finally {
// completed(rect);
// }
// });
// });
}
// 添加已经有计算好的高度和 attributedString
...
...
@@ -651,6 +707,11 @@
return
range
;
}
-
(
NSRange
)
comfromBtnRangeForModelID
:
(
NSString
*
)
modelId
{
NSRange
range
=
[[
self
.
comefromRangeDict
objectForKey
:
modelId
]
rangeValue
];
return
range
;
}
// 取出解析好的富文本
-
(
NSAttributedString
*
)
attributedStringForModelID
:
(
NSString
*
)
modelId
{
...
...
@@ -709,6 +770,7 @@
[
self
.
cellWidthDict
removeObjectForKey
:
model
.
ID
];
[
self
.
cellStringDict
removeObjectForKey
:
model
.
ID
];
[
self
.
patAudienceRangeDict
removeObjectForKey
:
model
.
ID
];
[
self
.
comefromRangeDict
removeObjectForKey
:
model
.
ID
];
}
else
{
...
...
@@ -719,6 +781,7 @@
[
self
.
cellWidthDict
removeObjectForKey
:
model
.
ID
];
[
self
.
cellStringDict
removeObjectForKey
:
model
.
ID
];
[
self
.
patAudienceRangeDict
removeObjectForKey
:
model
.
ID
];
[
self
.
comefromRangeDict
removeObjectForKey
:
model
.
ID
];
});
...
...
@@ -782,6 +845,19 @@
}
}
if
(
model
.
type
.
integerValue
==
CID_ENTER_ROOM
)
{
if
(
model
.
toUid
!=
nil
&&
[
model
.
toUid
length
]
>
0
&&
model
.
toNickName
!=
nil
&&
[
model
.
toNickName
length
]
>
0
)
{
// 消息互通,别的直播间的消息
// 进入房间的消息,需要单独在前面加一个来自
[
self
.
comefromRangeDict
setValue
:[
NSValue
valueWithRange
:
NSMakeRange
(
attr
.
length
+
1
,
1
)]
forKey
:
model
.
ID
];
NSAttributedString
*
comefromAtrr
=
[
FUSFormatContentHelper
fus_createAttributedStringOrderBtn
:[
NSString
stringWithFormat
:
@"%@ %@"
,[
NSString
fus_versionLocalString
:
@"来自"
],
model
.
toNickName
]
font
:[
UIFont
fus_themeFont
:
_fontSize
]
textColor
:
[
UIColor
whiteColor
]
backgroundColor
:
[
UIColor
colorWithHex
:
@"#000000"
alpha
:
0
.
34
]];
[
attr
appendAttributedString
:
comefromAtrr
];
}
}
//在主线程组合生成额外按钮
NSAttributedString
*
orderBtnAttr
=
nil
;
...
...
@@ -797,9 +873,11 @@
CGFloat
imageH
=
14
;
CGFloat
imageW
=
0
;
dispatch_async
(
dispatch_get_global_queue
(
0
,
0
),
^
{
MJWeakSelf
// dispatch_async(dispatch_get_global_queue(0, 0), ^{
[
self
.
chatParseQueue
addOperationWithBlock
:
^
{
[
self
createContentAttributedStringWithModel
:
model
imageSize
:
CGSizeMake
(
imageW
,
imageH
)
fontSize
:
s
elf
.
fontSize
complete
:^
(
NSMutableAttributedString
*
attributedString
)
{
[
weakSelf
createContentAttributedStringWithModel
:
model
imageSize
:
CGSizeMake
(
imageW
,
imageH
)
fontSize
:
weakS
elf
.
fontSize
complete
:^
(
NSMutableAttributedString
*
attributedString
)
{
NSMutableAttributedString
*
contentAttr
=
[
attributedString
mutableCopy
];
...
...
@@ -817,10 +895,13 @@
}
[
self
fus_rectWithAttr
:
attr
completed
:
^
(
CGRect
rect
)
{
dispatch_async_on_main_queue
(
^
{
complete
([[
NSMutableAttributedString
alloc
]
initWithAttributedString
:
attr
],
rect
);
});
}];
}];
});
// });
}];
}
// 根据 string 创建一个可变的可变富文本
...
...
@@ -956,6 +1037,17 @@
[
attr
appendAttributedString
:
newsAttr
];
}
if
(
model
.
toUid
!=
nil
&&
[
model
.
toUid
length
]
>
0
&&
model
.
toNickName
!=
nil
&&
[
model
.
toNickName
length
]
>
0
)
{
// 消息互通,别的直播间的消息
[
self
.
comefromRangeDict
setValue
:[
NSValue
valueWithRange
:
NSMakeRange
(
attr
.
length
+
1
,
1
)]
forKey
:
model
.
ID
];
NSAttributedString
*
comefromAtrr
=
[
FUSFormatContentHelper
fus_createAttributedStringOrderBtn
:[
NSString
stringWithFormat
:
@"%@ %@"
,[
NSString
fus_versionLocalString
:
@"来自"
],
model
.
toNickName
]
font
:[
UIFont
fus_themeFont
:
_fontSize
]
textColor
:
[
UIColor
whiteColor
]
backgroundColor
:
[
UIColor
colorWithHex
:
@"#000000"
alpha
:
0
.
34
]];
[
attr
appendAttributedString
:
comefromAtrr
];
}
}
return
[[
NSAttributedString
alloc
]
initWithAttributedString
:
attr
];
...
...
@@ -1179,7 +1271,8 @@
-
(
void
)
fus_sendBulletModelWithMessage
:
(
FUSLiveChatModel
*
)
message
{
dispatch_async
(
dispatch_get_global_queue
(
0
,
0
),
^
{
// dispatch_async(dispatch_get_global_queue(0, 0), ^{
[
self
.
chatParseQueue
addOperationWithBlock
:
^
{
__weak
typeof
(
self
)
weakSelf
=
self
;
CGSize
imageSize
=
CGSizeMake
(
45
,
14
);
...
...
@@ -1215,7 +1308,8 @@
[[
NSNotificationCenter
defaultCenter
]
postNotificationName
:
NOTIFICATION_SHOW_BULLETS
object
:
bulletModel
];
});
}];
});
// });
}];
}
#pragma mark - socket
...
...
Modules/FUSShowRoomModule/FUSShowRoomModule/Features/NewLive/Main/View/FunctionView/ChatTableView/FUSLiveChatTableView.h
View file @
e4e310c5
...
...
@@ -8,20 +8,34 @@
#import <UIKit/UIKit.h>
#import "FUSLiveChatModel.h"
#import "FUSLiveChatTableClickTypeRangeModel.h"
#define TABLE_VIEW_WIDTH (UIView.fus_screenW - 80)
#define TABLE_VIEW_HEIGHT 220
@class
FUSLiveChatDataSourceHelper
;
@interface
FUSLiveChatTableView
:
UITableView
#pragma mark - Property
/**
点击昵称回调
*/
@property
(
nonatomic
,
copy
)
void
(
^
onClickNicknameHandler
)(
FUSLiveChatModel
*
model
);
//
@property (nonatomic, copy) void(^onClickNicknameHandler)(FUSLiveChatModel *model);
/// 点击拍一拍回调
@property
(
nonatomic
,
copy
)
void
(
^
onClickPatAudiencetHandler
)(
FUSLiveChatModel
*
model
);
//@property (nonatomic, copy) void(^onClickPatAudiencetHandler)(FUSLiveChatModel *model);
/**
数据源
*/
@property
(
nonatomic
,
strong
)
FUSLiveChatDataSourceHelper
*
dataSourceHelper
;
/// 点击各种按钮的回调
@property
(
nonatomic
,
copy
)
void
(
^
onClickMessageWithModel
)(
FUSLiveChatDataClickType
type
,
FUSLiveChatModel
*
model
,
NSRange
range
);
// 宽度改变的回调
@property
(
nonatomic
,
copy
)
void
(
^
tableViewWidthDidChangedHandler
)(
CGFloat
tableViewWidth
);
/**
允许发送通知
...
...
Modules/FUSShowRoomModule/FUSShowRoomModule/Features/NewLive/Main/View/FunctionView/ChatTableView/FUSLiveChatTableView.m
View file @
e4e310c5
...
...
@@ -28,10 +28,6 @@
*/
@property
(
nonatomic
,
strong
)
NSTimer
*
timer
;
/**
数据源
*/
@property
(
nonatomic
,
strong
)
FUSLiveChatDataSourceHelper
*
dataSourceHelper
;
@property
(
nonatomic
,
strong
)
UIButton
*
scrollToBottomBtn
;
...
...
@@ -101,6 +97,10 @@
// 设置 pk 时的 scrollToBottomBtn 值
self
.
scrollToBottomBtn
.
y
=
self
.
height
-
(
self
.
scrollToBottomBtn
.
height
+
10
);
if
(
self
.
tableViewWidthDidChangedHandler
)
{
self
.
tableViewWidthDidChangedHandler
(
CGRectGetWidth
(
frame
));
}
}
#pragma mark - override
...
...
@@ -176,6 +176,7 @@
NSAttributedString
*
attr
=
[
self
.
dataSourceHelper
attributedStringForModelID
:
model
.
ID
];
NSRange
patAudienceRange
=
[
self
.
dataSourceHelper
patAudienceRangeForModelID
:
model
.
ID
];
NSRange
comefromRange
=
[
self
.
dataSourceHelper
comfromBtnRangeForModelID
:
model
.
ID
];
CGFloat
height
=
[
self
.
dataSourceHelper
heightForModelID
:
model
.
ID
];
CGFloat
width
=
[
self
.
dataSourceHelper
widthForModelID
:
model
.
ID
];
...
...
@@ -197,21 +198,35 @@
showBackground
=
YES
;
}
[
cell
fus_setupCellWithModel
:
model
attributedString
:
attr
patAudienceRange
:
patAudienceRange
height
:
height
width
:
width
showBackground
:
showBackground
];
FUSLiveChatTableClickTypeRangeModel
*
rangeModel
=
[[
FUSLiveChatTableClickTypeRangeModel
alloc
]
init
];
// rangeModel.nicknameRange = range;
rangeModel
.
patAudienceRange
=
patAudienceRange
;
// rangeModel.orderBtnRange = orderBtnRange;
rangeModel
.
comefromRange
=
comefromRange
;
[
cell
setOnClickNicknameWithModel
:
^
(
FUSLiveChatModel
*
model
)
{
[
cell
fus_setupCellWithModel
:
model
attributedString
:
attr
rangeModel
:
rangeModel
height
:
height
width
:
width
showBackground
:
showBackground
];
if
(
weakSelf
.
onClickNicknameHandler
)
{
weakSelf
.
onClickNicknameHandler
(
model
);
[
cell
setOnClickMessageWithModel
:
^
(
FUSLiveChatDataClickType
type
,
FUSLiveChatModel
*
model
,
NSRange
range
)
{
if
(
weakSelf
.
onClickMessageWithModel
)
{
weakSelf
.
onClickMessageWithModel
(
type
,
model
,
range
);
}
}];
[
cell
setOnClickPatAudienceWithModel
:
^
(
FUSLiveChatModel
*
model
)
{
// 点击了撩一撩
if
(
weakSelf
.
onClickPatAudiencetHandler
)
{
weakSelf
.
onClickPatAudiencetHandler
(
model
);
}
}];
// [cell fus_setupCellWithModel:model attributedString:attr patAudienceRange:patAudienceRange height:height width:width showBackground:showBackground];
//
// [cell setOnClickNicknameWithModel:^(FUSLiveChatModel *model) {
//
// if (weakSelf.onClickNicknameHandler) {
// weakSelf.onClickNicknameHandler(model);
// }
// }];
//
// [cell setOnClickPatAudienceWithModel:^(FUSLiveChatModel *model) {
// // 点击了撩一撩
// if (weakSelf.onClickPatAudiencetHandler) {
// weakSelf.onClickPatAudiencetHandler(model);
// }
// }];
return
cell
;
}
...
...
Modules/FUSShowRoomModule/FUSShowRoomModule/Features/NewLive/Main/View/FunctionView/ChatTableView/FUSLiveChatTableViewCell.h
View file @
e4e310c5
...
...
@@ -8,6 +8,7 @@
#import <UIKit/UIKit.h>
#import "FUSLiveChatModel.h"
#import "FUSLiveChatTableClickTypeRangeModel.h"
#define CELL_MARGIN 1 // cell 上下空间
#define CELL_LEADING_SPACE 5 // cell 前后距离 20 / 10
...
...
@@ -19,20 +20,23 @@
//@property (nonatomic, copy) void(^onClickNickname)(NSString *);
@property
(
nonatomic
,
copy
)
void
(
^
onClickNicknameWithModel
)(
FUSLiveChatModel
*
);
//
@property (nonatomic, copy) void(^onClickNicknameWithModel)(FUSLiveChatModel *);
@property
(
nonatomic
,
copy
)
void
(
^
onClickPatAudienceWithModel
)(
FUSLiveChatModel
*
);
//@property (nonatomic, copy) void(^onClickPatAudienceWithModel)(FUSLiveChatModel *);
/// 点击各种按钮的回调
@property
(
nonatomic
,
copy
)
void
(
^
onClickMessageWithModel
)(
FUSLiveChatDataClickType
type
,
FUSLiveChatModel
*
model
,
NSRange
range
);
-
(
void
)
fus_setupCellWithModel
:(
FUSLiveChatModel
*
)
model
attributedString
:(
NSAttributedString
*
)
attr
patAudienceRange
:(
NSRange
)
patAudienceRange
rangeModel
:(
FUSLiveChatTableClickTypeRangeModel
*
)
rangeModel
height
:(
CGFloat
)
height
width
:(
CGFloat
)
width
showBackground
:(
BOOL
)
showBackground
;
-
(
void
)
fus_changeCellToModel
:(
FUSLiveChatModel
*
)
model
attributedString
:(
NSAttributedString
*
)
attr
patAudienceRange
:(
NSRange
)
patAudienceRange
rangeModel
:(
FUSLiveChatTableClickTypeRangeModel
*
)
rangeModel
height
:(
CGFloat
)
height
width
:(
CGFloat
)
width
completionHandler
:(
void
(
^
)(
FUSLiveChatModel
*
oldModel
))
completionHandler
;
...
...
Modules/FUSShowRoomModule/FUSShowRoomModule/Features/NewLive/Main/View/FunctionView/ChatTableView/FUSLiveChatTableViewCell.m
View file @
e4e310c5
...
...
@@ -15,6 +15,7 @@
#import "FUSLiveHelper.h"
#import "FUSLiveChatTableView.h"
#import <FUSShowRoomModule/FUSShowRoomModule-Swift.h>
@interface
FUSLiveChatTableViewCell
()
<
FUSLiveChatLabelDelegate
>
//@property (nonatomic, strong) UIButton *nickNameBtn;
...
...
@@ -30,8 +31,8 @@
// 背景 View
@property
(
nonatomic
,
strong
)
UIImageView
*
bgView
;
///
拍一拍的
范围
@property
(
nonatomic
,
assign
)
NSRange
patAudienceRange
;
///
点击的类型
范围
@property
(
nonatomic
,
strong
)
FUSLiveChatTableClickTypeRangeModel
*
rangeModel
;
@end
...
...
@@ -116,27 +117,88 @@
}
}
if
(
weakSelf
.
onClickMessageWithModel
==
nil
)
{
// 没有设置点击事件
return
;
}
if
(
weakSelf
.
model
.
patStatus
==
1
&&
range
.
location
==
weakSelf
.
rangeModel
.
patAudienceRange
.
location
)
{
if
(
weakSelf
.
model
.
patStatus
==
1
&&
range
.
location
==
weakSelf
.
patAudienceRange
.
location
)
{
// 撩一撩
if
([
FUSLiveHelper
shareInstance
].
liveType
==
FUSLiveTypeAudience
)
{
// 拍一拍只算一个长度,因为只是一个控件
if
([
FUSSwiftLiveHelper
shared
].
liveType
==
FUSLiveTypeAudience
)
{
// 如果是观众端,那么直接无视
return
;
}
if
(
weakSelf
.
onClickPatAudienceWithModel
)
{
weakSelf
.
onClickPatAudienceWithModel
(
weakSelf
.
model
);
weakSelf
.
onClickMessageWithModel
(
FUSLiveChatDataClickTypePatAudience
,
weakSelf
.
model
,
range
);
}
else
if
([
weakSelf
.
model
ffisClickOrderModel
]
&&
range
.
location
==
weakSelf
.
rangeModel
.
orderBtnRange
.
location
)
{
// 通用order按钮
weakSelf
.
onClickMessageWithModel
(
FUSLiveChatDataClickTypeOrder
,
weakSelf
.
model
,
range
);
}
else
if
(
weakSelf
.
rangeModel
.
comefromRange
.
location
!=
kCFNotFound
&&
range
.
location
==
weakSelf
.
rangeModel
.
comefromRange
.
location
)
{
// 来自
weakSelf
.
onClickMessageWithModel
(
FUSLiveChatDataClickTypeComefrom
,
weakSelf
.
model
,
range
);
}
else
if
(
weakSelf
.
rangeModel
.
nicknameRange
.
location
!=
kCFNotFound
&&
NSMaxRange
(
weakSelf
.
rangeModel
.
nicknameRange
)
>
0
)
{
// 有昵称的rang,并且点到了昵称
if
(
range
.
location
>=
weakSelf
.
rangeModel
.
nicknameRange
.
location
&&
NSMaxRange
(
range
)
<=
NSMaxRange
(
weakSelf
.
rangeModel
.
nicknameRange
))
{
weakSelf
.
onClickMessageWithModel
(
FUSLiveChatDataClickTypeNickname
,
weakSelf
.
model
,
range
);
}
// else if ( weakSelf.model.socketCID == 9999 ) {
// // 有昵称,但是没点到昵称,那么应该就是点到内容了
// weakSelf.onClickMessageWithModel(FFLiveChatDataClickTypeContent, weakSelf.model, range);
// }
else
if
([
weakSelf
.
model
.
type
isEqualToString
:
@"-19994"
])
{
// 超链接,直接分配给nickname
weakSelf
.
onClickMessageWithModel
(
FUSLiveChatDataClickTypeNickname
,
weakSelf
.
model
,
range
);
}
else
{
//其他情况
if
((
!
[
NSString
isNull
:
weakSelf
.
model
.
uid
]
&&
weakSelf
.
model
.
uid
.
integerValue
!=
0
)
||
weakSelf
.
model
.
clickType
==
FUSLiveChatModelClickTypeDewGift
||
(
weakSelf
.
model
.
clickType
==
FUSLiveChatModelClickTypeOtherLiveRoom
&&
!
[
NSString
isNull
:
weakSelf
.
model
.
toUid
]))
{
// 能nickname的就交付给nickname
if
(
weakSelf
.
onClickNicknameWithModel
)
weakSelf
.
onClickNicknameWithModel
(
weakSelf
.
model
);
//其他
if
(
!
[
NSString
isNullWithString
:
weakSelf
.
model
.
msg
])
{
NSRange
textRange
=
[
text
.
string
rangeOfString
:
weakSelf
.
model
.
msg
];
if
(
textRange
.
location
!=
NSNotFound
&&
range
.
location
>=
textRange
.
location
&&
NSMaxRange
(
range
)
<=
NSMaxRange
(
textRange
))
{
// 检测到确实点了text的情况
weakSelf
.
onClickMessageWithModel
(
FUSLiveChatDataClickTypeContent
,
weakSelf
.
model
,
range
);
return
;
}
// 兜底都给nickname,因为它有nickname
weakSelf
.
onClickMessageWithModel
(
FUSLiveChatDataClickTypeNickname
,
weakSelf
.
model
,
range
);
}
}
}
else
{
//其他情况
weakSelf
.
onClickMessageWithModel
(
FUSLiveChatDataClickTypeNickname
,
weakSelf
.
model
,
range
);
}
// if (weakSelf.model.patStatus == 1 && range.location == weakSelf.patAudienceRange.location) {
// // 撩一撩
// if ([FUSLiveHelper shareInstance].liveType == FUSLiveTypeAudience) {
// // 如果是观众端,那么直接无视
// return;
// }
//
// if (weakSelf.onClickPatAudienceWithModel) {
// weakSelf.onClickPatAudienceWithModel(weakSelf.model);
// }
// }
// else {
// //其他情况
// if ((![NSString isNull:weakSelf.model.uid] && weakSelf.model.uid.integerValue != 0)
// || weakSelf.model.clickType == FUSLiveChatModelClickTypeDewGift
// || (weakSelf.model.clickType == FUSLiveChatModelClickTypeOtherLiveRoom && ![NSString isNull:weakSelf.model.toUid])) {
// // 能nickname的就交付给nickname
// if (weakSelf.onClickNicknameWithModel) weakSelf.onClickNicknameWithModel(weakSelf.model);
// }
// }
};
}
...
...
@@ -152,13 +214,13 @@
-
(
void
)
fus_setupCellWithModel
:
(
FUSLiveChatModel
*
)
model
attributedString
:
(
NSAttributedString
*
)
attr
patAudienceRange
:
(
NSRange
)
patAudienceRange
rangeModel
:
(
FUSLiveChatTableClickTypeRangeModel
*
)
rangeModel
height
:
(
CGFloat
)
height
width
:
(
CGFloat
)
width
showBackground
:
(
BOOL
)
showBackground
{
_
patAudienceRange
=
patAudienceRange
;
_
rangeModel
=
rangeModel
;
if
(
attr
.
length
&&
[
self
.
contentLabel
.
attributedText
isEqualToAttributedString
:
attr
])
{
// 设置 frame
...
...
@@ -218,7 +280,7 @@
-
(
void
)
fus_changeCellToModel
:
(
FUSLiveChatModel
*
)
model
attributedString
:
(
NSAttributedString
*
)
attr
patAudienceRange
:
(
NSRange
)
patAudienceRange
rangeModel
:
(
FUSLiveChatTableClickTypeRangeModel
*
)
rangeModel
height
:
(
CGFloat
)
height
width
:
(
CGFloat
)
width
completionHandler
:
(
void
(
^
)(
FUSLiveChatModel
*
oldModel
))
completionHandler
...
...
@@ -243,7 +305,7 @@
}
// 设置 lable
[
self
fus_setupCellWithModel
:
model
attributedString
:
attr
patAudienceRange
:
patAudienceRange
height
:
height
width
:
width
showBackground
:
showBackground
];
[
self
fus_setupCellWithModel
:
model
attributedString
:
attr
rangeModel
:
rangeModel
height
:
height
width
:
width
showBackground
:
showBackground
];
// 持有当前内容
self
.
currentString
=
model
.
msg
;
// 设置 frame
...
...
@@ -256,8 +318,9 @@
completionHandler
(
oldModel
);
}
MJWeakSelf
dispatch_after
(
dispatch_time
(
DISPATCH_TIME_NOW
,
(
int64_t
)(
1
.
0
*
NSEC_PER_SEC
)),
dispatch_get_main_queue
(),
^
{
_
isChanging
=
NO
;
weakSelf
.
isChanging
=
NO
;
});
}
...
...
Modules/FUSShowRoomModule/FUSShowRoomModule/Features/NewLive/Main/View/FunctionView/FUSLiveFunctionView.m
View file @
e4e310c5
...
...
@@ -632,18 +632,17 @@ BDAlphaPlayerMetalViewDelegate
self
.
specialEffectView
.
hidden
=
YES
;
[[
self
fus_viewWithLayer
:
FUSLiveFunctionLayerBigEffects
]
addSubview
:
self
.
specialEffectView
];
// ludy: gcp说,fusi解除惩罚的按钮都不要有
// self.releasePunishmentView = [[FUSLiveReleasePunishmentView alloc] initWithFrame:CGRectMake(0, self.activityView.y - 10 - 48, 48, 48)];
// self.releasePunishmentView.centerX = self.activityView.centerX;
// [[self fus_viewWithLayer:FUSLiveFunctionLayerFloatButtons] addSubview:self.releasePunishmentView];
//
// MJWeakSelf
// self.releasePunishmentView.clickedHandler = ^{
// [FUSLivePunishListAlertView fus_createWithAnimateShowOn:[weakSelf fus_viewWithLayer:FUSLiveFunctionLayerManualPopView]];
// };
// self.releasePunishmentView.hidenStateDidChange = ^(BOOL isHidden) {
// [weakSelf fus_reloadUIWithKeyboardSetPart];
// };
self
.
releasePunishmentView
=
[[
FUSLiveReleasePunishmentView
alloc
]
initWithFrame
:
CGRectMake
(
0
,
self
.
activityView
.
y
-
10
-
48
,
48
,
48
)];
self
.
releasePunishmentView
.
centerX
=
self
.
activityView
.
centerX
;
[[
self
fus_viewWithLayer
:
FUSLiveFunctionLayerFloatButtons
]
addSubview
:
self
.
releasePunishmentView
];
MJWeakSelf
self
.
releasePunishmentView
.
clickedHandler
=
^
{
[
FUSLivePunishListAlertView
fus_createWithAnimateShowOn
:[
weakSelf
fus_viewWithLayer
:
FUSLiveFunctionLayerManualPopView
]];
};
self
.
releasePunishmentView
.
hidenStateDidChange
=
^
(
BOOL
isHidden
)
{
[
weakSelf
fus_reloadUIWithKeyboardSetPart
];
};
}
...
...
@@ -921,8 +920,15 @@ BDAlphaPlayerMetalViewDelegate
__weak
typeof
(
_chatTableView
)
weakChatTableView
=
_chatTableView
;
__weak
typeof
(
_pusherChatTableView
)
weakPusherChatTableView
=
_pusherChatTableView
;
[
_chatTableView
setOnClick
PatAudiencetHandler
:
^
(
FUSLiveChatModel
*
model
)
{
[
_chatTableView
setOnClick
MessageWithModel
:
^
(
FUSLiveChatDataClickType
type
,
FUSLiveChatModel
*
model
,
NSRange
range
)
{
if
(
type
==
FUSLiveChatDataClickTypeContent
)
{
// TODO: V57 需要完成这个
// 点击内容
// [FUSLiveChatContentPopView fus_createWithModel:model];
}
else
if
(
type
==
FUSLiveChatDataClickTypePatAudience
)
{
// 点击拍一拍
if
([
NSString
isNullWithString
:
model
.
realUid
])
{
return
;
}
...
...
@@ -944,9 +950,15 @@ BDAlphaPlayerMetalViewDelegate
}
[
FUSDialogView
fus_showDialog
:
msg
];
}];
}];
[
_chatTableView
setOnClickNicknameHandler
:
^
(
FUSLiveChatModel
*
model
)
{
}
else
if
(
type
==
FUSLiveChatDataClickTypeOrder
)
{
// 点击其他功能按钮
if
(
model
.
order
==
101
)
{
[
FUSLivePunishmentManager
fus_gotoReleaseIfInNeed
];
}
}
else
if
(
type
==
FUSLiveChatDataClickTypeNickname
)
{
// 点击昵称
[
weakSelf
endEditing
:
YES
];
// 如果需要点击跳转到露水礼物,跳转到露水礼物
...
...
@@ -958,16 +970,69 @@ BDAlphaPlayerMetalViewDelegate
if
(
model
.
isJump
&&
model
.
clickType
==
FUSLiveChatModelClickTypeOtherLiveRoom
&&
!
[
NSString
isNull
:
model
.
toUid
]
&&
!
[
model
.
toUid
isEqualToString
:[
FUSLiveHelper
shareInstance
].
roomInfoModel
.
roomId
]
&&
[
FUSLiveHelper
shareInstance
].
liveType
!=
FUSLiveTypeAnchor
)
{
&&
!
[
NSString
isNullWithString
:
model
.
toUid
]
&&
!
[
model
.
toUid
isEqualToString
:
FUSSwiftLiveHelper
.
shared
.
roomInfoModel
.
roomId
]
&&
FUSSwiftLiveHelper
.
shared
.
liveType
!=
FUSLiveTypeAnchor
)
{
NSString
*
chatString
=
[
weakSelf
.
chatTableView
.
dataSourceHelper
attributedStringForModelID
:
model
.
ID
].
string
;
NSString
*
nickname
=
nil
;
NSString
*
uid
=
nil
;
if
(
!
[
NSString
isNullWithString
:
model
.
nickname
])
{
nickname
=
model
.
nickname
;
uid
=
model
.
uid
;
}
else
if
(
!
[
NSString
isNullWithString
:
model
.
sendNickName
])
{
nickname
=
model
.
sendNickName
;
uid
=
model
.
sendUid
;
}
if
(
!
[
NSString
isNullWithString
:
nickname
]
&&
!
[
NSString
isNullWithString
:
uid
])
{
NSRange
senderRange
=
[
chatString
rangeOfString
:
nickname
];
if
(
range
.
location
>=
senderRange
.
location
&&
NSMaxRange
(
range
)
<=
NSMaxRange
(
senderRange
))
{
NSDictionary
*
dict
=
[
model
modelToJSONObject
];
FUSRoomUserInfoModel
*
userInfoModel
=
[
FUSRoomUserInfoModel
fus_modelWithDict
:
dict
];
// userInfoModel.medals = nil;
[
weakSelf
.
userInfoView
fus_showUserInfoViewWithUserInfoViewType
:
FUSUserInfoViewTypeLive
userInfoModel
:
userInfoModel
shouldRequestData
:
YES
];
return
;
}
}
if
(
!
[
NSString
isNullWithString
:
model
.
toNickName
])
{
NSRange
toNickNameRange
=
[
chatString
rangeOfString
:
model
.
toNickName
];
if
(
range
.
location
>=
toNickNameRange
.
location
&&
NSMaxRange
(
range
)
<=
NSMaxRange
(
toNickNameRange
))
{
if
([
NSString
isNullWithString
:
model
.
toUid
])
{
return
;
}
FUSRoomUserInfoModel
*
userInfoModel
=
[[
FUSRoomUserInfoModel
alloc
]
init
];
userInfoModel
.
uid
=
model
.
toUid
;
userInfoModel
.
realUid
=
model
.
toUid
;
// [BFModule(StatisticService) trackWithEventId:@"room_comment_infocard" value:1 params:@{}];
[
weakSelf
.
userInfoView
fus_showUserInfoViewWithUserInfoViewType
:
FUSUserInfoViewTypeLive
userInfoModel
:
userInfoModel
shouldRequestData
:
YES
];
return
;
}
}
NSString
*
toSeeStr
=
[
NSString
stringWithFormat
:
@",%@"
,[
NSString
fus_versionLocalString
:
@"去围观看看吧>"
]];
NSRange
toSeeStrRange
=
[
chatString
rangeOfString
:
toSeeStr
];
if
((
range
.
location
>=
toSeeStrRange
.
location
&&
NSMaxRange
(
range
)
<=
NSMaxRange
(
toSeeStrRange
))
||
[
NSString
isNullWithString
:
model
.
msg
])
{
NSString
*
nick
=
[
NSString
stringWithFormat
:
@"_#%@"
,
model
.
toNickName
];
NSString
*
message
=
[
NSString
stringWithFormat
:[
NSString
fus_l
ocalString
:
@"是否跳转到%@的直播间"
],
nick
];
NSString
*
message
=
[
NSString
stringWithFormat
:[
NSString
fus_versionL
ocalString
:
@"是否跳转到%@的直播间"
],
nick
];
NSRange
nickRange
=
[
message
rangeOfString
:
nick
];
NSMutableAttributedString
*
messageAtt
=
[[
NSMutableAttributedString
alloc
]
initWithString
:
message
attributes
:@{
NSForegroundColorAttributeName
:
[
UIColor
fus_textColorRich
]}];
[
messageAtt
addAttribute
:
NSForegroundColorAttributeName
value
:[
UIColor
fus_appMainColor
]
range
:
nickRange
];
NSMutableAttributedString
*
messageAtt
=
[[
NSMutableAttributedString
alloc
]
initWithString
:
message
attributes
:@{
NSForegroundColorAttributeName
:
[
UIColor
whiteColor
]}];
[
messageAtt
addAttribute
:
NSForegroundColorAttributeName
value
:[
UIColor
colorWithHex
:
@"#007AFF"
alpha
:
1
]
range
:
nickRange
];
[
messageAtt
deleteCharactersInRange
:
NSMakeRange
(
nickRange
.
location
,
2
)];
[
FUSAlertView
showAlertWithAttributeTitle
:
nil
attributeMessage
:
messageAtt
cancelButtonTitle
:
[
NSString
fus_localString
:
@"取消"
]
otherButtonTitles
:
@[[
NSString
fus_localString
:
@"确认"
]]
sureHandler
:^
(
NSInteger
buttonIndex
)
{
...
...
@@ -975,8 +1040,11 @@ BDAlphaPlayerMetalViewDelegate
FUSRoomInfoModel
*
roomModel
=
[[
FUSRoomInfoModel
alloc
]
init
];
roomModel
.
roomId
=
model
.
toUid
;
roomModel
.
face
=
model
.
toFace
;
[[
FUSLiveHelper
shareInstance
]
fus_switchRoomWithRoomInfoModel
:
roomModel
behaviorSrc
:
@""
success
:
nil
failure
:
nil
];
// [FFSwiftLiveHelper.shared switchRoomWithRoomInfoModel:roomModel success:nil failure:nil];
NSString
*
behaviorSrc
=
model
.
barrageType
.
integerValue
==
FUSbarrageTypeGlobal
?
@"6"
:
@"7"
;
[[
FUSSwiftLiveHelper
shared
]
switchRoomWithRoomInfoModel
:
roomModel
hasPreloadVideo
:
NO
behaviorSrc
:
behaviorSrc
success
:
nil
failure
:
nil
];
[
FUSLiveHttpHelper
fus_requestJumpToRoomStatFlowDataWithToRoomId
:
model
.
toUid
key
:
model
.
keyId
keySort
:
model
.
keySort
source
:
2
success
:
nil
failure
:
nil
];
// 等于1的时候是系统弹幕也就是发宝箱
[
FUSDataStatisticsManager
fus_behaviorJoinRoomLogWithReqType
:
7
reqEventType
:[
model
.
msgType
.
description
isEqualToString
:
@"1"
]
?
2
:
1
extraInfo
:
@""
extraJson
:
@""
roomId
:
roomModel
.
roomId
];
}
...
...
@@ -985,15 +1053,114 @@ BDAlphaPlayerMetalViewDelegate
return
;
}
if
([
NSString
isNull
:
model
.
uid
])
{
// if (![NSString isNullWithString:model.msg]) {
// [FFLiveChatContentPopView ff_createWithModel:model];
// }
// 最后分配给用户信息卡,以前是分配给content的,现在在cell内已经判断优先给content了
NSDictionary
*
dict
=
[
model
modelToJSONObject
];
FUSRoomUserInfoModel
*
userInfoModel
=
[
FUSRoomUserInfoModel
fus_modelWithDict
:
dict
];
// userInfoModel.medals = nil;
if
(
userInfoModel
.
realUid
!=
nil
)
{
[
weakSelf
.
userInfoView
fus_showUserInfoViewWithUserInfoViewType
:
FUSUserInfoViewTypeLive
userInfoModel
:
userInfoModel
shouldRequestData
:
YES
];
}
return
;
}
if
([
NSString
isNullWithString
:
model
.
realUid
]
||
model
.
realUid
.
length
<=
1
)
{
return
;
}
NSDictionary
*
dict
=
[
model
fus_getDictionary
];
NSDictionary
*
dict
=
[
model
modelToJSONObject
];
FUSRoomUserInfoModel
*
userInfoModel
=
[
FUSRoomUserInfoModel
fus_modelWithDict
:
dict
];
[
FUSTalkingData
fus_trackEvent
:
FUSLiveEventTrackParams
.
fus_EVENT_ROOM_COMMENT_INFOCARD
label
:
nil
parameters
:
nil
];
// userInfoModel.medals = nil;
[
weakSelf
.
userInfoView
fus_showUserInfoViewWithUserInfoViewType
:
FUSUserInfoViewTypeLive
userInfoModel
:
userInfoModel
shouldRequestData
:
YES
];
}
else
if
(
type
==
FUSLiveChatDataClickTypeComefrom
)
{
// 来自
FUSRoomUserInfoModel
*
userInfoModel
=
[[
FUSRoomUserInfoModel
alloc
]
init
];
userInfoModel
.
realUid
=
model
.
toUid
;
userInfoModel
.
face
=
model
.
toFace
;
userInfoModel
.
nickname
=
model
.
toNickName
;
[
weakSelf
.
userInfoView
fus_showUserInfoViewWithUserInfoViewType
:
FUSUserInfoViewTypeLive
userInfoModel
:
userInfoModel
shouldRequestData
:
YES
];
}
}];
// [_chatTableView setOnClickPatAudiencetHandler:^(FUSLiveChatModel *model) {
//
// if ([NSString isNullWithString:model.realUid]) {
// return;
// }
//
// model.patStatus = NO;
// [weakChatTableView fus_UpdataMessageWithModel:model];
// [weakPusherChatTableView fus_UpdataMessageWithModel:model];
// [FUSLiveHttpHelper fus_livePatUserWithRoomId:[FUSLiveHelper shareInstance].roomInfoModel.roomId toUserId:model.realUid succeed:^{
//
// } failure:^(NSString *msg, NSInteger code) {
//
// // -20109为已经拍过这个用户了,所以不需要重新显示了
// if (code != -20109) {
//
// // 拍失败则重新显示
// model.patStatus = YES;
// [weakChatTableView fus_UpdataMessageWithModel:model];
// [weakPusherChatTableView fus_UpdataMessageWithModel:model];
// }
// [FUSDialogView fus_showDialog:msg];
// }];
// }];
//
// [_chatTableView setOnClickNicknameHandler:^(FUSLiveChatModel *model) {
// [weakSelf endEditing:YES];
//
// // 如果需要点击跳转到露水礼物,跳转到露水礼物
// if (model.clickType == FUSLiveChatModelClickTypeDewGift) {
// [weakSelf fus_showSendGiftView];
// [[FUSLiveGiftView shareGiftView] fus_jumpToDewPageIfExist];
// return;
// }
//
// if (model.isJump
// && model.clickType == FUSLiveChatModelClickTypeOtherLiveRoom
// && ![NSString isNull:model.toUid]
// && ![model.toUid isEqualToString:[FUSLiveHelper shareInstance].roomInfoModel.roomId]
// && [FUSLiveHelper shareInstance].liveType != FUSLiveTypeAnchor) {
//
// NSString *nick = [NSString stringWithFormat:@"_#%@",model.toNickName];
//
// NSString *message = [NSString stringWithFormat:[NSString fus_localString:@"是否跳转到%@的直播间"],nick];
// NSRange nickRange = [message rangeOfString:nick];
// NSMutableAttributedString *messageAtt = [[NSMutableAttributedString alloc] initWithString:message attributes:@{NSForegroundColorAttributeName:[UIColor fus_textColorRich]}];
// [messageAtt addAttribute:NSForegroundColorAttributeName value:[UIColor fus_appMainColor] range:nickRange];
// [messageAtt deleteCharactersInRange:NSMakeRange(nickRange.location, 2)];
//
// [FUSAlertView showAlertWithAttributeTitle:nil attributeMessage:messageAtt cancelButtonTitle:[NSString fus_localString:@"取消"] otherButtonTitles:@[[NSString fus_localString:@"确认"]] sureHandler:^(NSInteger buttonIndex) {
// if (buttonIndex == 1) {
// FUSRoomInfoModel *roomModel = [[FUSRoomInfoModel alloc]init];
// roomModel.roomId = model.toUid;
// roomModel.face = model.toFace;
// [[FUSLiveHelper shareInstance] fus_switchRoomWithRoomInfoModel:roomModel behaviorSrc:@"" success:nil failure:nil];
// [FUSLiveHttpHelper fus_requestJumpToRoomStatFlowDataWithToRoomId:model.toUid key:model.keyId keySort:model.keySort source:2 success:nil failure:nil];
// [FUSDataStatisticsManager fus_behaviorJoinRoomLogWithReqType:7 reqEventType:[model.msgType.description isEqualToString:@"1"] ? 2 : 1 extraInfo:@"" extraJson:@"" roomId:roomModel.roomId];
// }
//
// } cancelHandler:nil];
//
// return;
// }
//
// if ([NSString isNull:model.uid]) {
// return;
// }
//
// NSDictionary *dict = [model fus_getDictionary];
// FUSRoomUserInfoModel *userInfoModel = [FUSRoomUserInfoModel fus_modelWithDict:dict];
// [FUSTalkingData fus_trackEvent:FUSLiveEventTrackParams.fus_EVENT_ROOM_COMMENT_INFOCARD label:nil parameters:nil];
// [weakSelf.userInfoView fus_showUserInfoViewWithUserInfoViewType:FUSUserInfoViewTypeLive userInfoModel:userInfoModel shouldRequestData:YES];
// }];
// 添加一个过渡遮罩
...
...
@@ -1209,7 +1376,13 @@ BDAlphaPlayerMetalViewDelegate
__weak
typeof
(
_chatTableView
)
weakChatTableView
=
_chatTableView
;
__weak
typeof
(
_pusherChatTableView
)
weakPusherChatTableView
=
_pusherChatTableView
;
[
_pusherChatTableView
setOnClickPatAudiencetHandler
:
^
(
FUSLiveChatModel
*
model
)
{
[
_pusherChatTableView
setOnClickMessageWithModel
:
^
(
FUSLiveChatDataClickType
type
,
FUSLiveChatModel
*
model
,
NSRange
range
)
{
if
(
type
==
FUSLiveChatDataClickTypeContent
)
{
// TODO: V57 需要完成这个
// [FFLiveChatContentPopView ff_createWithModel:model];
}
else
if
(
type
==
FUSLiveChatDataClickTypePatAudience
)
{
if
([
NSString
isNullWithString
:
model
.
realUid
])
{
return
;
...
...
@@ -1232,9 +1405,14 @@ BDAlphaPlayerMetalViewDelegate
}
[
FUSDialogView
fus_showDialog
:
msg
];
}];
}];
}
else
if
(
type
==
FUSLiveChatDataClickTypeOrder
)
{
if
(
model
.
order
==
101
)
{
[
FUSLivePunishmentManager
fus_gotoReleaseIfInNeed
];
}
}
else
if
(
type
==
FUSLiveChatDataClickTypeNickname
)
{
[
_pusherChatTableView
setOnClickNicknameHandler
:
^
(
FUSLiveChatModel
*
model
)
{
[
weakSelf
endEditing
:
YES
];
// 如果需要点击跳转到露水礼物,跳转到露水礼物
...
...
@@ -1244,43 +1422,98 @@ BDAlphaPlayerMetalViewDelegate
return
;
}
if
(
model
.
isJump
&&
model
.
clickType
==
FUSLiveChatModelClickTypeOtherLiveRoom
&&
!
[
NSString
isNull
:
model
.
toUid
]
&&
!
[
model
.
toUid
isEqualToString
:[
FUSLiveHelper
shareInstance
].
roomInfoModel
.
roomId
]
&&
[
FUSLiveHelper
shareInstance
].
liveType
!=
FUSLiveTypeAnchor
)
{
NSString
*
message
=
[
NSString
stringWithFormat
:[
NSString
fus_localString
:
@"是否跳转到%@的直播间"
],
model
.
toNickName
];
NSRange
nickRange
=
[
message
rangeOfString
:
model
.
toNickName
];
NSMutableAttributedString
*
messageAtt
=
[[
NSMutableAttributedString
alloc
]
initWithString
:
message
attributes
:@{
NSForegroundColorAttributeName
:
[
UIColor
fus_textColorRich
]}];
[
messageAtt
addAttribute
:
NSForegroundColorAttributeName
value
:[
UIColor
fus_appMainColor
]
range
:
nickRange
];
[
FUSAlertView
showAlertWithAttributeTitle
:
nil
attributeMessage
:
messageAtt
cancelButtonTitle
:
[
NSString
fus_localString
:
@"取消"
]
otherButtonTitles
:
@[[
NSString
fus_localString
:
@"确认"
]]
sureHandler
:^
(
NSInteger
buttonIndex
)
{
if
(
buttonIndex
==
1
)
{
FUSRoomInfoModel
*
roomModel
=
[[
FUSRoomInfoModel
alloc
]
init
];
roomModel
.
roomId
=
model
.
toUid
;
roomModel
.
face
=
model
.
toFace
;
[[
FUSLiveHelper
shareInstance
]
fus_switchRoomWithRoomInfoModel
:
roomModel
behaviorSrc
:
@""
success
:
nil
failure
:
nil
];
[
FUSLiveHttpHelper
fus_requestJumpToRoomStatFlowDataWithToRoomId
:
model
.
toUid
key
:
model
.
keyId
keySort
:
model
.
keySort
source
:
2
success
:
nil
failure
:
nil
];
[
FUSDataStatisticsManager
fus_behaviorJoinRoomLogWithReqType
:
7
reqEventType
:[
model
.
msgType
.
description
isEqualToString
:
@"1"
]
?
2
:
1
extraInfo
:
@""
extraJson
:
@""
roomId
:
roomModel
.
roomId
];
}
}
cancelHandler
:
nil
];
return
;
}
if
([
NSString
isNull
:
model
.
uid
])
{
if
([
NSString
isNullWithString
:
model
.
realUid
]
||
model
.
realUid
.
length
<=
1
)
{
return
;
}
FUSRoomUserInfoModel
*
userInfoModel
=
[[
FUSRoomUserInfoModel
alloc
]
init
];
[
userInfoModel
fus_setValueWithModel
:
model
];
[
FUSTalkingData
fus_trackEvent
:
FUSLiveEventTrackParams
.
fus_EVENT_ROOM_COMMENT_INFOCARD
label
:
nil
parameters
:
nil
];
// [BFModule(StatisticService) trackWithEventId:@"room_comment_infocard" value:1 params:@{}];
// userInfoModel.cannotBeAt = YES;
[
weakSelf
.
userInfoView
fus_showUserInfoViewWithUserInfoViewType
:
FUSUserInfoViewTypeLive
userInfoModel
:
userInfoModel
shouldRequestData
:
YES
];
}
else
if
(
type
==
FUSLiveChatDataClickTypeComefrom
)
{
// 来自
FUSRoomUserInfoModel
*
userInfoModel
=
[[
FUSRoomUserInfoModel
alloc
]
init
];
userInfoModel
.
realUid
=
model
.
toUid
;
userInfoModel
.
face
=
model
.
toFace
;
userInfoModel
.
nickname
=
model
.
toNickName
;
[
weakSelf
.
userInfoView
fus_showUserInfoViewWithUserInfoViewType
:
FUSUserInfoViewTypeLive
userInfoModel
:
userInfoModel
shouldRequestData
:
YES
];
}
}];
// [_pusherChatTableView setOnClickPatAudiencetHandler:^(FUSLiveChatModel *model) {
//
// if ([NSString isNullWithString:model.realUid]) {
// return;
// }
//
// model.patStatus = NO;
// [weakChatTableView fus_UpdataMessageWithModel:model];
// [weakPusherChatTableView fus_UpdataMessageWithModel:model];
// [FUSLiveHttpHelper fus_livePatUserWithRoomId:[FUSLiveHelper shareInstance].roomInfoModel.roomId toUserId:model.realUid succeed:^{
//
// } failure:^(NSString *msg, NSInteger code) {
//
// // -20109为已经拍过这个用户了,所以不需要重新显示了
// if (code != -20109) {
//
// // 拍失败则重新显示
// model.patStatus = YES;
// [weakChatTableView fus_UpdataMessageWithModel:model];
// [weakPusherChatTableView fus_UpdataMessageWithModel:model];
// }
// [FUSDialogView fus_showDialog:msg];
// }];
// }];
//
// [_pusherChatTableView setOnClickNicknameHandler:^(FUSLiveChatModel *model) {
// [weakSelf endEditing:YES];
//
// // 如果需要点击跳转到露水礼物,跳转到露水礼物
// if (model.clickType == FUSLiveChatModelClickTypeDewGift) {
// [weakSelf fus_showSendGiftView];
// [[FUSLiveGiftView shareGiftView] fus_jumpToDewPageIfExist];
// return;
// }
//
// if (model.isJump
// && model.clickType == FUSLiveChatModelClickTypeOtherLiveRoom
// && ![NSString isNull:model.toUid]
// && ![model.toUid isEqualToString:[FUSLiveHelper shareInstance].roomInfoModel.roomId]
// && [FUSLiveHelper shareInstance].liveType != FUSLiveTypeAnchor) {
//
//
// NSString *message = [NSString stringWithFormat:[NSString fus_localString:@"是否跳转到%@的直播间"],model.toNickName];
// NSRange nickRange = [message rangeOfString:model.toNickName];
// NSMutableAttributedString *messageAtt = [[NSMutableAttributedString alloc] initWithString:message attributes:@{NSForegroundColorAttributeName:[UIColor fus_textColorRich]}];
// [messageAtt addAttribute:NSForegroundColorAttributeName value:[UIColor fus_appMainColor] range:nickRange];
//
// [FUSAlertView showAlertWithAttributeTitle:nil attributeMessage:messageAtt cancelButtonTitle:[NSString fus_localString:@"取消"] otherButtonTitles:@[[NSString fus_localString:@"确认"]] sureHandler:^(NSInteger buttonIndex) {
// if (buttonIndex == 1) {
// FUSRoomInfoModel *roomModel = [[FUSRoomInfoModel alloc]init];
// roomModel.roomId = model.toUid;
// roomModel.face = model.toFace;
// [[FUSLiveHelper shareInstance] fus_switchRoomWithRoomInfoModel:roomModel behaviorSrc:@"" success:nil failure:nil];
// [FUSLiveHttpHelper fus_requestJumpToRoomStatFlowDataWithToRoomId:model.toUid key:model.keyId keySort:model.keySort source:2 success:nil failure:nil];
// [FUSDataStatisticsManager fus_behaviorJoinRoomLogWithReqType:7 reqEventType:[model.msgType.description isEqualToString:@"1"] ? 2 : 1 extraInfo:@"" extraJson:@"" roomId:roomModel.roomId];
// }
//
// } cancelHandler:nil];
//
// return;
// }
//
// if ([NSString isNull:model.uid]) {
// return;
// }
//
// FUSRoomUserInfoModel *userInfoModel = [[FUSRoomUserInfoModel alloc]init];
// [userInfoModel fus_setValueWithModel:model];
// [FUSTalkingData fus_trackEvent:FUSLiveEventTrackParams.fus_EVENT_ROOM_COMMENT_INFOCARD label:nil parameters:nil];
// // userInfoModel.cannotBeAt = YES;
// [weakSelf.userInfoView fus_showUserInfoViewWithUserInfoViewType:FUSUserInfoViewTypeLive userInfoModel:userInfoModel shouldRequestData:YES];
// }];
// 添加一个过渡遮罩
CAGradientLayer
*
gradientLayer
=
[
CAGradientLayer
layer
];
...
...
Modules/FUSShowRoomModule/FUSShowRoomModule/Features/NewLive/Main/View/FunctionView/PK/FUSPKNew/FUSView/FUSPKContentView/SubViews/UserContributeView/FFPKUserContributeListView.swift
View file @
e4e310c5
...
...
@@ -51,6 +51,9 @@ extension FFPKUserContributeListView{
class
FFPKUserContributeListView
:
FUSBaseView
{
/// 刷新头像的垃圾袋
private
var
refreshCollectionViewActionDisposebag
=
DisposeBag
()
/// 点击了头像
public
var
faceDidClick
:
((
FFPKContributeUserModel
?)
->
Void
)?
...
...
@@ -142,29 +145,56 @@ class FFPKUserContributeListView: FUSBaseView {
})
.
disposed
(
by
:
disposeBag
)
if
FUSSwiftLiveHelper
.
shared
.
liveType
==
.
anchor
{
// 主播根据是否关闭pk动效做优化
FFPKControlDataHelper
.
share
.
pkAnimationIsOn
.
distinctUntilChanged
()
.
subscribe
(
onNext
:
{[
weak
self
]
isOn
in
guard
let
self
=
self
else
{
return
}
/// 关闭动效的话2秒更新一次
let
refreshDelay
:
Int
=
isOn
?
800
:
2000
self
.
fus_setupCollectionViewUpdateAction
(
refreshDelay
:
refreshDelay
)
})
.
disposed
(
by
:
disposeBag
)
}
else
{
self
.
fus_setupCollectionViewUpdateAction
(
refreshDelay
:
800
)
}
}
/// 设置刷新计时器,单位毫秒
private
func
fus_setupCollectionViewUpdateAction
(
refreshDelay
:
Int
)
{
self
.
refreshCollectionViewActionDisposebag
=
.
init
()
// ui在这里更新,和数据传输严格分离,解决崩溃问题
Observable
<
Int
>.
interval
(
.
milliseconds
(
800
),
scheduler
:
MainScheduler
.
instance
)
Observable
<
Int
>.
interval
(
.
milliseconds
(
refreshDelay
),
scheduler
:
MainScheduler
.
instance
)
.
subscribe
(
onNext
:
{[
weak
self
]
_
in
self
?
.
ff_updateCollectionViewCacheData
()
})
.
disposed
(
by
:
disposeB
ag
)
.
disposed
(
by
:
self
.
refreshCollectionViewActionDisposeb
ag
)
}
func
setUsers
(
_
users
:
[
FFPKContributeUserModel
],
total
:
Int
,
showAnim
:
Bool
,
sideColor
:
FFPKSideColor
)
{
// dispatch_async_on_main_queue {
self
.
totalUser
=
total
self
.
showAnim
=
showAnim
self
.
sideColor
=
sideColor
if
FUSSwiftLiveHelper
.
shared
.
liveType
==
.
anchor
&&
FFPKControlDataHelper
.
share
.
pkAnimationIsOn
.
value
==
false
{
// 主播根据是否关闭pk动效做优化
self
.
showAnim
=
false
}
if
self
.
users
.
count
<=
0
||
UIApplication
.
shared
.
applicationState
!=
.
active
{
// self.updateCollectionView(with: users, isReloadData: true)
self
.
ff_preUpdateCollectionView
(
with
:
users
,
isReloadData
:
true
)
}
else
{
// self.updateCollectionView(with: users, isReloadData: false)
self
.
ff_preUpdateCollectionView
(
with
:
users
,
isReloadData
:
false
)
}
// }
}
/// 准备更新 CollectionView,这里仅仅做数据收集
...
...
Modules/FUSShowRoomModule/FUSShowRoomModule/Features/NewLive/Main/View/FunctionView/PK/FUSPKNew/FUSView/FUSPKControlView/FFPKControlPKModeView.swift
View file @
e4e310c5
...
...
@@ -21,9 +21,12 @@ class FFPKControlPKModeView: FFPKControlSubBaseView {
/// 当前选择
var
currentSelect
:
Int
=
0
let
itemWidth
:
CGFloat
=
172
let
itemMargin
:
CGFloat
=
12
let
collectionMargin
:
CGFloat
=
18
let
pkModeItemWidth
:
CGFloat
=
172
let
pkModeItemMargin
:
CGFloat
=
12
let
pkModeCollectionMargin
:
CGFloat
=
18
let
gamePlayItemWidth
:
CGFloat
=
160
let
gamePlayItemMargin
:
CGFloat
=
6
override
func
makeUI
()
{
super
.
makeUI
()
...
...
@@ -69,10 +72,10 @@ class FFPKControlPKModeView: FFPKControlSubBaseView {
if
let
layout
=
self
.
collectionView
.
collectionViewLayout
as?
JJCollectionViewRoundFlowLayout_Swift
{
layout
.
scrollDirection
=
.
horizontal
layout
.
minimumLineSpacing
=
itemMargin
layout
.
minimumInteritemSpacing
=
itemMargin
layout
.
itemSize
=
CGSize
(
width
:
itemWidth
,
height
:
196
)
layout
.
sectionInset
=
UIEdgeInsets
(
top
:
0
,
left
:
collectionMargin
,
bottom
:
0
,
right
:
c
ollectionMargin
)
//
layout.minimumLineSpacing = itemMargin
//
layout.minimumInteritemSpacing = itemMargin
//
layout.itemSize = CGSize(width: itemWidth, height: 196)
layout
.
sectionInset
=
UIEdgeInsets
(
top
:
0
,
left
:
pkModeCollectionMargin
,
bottom
:
0
,
right
:
pkModeC
ollectionMargin
)
layout
.
collectionCellAlignmentType
=
.
Center
layout
.
isRoundEnabled
=
false
...
...
@@ -83,7 +86,7 @@ class FFPKControlPKModeView: FFPKControlSubBaseView {
self
.
collectionView
.
snp
.
makeConstraints
{
make
in
make
.
left
.
right
.
equalToSuperview
()
make
.
top
.
equalTo
(
modeDescLabel
.
snp
.
bottom
)
.
offset
(
10
)
make
.
height
.
equalTo
(
210
)
//
make.height.equalTo(210)
}
self
.
nextBtn
.
style
=
.
gradientLeftToRight
...
...
@@ -94,6 +97,7 @@ class FFPKControlPKModeView: FFPKControlSubBaseView {
make
.
top
.
equalTo
(
collectionView
.
snp
.
bottom
)
.
offset
(
14
)
make
.
centerX
.
equalToSuperview
()
make
.
size
.
equalTo
(
CGSizeMake
(
252
,
44
))
make
.
bottom
.
equalToSuperview
()
.
offset
(
-
UIView
.
fus_SafeBottom
()
-
10
)
}
self
.
nextBtn
.
isHidden
=
true
}
...
...
@@ -144,21 +148,37 @@ class FFPKControlPKModeView: FFPKControlSubBaseView {
func
ff_reloadCollectionView
(){
if
self
.
viewType
==
.
pkGamePlay
{
// 玩法一直都是竖直的
self
.
collectionViewLayout
?
.
scrollDirection
=
.
vertical
self
.
collectionViewLayout
?
.
minimumLineSpacing
=
self
.
gamePlayItemMargin
self
.
collectionViewLayout
?
.
minimumInteritemSpacing
=
self
.
gamePlayItemMargin
self
.
collectionViewLayout
?
.
collectionCellAlignmentType
=
.
Left
let
leftRightMargin
:
CGFloat
=
(
self
.
collectionView
.
width
-
(
gamePlayItemWidth
*
2
+
gamePlayItemMargin
))
/
2.0
self
.
collectionViewLayout
?
.
sectionInset
=
UIEdgeInsets
(
top
:
0
,
left
:
leftRightMargin
,
bottom
:
0
,
right
:
leftRightMargin
)
}
else
{
// pk 模式不变
let
itemCount
:
CGFloat
=
CGFloat
(
self
.
dataList
.
count
)
if
itemCount
<=
1
{
self
.
collectionViewLayout
?
.
scrollDirection
=
.
vertical
}
if
itemCount
*
itemWidth
+
(
itemCount
-
1
)
*
itemMargin
+
2*
c
ollectionMargin
<
UIView
.
fus_screenW
()
{
if
itemCount
*
pkModeItemWidth
+
(
itemCount
-
1
)
*
pkModeItemMargin
+
2*
pkModeC
ollectionMargin
<
UIView
.
fus_screenW
()
{
self
.
collectionViewLayout
?
.
scrollDirection
=
.
vertical
}
else
{
self
.
collectionViewLayout
?
.
scrollDirection
=
.
horizontal
}
self
.
collectionViewLayout
?
.
minimumLineSpacing
=
self
.
pkModeItemMargin
self
.
collectionViewLayout
?
.
minimumInteritemSpacing
=
self
.
pkModeItemMargin
self
.
collectionViewLayout
?
.
sectionInset
=
UIEdgeInsets
(
top
:
0
,
left
:
pkModeCollectionMargin
,
bottom
:
0
,
right
:
pkModeCollectionMargin
)
self
.
collectionViewLayout
?
.
collectionCellAlignmentType
=
.
Center
}
self
.
collectionView
.
reloadData
()
}
}
extension
FFPKControlPKModeView
:
UICollectionViewDelegate
,
UICollectionViewDataSource
{
extension
FFPKControlPKModeView
:
UICollectionViewDelegate
,
UICollectionViewDataSource
,
UICollectionViewDelegateFlowLayout
{
func
numberOfSections
(
in
collectionView
:
UICollectionView
)
->
Int
{
return
1
}
...
...
@@ -172,6 +192,17 @@ extension FFPKControlPKModeView: UICollectionViewDelegate, UICollectionViewDataS
}
return
.
init
()
}
func
collectionView
(
_
collectionView
:
UICollectionView
,
layout
collectionViewLayout
:
UICollectionViewLayout
,
sizeForItemAt
indexPath
:
IndexPath
)
->
CGSize
{
if
self
.
viewType
==
.
pkGamePlay
{
if
indexPath
.
row
==
0
{
return
CGSizeMake
(
gamePlayItemWidth
*
2
+
gamePlayItemMargin
,
134
)
}
return
CGSize
(
width
:
gamePlayItemWidth
,
height
:
100
)
}
else
{
return
CGSize
(
width
:
pkModeItemWidth
,
height
:
196
)
}
}
func
collectionView
(
_
collectionView
:
UICollectionView
,
didSelectItemAt
indexPath
:
IndexPath
)
{
self
.
currentSelect
=
indexPath
.
row
collectionView
.
reloadData
()
...
...
Modules/FUSShowRoomModule/FUSShowRoomModule/Features/NewLive/Main/View/FunctionView/PK/FUSPKNew/FUSView/FUSPKControlView/FFPKControlSettingView.swift
View file @
e4e310c5
...
...
@@ -16,6 +16,7 @@ class FFPKControlSettingView: FFPKControlSubBaseView {
let
sectionColorView
=
UIView
()
let
acceptPkView
=
FFPKControlSettingSwitchView
()
let
messageIntercommunicationView
=
FFPKControlSettingSwitchView
()
let
pkAnimationControlView
=
FFPKControlSettingSwitchView
()
// 数据
var
acceptPk
:
Int
=
1
...
...
@@ -61,10 +62,18 @@ class FFPKControlSettingView: FFPKControlSubBaseView {
messageIntercommunicationView
.
titleLabel
.
text
=
.
fus_versionLocalString
(
"公屏消息互通"
)
sectionColorView
.
addSubview
(
messageIntercommunicationView
)
messageIntercommunicationView
.
snp
.
makeConstraints
{
make
in
make
.
left
.
right
.
bottom
.
equalToSuperview
()
make
.
left
.
right
.
equalToSuperview
()
make
.
height
.
equalTo
(
62
)
make
.
top
.
equalTo
(
acceptPkView
.
snp
.
bottom
)
}
pkAnimationControlView
.
titleLabel
.
text
=
.
fus_versionLocalString
(
"关闭 PK 动效"
)
sectionColorView
.
addSubview
(
pkAnimationControlView
)
pkAnimationControlView
.
snp
.
makeConstraints
{
make
in
make
.
left
.
right
.
bottom
.
equalToSuperview
()
make
.
height
.
equalTo
(
62
)
make
.
top
.
equalTo
(
messageIntercommunicationView
.
snp
.
bottom
)
}
}
override
func
bindViewModel
()
{
...
...
@@ -107,6 +116,11 @@ class FFPKControlSettingView: FFPKControlSubBaseView {
})
.
disposed
(
by
:
disposeBag
)
self
.
pkAnimationControlView
.
switchControl
.
isOn
=
!
FFPKControlDataHelper
.
share
.
pkAnimationIsOn
.
value
self
.
pkAnimationControlView
.
switchDidClicked
=
{
isOn
in
FFPKControlDataHelper
.
share
.
pkAnimationIsOn
.
accept
(
!
isOn
)
}
}
override
func
ff_setupViewModel
()
{
...
...
Modules/FUSShowRoomModule/FUSShowRoomModule/Features/NewLive/Main/View/FunctionView/PK/FUSPKNew/FUSView/FUSPKControlView/ViewModel/FFPKControlDataHelper.swift
View file @
e4e310c5
...
...
@@ -61,6 +61,9 @@ import SwiftyJSON
/// 惩罚列表
public
let
vsPunishList
:
BehaviorRelay
<
[
FFVSPunishGetListDataModel
]
>
=
.
init
(
value
:
.
init
())
/// pk动画是否开启
public
let
pkAnimationIsOn
:
BehaviorRelay
<
Bool
>
=
.
init
(
value
:
true
)
/// 当前请求数据的语言
private
var
baseDataLanguage
=
FUSLocalizationHelper
.
fus_currentLanguage
()
.
languageType
...
...
@@ -82,6 +85,15 @@ import SwiftyJSON
})
.
disposed
(
by
:
disposeBag
)
let
pkAnimationIsOnValue
=
UserDefaults
.
standard
.
value
(
forKey
:
FUSShowRoomUDKeyStore
.
pkAnimationControlLocalStoreKey
)
??
true
self
.
pkAnimationIsOn
.
accept
(
true
)
self
.
pkAnimationIsOn
.
skip
(
1
)
.
distinctUntilChanged
()
.
subscribe
(
onNext
:
{
pkAnimationIsOn
in
UserDefaults
.
standard
.
setValue
(
pkAnimationIsOn
,
forKey
:
FUSShowRoomUDKeyStore
.
pkAnimationControlLocalStoreKey
)
})
.
disposed
(
by
:
disposeBag
)
}
...
...
Modules/FUSShowRoomModule/FUSShowRoomModule/Others/FUSShowRoomUDKeyStore.swift
0 → 100644
View file @
e4e310c5
//
// FUSShowRoomUDKeyStore.swift
// FUSShowRoomModule
//
// Created by aaa on 2026/2/28.
//
import
UIKit
@objc
public
class
FUSShowRoomUDKeyStore
:
NSObject
{
@objc
public
static
let
pkAnimationControlLocalStoreKey
:
String
=
"FUSShowRoomUDKeyStore_pkAnimationControlLocalStoreKey"
}
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment