Skip to content

Commit

Permalink
Add Html-TextView source code instead of referencing a library due to…
Browse files Browse the repository at this point in the history
… unavailability of JCenter under Apache License 2.0.
  • Loading branch information
zamojski committed Nov 23, 2024
1 parent 6511091 commit 2533d5d
Show file tree
Hide file tree
Showing 20 changed files with 2,344 additions and 2 deletions.
1 change: 0 additions & 1 deletion app/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -119,7 +119,6 @@ dependencies {
implementation "ch.acra:acra-http:$acraVersion"
implementation "ch.acra:acra-dialog:$acraVersion"
implementation "ch.acra:acra-limiter:$acraVersion"
implementation 'org.sufficientlysecure:html-textview:4.0'
implementation 'com.squareup.okhttp3:okhttp:4.12.0'
implementation "com.github.permissions-dispatcher:permissionsdispatcher:$permissionsDispatcherVersion"
annotationProcessor "com.github.permissions-dispatcher:permissionsdispatcher-processor:$permissionsDispatcherVersion"
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
/*
* Copyright (C) 2016 Richard Thai
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package org.sufficientlysecure.htmltextview;

import android.text.style.ClickableSpan;

/**
* This span defines what should happen if a table is clicked. This abstract class is defined so
* that applications can access the raw table HTML and do whatever they'd like to render it (e.g.
* show it in a WebView).
*/
public abstract class ClickableTableSpan extends ClickableSpan {
protected String tableHtml;

// This sucks, but we need this so that each table can get its own ClickableTableSpan.
// Otherwise, we end up removing the clicking from earlier tables.
public abstract ClickableTableSpan newInstance();

public void setTableHtml(String tableHtml) {
this.tableHtml = tableHtml;
}

public String getTableHtml() {
return tableHtml;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
/*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package org.sufficientlysecure.htmltextview;

import android.graphics.Canvas;
import android.graphics.Paint;
import android.text.Layout;
import android.text.style.LeadingMarginSpan;
import android.text.style.LineBackgroundSpan;

import androidx.annotation.NonNull;

public class DesignQuoteSpan implements LeadingMarginSpan, LineBackgroundSpan {

private int backgroundColor, stripColor;
private float stripeWidth, gap;

DesignQuoteSpan(int backgroundColor, int stripColor, float stripWidth, float gap) {
this.backgroundColor = backgroundColor;
this.stripColor = stripColor;
this.stripeWidth = stripWidth;
this.gap = gap;
}

@Override
public int getLeadingMargin(boolean first) {
return (int) (stripeWidth + gap);
}

@Override
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) {
Paint.Style style = p.getStyle();
int paintColor = p.getColor();
p.setStyle(Paint.Style.FILL);
p.setColor(stripColor);
c.drawRect((float) x, (float) top, x + dir * stripeWidth, (float) bottom, p);
p.setStyle(style);
p.setColor(paintColor);
}

@Override
public void drawBackground(@NonNull Canvas canvas, @NonNull Paint paint,
int left, int right, int top, int baseline, int bottom,
@NonNull CharSequence text, int start, int end, int lineNumber) {
int paintColor = paint.getColor();
paint.setColor(backgroundColor);
canvas.drawRect((float) left, (float) top, (float) right, (float) bottom, paint);
paint.setColor(paintColor);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
/*
* Copyright (C) 2016 Richard Thai
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package org.sufficientlysecure.htmltextview;

import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.text.style.ReplacementSpan;

/**
* This span defines how a table should be rendered in the HtmlTextView. The default implementation
* is a cop-out which replaces the HTML table with some text ("[tap for table]" is the default).
* <p/>
* This is to be used in conjunction with the ClickableTableSpan which will redirect a click to the
* text some application-defined action (i.e. render the raw HTML in a WebView).
*/
public class DrawTableLinkSpan extends ReplacementSpan {

private static final String DEFAULT_TABLE_LINK_TEXT = "";
private static float DEFAULT_TEXT_SIZE = 80f;
private static int DEFAULT_TEXT_COLOR = Color.BLUE;

protected String mTableLinkText = DEFAULT_TABLE_LINK_TEXT;
protected float mTextSize = DEFAULT_TEXT_SIZE;
protected int mTextColor = DEFAULT_TEXT_COLOR;

// This sucks, but we need this so that each table can get drawn.
// Otherwise, we end up with the default table link text (nothing) for earlier tables.
public DrawTableLinkSpan newInstance() {
final DrawTableLinkSpan drawTableLinkSpan = new DrawTableLinkSpan();
drawTableLinkSpan.setTableLinkText(mTableLinkText);
drawTableLinkSpan.setTextSize(mTextSize);
drawTableLinkSpan.setTextColor(mTextColor);

return drawTableLinkSpan;
}

@Override
public int getSize(Paint paint, CharSequence text, int start, int end, Paint.FontMetricsInt fm) {
int width = (int) paint.measureText(mTableLinkText, 0, mTableLinkText.length());
mTextSize = paint.getTextSize();
return width;
}

@Override
public void draw(Canvas canvas, CharSequence text, int start, int end, float x, int top, int y, int bottom, Paint paint) {
final Paint paint2 = new Paint();
paint2.setStyle(Paint.Style.STROKE);
paint2.setColor(mTextColor);
paint2.setAntiAlias(true);
paint2.setTextSize(mTextSize);

canvas.drawText(mTableLinkText, x, bottom, paint2);
}

public void setTableLinkText(String tableLinkText) {
this.mTableLinkText = tableLinkText;
}

public void setTextSize(float textSize) {
this.mTextSize = textSize;
}

public void setTextColor(int textColor) {
this.mTextColor = textColor;
}

public String getTableLinkText() {
return mTableLinkText;
}

public float getTextSize() {
return mTextSize;
}

public int getTextColor() {
return mTextColor;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
/*
* Copyright (C) 2016 Daniel Passos <[email protected]>
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package org.sufficientlysecure.htmltextview;

import android.content.Context;
import android.graphics.drawable.Drawable;
import android.text.Html;
import android.util.Log;
import android.widget.TextView;

import java.io.IOException;
import java.io.InputStream;

/**
* Assets Image Getter
* <p>
* Load image from assets folder
*
* @author <a href="mailto:[email protected]">Daniel Passos</a>
*/
public class HtmlAssetsImageGetter implements Html.ImageGetter {

private final Context context;

public HtmlAssetsImageGetter(Context context) {
this.context = context;
}

public HtmlAssetsImageGetter(TextView textView) {
this.context = textView.getContext();
}

@Override
public Drawable getDrawable(String source) {

try {
InputStream inputStream = context.getAssets().open(source);
Drawable d = Drawable.createFromStream(inputStream, null);
d.setBounds(0, 0, d.getIntrinsicWidth(), d.getIntrinsicHeight());
return d;
} catch (IOException e) {
// prevent a crash if the resource still can't be found
Log.e(HtmlTextView.TAG, "source could not be found: " + source);
return null;
}

}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
/*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package org.sufficientlysecure.htmltextview;

import android.text.Html;
import android.text.Html.ImageGetter;
import android.text.Spanned;

import androidx.annotation.NonNull;
import androidx.annotation.Nullable;

public class HtmlFormatter {

private HtmlFormatter() {
}

public static Spanned formatHtml(@NonNull final HtmlFormatterBuilder builder) {
return formatHtml(
builder.getHtml(), builder.getImageGetter(), builder.getClickableTableSpan(),
builder.getDrawTableLinkSpan(), new TagClickListenerProvider() {
@Override public OnClickATagListener provideTagClickListener() {
return builder.getOnClickATagListener();
}
}, builder.getIndent(),
builder.isRemoveTrailingWhiteSpace()
);
}

interface TagClickListenerProvider {
OnClickATagListener provideTagClickListener();
}

public static Spanned formatHtml(@Nullable String html, ImageGetter imageGetter, ClickableTableSpan clickableTableSpan, DrawTableLinkSpan drawTableLinkSpan, TagClickListenerProvider tagClickListenerProvider, float indent, boolean removeTrailingWhiteSpace) {
final HtmlTagHandler htmlTagHandler = new HtmlTagHandler();
htmlTagHandler.setClickableTableSpan(clickableTableSpan);
htmlTagHandler.setDrawTableLinkSpan(drawTableLinkSpan);
htmlTagHandler.setOnClickATagListenerProvider(tagClickListenerProvider);
htmlTagHandler.setListIndentPx(indent);

html = htmlTagHandler.overrideTags(html);

Spanned formattedHtml;
if (removeTrailingWhiteSpace) {
formattedHtml = removeHtmlBottomPadding(Html.fromHtml(html, imageGetter, new WrapperContentHandler(htmlTagHandler)));
} else {
formattedHtml = Html.fromHtml(html, imageGetter, new WrapperContentHandler(htmlTagHandler));
}

return formattedHtml;
}

/**
* Html.fromHtml sometimes adds extra space at the bottom.
* This methods removes this space again.
* See https://github.com/SufficientlySecure/html-textview/issues/19
*/
@Nullable
private static Spanned removeHtmlBottomPadding(@Nullable Spanned text) {
if (text == null) {
return null;
}

while (text.length() > 0 && text.charAt(text.length() - 1) == '\n') {
text = (Spanned) text.subSequence(0, text.length() - 1);
}
return text;
}
}
Loading

0 comments on commit 2533d5d

Please sign in to comment.