fix(ios): apply text color to HTMLView content (#10708)

This commit is contained in:
Dimitris-Rafail Katsampas
2025-02-23 00:17:47 +02:00
committed by GitHub
parent 8c4d7ca8be
commit 640db9529e
4 changed files with 67 additions and 38 deletions

View File

@ -1,8 +1,6 @@
import { CssProperty } from '../core/properties'; import { View, CSSType } from '../core/view';
import { View, CSSType } from '../core/view';
import { booleanConverter } from '../core/view-base'; import { booleanConverter } from '../core/view-base';
import { Property } from '../core/properties'; import { Property } from '../core/properties';
import { Style } from '../styling/style';
import { Color } from '../../color'; import { Color } from '../../color';
import { HtmlView as HtmlViewDefinition } from '.'; import { HtmlView as HtmlViewDefinition } from '.';
@ -30,10 +28,9 @@ export const selectableProperty = new Property<HtmlViewBase, boolean>({
}); });
selectableProperty.register(HtmlViewBase); selectableProperty.register(HtmlViewBase);
export const linkColorProperty = new CssProperty<Style, Color>({ export const linkColorProperty = new Property<HtmlViewBase, Color>({
name: 'linkColor', name: 'linkColor',
cssName: 'link-color',
equalityComparer: Color.equals, equalityComparer: Color.equals,
valueConverter: (value) => new Color(value), valueConverter: (value) => new Color(value),
}); });
linkColorProperty.register(Style); linkColorProperty.register(HtmlViewBase);

View File

