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 #3956

Merged
merged 1 commit into from
Jul 18, 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
10 changes: 6 additions & 4 deletions ios/sdk/base/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
24 changes: 10 additions & 14 deletions ios/sdk/base/HippyFont.mm
Original file line number Diff line number Diff line change
Expand Up @@ -307,20 +307,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
12 changes: 0 additions & 12 deletions ios/sdk/base/HippyRootView.mm
Original file line number Diff line number Diff line change
Expand Up @@ -436,7 +436,6 @@ - (NSNumber *)allocateRootTag

@implementation HippyRootContentView {
__weak HippyBridge *_bridge;
UIColor *_backgroundColor;
}

- (instancetype)initWithFrame:(CGRect)frame
Expand Down Expand Up @@ -484,17 +483,6 @@ - (void)setFrame:(CGRect)frame {
}
}

- (void)setBackgroundColor:(UIColor *)backgroundColor {
_backgroundColor = backgroundColor;
if (self.hippyTag && _bridge.isValid) {
[_bridge.uiManager setBackgroundColor:backgroundColor forView:self];
}
}

- (UIColor *)backgroundColor {
return _backgroundColor;
}

- (void)invalidate {
if (self.userInteractionEnabled) {
self.userInteractionEnabled = NO;
Expand Down
10 changes: 10 additions & 0 deletions ios/sdk/component/textinput/HippyBaseTextInput.h
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,16 @@
#import "HippyView.h"

@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
54 changes: 54 additions & 0 deletions ios/sdk/component/textinput/HippyBaseTextInput.m
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
*/

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

@implementation HippyBaseTextInput
- (void)focus {
Expand All @@ -42,4 +43,57 @@ - (void)keyboardHeightChanged:(NSNotification *)aNotification {
// base method, should be override
}


#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
11 changes: 9 additions & 2 deletions ios/sdk/component/textinput/HippyShadowTextView.h
Original file line number Diff line number Diff line change
Expand Up @@ -26,13 +26,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
76 changes: 76 additions & 0 deletions ios/sdk/component/textinput/HippyShadowTextView.mm
Original file line number Diff line number Diff line change
Expand Up @@ -24,16 +24,33 @@
#import "MTTLayout.h"
#import "x5LayoutUtil.h"
#import "HippyShadowView+MTTLayout.h"
#import "HippyFont.h"


@interface HippyShadowTextView ()

/// Cached font
@property (nonatomic, strong) UIFont *font;
/// Whether font needs to be updated.
@property (nonatomic, assign) BOOL isFontDirty;
/// Cached attributes
@property (nonatomic, strong) NSDictionary *dicAttributes;

/// rebuild and update the font property
- (void)rebuildAndUpdateFont;

@end

static MTTSize x5MeasureFunc(
MTTNodeRef node, float width, MeasureMode widthMeasureMode, __unused float height, __unused MeasureMode heightMeasureMode, void *layoutContext) {
HippyShadowTextView *shadowText = (__bridge HippyShadowTextView *)MTTNodeGetContext(node);
NSString *text = shadowText.text ?: shadowText.placeholder;
if (nil == shadowText.dicAttributes) {
if (shadowText.isFontDirty) {
[shadowText rebuildAndUpdateFont];
shadowText.isFontDirty = NO;
}
// Keep this historical code, default fontSize 16.
if (shadowText.font == nil) {
shadowText.font = [UIFont systemFontOfSize:16];
}
Expand Down Expand Up @@ -95,4 +112,63 @@ - (NSDictionary *)mergeProps:(NSDictionary *)props {
return newProps;
}

- (void)dirtyText {
[super dirtyText];
self.isFontDirty = YES;
self.dicAttributes = nil;
}

- (void)collectUpdatedProperties:(NSMutableSet<HippyApplierBlock> *)applierBlocks
virtualApplierBlocks:(NSMutableSet<HippyApplierVirtualBlock> *)virtualApplierBlocks
parentProperties:(NSDictionary<NSString *,id> *)parentProperties {
[super collectUpdatedProperties:applierBlocks
virtualApplierBlocks:virtualApplierBlocks
parentProperties:parentProperties];

// Set needs layout for font change event, etc.
NSNumber *currentTag = self.hippyTag;
[applierBlocks addObject:^(NSDictionary<NSNumber *, UIView *> *viewRegistry){
UIView *view = viewRegistry[currentTag];
[view setNeedsLayout];
}];
}


#pragma mark - Font Related

- (void)setFontSize:(NSNumber *)fontSize {
_fontSize = fontSize;
self.isFontDirty = YES;
}

- (void)setFontStyle:(NSString *)fontStyle {
_fontStyle = fontStyle;
self.isFontDirty = YES;
}

- (void)setFontWeight:(NSString *)fontWeight {
_fontWeight = fontWeight;
self.isFontDirty = YES;
}

- (void)setFontFamily:(NSString *)fontFamily {
_fontFamily = fontFamily;
self.isFontDirty = YES;
}

- (void)rebuildAndUpdateFont {
// Convert fontName to fontFamily if needed
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:1.0];
if (self.font != font) {
self.font = font;
}
}

@end
66 changes: 9 additions & 57 deletions ios/sdk/component/textinput/HippyTextViewManager.mm
Original file line number Diff line number Diff line change
Expand Up @@ -168,6 +168,11 @@ - (HippyShadowView *)shadowView {
HIPPY_EXPORT_SHADOW_PROPERTY(lineSpacing, NSNumber)
HIPPY_EXPORT_SHADOW_PROPERTY(lineHeightMultiple, NSNumber)

HIPPY_EXPORT_SHADOW_PROPERTY(fontSize, NSNumber)
HIPPY_EXPORT_SHADOW_PROPERTY(fontWeight, NSString)
HIPPY_EXPORT_SHADOW_PROPERTY(fontStyle, NSString)
HIPPY_EXPORT_SHADOW_PROPERTY(fontFamily, NSString)

HIPPY_EXPORT_VIEW_PROPERTY(lineHeight, NSNumber)
HIPPY_EXPORT_VIEW_PROPERTY(lineSpacing, NSNumber)
HIPPY_EXPORT_VIEW_PROPERTY(lineHeightMultiple, NSNumber)
Expand Down Expand Up @@ -195,44 +200,10 @@ - (HippyShadowView *)shadowView {
HIPPY_EXPORT_VIEW_PROPERTY(selection, HippyTextSelection)
HIPPY_EXPORT_VIEW_PROPERTY(text, NSString)

HIPPY_CUSTOM_SHADOW_PROPERTY(fontSize, NSNumber, HippyShadowTextView) {
view.font = [HippyFont updateFont:view.font withSize:json];
}

HIPPY_CUSTOM_SHADOW_PROPERTY(fontWeight, NSString, HippyShadowTextView) {
view.font = [HippyFont updateFont:view.font withWeight:json];
}

HIPPY_CUSTOM_SHADOW_PROPERTY(fontStyle, NSString, HippyShadowTextView) {
view.font = [HippyFont updateFont:view.font withStyle:json]; // defaults to normal
}

HIPPY_CUSTOM_SHADOW_PROPERTY(fontFamily, NSString, HippyShadowTextView) {
// Convert fontName to fontFamily if needed
NSString *familyName = [self familyNameWithCSSNameMatching:json];
view.font = [HippyFont updateFont:view.font withFamily:familyName];
}

HIPPY_CUSTOM_VIEW_PROPERTY(fontSize, NSNumber, HippyBaseTextInput) {
UIFont *theFont = [HippyFont updateFont:view.font withSize:json ?: @(defaultView.font.pointSize)];
view.font = theFont;
}

HIPPY_CUSTOM_VIEW_PROPERTY(fontWeight, NSString, __unused HippyBaseTextInput) {
UIFont *theFont = [HippyFont updateFont:view.font withWeight:json]; // defaults to normal
view.font = theFont;
}

HIPPY_CUSTOM_VIEW_PROPERTY(fontStyle, NSString, __unused HippyBaseTextInput) {
UIFont *theFont = [HippyFont updateFont:view.font withStyle:json];
view.font = theFont; // defaults to normal
}

HIPPY_CUSTOM_VIEW_PROPERTY(fontFamily, NSString, HippyBaseTextInput) {
// Convert fontName to fontFamily if needed
NSString *familyName = [self familyNameWithCSSNameMatching:json];
view.font = [HippyFont updateFont:view.font withFamily:familyName ?: defaultView.font.familyName];
}
HIPPY_EXPORT_VIEW_PROPERTY(fontSize, NSNumber)
HIPPY_EXPORT_VIEW_PROPERTY(fontWeight, NSString)
HIPPY_EXPORT_VIEW_PROPERTY(fontStyle, NSString)
HIPPY_EXPORT_VIEW_PROPERTY(fontFamily, NSString)

- (HippyViewManagerUIBlock)uiBlockToAmendWithShadowView:(HippyShadowView *)shadowView {
NSNumber *hippyTag = shadowView.hippyTag;
Expand All @@ -242,23 +213,4 @@ - (HippyViewManagerUIBlock)uiBlockToAmendWithShadowView:(HippyShadowView *)shado
};
}


#pragma mark - Private

/// Get the
/// JS side usually pass a `fontName` instead of `fontFamily`
/// - Parameter json: id
- (NSString *)familyNameWithCSSNameMatching:(id)json {
NSString *familyName = json;
if (json && ![[UIFont familyNames] containsObject:json]) {
// Not a real FamilyName
// Using CSS name matching semantics.
// fontSize here is just a placeholder for getting font.
UIFont *cssFont = [UIFont fontWithName:json size:14.0];
familyName = cssFont.familyName;
}
return familyName;
}


@end
19 changes: 12 additions & 7 deletions ios/sdk/module/uimanager/HippyUIManager.h
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,18 @@ HIPPY_EXTERN NSString *const HippyUIManagerRootViewKey;
*/
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;


#pragma mark -

@protocol HippyScrollableProtocol;

/**
Expand Down Expand Up @@ -110,13 +122,6 @@ HIPPY_EXTERN NSString *const HippyUIManagerDidEndBatchNotification;
*/
- (void)setIntrinsicContentSize:(CGSize)size forView:(UIView *)view;

/**
* Update the background color of a view. The source of truth for
* backgroundColor is the shadow view, so if to update backgroundColor from
* native code you will need to call this method.
*/
- (void)setBackgroundColor:(UIColor *)color forView:(UIView *)view;

/**
* Schedule a block to be executed on the UI thread. Useful if you need to execute
* view logic after all currently queued view updates have completed.
Expand Down
Loading
Loading