添加侧边栏
This commit is contained in:
@@ -19,10 +19,11 @@
|
||||
#import "LSTPopView.h"
|
||||
#import "KBAIMessageVC.h"
|
||||
#import "KBAICommentInputView.h"
|
||||
#import "KBAIPersonaSidebarView.h"
|
||||
#import <Masonry/Masonry.h>
|
||||
#import <SDWebImage/SDWebImage.h>
|
||||
|
||||
@interface KBAIHomeVC () <UICollectionViewDelegate, UICollectionViewDataSource, KBVoiceToTextManagerDelegate, KBVoiceRecordManagerDelegate, UIGestureRecognizerDelegate, KBChatLimitPopViewDelegate>
|
||||
@interface KBAIHomeVC () <UICollectionViewDelegate, UICollectionViewDataSource, KBVoiceToTextManagerDelegate, KBVoiceRecordManagerDelegate, UIGestureRecognizerDelegate, KBChatLimitPopViewDelegate, KBAIPersonaSidebarViewDelegate>
|
||||
|
||||
/// 人设列表容器
|
||||
@property (nonatomic, strong) UICollectionView *collectionView;
|
||||
@@ -90,11 +91,22 @@
|
||||
|
||||
/// 右上角消息按钮
|
||||
@property (nonatomic, strong) UIButton *messageButton;
|
||||
/// 左上角人设列表按钮
|
||||
@property (nonatomic, strong) UIButton *sidebarButton;
|
||||
|
||||
/// 侧边栏 PopView
|
||||
@property (nonatomic, weak) LSTPopView *sidebarPopView;
|
||||
@property (nonatomic, strong) KBAIPersonaSidebarView *sidebarView;
|
||||
|
||||
/// 侧边栏选中的人设 ID
|
||||
@property (nonatomic, assign) NSInteger selectedPersonaId;
|
||||
|
||||
@end
|
||||
|
||||
@implementation KBAIHomeVC
|
||||
|
||||
static NSString * const KBAISelectedPersonaIdKey = @"KBAISelectedPersonaId";
|
||||
|
||||
#pragma mark - Keyboard Gate
|
||||
|
||||
/// 查找当前 view 树里的 firstResponder
|
||||
@@ -194,6 +206,14 @@
|
||||
make.right.equalTo(self.view).offset(-16);
|
||||
make.width.height.mas_equalTo(32);
|
||||
}];
|
||||
|
||||
// 左上角人设列表按钮
|
||||
[self.view addSubview:self.sidebarButton];
|
||||
[self.sidebarButton mas_makeConstraints:^(MASConstraintMaker *make) {
|
||||
make.top.equalTo(self.view).offset(KB_STATUSBAR_HEIGHT + 10);
|
||||
make.left.equalTo(self.view).offset(16);
|
||||
make.width.height.mas_equalTo(32);
|
||||
}];
|
||||
|
||||
// 底部毛玻璃背景
|
||||
[self.view addSubview:self.bottomBackgroundView];
|
||||
@@ -262,6 +282,7 @@
|
||||
}
|
||||
|
||||
self.isLoading = YES;
|
||||
NSInteger oldCount = self.personas.count;
|
||||
|
||||
__weak typeof(self) weakSelf = self;
|
||||
[self.aiVM fetchPersonasWithPageNum:self.currentPage
|
||||
@@ -283,9 +304,31 @@
|
||||
weakSelf.hasMore = pageModel.hasMore;
|
||||
|
||||
dispatch_async(dispatch_get_main_queue(), ^{
|
||||
[weakSelf.collectionView reloadData];
|
||||
if (weakSelf.currentPage == 1) {
|
||||
[weakSelf.collectionView reloadData];
|
||||
[weakSelf preloadDataForIndexes:@[@0, @1, @2]];
|
||||
} else if (pageModel.records.count > 0) {
|
||||
NSInteger newCount = weakSelf.personas.count;
|
||||
NSMutableArray<NSIndexPath *> *indexPaths = [NSMutableArray array];
|
||||
for (NSInteger i = oldCount; i < newCount; i++) {
|
||||
[indexPaths addObject:[NSIndexPath indexPathForItem:i inSection:0]];
|
||||
}
|
||||
[UIView performWithoutAnimation:^{
|
||||
[weakSelf.collectionView performBatchUpdates:^{
|
||||
[weakSelf.collectionView insertItemsAtIndexPaths:indexPaths];
|
||||
} completion:nil];
|
||||
}];
|
||||
}
|
||||
if (weakSelf.selectedPersonaId <= 0 && weakSelf.personas.count > 0) {
|
||||
NSInteger index = MIN(MAX(weakSelf.currentIndex, 0), weakSelf.personas.count - 1);
|
||||
[weakSelf storeSelectedPersonaId:weakSelf.personas[index].personaId];
|
||||
}
|
||||
if (weakSelf.sidebarView) {
|
||||
[weakSelf.sidebarView updatePersonas:weakSelf.personas
|
||||
reset:(weakSelf.currentPage == 1)
|
||||
hasMore:weakSelf.hasMore
|
||||
currentPage:weakSelf.currentPage];
|
||||
[weakSelf.sidebarView updateSelectedPersonaId:[weakSelf storedSelectedPersonaId]];
|
||||
}
|
||||
});
|
||||
|
||||
@@ -644,8 +687,44 @@
|
||||
return nil;
|
||||
}
|
||||
|
||||
- (NSInteger)indexOfPersonaId:(NSInteger)personaId {
|
||||
if (personaId <= 0) {
|
||||
return NSNotFound;
|
||||
}
|
||||
for (NSInteger i = 0; i < self.personas.count; i++) {
|
||||
KBPersonaModel *persona = self.personas[i];
|
||||
if (persona.personaId == personaId) {
|
||||
return i;
|
||||
}
|
||||
}
|
||||
return NSNotFound;
|
||||
}
|
||||
|
||||
#pragma mark - Private
|
||||
|
||||
- (NSInteger)storedSelectedPersonaId {
|
||||
NSInteger savedId = [[NSUserDefaults standardUserDefaults] integerForKey:KBAISelectedPersonaIdKey];
|
||||
if (savedId > 0) {
|
||||
return savedId;
|
||||
}
|
||||
if (self.currentIndex >= 0 && self.currentIndex < self.personas.count) {
|
||||
return self.personas[self.currentIndex].personaId;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
- (void)storeSelectedPersonaId:(NSInteger)personaId {
|
||||
if (personaId <= 0) {
|
||||
return;
|
||||
}
|
||||
self.selectedPersonaId = personaId;
|
||||
[[NSUserDefaults standardUserDefaults] setInteger:personaId forKey:KBAISelectedPersonaIdKey];
|
||||
[[NSUserDefaults standardUserDefaults] synchronize];
|
||||
if (self.sidebarView) {
|
||||
[self.sidebarView updateSelectedPersonaId:personaId];
|
||||
}
|
||||
}
|
||||
|
||||
- (void)updateCollectionViewScrollState {
|
||||
BOOL shouldEnable = !self.isWaitingForAIResponse
|
||||
&& !self.isVoiceRecording
|
||||
@@ -766,6 +845,46 @@
|
||||
[KB_CURRENT_NAV pushViewController:vc animated:true];
|
||||
}
|
||||
|
||||
#pragma mark - KBAIPersonaSidebarViewDelegate
|
||||
|
||||
- (void)personaSidebarView:(KBAIPersonaSidebarView *)view
|
||||
requestPersonasAtPage:(NSInteger)page {
|
||||
if (self.isLoading) {
|
||||
[view endLoadingMore];
|
||||
return;
|
||||
}
|
||||
self.currentPage = MAX(1, page);
|
||||
if (self.currentPage == 1) {
|
||||
[self.personas removeAllObjects];
|
||||
[view resetLoadMore];
|
||||
}
|
||||
[self loadPersonas];
|
||||
}
|
||||
|
||||
- (void)personaSidebarView:(KBAIPersonaSidebarView *)view
|
||||
didSelectPersona:(KBPersonaModel *)persona {
|
||||
if (!persona) {
|
||||
return;
|
||||
}
|
||||
|
||||
[self storeSelectedPersonaId:persona.personaId];
|
||||
|
||||
NSInteger index = [self indexOfPersonaId:persona.personaId];
|
||||
if (index != NSNotFound) {
|
||||
self.currentIndex = index;
|
||||
NSIndexPath *indexPath = [NSIndexPath indexPathForItem:index inSection:0];
|
||||
[self.collectionView scrollToItemAtIndexPath:indexPath
|
||||
atScrollPosition:UICollectionViewScrollPositionCenteredVertically
|
||||
animated:NO];
|
||||
[self preloadAdjacentCellsForIndex:index];
|
||||
[self saveSelectedPersonaToAppGroup:persona];
|
||||
}
|
||||
|
||||
if (self.sidebarPopView) {
|
||||
[self.sidebarPopView dismiss];
|
||||
}
|
||||
}
|
||||
|
||||
- (UIView *)bottomBackgroundView {
|
||||
if (!_bottomBackgroundView) {
|
||||
_bottomBackgroundView = [[UIView alloc] init];
|
||||
@@ -807,6 +926,16 @@
|
||||
return _messageButton;
|
||||
}
|
||||
|
||||
- (UIButton *)sidebarButton {
|
||||
if (!_sidebarButton) {
|
||||
_sidebarButton = [UIButton buttonWithType:UIButtonTypeCustom];
|
||||
UIImage *icon = [UIImage imageNamed:@"ai_more_icon"];
|
||||
[_sidebarButton setImage:icon forState:UIControlStateNormal];
|
||||
[_sidebarButton addTarget:self action:@selector(sidebarButtonTapped) forControlEvents:UIControlEventTouchUpInside];
|
||||
}
|
||||
return _sidebarButton;
|
||||
}
|
||||
|
||||
#pragma mark - Actions
|
||||
|
||||
- (void)messageButtonTapped {
|
||||
@@ -814,6 +943,41 @@
|
||||
[self.navigationController pushViewController:vc animated:YES];
|
||||
}
|
||||
|
||||
- (void)sidebarButtonTapped {
|
||||
[self showPersonaSidebar];
|
||||
}
|
||||
|
||||
- (void)showPersonaSidebar {
|
||||
if (!self.sidebarView) {
|
||||
CGFloat width = KB_SCREEN_WIDTH * 0.7;
|
||||
CGFloat height = KB_SCREEN_HEIGHT;
|
||||
self.sidebarView = [[KBAIPersonaSidebarView alloc] initWithFrame:CGRectMake(0, 0, width, height)];
|
||||
self.sidebarView.delegate = self;
|
||||
}
|
||||
|
||||
self.sidebarView.selectedPersonaId = [self storedSelectedPersonaId];
|
||||
[self.sidebarView updatePersonas:self.personas
|
||||
reset:YES
|
||||
hasMore:self.hasMore
|
||||
currentPage:self.currentPage];
|
||||
[self.sidebarView requestPersonasIfNeeded];
|
||||
|
||||
if (self.sidebarPopView) {
|
||||
[self.sidebarPopView dismiss];
|
||||
}
|
||||
|
||||
LSTPopView *popView = [LSTPopView initWithCustomView:self.sidebarView
|
||||
parentView:nil
|
||||
popStyle:LSTPopStyleSmoothFromLeft
|
||||
dismissStyle:LSTDismissStyleSmoothToLeft];
|
||||
popView.bgColor = [[UIColor blackColor] colorWithAlphaComponent:0.35];
|
||||
popView.hemStyle = LSTHemStyleLeft;
|
||||
popView.isClickBgDismiss = YES;
|
||||
popView.isAvoidKeyboard = NO;
|
||||
self.sidebarPopView = popView;
|
||||
[popView pop];
|
||||
}
|
||||
|
||||
/// 文本输入发送 - 直接调用 handleTranscribedText
|
||||
- (void)handleCommentInputSend:(NSString *)text {
|
||||
NSString *trimmedText = [text stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]];
|
||||
|
||||
Reference in New Issue
Block a user