Compare commits
7 Commits
a83fd918a8
...
635ad932c7
| Author | SHA1 | Date | |
|---|---|---|---|
| 635ad932c7 | |||
| cbe0a53cac | |||
| 5c273c3963 | |||
| c9743cb363 | |||
| f0cb69948e | |||
| 0144f9cc6d | |||
| ae4070ae88 |
@@ -102,6 +102,7 @@ static void KBSkinInstallNotificationCallback(CFNotificationCenterRef center,
|
|||||||
@property(nonatomic, strong) NSMutableArray<KBChatMessage *> *chatMessages;
|
@property(nonatomic, strong) NSMutableArray<KBChatMessage *> *chatMessages;
|
||||||
@property(nonatomic, strong) AVAudioPlayer *chatAudioPlayer;
|
@property(nonatomic, strong) AVAudioPlayer *chatAudioPlayer;
|
||||||
@property(nonatomic, assign) BOOL chatPanelVisible;
|
@property(nonatomic, assign) BOOL chatPanelVisible;
|
||||||
|
@property(nonatomic, copy) NSString *chatPanelBaselineText; // 打开聊天面板时宿主输入框已有的文本
|
||||||
@property(nonatomic, strong, nullable) id kb_fullAccessObserverToken;
|
@property(nonatomic, strong, nullable) id kb_fullAccessObserverToken;
|
||||||
@property(nonatomic, strong, nullable) id kb_skinObserverToken;
|
@property(nonatomic, strong, nullable) id kb_skinObserverToken;
|
||||||
@end
|
@end
|
||||||
@@ -563,6 +564,9 @@ static NSString *KBFormatMB(uint64_t bytes) {
|
|||||||
}
|
}
|
||||||
self.chatPanelVisible = show;
|
self.chatPanelVisible = show;
|
||||||
if (show) {
|
if (show) {
|
||||||
|
// 记录打开聊天面板时宿主输入框已有的文本,发送时只取新增部分
|
||||||
|
[[KBInputBufferManager shared] refreshFromProxyIfPossible:self.textDocumentProxy];
|
||||||
|
self.chatPanelBaselineText = [KBInputBufferManager shared].liveText ?: @"";
|
||||||
[self kb_ensureChatPanelViewIfNeeded];
|
[self kb_ensureChatPanelViewIfNeeded];
|
||||||
self.chatPanelView.hidden = NO;
|
self.chatPanelView.hidden = NO;
|
||||||
self.chatPanelView.alpha = 0.0;
|
self.chatPanelView.alpha = 0.0;
|
||||||
@@ -1033,7 +1037,15 @@ static NSString *KBFormatMB(uint64_t bytes) {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
[[KBInputBufferManager shared] refreshFromProxyIfPossible:self.textDocumentProxy];
|
[[KBInputBufferManager shared] refreshFromProxyIfPossible:self.textDocumentProxy];
|
||||||
NSString *rawText = [KBInputBufferManager shared].liveText ?: @"";
|
NSString *fullText = [KBInputBufferManager shared].liveText ?: @"";
|
||||||
|
|
||||||
|
// 去掉打开聊天面板前宿主输入框里已有的基线文本,只取新增部分
|
||||||
|
NSString *baseline = self.chatPanelBaselineText ?: @"";
|
||||||
|
NSString *rawText = fullText;
|
||||||
|
if (baseline.length > 0 && [fullText hasPrefix:baseline]) {
|
||||||
|
rawText = [fullText substringFromIndex:baseline.length];
|
||||||
|
}
|
||||||
|
|
||||||
NSString *trim =
|
NSString *trim =
|
||||||
[rawText stringByTrimmingCharactersInSet:
|
[rawText stringByTrimmingCharactersInSet:
|
||||||
[NSCharacterSet whitespaceAndNewlineCharacterSet]];
|
[NSCharacterSet whitespaceAndNewlineCharacterSet]];
|
||||||
@@ -1042,6 +1054,7 @@ static NSString *KBFormatMB(uint64_t bytes) {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
[self kb_sendChatText:trim];
|
[self kb_sendChatText:trim];
|
||||||
|
// 只清除新增的文本,保留基线文本
|
||||||
[self kb_clearHostInputForText:rawText];
|
[self kb_clearHostInputForText:rawText];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -140,6 +140,10 @@
|
|||||||
"Nickname" = "Nickname";
|
"Nickname" = "Nickname";
|
||||||
"Gender" = "Gender";
|
"Gender" = "Gender";
|
||||||
"User ID" = "User ID";
|
"User ID" = "User ID";
|
||||||
|
"Modify Gender" = "Modify Gender";
|
||||||
|
"Male" = "Male";
|
||||||
|
"Female" = "Female";
|
||||||
|
"The Third Gender" = "The Third Gender";
|
||||||
|
|
||||||
" Paste Ta's Words" = " Paste Ta's Words";
|
" Paste Ta's Words" = " Paste Ta's Words";
|
||||||
|
|
||||||
@@ -192,10 +196,6 @@
|
|||||||
"测试" = "Test";
|
"测试" = "Test";
|
||||||
"这里是设置内容占位" = "Settings content placeholder";
|
"这里是设置内容占位" = "Settings content placeholder";
|
||||||
"设置" = "Settings";
|
"设置" = "Settings";
|
||||||
"使用引导" = "Usage Guide";
|
|
||||||
"螃蟹啊斯柯达积分卡" = "Crab points card";
|
|
||||||
"❎不是自己的键盘" = "❎ Not our keyboard";
|
|
||||||
"是自己的键盘" = "Our keyboard";
|
|
||||||
|
|
||||||
// English-only keys with Chinese equivalents
|
// English-only keys with Chinese equivalents
|
||||||
"Change The Nickname" = "Change Nickname";
|
"Change The Nickname" = "Change Nickname";
|
||||||
|
|||||||
@@ -103,7 +103,6 @@
|
|||||||
"Please check this app's wireless-data permission or network connection in Settings." = "请在“设置”中检查本应用的无线数据权限或网络连接。";
|
"Please check this app's wireless-data permission or network connection in Settings." = "请在“设置”中检查本应用的无线数据权限或网络连接。";
|
||||||
|
|
||||||
// 权限与引导(英文 key)
|
// 权限与引导(英文 key)
|
||||||
"Usage Guide" = "使用引导";
|
|
||||||
"Turn on Allow Full Access to experience all features" = "开启【允许完全访问】,体验完整功能";
|
"Turn on Allow Full Access to experience all features" = "开启【允许完全访问】,体验完整功能";
|
||||||
"Allow Full Access" = "允许完全访问";
|
"Allow Full Access" = "允许完全访问";
|
||||||
"Follow: Settings → General → Keyboard → Keyboards → %@ → Allow Full Access" = "请按路径:设置→通用→键盘→键盘→%@→允许完全访问";
|
"Follow: Settings → General → Keyboard → Keyboards → %@ → Allow Full Access" = "请按路径:设置→通用→键盘→键盘→%@→允许完全访问";
|
||||||
@@ -142,6 +141,10 @@
|
|||||||
"Nickname" = "用户名";
|
"Nickname" = "用户名";
|
||||||
"Gender" = "性别";
|
"Gender" = "性别";
|
||||||
"User ID" = "用户ID";
|
"User ID" = "用户ID";
|
||||||
|
"Modify Gender" = "修改性别";
|
||||||
|
"Male" = "男";
|
||||||
|
"Female" = "女";
|
||||||
|
"The Third Gender" = "第三性别";
|
||||||
|
|
||||||
" Paste Ta's Words" = " 粘贴TA的话";
|
" Paste Ta's Words" = " 粘贴TA的话";
|
||||||
|
|
||||||
@@ -195,10 +198,6 @@
|
|||||||
"Test" = "测试";
|
"Test" = "测试";
|
||||||
"暂无数据" = "暂无数据"; // 已有英文 key "No data"
|
"暂无数据" = "暂无数据"; // 已有英文 key "No data"
|
||||||
"Settings" = "设置";
|
"Settings" = "设置";
|
||||||
"Usage Guide" = "使用引导";
|
|
||||||
"螃蟹啊斯柯达积分卡" = "螃蟹啊斯柯达积分卡";
|
|
||||||
"❎不是自己的键盘" = "❎不是自己的键盘";
|
|
||||||
"是自己的键盘" = "是自己的键盘";
|
|
||||||
|
|
||||||
|
|
||||||
"Change The Nickname" = "修改名称";
|
"Change The Nickname" = "修改名称";
|
||||||
|
|||||||
22
keyBoard/Assets.xcassets/My/my_svip_icon.imageset/Contents.json
vendored
Normal file
22
keyBoard/Assets.xcassets/My/my_svip_icon.imageset/Contents.json
vendored
Normal file
@@ -0,0 +1,22 @@
|
|||||||
|
{
|
||||||
|
"images" : [
|
||||||
|
{
|
||||||
|
"idiom" : "universal",
|
||||||
|
"scale" : "1x"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"filename" : "my_svip_icon@2x.png",
|
||||||
|
"idiom" : "universal",
|
||||||
|
"scale" : "2x"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"filename" : "my_svip_icon@3x.png",
|
||||||
|
"idiom" : "universal",
|
||||||
|
"scale" : "3x"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"info" : {
|
||||||
|
"author" : "xcode",
|
||||||
|
"version" : 1
|
||||||
|
}
|
||||||
|
}
|
||||||
BIN
keyBoard/Assets.xcassets/My/my_svip_icon.imageset/my_svip_icon@2x.png
vendored
Normal file
BIN
keyBoard/Assets.xcassets/My/my_svip_icon.imageset/my_svip_icon@2x.png
vendored
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 6.2 KiB |
BIN
keyBoard/Assets.xcassets/My/my_svip_icon.imageset/my_svip_icon@3x.png
vendored
Normal file
BIN
keyBoard/Assets.xcassets/My/my_svip_icon.imageset/my_svip_icon@3x.png
vendored
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 12 KiB |
@@ -308,6 +308,12 @@ static NSString * const KBAISelectedPersonaIdKey = @"KBAISelectedPersonaId";
|
|||||||
if (weakSelf.currentPage == 1) {
|
if (weakSelf.currentPage == 1) {
|
||||||
[weakSelf.collectionView reloadData];
|
[weakSelf.collectionView reloadData];
|
||||||
[weakSelf preloadDataForIndexes:@[@0, @1, @2]];
|
[weakSelf preloadDataForIndexes:@[@0, @1, @2]];
|
||||||
|
// 首次加载完成后,主动保存默认 persona 到 AppGroup,
|
||||||
|
// 避免用户未滑动时键盘扩展拿不到数据
|
||||||
|
if (weakSelf.personas.count > 0) {
|
||||||
|
NSInteger index = MIN(MAX(weakSelf.currentIndex, 0), weakSelf.personas.count - 1);
|
||||||
|
[weakSelf saveSelectedPersonaToAppGroup:weakSelf.personas[index]];
|
||||||
|
}
|
||||||
} else if (pageModel.records.count > 0) {
|
} else if (pageModel.records.count > 0) {
|
||||||
NSInteger newCount = weakSelf.personas.count;
|
NSInteger newCount = weakSelf.personas.count;
|
||||||
NSMutableArray<NSIndexPath *> *indexPaths = [NSMutableArray array];
|
NSMutableArray<NSIndexPath *> *indexPaths = [NSMutableArray array];
|
||||||
|
|||||||
@@ -99,9 +99,8 @@
|
|||||||
- (void)buttonTapped:(UIButton *)button {
|
- (void)buttonTapped:(UIButton *)button {
|
||||||
NSInteger index = button.tag;
|
NSInteger index = button.tag;
|
||||||
if (index != self.selectedIndex) {
|
if (index != self.selectedIndex) {
|
||||||
self.selectedIndex = index;
|
// 先通知 delegate,由 delegate 决定是否允许切换(如登录拦截)
|
||||||
[self updateButtonStates];
|
// delegate 允许时会主动调用 setSelectedIndex: 来更新状态
|
||||||
|
|
||||||
if ([self.delegate respondsToSelector:@selector(customTabBar:
|
if ([self.delegate respondsToSelector:@selector(customTabBar:
|
||||||
didSelectItemAtIndex:)]) {
|
didSelectItemAtIndex:)]) {
|
||||||
[self.delegate customTabBar:self didSelectItemAtIndex:index];
|
[self.delegate customTabBar:self didSelectItemAtIndex:index];
|
||||||
|
|||||||
@@ -154,12 +154,15 @@
|
|||||||
|
|
||||||
- (void)customTabBar:(KBCustomTabBar *)tabBar
|
- (void)customTabBar:(KBCustomTabBar *)tabBar
|
||||||
didSelectItemAtIndex:(NSInteger)index {
|
didSelectItemAtIndex:(NSInteger)index {
|
||||||
// 登录检查
|
// 登录检查:未登录时跳登录页,不切换 Tab,不更新选中状态
|
||||||
if ((index == 1 || index == 2) && ![KBUserSessionManager shared].isLoggedIn) {
|
if ((index == 1 || index == 2 || index == 3) && ![KBUserSessionManager shared].isLoggedIn) {
|
||||||
[[KBUserSessionManager shared] goLoginVC];
|
[[KBUserSessionManager shared] goLoginVC];
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 更新自定义 TabBar 的选中状态
|
||||||
|
[self.customTabBar setSelectedIndex:index];
|
||||||
|
|
||||||
// 切换 VC
|
// 切换 VC
|
||||||
self.selectedIndex = index;
|
self.selectedIndex = index;
|
||||||
|
|
||||||
|
|||||||
@@ -212,6 +212,7 @@
|
|||||||
// }
|
// }
|
||||||
// }];
|
// }];
|
||||||
[[KBNetworkManager shared] POST:API_CHARACTER_ADD_USER_CHARACTER jsonBody:params headers:nil autoShowBusinessError:true completion:^(NSDictionary * _Nullable json, NSURLResponse * _Nullable response, NSError * _Nullable error) {
|
[[KBNetworkManager shared] POST:API_CHARACTER_ADD_USER_CHARACTER jsonBody:params headers:nil autoShowBusinessError:true completion:^(NSDictionary * _Nullable json, NSURLResponse * _Nullable response, NSError * _Nullable error) {
|
||||||
|
[KBHUD dismiss];
|
||||||
if (!error) {
|
if (!error) {
|
||||||
[self refreshUserCharacterCacheForKeyboard];
|
[self refreshUserCharacterCacheForKeyboard];
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -28,6 +28,9 @@ typedef NS_ENUM(NSInteger, UserSex) {
|
|||||||
/// 是否是 VIP
|
/// 是否是 VIP
|
||||||
@property (nonatomic, assign) BOOL isVip;
|
@property (nonatomic, assign) BOOL isVip;
|
||||||
|
|
||||||
|
/// 1: vip 2:svip
|
||||||
|
@property (nonatomic, assign) NSInteger vipLevel;
|
||||||
|
|
||||||
// token
|
// token
|
||||||
@property (nonatomic, copy, nullable) NSString *token; // token/access_token/accessToken
|
@property (nonatomic, copy, nullable) NSString *token; // token/access_token/accessToken
|
||||||
|
|
||||||
|
|||||||
@@ -182,7 +182,7 @@
|
|||||||
- (UILabel *)titleLabel {
|
- (UILabel *)titleLabel {
|
||||||
if (!_titleLabel) {
|
if (!_titleLabel) {
|
||||||
_titleLabel = [UILabel new];
|
_titleLabel = [UILabel new];
|
||||||
_titleLabel.text = @"Modify Gender";
|
_titleLabel.text = KBLocalized(@"Modify Gender");
|
||||||
_titleLabel.textColor = [UIColor blackColor];
|
_titleLabel.textColor = [UIColor blackColor];
|
||||||
_titleLabel.font = [KBFont medium:16];
|
_titleLabel.font = [KBFont medium:16];
|
||||||
}
|
}
|
||||||
@@ -226,7 +226,7 @@
|
|||||||
- (UIButton *)saveButton {
|
- (UIButton *)saveButton {
|
||||||
if (!_saveButton) {
|
if (!_saveButton) {
|
||||||
_saveButton = [UIButton buttonWithType:UIButtonTypeCustom];
|
_saveButton = [UIButton buttonWithType:UIButtonTypeCustom];
|
||||||
[_saveButton setTitle:@"Save" forState:UIControlStateNormal];
|
[_saveButton setTitle:KBLocalized(@"Save") forState:UIControlStateNormal];
|
||||||
[_saveButton setTitleColor:UIColor.whiteColor forState:UIControlStateNormal];
|
[_saveButton setTitleColor:UIColor.whiteColor forState:UIControlStateNormal];
|
||||||
_saveButton.titleLabel.font = [KBFont medium:16];
|
_saveButton.titleLabel.font = [KBFont medium:16];
|
||||||
_saveButton.backgroundColor = [UIColor colorWithRed:0.02 green:0.75 blue:0.67 alpha:1.0];
|
_saveButton.backgroundColor = [UIColor colorWithRed:0.02 green:0.75 blue:0.67 alpha:1.0];
|
||||||
|
|||||||
@@ -136,9 +136,17 @@
|
|||||||
[self kb_applyVipLayout:isVip];
|
[self kb_applyVipLayout:isVip];
|
||||||
self.vipIconView.hidden = !isVip;
|
self.vipIconView.hidden = !isVip;
|
||||||
self.vipExpiryLabel.hidden = !isVip;
|
self.vipExpiryLabel.hidden = !isVip;
|
||||||
|
if (isVip) {
|
||||||
|
self.vipIconView.image = [UIImage imageNamed:[self kb_vipIconNameFromVipLevel:user.vipLevel]];
|
||||||
|
}
|
||||||
self.vipExpiryLabel.text = isVip ? [self vipExpiryDisplayTextFrom:user.vipExpiry] : nil;
|
self.vipExpiryLabel.text = isVip ? [self vipExpiryDisplayTextFrom:user.vipExpiry] : nil;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
- (NSString *)kb_vipIconNameFromVipLevel:(NSInteger)vipLevel {
|
||||||
|
if (vipLevel == 2) { return @"my_svip_icon"; }
|
||||||
|
return @"my_vip_icon";
|
||||||
|
}
|
||||||
|
|
||||||
- (void)kb_applyVipLayout:(BOOL)isVip {
|
- (void)kb_applyVipLayout:(BOOL)isVip {
|
||||||
NSInteger state = isVip ? 1 : 0;
|
NSInteger state = isVip ? 1 : 0;
|
||||||
if (self.kb_vipLayoutState == state) { return; }
|
if (self.kb_vipLayoutState == state) { return; }
|
||||||
|
|||||||
@@ -576,8 +576,11 @@ autoShowBusinessError:YES
|
|||||||
if (!_manager) {
|
if (!_manager) {
|
||||||
NSURLSessionConfiguration *cfg = [NSURLSessionConfiguration ephemeralSessionConfiguration];
|
NSURLSessionConfiguration *cfg = [NSURLSessionConfiguration ephemeralSessionConfiguration];
|
||||||
cfg.requestCachePolicy = NSURLRequestReloadIgnoringLocalCacheData;
|
cfg.requestCachePolicy = NSURLRequestReloadIgnoringLocalCacheData;
|
||||||
|
cfg.timeoutIntervalForRequest = self.timeout; // 单次请求超时
|
||||||
|
cfg.timeoutIntervalForResource = 60.0; // 整个资源传输最大 60s
|
||||||
|
|
||||||
// 不在会话级别设置超时,避免与 per-request 的 serializer.timeoutInterval 产生不一致
|
// 不在会话级别设置超时,避免与 per-request 的 serializer.timeoutInterval 产生不一致
|
||||||
if (@available(iOS 11.0, *)) { cfg.waitsForConnectivity = YES; }
|
// if (@available(iOS 11.0, *)) { cfg.waitsForConnectivity = YES; }
|
||||||
_manager = [[AFHTTPSessionManager alloc] initWithBaseURL:nil sessionConfiguration:cfg];
|
_manager = [[AFHTTPSessionManager alloc] initWithBaseURL:nil sessionConfiguration:cfg];
|
||||||
// 默认不使用 JSON 解析器,保持原生数据,再按需解析
|
// 默认不使用 JSON 解析器,保持原生数据,再按需解析
|
||||||
_manager.responseSerializer = [AFHTTPResponseSerializer serializer];
|
_manager.responseSerializer = [AFHTTPResponseSerializer serializer];
|
||||||
|
|||||||
Reference in New Issue
Block a user