添加消息长按弹窗

This commit is contained in:
2026-02-03 15:53:07 +08:00
parent d482cfcb7d
commit a0923c8572
6 changed files with 368 additions and 1 deletions

View File

@@ -12,6 +12,9 @@
#import "KBImagePositionButton.h"
#import "KBAICommentView.h"
#import "KBAIChatMessageCacheManager.h"
#import "KBChatMessageActionPopView.h"
#import "AIReportVC.h"
#import "KBHUD.h"
#import <Masonry/Masonry.h>
#import <SDWebImage/SDWebImage.h>
#import <LSTPopView/LSTPopView.h>
@@ -19,7 +22,7 @@
///
static NSString * const KBChatSessionDidResetNotification = @"KBChatSessionDidResetNotification";
@interface KBPersonaChatCell () <KBChatTableViewDelegate>
@interface KBPersonaChatCell () <KBChatTableViewDelegate, KBChatMessageActionPopViewDelegate>
///
@property (nonatomic, strong) UIImageView *backgroundImageView;
@@ -65,6 +68,9 @@ static NSString * const KBChatSessionDidResetNotification = @"KBChatSessionDidRe
@property (nonatomic, assign) BOOL shouldAutoPlayPrologueAudio;
@property (nonatomic, assign) BOOL hasPlayedPrologueAudio;
@property (nonatomic, assign) BOOL shouldShowOpeningMessage;
@property (nonatomic, weak) LSTPopView *messageActionPopView;
@property (nonatomic, strong) KBAiChatMessage *selectedActionMessage;
@property (nonatomic, strong) UIControl *messageActionMaskView;
@end
@@ -898,6 +904,126 @@ static NSString * const KBChatSessionDidResetNotification = @"KBChatSessionDidRe
[self loadMoreHistory];
}
- (void)chatTableView:(KBChatTableView *)chatView
didLongPressMessage:(KBAiChatMessage *)message
sourceRect:(CGRect)sourceRect {
[self showMessageActionPopForMessage:message sourceRect:sourceRect];
}
#pragma mark - KBChatMessageActionPopViewDelegate
- (void)chatMessageActionPopView:(KBChatMessageActionPopView *)view
didSelectAction:(KBChatMessageActionType)action {
[self dismissMessageActionPop];
KBAiChatMessage *message = self.selectedActionMessage;
self.selectedActionMessage = nil;
if (!message) {
return;
}
switch (action) {
case KBChatMessageActionTypeCopy: {
if (message.text.length > 0) {
[UIPasteboard generalPasteboard].string = message.text;
[KBHUD showSuccess:KBLocalized(@"复制成功")];
}
} break;
case KBChatMessageActionTypeDelete: {
NSInteger idx = [self.messages indexOfObjectIdenticalTo:message];
if (idx != NSNotFound) {
[self.messages removeObjectAtIndex:idx];
[self.chatView reloadWithMessages:self.messages
keepOffset:YES
scrollToBottom:NO];
if (self.persona.personaId > 0) {
if (self.messages.count > 0) {
[[KBAIChatMessageCacheManager shared] saveMessages:self.messages
forCompanionId:self.persona.personaId];
} else {
[[KBAIChatMessageCacheManager shared] clearMessagesForCompanionId:self.persona.personaId];
}
}
}
} break;
case KBChatMessageActionTypeReport: {
if (self.persona.personaId <= 0) {
return;
}
AIReportVC *vc = [[AIReportVC alloc] init];
vc.personaId = self.persona.personaId;
[KB_CURRENT_NAV pushViewController:vc animated:YES];
} break;
default:
break;
}
}
#pragma mark - Message Action Pop
- (void)showMessageActionPopForMessage:(KBAiChatMessage *)message
sourceRect:(CGRect)sourceRect {
if (!message) {
return;
}
[self dismissMessageActionPop];
self.selectedActionMessage = message;
CGFloat width = 240;
CGFloat height = 156;
KBChatMessageActionPopView *content = [[KBChatMessageActionPopView alloc]
initWithFrame:CGRectMake(0, 0, width, height)];
content.delegate = self;
UIWindow *window = [UIApplication sharedApplication].keyWindow;
if (!window) {
window = [UIApplication sharedApplication].windows.firstObject;
}
if (!window) {
return;
}
UIControl *mask = [[UIControl alloc] initWithFrame:window.bounds];
[mask addTarget:self action:@selector(dismissMessageActionPop) forControlEvents:UIControlEventTouchUpInside];
[window addSubview:mask];
self.messageActionMaskView = mask;
BOOL isUserMessage = (message.type == KBAiChatMessageTypeUser);
CGFloat margin = 12.0;
CGFloat spacing = 8.0;
CGFloat topSafe = 0.0;
CGFloat bottomSafe = 0.0;
if (@available(iOS 11.0, *)) {
topSafe = window.safeAreaInsets.top;
bottomSafe = window.safeAreaInsets.bottom;
}
CGFloat x = isUserMessage ? CGRectGetMaxX(sourceRect) - width : CGRectGetMinX(sourceRect);
x = MAX(margin, MIN(x, CGRectGetWidth(window.bounds) - width - margin));
CGFloat y = CGRectGetMinY(sourceRect) - height - spacing;
if (y < topSafe + margin) {
y = CGRectGetMaxY(sourceRect) + spacing;
}
if (y + height > CGRectGetHeight(window.bounds) - bottomSafe - margin) {
y = MAX(topSafe + margin, CGRectGetHeight(window.bounds) - bottomSafe - margin - height);
}
content.frame = CGRectMake(x, y, width, height);
[mask addSubview:content];
}
- (void)dismissMessageActionPop {
if (self.messageActionPopView) {
[self.messageActionPopView dismiss];
self.messageActionPopView = nil;
}
if (self.messageActionMaskView) {
[self.messageActionMaskView removeFromSuperview];
self.messageActionMaskView = nil;
}
}
#pragma mark - Lazy Load
- (UIImageView *)backgroundImageView {