Skip to content

Commit

Permalink
Add singleline implementation
Browse files Browse the repository at this point in the history
  • Loading branch information
tomekzaw committed Oct 21, 2024
1 parent 4214989 commit 20166dd
Show file tree
Hide file tree
Showing 4 changed files with 86 additions and 6 deletions.
19 changes: 19 additions & 0 deletions apple/MarkdownTextFieldObserver.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
#import <UIKit/UIKit.h>
#import <React/RCTUITextField.h>
#import <RNLiveMarkdown/RCTMarkdownUtils.h>

NS_ASSUME_NONNULL_BEGIN

@interface MarkdownTextFieldObserver : NSObject

@property (nonatomic, nullable, strong) RCTMarkdownUtils *markdownUtils;

@property (nonatomic, nullable, strong) RCTUITextField *textField;

@property (nonatomic) BOOL active;

- (void)textFieldDidChange:(UITextField *)textField;

@end

NS_ASSUME_NONNULL_END
33 changes: 33 additions & 0 deletions apple/MarkdownTextFieldObserver.mm
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
#import <RNLiveMarkdown/MarkdownTextFieldObserver.h>

@implementation MarkdownTextFieldObserver

- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary<NSKeyValueChangeKey,id> *)change context:(void *)context
{
react_native_assert(_textField != nil);

if (_active && ([keyPath isEqualToString:@"text"] || [keyPath isEqualToString:@"attributedText"])) {
[self textFieldDidChange:_textField];
}
}

- (void)textFieldDidChange:(__unused UITextField *)textField {
react_native_assert(_markdownUtils != nil);
react_native_assert(_textField != nil);
react_native_assert(_textField.defaultTextAttributes != nil);

if (_textField.markedTextRange != nil) {
return; // skip formatting during multi-stage input to avoid breaking internal state
}

NSMutableAttributedString *attributedText = [textField.attributedText mutableCopy];
[_markdownUtils applyFormatting:attributedText withDefaultTextAttributes:_textField.defaultTextAttributes];

UITextRange *textRange = _textField.selectedTextRange;
_active = NO; // prevent recursion
_textField.attributedText = attributedText;
_active = YES;
[_textField setSelectedTextRange:textRange notifyDelegate:NO];
}

@end
32 changes: 30 additions & 2 deletions apple/MarkdownTextInputDecoratorView.mm
Original file line number Diff line number Diff line change
Expand Up @@ -6,14 +6,17 @@
#import <RNLiveMarkdown/MarkdownLayoutManager.h>
#import <RNLiveMarkdown/MarkdownTextInputDecoratorView.h>
#import <RNLiveMarkdown/MarkdownTextStorageDelegate.h>
#import <RNLiveMarkdown/MarkdownTextFieldObserver.h>

#import <objc/runtime.h>

@implementation MarkdownTextInputDecoratorView {
RCTMarkdownUtils *_markdownUtils;
RCTMarkdownStyle *_markdownStyle;
MarkdownTextStorageDelegate *_markdownTextStorageDelegate;
MarkdownTextFieldObserver *_markdownTextFieldObserver;
__weak RCTUITextView *_textView;
__weak RCTUITextField *_textField;
}

- (void)didMoveToWindow {
Expand Down Expand Up @@ -52,8 +55,25 @@ - (void)didMoveToWindow {
[_markdownUtils setMarkdownStyle:_markdownStyle];

if ([backedTextInputView isKindOfClass:[RCTUITextField class]]) {
// TODO: implement for singleline input
react_native_assert(false && "Not implemented for singleline input yet");
_textField = (RCTUITextField *)backedTextInputView;

// make sure `adjustsFontSizeToFitWidth` is disabled, otherwise formatting will be overwritten
react_native_assert(_textField.adjustsFontSizeToFitWidth == NO);

_markdownTextFieldObserver = [[MarkdownTextFieldObserver alloc] init];
_markdownTextFieldObserver.markdownUtils = _markdownUtils;
_markdownTextFieldObserver.textField = _textField;
_markdownTextFieldObserver.active = YES;

// register observers for future edits
[_textField addTarget:_markdownTextFieldObserver action:@selector(textFieldDidChange:) forControlEvents:UIControlEventEditingChanged];
[_textField addObserver:_markdownTextFieldObserver forKeyPath:@"text" options:NSKeyValueObservingOptionNew context:NULL];
[_textField addObserver:_markdownTextFieldObserver forKeyPath:@"attributedText" options:NSKeyValueObservingOptionNew context:NULL];

// format initial value
[_markdownTextFieldObserver textFieldDidChange:_textField];

// TODO: register blockquotes layout manager
} else if ([backedTextInputView isKindOfClass:[RCTUITextView class]]) {
_textView = (RCTUITextView *)backedTextInputView;

Expand Down Expand Up @@ -94,6 +114,14 @@ - (void)willMoveToWindow:(UIWindow *)newWindow
object_setClass(_textView.layoutManager, [NSLayoutManager class]);
}
}

if (_textField != nil) {
[_textField removeTarget:_markdownTextFieldObserver action:@selector(textFieldDidChange:) forControlEvents:UIControlEventEditingChanged];
[_textField removeObserver:_markdownTextFieldObserver forKeyPath:@"text" context:NULL];
[_textField removeObserver:_markdownTextFieldObserver forKeyPath:@"attributedText" context:NULL];
_markdownTextFieldObserver = nil;
_textField = nil;
}
}

- (void)setMarkdownStyle:(RCTMarkdownStyle *)markdownStyle
Expand Down
8 changes: 4 additions & 4 deletions example/ios/Podfile.lock
Original file line number Diff line number Diff line change
Expand Up @@ -1497,7 +1497,7 @@ PODS:
- React-logger (= 0.75.2)
- React-perflogger (= 0.75.2)
- React-utils (= 0.75.2)
- RNLiveMarkdown (0.1.172):
- RNLiveMarkdown (0.1.176):
- DoubleConversion
- glog
- hermes-engine
Expand All @@ -1517,9 +1517,9 @@ PODS:
- ReactCodegen
- ReactCommon/turbomodule/bridging
- ReactCommon/turbomodule/core
- RNLiveMarkdown/newarch (= 0.1.172)
- RNLiveMarkdown/newarch (= 0.1.176)
- Yoga
- RNLiveMarkdown/newarch (0.1.172):
- RNLiveMarkdown/newarch (0.1.176):
- DoubleConversion
- glog
- hermes-engine
Expand Down Expand Up @@ -1805,7 +1805,7 @@ SPEC CHECKSUMS:
React-utils: 81a715d9c0a2a49047e77a86f3a2247408540deb
ReactCodegen: 60973d382704c793c605b9be0fc7f31cb279442f
ReactCommon: 6ef348087d250257c44c0204461c03f036650e9b
RNLiveMarkdown: 0d4f090ee84cfa2d2684b5b079547c5c9d2453b2
RNLiveMarkdown: 0b8756147a5e8eeea98d3e1187c0c27d5a96d1ff
SocketRocket: abac6f5de4d4d62d24e11868d7a2f427e0ef940d
Yoga: 2a45d7e59592db061217551fd3bbe2dd993817ae

Expand Down

0 comments on commit 20166dd

Please sign in to comment.