键盘添加撤销操作

This commit is contained in:
2025-12-19 19:21:08 +08:00
parent 68306aa07f
commit 1c8834caf6
10 changed files with 332 additions and 15 deletions

View File

@@ -19,6 +19,7 @@
#import "KBHostAppLauncher.h" #import "KBHostAppLauncher.h"
#import "KBKeyboardSubscriptionView.h" #import "KBKeyboardSubscriptionView.h"
#import "KBKeyboardSubscriptionProduct.h" #import "KBKeyboardSubscriptionProduct.h"
#import "KBBackspaceUndoManager.h"
// 使 static kb_consumePendingShopSkin // 使 static kb_consumePendingShopSkin
@interface KeyboardViewController (KBSkinShopBridge) @interface KeyboardViewController (KBSkinShopBridge)
@@ -249,6 +250,9 @@ static void KBSkinInstallNotificationCallback(CFNotificationCenterRef center,
// MARK: - KBKeyBoardMainViewDelegate // MARK: - KBKeyBoardMainViewDelegate
- (void)keyBoardMainView:(KBKeyBoardMainView *)keyBoardMainView didTapKey:(KBKey *)key { - (void)keyBoardMainView:(KBKeyBoardMainView *)keyBoardMainView didTapKey:(KBKey *)key {
if (key.type != KBKeyTypeShift && key.type != KBKeyTypeModeChange) {
[[KBBackspaceUndoManager shared] registerNonClearAction];
}
switch (key.type) { switch (key.type) {
case KBKeyTypeCharacter: case KBKeyTypeCharacter:
[self.textDocumentProxy insertText:key.output ?: key.title ?: @""]; break; [self.textDocumentProxy insertText:key.output ?: key.title ?: @""]; break;
@@ -285,9 +289,14 @@ static void KBSkinInstallNotificationCallback(CFNotificationCenterRef center,
- (void)keyBoardMainView:(KBKeyBoardMainView *)keyBoardMainView didSelectEmoji:(NSString *)emoji { - (void)keyBoardMainView:(KBKeyBoardMainView *)keyBoardMainView didSelectEmoji:(NSString *)emoji {
if (emoji.length == 0) { return; } if (emoji.length == 0) { return; }
[[KBBackspaceUndoManager shared] registerNonClearAction];
[self.textDocumentProxy insertText:emoji]; [self.textDocumentProxy insertText:emoji];
} }
- (void)keyBoardMainViewDidTapUndo:(KBKeyBoardMainView *)keyBoardMainView {
[[KBBackspaceUndoManager shared] performUndoFromResponder:self.view];
}
- (void)keyBoardMainViewDidTapEmojiSearch:(KBKeyBoardMainView *)keyBoardMainView { - (void)keyBoardMainViewDidTapEmojiSearch:(KBKeyBoardMainView *)keyBoardMainView {
[KBHUD showInfo:KBLocalized(@"Search coming soon")]; [KBHUD showInfo:KBLocalized(@"Search coming soon")];
} }

View File

@@ -6,6 +6,7 @@
#import "KBBackspaceLongPressHandler.h" #import "KBBackspaceLongPressHandler.h"
#import "KBResponderUtils.h" #import "KBResponderUtils.h"
#import "KBSkinManager.h" #import "KBSkinManager.h"
#import "KBBackspaceUndoManager.h"
static const NSTimeInterval kKBBackspaceLongPressMinDuration = 0.35; static const NSTimeInterval kKBBackspaceLongPressMinDuration = 0.35;
static const NSTimeInterval kKBBackspaceRepeatInterval = 0.06; static const NSTimeInterval kKBBackspaceRepeatInterval = 0.06;
@@ -96,6 +97,7 @@ typedef NS_ENUM(NSInteger, KBBackspaceChunkClass) {
} }
switch (gr.state) { switch (gr.state) {
case UIGestureRecognizerStateBegan: { case UIGestureRecognizerStateBegan: {
[[KBBackspaceUndoManager shared] registerNonClearAction];
self.backspaceHoldToken += 1; self.backspaceHoldToken += 1;
NSUInteger token = self.backspaceHoldToken; NSUInteger token = self.backspaceHoldToken;
self.backspaceHoldActive = YES; self.backspaceHoldActive = YES;
@@ -406,6 +408,12 @@ typedef NS_ENUM(NSInteger, KBBackspaceChunkClass) {
#pragma mark - Clear #pragma mark - Clear
- (void)kb_clearAllInput { - (void)kb_clearAllInput {
UIResponder *start = (UIResponder *)([self kb_hostView] ?: self.backspaceButton);
UIInputViewController *ivc = KBFindInputViewController(start);
if (ivc) {
NSString *before = ivc.textDocumentProxy.documentContextBeforeInput ?: @"";
[[KBBackspaceUndoManager shared] recordClearWithContext:before];
}
self.backspaceClearToken += 1; self.backspaceClearToken += 1;
NSUInteger token = self.backspaceClearToken; NSUInteger token = self.backspaceClearToken;
[self kb_clearAllInputStepForToken:token guard:0 emptyRounds:0]; [self kb_clearAllInputStepForToken:token guard:0 emptyRounds:0];

View File

@@ -0,0 +1,29 @@
//
// KBBackspaceUndoManager.h
// CustomKeyboard
//
#import <UIKit/UIKit.h>
NS_ASSUME_NONNULL_BEGIN
extern NSNotificationName const KBBackspaceUndoStateDidChangeNotification;
@interface KBBackspaceUndoManager : NSObject
@property (nonatomic, readonly) BOOL hasUndo;
+ (instancetype)shared;
/// 记录一次“立刻清空”删除的内容(基于 documentContextBeforeInput
- (void)recordClearWithContext:(NSString *)context;
/// 在指定 responder 处执行撤销(向光标处插回删除的内容)
- (void)performUndoFromResponder:(UIResponder *)responder;
/// 非清空行为触发时,清理撤销状态
- (void)registerNonClearAction;
@end
NS_ASSUME_NONNULL_END

View File

@@ -0,0 +1,170 @@
//
// KBBackspaceUndoManager.m
// CustomKeyboard
//
#import "KBBackspaceUndoManager.h"
#import "KBResponderUtils.h"
NSNotificationName const KBBackspaceUndoStateDidChangeNotification = @"KBBackspaceUndoStateDidChangeNotification";
@interface KBBackspaceUndoManager ()
@property (nonatomic, strong) NSMutableArray<NSString *> *segments; // deletion order (last -> first)
@property (nonatomic, assign) BOOL lastActionWasClear;
@property (nonatomic, assign) BOOL hasUndo;
@end
@implementation KBBackspaceUndoManager
+ (instancetype)shared {
static KBBackspaceUndoManager *mgr = nil;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
mgr = [[KBBackspaceUndoManager alloc] init];
});
return mgr;
}
- (instancetype)init {
if (self = [super init]) {
_segments = [NSMutableArray array];
}
return self;
}
- (void)recordClearWithContext:(NSString *)context {
if (context.length == 0) { return; }
NSString *segment = [self kb_segmentForClearFromContext:context];
if (segment.length == 0) { return; }
if (!self.lastActionWasClear) {
[self.segments removeAllObjects];
}
[self.segments addObject:segment];
self.lastActionWasClear = YES;
[self kb_updateHasUndo:YES];
}
- (void)performUndoFromResponder:(UIResponder *)responder {
if (self.segments.count == 0) { return; }
UIInputViewController *ivc = KBFindInputViewController(responder);
if (!ivc) { return; }
id<UITextDocumentProxy> proxy = ivc.textDocumentProxy;
NSString *text = [self kb_buildUndoText];
if (text.length == 0) { return; }
[proxy insertText:text];
[self.segments removeAllObjects];
self.lastActionWasClear = NO;
[self kb_updateHasUndo:NO];
}
- (void)registerNonClearAction {
self.lastActionWasClear = NO;
if (self.segments.count == 0) { return; }
[self.segments removeAllObjects];
[self kb_updateHasUndo:NO];
}
#pragma mark - Helpers
- (void)kb_updateHasUndo:(BOOL)hasUndo {
if (self.hasUndo == hasUndo) { return; }
self.hasUndo = hasUndo;
[[NSNotificationCenter defaultCenter] postNotificationName:KBBackspaceUndoStateDidChangeNotification object:self];
}
- (NSString *)kb_segmentForClearFromContext:(NSString *)context {
NSInteger length = context.length;
if (length == 0) { return @""; }
static NSCharacterSet *sentenceBoundarySet = nil;
static NSCharacterSet *whitespaceSet = nil;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
sentenceBoundarySet = [NSCharacterSet characterSetWithCharactersInString:@".!?;。!?;…\n"];
whitespaceSet = [NSCharacterSet whitespaceAndNewlineCharacterSet];
});
NSInteger end = length;
while (end > 0) {
unichar ch = [context characterAtIndex:end - 1];
if ([whitespaceSet characterIsMember:ch]) {
end -= 1;
} else {
break;
}
}
NSInteger searchEnd = end;
while (searchEnd > 0) {
unichar ch = [context characterAtIndex:searchEnd - 1];
if ([sentenceBoundarySet characterIsMember:ch]) {
searchEnd -= 1;
} else {
break;
}
}
NSInteger boundaryIndex = NSNotFound;
for (NSInteger i = searchEnd - 1; i >= 0; i--) {
unichar ch = [context characterAtIndex:i];
if ([sentenceBoundarySet characterIsMember:ch]) {
boundaryIndex = i;
break;
}
}
NSInteger start = (boundaryIndex == NSNotFound) ? 0 : (boundaryIndex + 1);
if (start >= length) { return @""; }
return [context substringFromIndex:start];
}
- (NSString *)kb_buildUndoText {
if (self.segments.count == 0) { return @""; }
NSArray<NSString *> *ordered = [[self.segments reverseObjectEnumerator] allObjects];
NSMutableString *result = [NSMutableString string];
for (NSInteger i = 0; i < ordered.count; i++) {
NSString *segment = ordered[i] ?: @"";
if (segment.length == 0) { continue; }
if (i < ordered.count - 1) {
segment = [self kb_replaceTrailingBoundaryWithComma:segment];
}
[result appendString:segment];
}
return result;
}
- (NSString *)kb_replaceTrailingBoundaryWithComma:(NSString *)segment {
if (segment.length == 0) { return segment; }
static NSCharacterSet *boundarySet = nil;
static NSCharacterSet *englishBoundarySet = nil;
static NSCharacterSet *whitespaceSet = nil;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
boundarySet = [NSCharacterSet characterSetWithCharactersInString:@".!?;。!?;…\n"];
englishBoundarySet = [NSCharacterSet characterSetWithCharactersInString:@".!?;"];
whitespaceSet = [NSCharacterSet whitespaceAndNewlineCharacterSet];
});
NSInteger idx = segment.length - 1;
while (idx >= 0) {
unichar ch = [segment characterAtIndex:idx];
if ([whitespaceSet characterIsMember:ch]) {
idx -= 1;
continue;
}
if (![boundarySet characterIsMember:ch]) {
return segment;
}
NSString *comma = [englishBoundarySet characterIsMember:ch] ? @"," : @"";
NSMutableString *mutable = [segment mutableCopy];
NSRange r = NSMakeRange(idx, 1);
[mutable replaceCharactersInRange:r withString:comma];
return mutable;
}
return segment;
}
@end

View File

@@ -26,6 +26,7 @@
#import <MJExtension/MJExtension.h> #import <MJExtension/MJExtension.h>
#import "KBBizCode.h" #import "KBBizCode.h"
#import "KBBackspaceLongPressHandler.h" #import "KBBackspaceLongPressHandler.h"
#import "KBBackspaceUndoManager.h"
@interface KBFunctionView () <KBFunctionBarViewDelegate, KBStreamOverlayViewDelegate, KBFunctionTagListViewDelegate> @interface KBFunctionView () <KBFunctionBarViewDelegate, KBStreamOverlayViewDelegate, KBFunctionTagListViewDelegate>
// UI // UI
@@ -769,6 +770,7 @@ static void KBULDarwinCallback(CFNotificationCenterRef center, void *observer, C
} }
- (void)onTapDelete { - (void)onTapDelete {
NSLog(@"点击:删除"); NSLog(@"点击:删除");
[[KBBackspaceUndoManager shared] registerNonClearAction];
UIInputViewController *ivc = KBFindInputViewController(self); UIInputViewController *ivc = KBFindInputViewController(self);
id<UITextDocumentProxy> proxy = ivc.textDocumentProxy; id<UITextDocumentProxy> proxy = ivc.textDocumentProxy;
[proxy deleteBackward]; [proxy deleteBackward];
@@ -779,6 +781,7 @@ static void KBULDarwinCallback(CFNotificationCenterRef center, void *observer, C
} }
- (void)onTapSend { - (void)onTapSend {
NSLog(@"点击:发送"); NSLog(@"点击:发送");
[[KBBackspaceUndoManager shared] registerNonClearAction];
// App // App
UIInputViewController *ivc = KBFindInputViewController(self); UIInputViewController *ivc = KBFindInputViewController(self);
id<UITextDocumentProxy> proxy = ivc.textDocumentProxy; id<UITextDocumentProxy> proxy = ivc.textDocumentProxy;

View File

@@ -23,6 +23,8 @@ NS_ASSUME_NONNULL_BEGIN
/// 点击了右侧设置按钮 /// 点击了右侧设置按钮
- (void)keyBoardMainViewDidTapSettings:(KBKeyBoardMainView *)keyBoardMainView; - (void)keyBoardMainViewDidTapSettings:(KBKeyBoardMainView *)keyBoardMainView;
/// 点击了撤销删除按钮
- (void)keyBoardMainViewDidTapUndo:(KBKeyBoardMainView *)keyBoardMainView;
/// emoji 视图里选择了一个表情 /// emoji 视图里选择了一个表情
- (void)keyBoardMainView:(KBKeyBoardMainView *)keyBoardMainView didSelectEmoji:(NSString *)emoji; - (void)keyBoardMainView:(KBKeyBoardMainView *)keyBoardMainView didSelectEmoji:(NSString *)emoji;

View File

@@ -115,6 +115,12 @@
} }
} }
- (void)toolBarDidTapUndo:(KBToolBar *)toolBar {
if ([self.delegate respondsToSelector:@selector(keyBoardMainViewDidTapUndo:)]) {
[self.delegate keyBoardMainViewDidTapUndo:self];
}
}
#pragma mark - KBKeyboardViewDelegate #pragma mark - KBKeyboardViewDelegate
- (void)keyboardView:(KBKeyboardView *)keyboard didTapKey:(KBKey *)key { - (void)keyboardView:(KBKeyboardView *)keyboard didTapKey:(KBKey *)key {

View File

@@ -17,6 +17,8 @@ NS_ASSUME_NONNULL_BEGIN
- (void)toolBar:(KBToolBar *)toolBar didTapActionAtIndex:(NSInteger)index; - (void)toolBar:(KBToolBar *)toolBar didTapActionAtIndex:(NSInteger)index;
/// 右侧设置按钮点击 /// 右侧设置按钮点击
- (void)toolBarDidTapSettings:(KBToolBar *)toolBar; - (void)toolBarDidTapSettings:(KBToolBar *)toolBar;
/// 右侧撤销删除按钮点击
- (void)toolBarDidTapUndo:(KBToolBar *)toolBar;
@end @end
/// 顶部工具栏:左侧 4 个按钮,右侧 1 个设置按钮。 /// 顶部工具栏:左侧 4 个按钮,右侧 1 个设置按钮。
@@ -30,6 +32,7 @@ NS_ASSUME_NONNULL_BEGIN
/// 暴露按钮以便外部定制(只读;首次访问时懒加载创建) /// 暴露按钮以便外部定制(只读;首次访问时懒加载创建)
@property (nonatomic, strong, readonly) NSArray<UIButton *> *leftButtons; @property (nonatomic, strong, readonly) NSArray<UIButton *> *leftButtons;
@property (nonatomic, strong, readonly) UIButton *settingsButton; @property (nonatomic, strong, readonly) UIButton *settingsButton;
@property (nonatomic, strong, readonly) UIButton *undoButton;
@end @end

View File

@@ -7,12 +7,16 @@
#import "KBToolBar.h" #import "KBToolBar.h"
#import "KBResponderUtils.h" // UIInputViewController #import "KBResponderUtils.h" // UIInputViewController
#import "KBBackspaceUndoManager.h"
@interface KBToolBar () @interface KBToolBar ()
@property (nonatomic, strong) UIView *leftContainer; @property (nonatomic, strong) UIView *leftContainer;
@property (nonatomic, strong) NSArray<UIButton *> *leftButtonsInternal; @property (nonatomic, strong) NSArray<UIButton *> *leftButtonsInternal;
//@property (nonatomic, strong) UIButton *settingsButtonInternal; //@property (nonatomic, strong) UIButton *settingsButtonInternal;
@property (nonatomic, strong) UIButton *globeButtonInternal; // @property (nonatomic, strong) UIButton *globeButtonInternal; //
@property (nonatomic, strong) UIButton *undoButtonInternal; //
@property (nonatomic, assign) BOOL kbNeedsInputModeSwitchKey;
@property (nonatomic, assign) BOOL kbUndoVisible;
@end @end
@implementation KBToolBar @implementation KBToolBar
@@ -22,10 +26,18 @@
self.backgroundColor = [UIColor clearColor]; self.backgroundColor = [UIColor clearColor];
_leftButtonTitles = @[KBLocalized(@"Recharge Now")]; // _leftButtonTitles = @[KBLocalized(@"Recharge Now")]; //
[self setupUI]; [self setupUI];
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(kb_undoStateChanged)
name:KBBackspaceUndoStateDidChangeNotification
object:nil];
} }
return self; return self;
} }
- (void)dealloc {
[[NSNotificationCenter defaultCenter] removeObserver:self];
}
#pragma mark - Public #pragma mark - Public
@@ -33,6 +45,10 @@
return self.leftButtonsInternal; return self.leftButtonsInternal;
} }
- (UIButton *)undoButton {
return self.undoButtonInternal;
}
//- (UIButton *)settingsButton { //- (UIButton *)settingsButton {
// return self.settingsButtonInternal; // return self.settingsButtonInternal;
//} //}
@@ -53,6 +69,7 @@
[self addSubview:self.leftContainer]; [self addSubview:self.leftContainer];
// [self addSubview:self.settingsButtonInternal]; // [self addSubview:self.settingsButtonInternal];
[self addSubview:self.globeButtonInternal]; [self addSubview:self.globeButtonInternal];
[self addSubview:self.undoButtonInternal];
// //
// [self.settingsButtonInternal mas_makeConstraints:^(MASConstraintMaker *make) { // [self.settingsButtonInternal mas_makeConstraints:^(MASConstraintMaker *make) {
@@ -68,14 +85,15 @@
make.width.height.mas_equalTo(32); make.width.height.mas_equalTo(32);
}]; }];
// //
[self.leftContainer mas_makeConstraints:^(MASConstraintMaker *make) { [self.undoButtonInternal mas_makeConstraints:^(MASConstraintMaker *make) {
make.left.equalTo(self.globeButtonInternal.mas_right).offset(8); make.right.equalTo(self.mas_right).offset(-12);
make.right.equalTo(self).offset(-12);
make.centerY.equalTo(self.mas_centerY); make.centerY.equalTo(self.mas_centerY);
make.height.mas_equalTo(32); make.height.mas_equalTo(32);
}]; }];
[self kb_updateLeftContainerConstraints];
// = // =
NSMutableArray<UIButton *> *buttons = [NSMutableArray arrayWithCapacity:_leftButtonTitles.count]; NSMutableArray<UIButton *> *buttons = [NSMutableArray arrayWithCapacity:_leftButtonTitles.count];
UIView *previous = nil; UIView *previous = nil;
@@ -110,6 +128,7 @@
// //
[self kb_refreshGlobeVisibility]; [self kb_refreshGlobeVisibility];
[self kb_updateUndoVisibilityAnimated:NO];
} }
- (UIButton *)buildActionButtonAtIndex:(NSInteger)idx { - (UIButton *)buildActionButtonAtIndex:(NSInteger)idx {
@@ -147,6 +166,12 @@
} }
} }
- (void)onUndo {
if ([self.delegate respondsToSelector:@selector(toolBarDidTapUndo:)]) {
[self.delegate toolBarDidTapUndo:self];
}
}
#pragma mark - Lazy #pragma mark - Lazy
- (UIView *)leftContainer { - (UIView *)leftContainer {
@@ -182,6 +207,23 @@
return _globeButtonInternal; return _globeButtonInternal;
} }
- (UIButton *)undoButtonInternal {
if (!_undoButtonInternal) {
_undoButtonInternal = [UIButton buttonWithType:UIButtonTypeSystem];
_undoButtonInternal.layer.cornerRadius = 16;
_undoButtonInternal.layer.masksToBounds = YES;
_undoButtonInternal.backgroundColor = [UIColor colorWithWhite:1 alpha:0.9];
_undoButtonInternal.titleLabel.font = [UIFont systemFontOfSize:14 weight:UIFontWeightMedium];
[_undoButtonInternal setTitle:@"撤销删除" forState:UIControlStateNormal];
[_undoButtonInternal setTitleColor:[UIColor blackColor] forState:UIControlStateNormal];
_undoButtonInternal.contentEdgeInsets = UIEdgeInsetsMake(0, 10, 0, 10);
_undoButtonInternal.hidden = YES;
_undoButtonInternal.alpha = 0.0;
[_undoButtonInternal addTarget:self action:@selector(onUndo) forControlEvents:UIControlEventTouchUpInside];
}
return _undoButtonInternal;
}
#pragma mark - Globe (Input Mode Switch) #pragma mark - Globe (Input Mode Switch)
// 宿 // 宿
@@ -193,18 +235,9 @@
} }
self.globeButtonInternal.hidden = !needSwitchKey; self.globeButtonInternal.hidden = !needSwitchKey;
self.kbNeedsInputModeSwitchKey = needSwitchKey;
// leftContainer 12 [self kb_updateLeftContainerConstraints];
[self.leftContainer mas_remakeConstraints:^(MASConstraintMaker *make) {
if (needSwitchKey) {
make.left.equalTo(self.globeButtonInternal.mas_right).offset(8);
} else {
make.left.equalTo(self.mas_left).offset(12);
}
make.right.equalTo(self).offset(-12);
make.centerY.equalTo(self.mas_centerY);
make.height.mas_equalTo(32);
}];
// //
// //
@@ -220,6 +253,54 @@
} }
} }
- (void)kb_updateLeftContainerConstraints {
[self.leftContainer mas_remakeConstraints:^(MASConstraintMaker *make) {
if (self.kbNeedsInputModeSwitchKey) {
make.left.equalTo(self.globeButtonInternal.mas_right).offset(8);
} else {
make.left.equalTo(self.mas_left).offset(12);
}
if (self.kbUndoVisible) {
make.right.equalTo(self.undoButtonInternal.mas_left).offset(-8);
} else {
make.right.equalTo(self).offset(-12);
}
make.centerY.equalTo(self.mas_centerY);
make.height.mas_equalTo(32);
}];
}
- (void)kb_undoStateChanged {
[self kb_updateUndoVisibilityAnimated:YES];
}
- (void)kb_updateUndoVisibilityAnimated:(BOOL)animated {
BOOL visible = [KBBackspaceUndoManager shared].hasUndo;
if (self.kbUndoVisible == visible) { return; }
self.kbUndoVisible = visible;
self.undoButtonInternal.hidden = NO;
[self kb_updateLeftContainerConstraints];
void (^changes)(void) = ^{
self.undoButtonInternal.alpha = visible ? 1.0 : 0.0;
[self layoutIfNeeded];
};
void (^finish)(BOOL) = ^(BOOL finished) {
self.undoButtonInternal.hidden = !visible;
};
if (animated) {
[UIView animateWithDuration:0.18
delay:0
options:UIViewAnimationOptionCurveEaseInOut
animations:changes
completion:finish];
} else {
changes();
finish(YES);
}
}
- (void)didMoveToWindow { - (void)didMoveToWindow {
[super didMoveToWindow]; [super didMoveToWindow];
[self kb_refreshGlobeVisibility]; [self kb_refreshGlobeVisibility];

View File

@@ -179,6 +179,7 @@
04FC956D2EB054B7007BD342 /* KBKeyboardView.m in Sources */ = {isa = PBXBuildFile; fileRef = 04FC956C2EB054B7007BD342 /* KBKeyboardView.m */; }; 04FC956D2EB054B7007BD342 /* KBKeyboardView.m in Sources */ = {isa = PBXBuildFile; fileRef = 04FC956C2EB054B7007BD342 /* KBKeyboardView.m */; };
04FC95702EB09516007BD342 /* KBFunctionView.m in Sources */ = {isa = PBXBuildFile; fileRef = 04FC956F2EB09516007BD342 /* KBFunctionView.m */; }; 04FC95702EB09516007BD342 /* KBFunctionView.m in Sources */ = {isa = PBXBuildFile; fileRef = 04FC956F2EB09516007BD342 /* KBFunctionView.m */; };
A1B2C9032FBD000100000001 /* KBBackspaceLongPressHandler.m in Sources */ = {isa = PBXBuildFile; fileRef = A1B2C9022FBD000100000001 /* KBBackspaceLongPressHandler.m */; }; A1B2C9032FBD000100000001 /* KBBackspaceLongPressHandler.m in Sources */ = {isa = PBXBuildFile; fileRef = A1B2C9022FBD000100000001 /* KBBackspaceLongPressHandler.m */; };
A1B2C9052FBD000200000001 /* KBBackspaceUndoManager.m in Sources */ = {isa = PBXBuildFile; fileRef = A1B2C9042FBD000200000001 /* KBBackspaceUndoManager.m */; };
04FC95732EB09570007BD342 /* KBFunctionBarView.m in Sources */ = {isa = PBXBuildFile; fileRef = 04FC95722EB09570007BD342 /* KBFunctionBarView.m */; }; 04FC95732EB09570007BD342 /* KBFunctionBarView.m in Sources */ = {isa = PBXBuildFile; fileRef = 04FC95722EB09570007BD342 /* KBFunctionBarView.m */; };
04FC95762EB095DE007BD342 /* KBFunctionPasteView.m in Sources */ = {isa = PBXBuildFile; fileRef = 04FC95752EB095DE007BD342 /* KBFunctionPasteView.m */; }; 04FC95762EB095DE007BD342 /* KBFunctionPasteView.m in Sources */ = {isa = PBXBuildFile; fileRef = 04FC95752EB095DE007BD342 /* KBFunctionPasteView.m */; };
04FC95792EB09BC8007BD342 /* KBKeyBoardMainView.m in Sources */ = {isa = PBXBuildFile; fileRef = 04FC95782EB09BC8007BD342 /* KBKeyBoardMainView.m */; }; 04FC95792EB09BC8007BD342 /* KBKeyBoardMainView.m in Sources */ = {isa = PBXBuildFile; fileRef = 04FC95782EB09BC8007BD342 /* KBKeyBoardMainView.m */; };
@@ -541,6 +542,8 @@
04FC956F2EB09516007BD342 /* KBFunctionView.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = KBFunctionView.m; sourceTree = "<group>"; }; 04FC956F2EB09516007BD342 /* KBFunctionView.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = KBFunctionView.m; sourceTree = "<group>"; };
A1B2C9012FBD000100000001 /* KBBackspaceLongPressHandler.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = KBBackspaceLongPressHandler.h; sourceTree = "<group>"; }; A1B2C9012FBD000100000001 /* KBBackspaceLongPressHandler.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = KBBackspaceLongPressHandler.h; sourceTree = "<group>"; };
A1B2C9022FBD000100000001 /* KBBackspaceLongPressHandler.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = KBBackspaceLongPressHandler.m; sourceTree = "<group>"; }; A1B2C9022FBD000100000001 /* KBBackspaceLongPressHandler.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = KBBackspaceLongPressHandler.m; sourceTree = "<group>"; };
A1B2C9032FBD000200000001 /* KBBackspaceUndoManager.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = KBBackspaceUndoManager.h; sourceTree = "<group>"; };
A1B2C9042FBD000200000001 /* KBBackspaceUndoManager.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = KBBackspaceUndoManager.m; sourceTree = "<group>"; };
04FC95712EB09570007BD342 /* KBFunctionBarView.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = KBFunctionBarView.h; sourceTree = "<group>"; }; 04FC95712EB09570007BD342 /* KBFunctionBarView.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = KBFunctionBarView.h; sourceTree = "<group>"; };
04FC95722EB09570007BD342 /* KBFunctionBarView.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = KBFunctionBarView.m; sourceTree = "<group>"; }; 04FC95722EB09570007BD342 /* KBFunctionBarView.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = KBFunctionBarView.m; sourceTree = "<group>"; };
04FC95742EB095DE007BD342 /* KBFunctionPasteView.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = KBFunctionPasteView.h; sourceTree = "<group>"; }; 04FC95742EB095DE007BD342 /* KBFunctionPasteView.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = KBFunctionPasteView.h; sourceTree = "<group>"; };
@@ -810,6 +813,8 @@
children = ( children = (
A1B2C9012FBD000100000001 /* KBBackspaceLongPressHandler.h */, A1B2C9012FBD000100000001 /* KBBackspaceLongPressHandler.h */,
A1B2C9022FBD000100000001 /* KBBackspaceLongPressHandler.m */, A1B2C9022FBD000100000001 /* KBBackspaceLongPressHandler.m */,
A1B2C9032FBD000200000001 /* KBBackspaceUndoManager.h */,
A1B2C9042FBD000200000001 /* KBBackspaceUndoManager.m */,
); );
path = Utils; path = Utils;
sourceTree = "<group>"; sourceTree = "<group>";
@@ -1898,6 +1903,7 @@
049FB22F2EC34EB900FAB05D /* KBStreamTextView.m in Sources */, 049FB22F2EC34EB900FAB05D /* KBStreamTextView.m in Sources */,
04FC95702EB09516007BD342 /* KBFunctionView.m in Sources */, 04FC95702EB09516007BD342 /* KBFunctionView.m in Sources */,
A1B2C9032FBD000100000001 /* KBBackspaceLongPressHandler.m in Sources */, A1B2C9032FBD000100000001 /* KBBackspaceLongPressHandler.m in Sources */,
A1B2C9052FBD000200000001 /* KBBackspaceUndoManager.m in Sources */,
049FB23F2EC4B6EF00FAB05D /* KBULBridgeNotification.m in Sources */, 049FB23F2EC4B6EF00FAB05D /* KBULBridgeNotification.m in Sources */,
04791F992ED49CE7004E8522 /* KBFont.m in Sources */, 04791F992ED49CE7004E8522 /* KBFont.m in Sources */,
04FC956D2EB054B7007BD342 /* KBKeyboardView.m in Sources */, 04FC956D2EB054B7007BD342 /* KBKeyboardView.m in Sources */,