react-native-advanced-text 0.2.10 → 0.2.12

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -33,6 +33,7 @@ android {
33
33
  defaultConfig {
34
34
  minSdkVersion getExtOrIntegerDefault("minSdkVersion")
35
35
  targetSdkVersion getExtOrIntegerDefault("targetSdkVersion")
36
+ consumerProguardFiles "consumer-rules.pro"
36
37
  }
37
38
 
38
39
  buildFeatures {
@@ -0,0 +1,3 @@
1
+ # NativeTextMeasurement is only called from C++ (ShadowNodes.cpp) via JNI,
2
+ # so R8 can't see it's used and would strip or rename it.
3
+ -keep class com.advancedtext.NativeTextMeasurement { *; }
@@ -8,6 +8,9 @@ import java.util.ArrayList
8
8
 
9
9
  class AdvancedTextViewPackage : ReactPackage {
10
10
  override fun createViewManagers(reactContext: ReactApplicationContext): List<ViewManager<*, *>> {
11
+ // Fabric measures text before any view exists, so hand the app's assets
12
+ // to the measurer as early as possible.
13
+ NativeTextMeasurement.assetManager = reactContext.assets
11
14
  val viewManagers: MutableList<ViewManager<*, *>> = ArrayList()
12
15
  viewManagers.add(AdvancedTextViewManager())
13
16
  return viewManagers
@@ -19,6 +19,7 @@ import android.view.Menu
19
19
  import android.view.MenuItem
20
20
  import android.view.View
21
21
  import android.view.MotionEvent
22
+ import android.view.accessibility.AccessibilityNodeInfo
22
23
  import android.widget.TextView
23
24
  import com.facebook.react.bridge.Arguments
24
25
  import com.facebook.react.bridge.ReactContext
@@ -173,7 +174,7 @@ class AdvancedTextView : TextView {
173
174
  fun setAdvancedFontFamily(family: String) {
174
175
  if (fontFamily == family) return
175
176
  fontFamily = family
176
- typeface = Typeface.create(family, Typeface.NORMAL)
177
+ typeface = NativeTextMeasurement.resolveTypeface(family, Typeface.NORMAL)
177
178
  }
178
179
 
179
180
  fun setMenuOptions(menuOptions: List<String>) {
@@ -281,9 +282,9 @@ class AdvancedTextView : TextView {
281
282
  setTextSize(fontSize)
282
283
 
283
284
  typeface = when (fontWeight) {
284
- "bold" -> Typeface.create(fontFamily, Typeface.BOLD)
285
- "italic" -> Typeface.create(fontFamily, Typeface.ITALIC)
286
- else -> Typeface.create(fontFamily, Typeface.NORMAL)
285
+ "bold" -> NativeTextMeasurement.resolveTypeface(fontFamily, Typeface.BOLD)
286
+ "italic" -> NativeTextMeasurement.resolveTypeface(fontFamily, Typeface.ITALIC)
287
+ else -> NativeTextMeasurement.resolveTypeface(fontFamily, Typeface.NORMAL)
287
288
  }
288
289
 
289
290
 
@@ -310,6 +311,15 @@ class AdvancedTextView : TextView {
310
311
  Log.d(TAG, "Text updated with ${wordPositions.size} spans")
311
312
  }
312
313
 
314
+ // Every word is a ClickableSpan so a tap can report it, but TalkBack treats
315
+ // each span as a link: it reads the text one word at a time and lists every
316
+ // word under Actions. Plain text keeps it reading as prose; granularity
317
+ // navigation still works since the characters are identical.
318
+ override fun onInitializeAccessibilityNodeInfo(info: AccessibilityNodeInfo) {
319
+ super.onInitializeAccessibilityNodeInfo(info)
320
+ info.text = text?.toString()
321
+ }
322
+
313
323
  override fun onDraw(canvas: Canvas) {
314
324
  drawHighlightedWordBackgrounds(canvas)
315
325
  super.onDraw(canvas)
@@ -1,10 +1,12 @@
1
1
  package com.advancedtext
2
2
 
3
+ import android.content.res.AssetManager
3
4
  import android.content.res.Resources
4
5
  import android.graphics.Typeface
5
6
  import android.text.StaticLayout
6
7
  import android.text.TextPaint
7
8
  import android.util.TypedValue
9
+ import com.facebook.react.common.assets.ReactFontManager
8
10
 
9
11
  /**
10
12
  * JNI bridge so the Fabric ShadowNode (C++ `measureContent()`) can ask
@@ -31,6 +33,20 @@ import android.util.TypedValue
31
33
  */
32
34
  object NativeTextMeasurement {
33
35
 
36
+ /** App assets, so fonts bundled under `assets/fonts/` resolve here too. */
37
+ @Volatile
38
+ var assetManager: AssetManager? = null
39
+
40
+ /**
41
+ * Resolves a font family the way React Native's own <Text> does: fonts
42
+ * registered at runtime (expo-font), then `assets/fonts/<family>.ttf|otf`,
43
+ * then system families. `AdvancedTextView` uses this too, so measuring and
44
+ * rendering always pick the same typeface.
45
+ */
46
+ @JvmStatic
47
+ fun resolveTypeface(fontFamily: String, style: Int): Typeface =
48
+ ReactFontManager.getInstance().getTypeface(fontFamily, style, assetManager)
49
+
34
50
  @JvmStatic
35
51
  fun measureHeight(
36
52
  text: String,
@@ -50,7 +66,7 @@ object NativeTextMeasurement {
50
66
  TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_SP, fontSizeSp, displayMetrics)
51
67
 
52
68
  val paint = TextPaint(TextPaint.ANTI_ALIAS_FLAG)
53
- paint.typeface = Typeface.create(fontFamily, typefaceStyle)
69
+ paint.typeface = resolveTypeface(fontFamily, typefaceStyle)
54
70
  paint.textSize = fontSizePx
55
71
  // Mirrors AdvancedTextView's own letterSpacing conversion: dp/points
56
72
  // prop -> em, scale-invariant so no density conversion is needed.
@@ -9,6 +9,21 @@
9
9
 
10
10
  using namespace facebook::react;
11
11
 
12
+ // Resolves a PostScript name, a family name, or an expo-font alias (expo-font
13
+ // only hooks +fontNamesForFamilyName:, which is also what RN's <Text> uses).
14
+ static UIFont *ATResolveFont(NSString *family, CGFloat size)
15
+ {
16
+ if (family.length == 0) {
17
+ return nil;
18
+ }
19
+ UIFont *font = [UIFont fontWithName:family size:size];
20
+ if (font) {
21
+ return font;
22
+ }
23
+ NSString *fontName = [UIFont fontNamesForFamilyName:family].firstObject;
24
+ return fontName ? [UIFont fontWithName:fontName size:size] : nil;
25
+ }
26
+
12
27
 
13
28
  @class AdvancedTextView;
14
29
 
@@ -446,10 +461,7 @@ using namespace facebook::react;
446
461
  if (_lineHeight > 0) {
447
462
  NSMutableParagraphStyle *paragraphStyle = [[NSMutableParagraphStyle alloc] init];
448
463
 
449
- UIFont *font = nil;
450
- if (_fontFamily && _fontFamily.length > 0) {
451
- font = [UIFont fontWithName:_fontFamily size:_fontSize > 0 ? _fontSize : 16.0];
452
- }
464
+ UIFont *font = ATResolveFont(_fontFamily, _fontSize > 0 ? _fontSize : 16.0);
453
465
  if (!font) {
454
466
  font = [UIFont systemFontOfSize:_fontSize > 0 ? _fontSize : 16.0];
455
467
  }
@@ -462,11 +474,7 @@ using namespace facebook::react;
462
474
  range:NSMakeRange(0, attributedString.length)];
463
475
  }
464
476
 
465
- UIFont *font = nil;
466
-
467
- if (_fontFamily && _fontFamily.length > 0) {
468
- font = [UIFont fontWithName:_fontFamily size:_fontSize > 0 ? _fontSize : 16.0];
469
- }
477
+ UIFont *font = ATResolveFont(_fontFamily, _fontSize > 0 ? _fontSize : 16.0);
470
478
 
471
479
  if (!font) {
472
480
  if (_fontWeight && [_fontWeight.lowercaseString isEqualToString:@"bold"]) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "react-native-advanced-text",
3
- "version": "0.2.10",
3
+ "version": "0.2.12",
4
4
  "description": " Advanced text component for React Native with custom select options.",
5
5
  "main": "./lib/module/index.js",
6
6
  "types": "./lib/typescript/src/index.d.ts",