Skip to content

Commit cbeea25

Browse files
committed
Implement code and pre blocks support on Android
1 parent 4cbff0f commit cbeea25

13 files changed

+492
-107
lines changed

android/src/main/java/com/expensify/livemarkdown/MarkdownBackgroundColorSpan.java

Lines changed: 0 additions & 11 deletions
This file was deleted.

android/src/main/java/com/expensify/livemarkdown/MarkdownFontFamilySpan.java renamed to android/src/main/java/com/expensify/livemarkdown/MarkdownBlockSpan.java

Lines changed: 15 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -6,19 +6,24 @@
66
import android.text.TextPaint;
77
import android.text.style.MetricAffectingSpan;
88

9+
import androidx.annotation.ColorInt;
910
import androidx.annotation.NonNull;
1011

11-
import com.facebook.react.common.assets.ReactFontManager.TypefaceStyle;
12-
import com.facebook.react.views.text.ReactFontManager;
12+
import com.facebook.react.common.assets.ReactFontManager;
13+
import com.facebook.react.uimanager.PixelUtil;
1314

14-
public class MarkdownFontFamilySpan extends MetricAffectingSpan implements MarkdownSpan {
15+
public class MarkdownBlockSpan extends MetricAffectingSpan implements MarkdownSpan {
1516

16-
private final @NonNull String mFontFamily;
1717
private final @NonNull AssetManager mAssetManager;
18+
private final @NonNull String mFontFamily;
19+
private final float mFontSize;
20+
private final int mColor;
1821

19-
public MarkdownFontFamilySpan(@NonNull String fontFamily, @NonNull AssetManager assetManager) {
20-
mFontFamily = fontFamily;
22+
public MarkdownBlockSpan(@NonNull AssetManager assetManager, @NonNull String fontFamily, float fontSize, @ColorInt int color) {
2123
mAssetManager = assetManager;
24+
mFontFamily = fontFamily;
25+
mFontSize = PixelUtil.toPixelFromDIP(fontSize);
26+
mColor = color;
2227
}
2328

2429
@Override
@@ -31,15 +36,15 @@ public void updateDrawState(TextPaint tp) {
3136
apply(tp);
3237
}
3338

34-
private void apply(@NonNull TextPaint textPaint) {
35-
int style = TypefaceStyle.NORMAL;
39+
void apply(@NonNull TextPaint textPaint) {
40+
int style = ReactFontManager.TypefaceStyle.NORMAL;
3641
if (textPaint.getTypeface() != null) {
3742
style = textPaint.getTypeface().getStyle();
38-
} else {
39-
style = TypefaceStyle.NORMAL;
4043
}
4144
Typeface typeface = ReactFontManager.getInstance().getTypeface(mFontFamily, style, mAssetManager);
4245
textPaint.setTypeface(typeface);
4346
textPaint.setFlags(textPaint.getFlags() | Paint.SUBPIXEL_TEXT_FLAG);
47+
textPaint.setTextSize(mFontSize);
48+
textPaint.setColor(mColor);
4449
}
4550
}
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
package com.expensify.livemarkdown;
2+
3+
import android.content.res.AssetManager;
4+
5+
import androidx.annotation.ColorInt;
6+
import androidx.annotation.NonNull;
7+
8+
public class MarkdownCodeSpan extends MarkdownBlockSpan {
9+
public MarkdownCodeSpan(@NonNull AssetManager assetManager, @NonNull String fontFamily, float fontSize, @ColorInt int color) {
10+
super(assetManager, fontFamily, fontSize, color);
11+
}
12+
}
13+

android/src/main/java/com/expensify/livemarkdown/MarkdownFontSizeSpan.java

Lines changed: 0 additions & 11 deletions
This file was deleted.
Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
package com.expensify.livemarkdown;
2+
3+
import android.graphics.Paint;
4+
import android.graphics.Typeface;
5+
import android.text.TextPaint;
6+
import android.text.style.LineHeightSpan;
7+
import android.text.style.StyleSpan;
8+
9+
import androidx.annotation.NonNull;
10+
11+
import com.facebook.react.uimanager.PixelUtil;
12+
13+
public class MarkdownH1Span extends StyleSpan implements LineHeightSpan, MarkdownSpan {
14+
15+
private final float mFontSize;
16+
private final Integer mLineHeight;
17+
18+
public MarkdownH1Span(float fontSize, Integer lineHeight) {
19+
super(Typeface.BOLD);
20+
mFontSize = PixelUtil.toPixelFromDIP(fontSize);
21+
mLineHeight = lineHeight;
22+
}
23+
24+
@Override
25+
public void updateMeasureState(@NonNull TextPaint textPaint) {
26+
super.updateMeasureState(textPaint);
27+
apply(textPaint);
28+
}
29+
30+
@Override
31+
public void updateDrawState(TextPaint tp) {
32+
super.updateDrawState(tp);
33+
apply(tp);
34+
}
35+
36+
private void apply(@NonNull TextPaint textPaint) {
37+
textPaint.setTextSize(mFontSize);
38+
}
39+
40+
@Override
41+
public void chooseHeight(CharSequence text, int start, int end, int spanstartv, int lineHeight, Paint.FontMetricsInt fm) {
42+
if (mLineHeight != null) {
43+
fm.top -= mLineHeight / 4;
44+
fm.ascent -= mLineHeight / 4;
45+
}
46+
}
47+
}

android/src/main/java/com/expensify/livemarkdown/MarkdownLineHeightSpan.java

Lines changed: 0 additions & 18 deletions
This file was deleted.
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
package com.expensify.livemarkdown;
2+
3+
import android.text.TextPaint;
4+
import android.text.style.MetricAffectingSpan;
5+
6+
import androidx.annotation.NonNull;
7+
8+
public class MarkdownLinkSpan extends MetricAffectingSpan implements MarkdownSpan {
9+
10+
private final int mForegroundColor;
11+
12+
public MarkdownLinkSpan(int foregroundColor) {
13+
mForegroundColor = foregroundColor;
14+
}
15+
16+
@Override
17+
public void updateMeasureState(@NonNull TextPaint textPaint) {
18+
apply(textPaint);
19+
}
20+
21+
@Override
22+
public void updateDrawState(TextPaint tp) {
23+
apply(tp);
24+
}
25+
26+
private void apply(@NonNull TextPaint textPaint) {
27+
textPaint.setUnderlineText(true);
28+
textPaint.setColor(mForegroundColor);
29+
}
30+
}
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
package com.expensify.livemarkdown;
2+
3+
import android.text.TextPaint;
4+
import android.text.style.MetricAffectingSpan;
5+
6+
import androidx.annotation.NonNull;
7+
8+
public class MarkdownMentionSpan extends MetricAffectingSpan implements MarkdownSpan {
9+
10+
private final int mBackgroundColor;
11+
private final int mForegroundColor;
12+
13+
public MarkdownMentionSpan(int backgroundColor, int foregroundColor) {
14+
mBackgroundColor = backgroundColor;
15+
mForegroundColor = foregroundColor;
16+
}
17+
18+
@Override
19+
public void updateMeasureState(@NonNull TextPaint textPaint) {
20+
apply(textPaint);
21+
}
22+
23+
@Override
24+
public void updateDrawState(TextPaint tp) {
25+
apply(tp);
26+
}
27+
28+
private void apply(@NonNull TextPaint textPaint) {
29+
textPaint.bgColor = mBackgroundColor;
30+
textPaint.setColor(mForegroundColor);
31+
}
32+
}
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
package com.expensify.livemarkdown;
2+
3+
import android.content.res.AssetManager;
4+
import android.graphics.Canvas;
5+
import android.graphics.Paint;
6+
import android.text.Layout;
7+
import android.text.style.LeadingMarginSpan;
8+
9+
import androidx.annotation.ColorInt;
10+
import androidx.annotation.NonNull;
11+
12+
public class MarkdownPreSpan extends MarkdownBlockSpan implements LeadingMarginSpan {
13+
14+
private final int mLeadingMargin;
15+
16+
public MarkdownPreSpan(@NonNull AssetManager assetManager, @NonNull String fontFamily, float fontSize, @ColorInt int color, int leadingMargin) {
17+
super(assetManager, fontFamily, fontSize, color);
18+
mLeadingMargin = leadingMargin;
19+
}
20+
21+
@Override
22+
public int getLeadingMargin(boolean first) {
23+
return mLeadingMargin;
24+
}
25+
26+
@Override
27+
public void drawLeadingMargin(Canvas c, Paint p, int x, int dir, int top, int baseline, int bottom, CharSequence text, int start, int end, boolean first, Layout layout) {}
28+
}

android/src/main/java/com/expensify/livemarkdown/MarkdownStyle.java

Lines changed: 57 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -25,42 +25,41 @@ public class MarkdownStyle {
2525

2626
@ColorInt
2727
private final int mBlockquoteBorderColor;
28-
2928
private final float mBlockquoteBorderWidth;
30-
3129
private final float mBlockquoteMarginLeft;
32-
3330
private final float mBlockquotePaddingLeft;
3431

3532
private final String mCodeFontFamily;
36-
3733
private final float mCodeFontSize;
38-
3934
@ColorInt
4035
private final int mCodeColor;
41-
4236
@ColorInt
4337
private final int mCodeBackgroundColor;
38+
@ColorInt
39+
private final int mCodeBorderColor;
40+
private final float mCodeBorderWidth;
41+
private final float mCodeBorderRadius;
42+
private final float mCodePadding;
4443

4544
private final String mPreFontFamily;
46-
4745
private final float mPreFontSize;
48-
4946
@ColorInt
5047
private final int mPreColor;
51-
5248
@ColorInt
5349
private final int mPreBackgroundColor;
50+
@ColorInt
51+
private final int mPreBorderColor;
52+
private final float mPreBorderWidth;
53+
private final float mPreBorderRadius;
54+
private final float mPrePadding;
5455

5556
@ColorInt
5657
private final int mMentionHereColor;
57-
5858
@ColorInt
5959
private final int mMentionHereBackgroundColor;
6060

6161
@ColorInt
6262
private final int mMentionUserColor;
63-
6463
@ColorInt
6564
private final int mMentionUserBackgroundColor;
6665

@@ -83,10 +82,18 @@ public MarkdownStyle(@NonNull ReadableMap map, @NonNull Context context) {
8382
mCodeFontSize = parseFloat(map, "code", "fontSize");
8483
mCodeColor = parseColor(map, "code", "color", context);
8584
mCodeBackgroundColor = parseColor(map, "code", "backgroundColor", context);
85+
mCodeBorderColor = parseColor(map, "code", "borderColor", context);
86+
mCodeBorderWidth = parseFloat(map, "code", "borderWidth");
87+
mCodeBorderRadius = parseFloat(map, "code", "borderRadius");
88+
mCodePadding = parseFloat(map, "code", "padding");
8689
mPreFontFamily = parseString(map, "pre", "fontFamily");
8790
mPreFontSize = parseFloat(map, "pre", "fontSize");
8891
mPreColor = parseColor(map, "pre", "color", context);
8992
mPreBackgroundColor = parseColor(map, "pre", "backgroundColor", context);
93+
mPreBorderColor = parseColor(map, "pre", "borderColor", context);
94+
mPreBorderWidth = parseFloat(map, "pre", "borderWidth");
95+
mPreBorderRadius = parseFloat(map, "pre", "borderRadius");
96+
mPrePadding = parseFloat(map, "pre", "padding");
9097
mMentionHereColor = parseColor(map, "mentionHere", "color", context);
9198
mMentionHereBackgroundColor = parseColor(map, "mentionHere", "backgroundColor", context);
9299
mMentionUserColor = parseColor(map, "mentionUser", "color", context);
@@ -99,14 +106,11 @@ private static int parseColor(@NonNull ReadableMap map, @NonNull String key, @No
99106
ReadableMap style = map.getMap(key);
100107
Objects.requireNonNull(style);
101108
Dynamic value = style.getDynamic(prop);
102-
switch (value.getType()) {
103-
case Number:
104-
return ColorPropConverter.getColor(value.asDouble(), context);
105-
case Map:
106-
return ColorPropConverter.getColor(value.asMap(), context);
107-
default:
108-
throw new JSApplicationCausedNativeException("ColorValue: the value must be a number or Object.");
109-
}
109+
return switch (value.getType()) {
110+
case Number -> ColorPropConverter.getColor(value.asDouble(), context);
111+
case Map -> ColorPropConverter.getColor(value.asMap(), context);
112+
default -> throw new JSApplicationCausedNativeException("ColorValue: the value must be a number or Object.");
113+
};
110114
}
111115

112116
private static float parseFloat(@NonNull ReadableMap map, @NonNull String key, @NonNull String prop) {
@@ -175,6 +179,23 @@ public int getCodeBackgroundColor() {
175179
return mCodeBackgroundColor;
176180
}
177181

182+
@ColorInt
183+
public int getCodeBorderColor() {
184+
return mCodeBorderColor;
185+
}
186+
187+
public float getCodeBorderWidth() {
188+
return mCodeBorderWidth;
189+
}
190+
191+
public float getCodeBorderRadius() {
192+
return mCodeBorderRadius;
193+
}
194+
195+
public float getCodePadding() {
196+
return mCodePadding;
197+
}
198+
178199
public String getPreFontFamily() {
179200
return mPreFontFamily;
180201
}
@@ -193,6 +214,23 @@ public int getPreBackgroundColor() {
193214
return mPreBackgroundColor;
194215
}
195216

217+
@ColorInt
218+
public int getPreBorderColor() {
219+
return mPreBorderColor;
220+
}
221+
222+
public float getPreBorderWidth() {
223+
return mPreBorderWidth;
224+
}
225+
226+
public float getPreBorderRadius() {
227+
return mPreBorderRadius;
228+
}
229+
230+
public float getPrePadding() {
231+
return mPrePadding;
232+
}
233+
196234
@ColorInt
197235
public int getMentionHereColor() {
198236
return mMentionHereColor;

0 commit comments

Comments
 (0)