@ -1,5 +1,6 @@
import { View } from '../core/view'; import { View } from '../core/view';
import { Property } from '../core/properties'; import { Property } from '../core/properties';
import { Color } from '../../color';
/** /**
* Represents a view with html content. Use this component instead WebView when you want to show just static HTML content. * Represents a view with html content. Use this component instead WebView when you want to show just static HTML content.
@ -39,3 +40,5 @@ export class HtmlView extends View {
} }
export const htmlProperty: Property<HtmlView, string>; export const htmlProperty: Property<HtmlView, string>;
export const selectableProperty: Property<HtmlView, boolean>;
export const linkColorProperty: Property<HtmlView, Color>;

View File

@ -11,17 +11,16 @@ const majorVersion = iOSNativeHelper.MajorVersion;
export class HtmlView extends HtmlViewBase { export class HtmlView extends HtmlViewBase {
nativeViewProtected: UITextView; nativeViewProtected: UITextView;
private currentHtml: string;
public createNativeView() { public createNativeView() {
const view = UITextView.new(); const nativeView = UITextView.new();
view.scrollEnabled = false; nativeView.scrollEnabled = false;
view.editable = false; nativeView.editable = false;
view.selectable = true; nativeView.selectable = true;
view.userInteractionEnabled = true; nativeView.userInteractionEnabled = true;
view.dataDetectorTypes = UIDataDetectorTypes.All; nativeView.dataDetectorTypes = UIDataDetectorTypes.All;
return view; return nativeView;
} }
public initNativeView(): void { public initNativeView(): void {
@ -60,24 +59,37 @@ export class HtmlView extends HtmlViewBase {
} }
private renderWithStyles() { private renderWithStyles() {
let html = this.currentHtml; const bodyStyles: string[] = [];
const styles = [];
if (this.nativeViewProtected.font) {
styles.push(`font-family: '${this.nativeViewProtected.font.fontName}';`);
styles.push(`font-size: ${this.nativeViewProtected.font.pointSize}px;`);
}
if (this.nativeViewProtected.textColor) {
const textColor = Color.fromIosColor(this.nativeViewProtected.textColor);
styles.push(`color: ${textColor.hex};`);
}
if (styles.length > 0) {
html += `<style>body {${styles.join('')}}</style>`;
}
const htmlString = NSString.stringWithString(html + '');
const nsData = htmlString.dataUsingEncoding(NSUnicodeStringEncoding);
this.nativeViewProtected.attributedText = NSAttributedString.alloc().initWithDataOptionsDocumentAttributesError(nsData, <any>{ [NSDocumentTypeDocumentAttribute]: NSHTMLTextDocumentType }, null);
if (majorVersion >= 13 && UIColor.labelColor) { let htmlContent = this.html ?? '';
htmlContent += '<style>';
bodyStyles.push(`font-size: ${this.style.fontSize}px;`);
if (this.style.fontFamily) {
bodyStyles.push(`font-family: '${this.style.fontFamily}';`);
}
if (this.style.color) {
bodyStyles.push(`color: ${this.style.color.hex};`);
}
htmlContent += `body {${bodyStyles.join('')}}`;
if (this.linkColor) {
htmlContent += `a, a:link, a:visited { color: ${this.linkColor.hex} !important; }`;
}
htmlContent += '</style>';
const htmlString = NSString.stringWithString(htmlContent);
const nsData = htmlString.dataUsingEncoding(NSUnicodeStringEncoding);
const attributes = NSDictionary.dictionaryWithObjectForKey(NSHTMLTextDocumentType, NSDocumentTypeDocumentAttribute);
this.nativeViewProtected.attributedText = NSAttributedString.alloc().initWithDataOptionsDocumentAttributesError(nsData, attributes, null);
if (!this.style.color && majorVersion >= 13 && UIColor.labelColor) {
this.nativeViewProtected.textColor = UIColor.labelColor; this.nativeViewProtected.textColor = UIColor.labelColor;
} }
} }
@ -86,7 +98,6 @@ export class HtmlView extends HtmlViewBase {
return ''; return '';
} }
[htmlProperty.setNative](value: string) { [htmlProperty.setNative](value: string) {
this.currentHtml = value;
this.renderWithStyles(); this.renderWithStyles();
} }
@ -106,14 +117,10 @@ export class HtmlView extends HtmlViewBase {
this.renderWithStyles(); this.renderWithStyles();
} }
[linkColorProperty.getDefault](): UIColor {
return this.nativeViewProtected.linkTextAttributes[NSForegroundColorAttributeName];
}
[linkColorProperty.setNative](value: Color | UIColor) { [linkColorProperty.setNative](value: Color | UIColor) {
const color = value instanceof Color ? value.ios : value; this.renderWithStyles();
const linkTextAttributes = NSDictionary.dictionaryWithObjectForKey(color, NSForegroundColorAttributeName);
this.nativeViewProtected.linkTextAttributes = linkTextAttributes;
} }
[fontInternalProperty.getDefault](): UIFont { [fontInternalProperty.getDefault](): UIFont {
return this.nativeViewProtected.font; return this.nativeViewProtected.font;
} }

View File

@ -6,6 +6,7 @@ import { Property, CssProperty, InheritedCssProperty } from '../core/properties'
import { CoreTypes } from '../../core-types'; import { CoreTypes } from '../../core-types';
import { ShadowCSSValues } from '../styling/css-shadow'; import { ShadowCSSValues } from '../styling/css-shadow';
import { StrokeCSSValues } from '../styling/css-stroke'; import { StrokeCSSValues } from '../styling/css-stroke';
import { FontStyleType, FontWeightType } from '../styling/font-interfaces';
/** /**
* @nsView TextBase * @nsView TextBase
@ -31,6 +32,13 @@ export class TextBase extends View implements AddChildFromBuilder {
*/ */
formattedText: FormattedString; formattedText: FormattedString;
/**
* Gets or sets font-family style property.
*
* @nsProperty
*/
fontFamily: string;
/** /**
* Gets or sets font-size style property. * Gets or sets font-size style property.
* *
@ -38,6 +46,20 @@ export class TextBase extends View implements AddChildFromBuilder {
*/ */
fontSize: number; fontSize: number;
/**
* Gets or sets font-style style property.
*
* @nsProperty
*/
fontStyle: FontStyleType;
/**
* Gets or sets font-weight style property.
*
* @nsProperty
*/
fontWeight: FontWeightType;
/** /**
* Gets or sets letterSpace style property. * Gets or sets letterSpace style property.
* *