added PrecomputedFutureTextSetterCompat with tests in the sample app

This commit is contained in:
luca 2020-03-23 13:24:28 +01:00
parent 8e3d898b40
commit c4a2bb94e2
10 changed files with 185 additions and 0 deletions

View File

@ -66,6 +66,7 @@ ext {
'x-annotations' : 'androidx.annotation:annotation:1.1.0', 'x-annotations' : 'androidx.annotation:annotation:1.1.0',
'x-recycler-view' : 'androidx.recyclerview:recyclerview:1.0.0', 'x-recycler-view' : 'androidx.recyclerview:recyclerview:1.0.0',
'x-core' : 'androidx.core:core:1.0.2', 'x-core' : 'androidx.core:core:1.0.2',
'x-appcompat' : 'androidx.appcompat:appcompat:1.1.0',
'commonmark' : "com.atlassian.commonmark:commonmark:$commonMarkVersion", 'commonmark' : "com.atlassian.commonmark:commonmark:$commonMarkVersion",
'commonmark-strikethrough': "com.atlassian.commonmark:commonmark-ext-gfm-strikethrough:$commonMarkVersion", 'commonmark-strikethrough': "com.atlassian.commonmark:commonmark-ext-gfm-strikethrough:$commonMarkVersion",
'commonmark-table' : "com.atlassian.commonmark:commonmark-ext-gfm-tables:$commonMarkVersion", 'commonmark-table' : "com.atlassian.commonmark:commonmark-ext-gfm-tables:$commonMarkVersion",

View File

@ -22,6 +22,7 @@ dependencies {
// @since 4.1.0 to allow PrecomputedTextSetterCompat // @since 4.1.0 to allow PrecomputedTextSetterCompat
// note that this dependency must be added on a client side explicitly // note that this dependency must be added on a client side explicitly
compileOnly it['x-core'] compileOnly it['x-core']
compileOnly it['x-appcompat']
} }
deps['test'].with { deps['test'].with {

View File

@ -0,0 +1,61 @@
package io.noties.markwon;
import android.text.Spanned;
import android.util.Log;
import android.widget.TextView;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.appcompat.widget.AppCompatTextView;
import androidx.core.text.PrecomputedTextCompat;
import java.util.concurrent.Executor;
/**
* Please note this class requires `androidx.core:core` artifact being explicitly added to your dependencies.
* This is intended to be used in a RecyclerView.
*
* @see io.noties.markwon.Markwon.TextSetter
*/
public class PrecomputedFutureTextSetterCompat implements Markwon.TextSetter {
/**
* @param executor for background execution of text pre-computation,
* if not provided the standard, single threaded one will be used.
*/
@NonNull
public static PrecomputedFutureTextSetterCompat create(@Nullable Executor executor) {
return new PrecomputedFutureTextSetterCompat(executor);
}
@NonNull
public static PrecomputedFutureTextSetterCompat create() {
return new PrecomputedFutureTextSetterCompat(null);
}
@Nullable
private final Executor executor;
@SuppressWarnings("WeakerAccess")
PrecomputedFutureTextSetterCompat(@Nullable Executor executor) {
this.executor = executor;
}
@Override
public void setText(
@NonNull TextView textView,
@NonNull Spanned markdown,
@NonNull TextView.BufferType bufferType,
@NonNull Runnable onComplete) {
if (textView instanceof AppCompatTextView) {
((AppCompatTextView) textView).setTextFuture(PrecomputedTextCompat.getTextFuture(
markdown, ((AppCompatTextView) textView).getTextMetricsParamsCompat(), executor
));
onComplete.run();
} else {
Log.w("Markwon, no-op", "PrecomputedFutureTextSetterCompat: textView provided is not an AppCompatTextView!");
}
}
}

View File

@ -54,6 +54,7 @@ dependencies {
deps.with { deps.with {
implementation it['x-recycler-view'] implementation it['x-recycler-view']
implementation it['x-core'] // for precomputedTextCompat implementation it['x-core'] // for precomputedTextCompat
implementation it['x-appcompat'] // for setTextFuture
implementation it['okhttp'] implementation it['okhttp']
implementation it['prism4j'] implementation it['prism4j']
implementation it['debug'] implementation it['debug']

View File

@ -28,6 +28,7 @@
<activity android:name=".simpleext.SimpleExtActivity" /> <activity android:name=".simpleext.SimpleExtActivity" />
<activity android:name=".customextension2.CustomExtensionActivity2" /> <activity android:name=".customextension2.CustomExtensionActivity2" />
<activity android:name=".precomputed.PrecomputedActivity" /> <activity android:name=".precomputed.PrecomputedActivity" />
<activity android:name=".precomputed.PrecomputedFutureActivity" />
<activity <activity
android:name=".editor.EditorActivity" android:name=".editor.EditorActivity"

View File

@ -30,6 +30,7 @@ import io.noties.markwon.sample.inlineparser.InlineParserActivity;
import io.noties.markwon.sample.latex.LatexActivity; import io.noties.markwon.sample.latex.LatexActivity;
import io.noties.markwon.sample.notification.NotificationActivity; import io.noties.markwon.sample.notification.NotificationActivity;
import io.noties.markwon.sample.precomputed.PrecomputedActivity; import io.noties.markwon.sample.precomputed.PrecomputedActivity;
import io.noties.markwon.sample.precomputed.PrecomputedFutureActivity;
import io.noties.markwon.sample.recycler.RecyclerActivity; import io.noties.markwon.sample.recycler.RecyclerActivity;
import io.noties.markwon.sample.simpleext.SimpleExtActivity; import io.noties.markwon.sample.simpleext.SimpleExtActivity;
import io.noties.markwon.sample.tasklist.TaskListActivity; import io.noties.markwon.sample.tasklist.TaskListActivity;
@ -123,6 +124,10 @@ public class MainActivity extends Activity {
activity = PrecomputedActivity.class; activity = PrecomputedActivity.class;
break; break;
case PRECOMPUTED_FUTURE_TEXT:
activity = PrecomputedFutureActivity.class;
break;
case EDITOR: case EDITOR:
activity = EditorActivity.class; activity = EditorActivity.class;
break; break;

View File

@ -23,6 +23,8 @@ public enum Sample {
PRECOMPUTED_TEXT(R.string.sample_precomputed_text), PRECOMPUTED_TEXT(R.string.sample_precomputed_text),
PRECOMPUTED_FUTURE_TEXT(R.string.sample_precomputed_future_text),
EDITOR(R.string.sample_editor), EDITOR(R.string.sample_editor),
INLINE_PARSER(R.string.sample_inline_parser), INLINE_PARSER(R.string.sample_inline_parser),

View File

@ -0,0 +1,95 @@
package io.noties.markwon.sample.precomputed;
import android.app.Activity;
import android.content.Context;
import android.os.Bundle;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import io.noties.markwon.Markwon;
import io.noties.markwon.PrecomputedFutureTextSetterCompat;
import io.noties.markwon.recycler.MarkwonAdapter;
import io.noties.markwon.sample.R;
public class PrecomputedFutureActivity extends Activity {
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_recycler);
final Markwon markwon = Markwon.builder(this)
.textSetter(PrecomputedFutureTextSetterCompat.create())
.build();
// create MarkwonAdapter and register two blocks that will be rendered differently
final MarkwonAdapter adapter = MarkwonAdapter.builder(R.layout.adapter_appcompat_default_entry, R.id.text)
.build();
final RecyclerView recyclerView = findViewById(R.id.recycler_view);
recyclerView.setLayoutManager(new LinearLayoutManager(this));
recyclerView.setHasFixedSize(true);
recyclerView.setAdapter(adapter);
adapter.setMarkdown(markwon, loadReadMe(this));
// please note that we should notify updates (adapter doesn't do it implicitly)
adapter.notifyDataSetChanged();
}
@NonNull
private static String loadReadMe(@NonNull Context context) {
InputStream stream = null;
try {
stream = context.getAssets().open("README.md");
} catch (IOException e) {
e.printStackTrace();
}
return readStream(stream);
}
@NonNull
private static String readStream(@Nullable InputStream inputStream) {
String out = null;
if (inputStream != null) {
BufferedReader reader = null;
//noinspection TryFinallyCanBeTryWithResources
try {
reader = new BufferedReader(new InputStreamReader(inputStream));
final StringBuilder builder = new StringBuilder();
String line;
while ((line = reader.readLine()) != null) {
builder.append(line)
.append('\n');
}
out = builder.toString();
} catch (IOException e) {
e.printStackTrace();
} finally {
if (reader != null) {
try {
reader.close();
} catch (IOException e) {
// no op
}
}
}
}
if (out == null) {
throw new RuntimeException("Cannot read stream");
}
return out;
}
}

View File

@ -0,0 +1,16 @@
<?xml version="1.0" encoding="utf-8"?>
<androidx.appcompat.widget.AppCompatTextView
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/text"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginLeft="16dip"
android:layout_marginRight="16dip"
android:lineSpacingExtra="2dip"
android:paddingTop="8dip"
android:paddingBottom="8dip"
android:textAppearance="?android:attr/textAppearanceMedium"
android:textColor="#000"
android:textSize="16sp"
tools:text="Hello" />

View File

@ -25,6 +25,8 @@
<string name="sample_precomputed_text"># \# PrecomputedText\n\nUsage of TextSetter and PrecomputedTextCompat</string> <string name="sample_precomputed_text"># \# PrecomputedText\n\nUsage of TextSetter and PrecomputedTextCompat</string>
<string name="sample_precomputed_future_text"># \# PrecomputedFutureText\n\nUsage of TextSetter and PrecomputedFutureTextSetterCompat</string>
<string name="sample_editor"># \# Editor\n\n`MarkwonEditor` sample usage to highlight user input in EditText</string> <string name="sample_editor"># \# Editor\n\n`MarkwonEditor` sample usage to highlight user input in EditText</string>
<string name="sample_inline_parser"># \# Inline Parser\n\nUsage of custom inline parser</string> <string name="sample_inline_parser"># \# Inline Parser\n\nUsage of custom inline parser</string>