Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(ios): add HippyFontChangeTriggerNotification for native font update #4056

Merged
merged 1 commit into from
Oct 11, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
23 changes: 20 additions & 3 deletions renderer/native/ios/renderer/HippyComponentMap.h
Original file line number Diff line number Diff line change
Expand Up @@ -21,9 +21,7 @@
*/

#import <Foundation/Foundation.h>

#import "HippyComponent.h"

#include <memory>

namespace hippy {
Expand All @@ -39,6 +37,7 @@ typedef NS_ENUM(NSUInteger, HippyComponentReferenceType) {
HippyComponentReferenceTypeWeak,
};

/// A structure that holds all root and components information
@interface HippyComponentMap : NSObject

/// Whether all recorded elements are strongly referenced,
Expand All @@ -62,27 +61,45 @@ typedef NS_ENUM(NSUInteger, HippyComponentReferenceType) {
rootNode:(std::weak_ptr<hippy::RootNode>)rootNode
forTag:(NSNumber *)tag;

/// Remove root component
/// - Parameter tag: hippyTag
- (void)removeRootComponentWithTag:(NSNumber *)tag;

/// Whether contain root component with given tag
/// - Parameter tag: hippyTag
- (BOOL)containRootComponentWithTag:(NSNumber *)tag;

/// Get all rootTags
- (NSArray<NSNumber *> *)allRootTags;

/// Get all root components
- (NSArray<id<HippyComponent>> *)rootComponents;

/// Get root component with given tag
/// - Parameter tag: hippyTag
- (__kindof id<HippyComponent>)rootComponentForTag:(NSNumber *)tag;

/// Get RootNode for given tag
/// - Parameter tag: hippyTag
- (std::weak_ptr<hippy::RootNode>)rootNodeForTag:(NSNumber *)tag;


#pragma mark -
#pragma mark - Components manage

/// Add a component to ComponentMap
- (void)addComponent:(__kindof id<HippyComponent>)component forRootTag:(NSNumber *)tag;

/// Remove one component from ComponentMap
- (void)removeComponent:(__kindof id<HippyComponent>)component forRootTag:(NSNumber *)tag;

/// Get all components for given root tag
/// - Parameter tag: hippyTag
- (NSDictionary<NSNumber *, __kindof id<HippyComponent>> *)componentsForRootTag:(NSNumber *)tag;

/// Get specific component on rootTag with given tag
/// - Parameters:
/// - componentTag: hippyTag
/// - tag: rootTag
- (__kindof id<HippyComponent>)componentForTag:(NSNumber *)componentTag onRootTag:(NSNumber *)tag;


Expand Down
4 changes: 4 additions & 0 deletions renderer/native/ios/renderer/HippyComponentMap.mm
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,10 @@ - (BOOL)containRootComponentWithTag:(NSNumber *)tag {
return nil != rootComponent;
}

- (NSArray<NSNumber *> *)allRootTags {
return [[_rootComponentsMap keyEnumerator] allObjects];
}

- (NSArray<id<HippyComponent>> *)rootComponents {
return [[_rootComponentsMap objectEnumerator] allObjects];
}
Expand Down
10 changes: 6 additions & 4 deletions renderer/native/ios/renderer/HippyFont.h
Original file line number Diff line number Diff line change
Expand Up @@ -39,10 +39,12 @@
variant:(NSArray<NSString *> *)variant
scaleMultiplier:(CGFloat)scaleMultiplier;

+ (UIFont *)updateFont:(UIFont *)font withFamily:(NSString *)family;
+ (UIFont *)updateFont:(UIFont *)font withSize:(NSNumber *)size;
+ (UIFont *)updateFont:(UIFont *)font withWeight:(NSString *)weight;
+ (UIFont *)updateFont:(UIFont *)font withStyle:(NSString *)style;
/// Get the
/// JS side usually pass a `fontName` instead of `fontFamily`
/// If not match, the original value is returned.
///
/// - Parameter fontFamily: NSString *
+ (NSString *)familyNameWithCSSNameMatching:(NSString *)fontName;

@end

Expand Down
28 changes: 13 additions & 15 deletions renderer/native/ios/renderer/HippyFont.mm
Original file line number Diff line number Diff line change
Expand Up @@ -115,7 +115,9 @@ @implementation HippyConvert (NativeRenderFont)

+ (UIFont *)UIFont:(id)json {
json = [self NSDictionary:json];
return [HippyFont updateFont:nil withFamily:[HippyConvert NSString:json[@"fontFamily"]] size:[HippyConvert NSNumber:json[@"fontSize"]]
return [HippyFont updateFont:nil
withFamily:[HippyConvert NSString:json[@"fontFamily"]]
size:[HippyConvert NSNumber:json[@"fontSize"]]
weight:[HippyConvert NSString:json[@"fontWeight"]]
style:[HippyConvert NSString:json[@"fontStyle"]]
variant:[HippyConvert NSStringArray:json[@"fontVariant"]]
Expand Down Expand Up @@ -322,20 +324,16 @@ + (UIFont *)updateFont:(UIFont *)font
return font;
}

+ (UIFont *)updateFont:(UIFont *)font withFamily:(NSString *)family {
return [self updateFont:font withFamily:family size:nil weight:nil style:nil variant:nil scaleMultiplier:1];
}

+ (UIFont *)updateFont:(UIFont *)font withSize:(NSNumber *)size {
return [self updateFont:font withFamily:nil size:size weight:nil style:nil variant:nil scaleMultiplier:1];
}

+ (UIFont *)updateFont:(UIFont *)font withWeight:(NSString *)weight {
return [self updateFont:font withFamily:nil size:nil weight:weight style:nil variant:nil scaleMultiplier:1];
}

+ (UIFont *)updateFont:(UIFont *)font withStyle:(NSString *)style {
return [self updateFont:font withFamily:nil size:nil weight:nil style:style variant:nil scaleMultiplier:1];
+ (NSString *)familyNameWithCSSNameMatching:(NSString *)fontName {
NSString *familyName = fontName;
if (fontName && ![[UIFont familyNames] containsObject:fontName]) {
// Not a real FamilyName
// Using CSS name matching semantics.
// fontSize here is just a placeholder for getting font.
UIFont *cssFont = [UIFont fontWithName:fontName size:14.0];
familyName = cssFont.familyName;
}
return familyName;
}

@end
9 changes: 9 additions & 0 deletions renderer/native/ios/renderer/HippyUIManager.h
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,15 @@ HIPPY_EXTERN NSString *const HippyUIManagerRootViewTagKey;
*/
HIPPY_EXTERN NSString *const HippyUIManagerDidEndBatchNotification;

/**
* This notification can be sent when the font is registered or modified on the native side
* and hippy needs to be refreshed.
*
* `notification.object` can carry rootTag to filter the RootView that needs to be refreshed.
* Default value nil indicating that a refresh is required.
*/
HIPPY_EXTERN NSString *const HippyFontChangeTriggerNotification;



/// The HippyUIManager responsible for updating the view hierarchy.
Expand Down
54 changes: 54 additions & 0 deletions renderer/native/ios/renderer/HippyUIManager.mm
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,8 @@
#import "HippyModuleMethod.h"
#import "HippyBridge+Private.h"
#import "HippyJSExecutor.h"
#import "HippyShadowText.h"
#import "HippyShadowTextView.h"
#import "dom/root_node.h"
#import "objc/runtime.h"
#import <os/lock.h>
Expand Down Expand Up @@ -181,6 +183,7 @@ - (void)setUiManager:(HippyUIManager *)uiManager;
NSString *const HippyUIManagerRootViewKey = @"HippyUIManagerRootViewKey";
NSString *const HippyUIManagerRootViewTagKey = @"HippyUIManagerRootViewTagKey";
NSString *const HippyUIManagerDidEndBatchNotification = @"HippyUIManagerDidEndBatchNotification";
NSString *const HippyFontChangeTriggerNotification = @"HippyFontChangeTriggerNotification";

@interface HippyUIManager() {
NSMutableArray<HippyViewManagerUIBlock> *_pendingUIBlocks;
Expand Down Expand Up @@ -233,6 +236,10 @@ - (void)initContext {
_componentDataLock = OS_UNFAIR_LOCK_INIT;
HippyScreenScale();
HippyScreenSize();
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(onFontChangedFromNative:)
name:HippyFontChangeTriggerNotification
object:nil];
}

- (void)invalidate {
Expand Down Expand Up @@ -1484,6 +1491,53 @@ - (void)domEventDidHandle:(const std::string &)eventName forNode:(int32_t)tag on
// no op
}


#pragma mark - Font Refresh

- (void)onFontChangedFromNative:(NSNotification *)notification {
NSNumber *targetRootTag = notification.object;
if ((targetRootTag != nil) && ![self.viewRegistry containRootComponentWithTag:targetRootTag]) {
// do compare if notification has target RootView.
return;
}

__weak __typeof(self)weakSelf = self;
[self.bridge.javaScriptExecutor executeAsyncBlockOnJavaScriptQueue:^{
__strong __typeof(weakSelf)strongSelf = weakSelf;
if (!strongSelf) {
return;
}

NSArray<NSNumber *> *allRootTags;
if (targetRootTag != nil) {
allRootTags = [NSArray arrayWithObject:targetRootTag];
} else {
// UIManager may have more than one Root
allRootTags = strongSelf->_shadowViewRegistry.allRootTags;
}

for (NSNumber *rootTag in allRootTags) {
NSArray<HippyShadowView *> *shadowViews = [strongSelf->_shadowViewRegistry componentsForRootTag:rootTag].allValues;
Class shadowTextClass = [HippyShadowText class];
Class shadowTextViewClass = [HippyShadowTextView class];
for (HippyShadowView *shadowView in shadowViews) {
if ([shadowView isKindOfClass:shadowTextClass] ||
[shadowView isKindOfClass:shadowTextViewClass]) {
[shadowView dirtyText:NO];
[shadowView dirtyPropagation:NativeRenderUpdateLifecycleLayoutDirtied];
}
}
// do layout and refresh UI
auto domManager = self.domManager.lock();
if (domManager) {
auto rootNode = [strongSelf->_shadowViewRegistry rootNodeForTag:rootTag];
domManager->DoLayout(rootNode);
domManager->EndBatch(rootNode);
}
}
}];
}

@end


Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -418,8 +418,7 @@ - (void)dirtyText:(BOOL)needToDoLayout {
BOOL isJSTaskRunner = (domManager->GetTaskRunner() && footstone::TaskRunner::GetCurrentTaskRunner());
if (isJSTaskRunner) {
domNodeAction();
}
else {
} else {
std::vector<std::function<void()>> ops = {domNodeAction};
domManager->PostTask(hippy::dom::Scene(std::move(ops)));
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,15 @@

@interface HippyBaseTextInput : HippyView

/// Font property - FontSize
@property (nonatomic, strong) NSNumber *fontSize;
/// Font property - FontWeight
@property (nonatomic, strong) NSString *fontWeight;
/// Font property - FontStyle
@property (nonatomic, strong) NSString *fontStyle;
/// Font property - FontFamily
@property (nonatomic, strong) NSString *fontFamily;

@property (nonatomic, strong) UIFont *font;
@property (nonatomic, assign) UIEdgeInsets contentInset;
@property (nonatomic, copy) NSString *value;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
*/

#import "HippyBaseTextInput.h"
#import "HippyFont.h"

static NSString *const kKeyboardHeightKey = @"keyboardHeight";

Expand Down Expand Up @@ -95,4 +96,56 @@ - (void)setOnKeyboardHeightChanged:(HippyDirectEventBlock)onKeyboardHeightChange
}
}


#pragma mark - Hippy Update Callback

- (void)hippyBridgeDidFinishTransaction {
// Use this opportunity to update font if needed.
[self layoutIfNeeded];
}

- (void)layoutSubviews {
[super layoutSubviews];
[self rebuildAndUpdateFont];
}


#pragma mark - Font Related

- (void)setFontSize:(NSNumber *)fontSize {
_fontSize = fontSize;
[self setNeedsLayout];
}

- (void)setFontStyle:(NSString *)fontStyle {
_fontStyle = fontStyle;
[self setNeedsLayout];
}

- (void)setFontWeight:(NSString *)fontWeight {
_fontWeight = fontWeight;
[self setNeedsLayout];
}

- (void)setFontFamily:(NSString *)fontFamily {
_fontFamily = fontFamily;
[self setNeedsLayout];
}

- (void)rebuildAndUpdateFont {
// Convert fontName to fontFamily if needed
CGFloat scaleMultiplier = 1.0; // scale not supported
NSString *familyName = [HippyFont familyNameWithCSSNameMatching:self.fontFamily];
UIFont *font = [HippyFont updateFont:self.font
withFamily:familyName
size:self.fontSize
weight:self.fontWeight
style:self.fontStyle
variant:nil
scaleMultiplier:scaleMultiplier];
if (self.font != font) {
self.font = font;
}
}

@end
Original file line number Diff line number Diff line change
Expand Up @@ -27,13 +27,20 @@
@property (nonatomic, copy) NSString *text;
@property (nonatomic, copy) NSString *placeholder;

@property (nonatomic, strong) UIFont *font;

/// ParagraphStyles - lineHeight
@property (nonatomic, strong) NSNumber *lineHeight;
/// ParagraphStyles - lineSpacing
@property (nonatomic, strong) NSNumber *lineSpacing;
/// ParagraphStyles - lineHeightMultiple
@property (nonatomic, strong) NSNumber *lineHeightMultiple;

/// Font property - FontSize
@property (nonatomic, strong) NSNumber *fontSize;
/// Font property - FontWeight
@property (nonatomic, strong) NSString *fontWeight;
/// Font property - FontStyle
@property (nonatomic, strong) NSString *fontStyle;
/// Font property - FontFamily
@property (nonatomic, strong) NSString *fontFamily;

@end
Loading
Loading