forked from mirrors/Fedilab
Add support for maths.
This commit is contained in:
parent
25ad71080e
commit
d5c51e6dca
8 changed files with 112 additions and 37 deletions
|
@ -327,7 +327,8 @@ public class Helper {
|
|||
public static final Pattern groupPattern = Pattern.compile("(![\\w_]+)");
|
||||
public static final Pattern mentionPattern = Pattern.compile("(@[\\w_.-]?[\\w]+)");
|
||||
public static final Pattern mentionLongPattern = Pattern.compile("(@[\\w_.-]+@[a-zA-Z0-9][a-zA-Z0-9.-]{1,61}[a-zA-Z0-9](?:\\.[a-zA-Z]{2,})+)");
|
||||
public static final Pattern mathsPattern = Pattern.compile("\\\\\\(|\\\\\\{|\\\\\\[");
|
||||
public static final Pattern mathsPattern = Pattern.compile("\\\\\\(|\\\\\\[");
|
||||
public static final Pattern mathsComposePattern = Pattern.compile("\\\\\\(.*\\\\\\)|\\\\\\[.*\\\\\\]");
|
||||
public static final Pattern twitterPattern = Pattern.compile("((@[\\w]+)@twitter\\.com)");
|
||||
public static final Pattern youtubePattern = Pattern.compile("(www\\.|m\\.)?(youtube\\.com|youtu\\.be|youtube-nocookie\\.com)/(((?!([\"'<])).)*)");
|
||||
public static final Pattern nitterPattern = Pattern.compile("(mobile\\.|www\\.)?twitter.com([\\w-/]+)");
|
||||
|
|
|
@ -28,6 +28,7 @@ import android.content.Context;
|
|||
import android.content.Intent;
|
||||
import android.content.SharedPreferences;
|
||||
import android.content.pm.PackageManager;
|
||||
import android.content.res.Configuration;
|
||||
import android.content.res.Resources;
|
||||
import android.graphics.Bitmap;
|
||||
import android.graphics.Color;
|
||||
|
@ -531,7 +532,9 @@ public class ComposeAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder
|
|||
if (promptDraftListener != null) {
|
||||
promptDraftListener.promptDraft();
|
||||
}
|
||||
statusList.get(holder.getLayoutPosition()).cursorPosition = holder.binding.content.getSelectionStart();
|
||||
if (holder.binding.content.getSelectionStart() > 0) {
|
||||
statusList.get(holder.getLayoutPosition()).cursorPosition = holder.binding.content.getSelectionStart();
|
||||
}
|
||||
//Copy/past
|
||||
int max_car = MastodonHelper.getInstanceMaxChars(context);
|
||||
if (currentLength > max_car) {
|
||||
|
@ -694,6 +697,24 @@ public class ComposeAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder
|
|||
updateCharacterCount(holder);
|
||||
return;
|
||||
}
|
||||
Matcher mathsPatterns = Helper.mathsComposePattern.matcher((s.toString()));
|
||||
if (mathsPatterns.find()) {
|
||||
if (holder.binding.laTexViewContainer.getVisibility() != View.VISIBLE) {
|
||||
holder.binding.laTexViewContainer.setVisibility(View.VISIBLE);
|
||||
|
||||
switch (context.getResources().getConfiguration().uiMode & Configuration.UI_MODE_NIGHT_MASK) {
|
||||
case Configuration.UI_MODE_NIGHT_YES:
|
||||
holder.binding.laTexView.setTextColor("white");
|
||||
break;
|
||||
case Configuration.UI_MODE_NIGHT_NO:
|
||||
holder.binding.laTexView.setTextColor("black");
|
||||
break;
|
||||
}
|
||||
}
|
||||
holder.binding.laTexView.setInputText(s.toString());
|
||||
} else {
|
||||
holder.binding.laTexViewContainer.setVisibility(View.GONE);
|
||||
}
|
||||
|
||||
String patternh = "^(.|\\s)*(:fedilab_hugs:)";
|
||||
final Pattern hPattern = Pattern.compile(patternh);
|
||||
|
@ -1272,7 +1293,34 @@ public class ComposeAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder
|
|||
|
||||
ComposeViewHolder holder = (ComposeViewHolder) viewHolder;
|
||||
boolean extraFeatures = sharedpreferences.getBoolean(context.getString(R.string.SET_EXTAND_EXTRA_FEATURES) + MainActivity.currentUserID + MainActivity.currentInstance, false);
|
||||
boolean mathsComposer = sharedpreferences.getBoolean(context.getString(R.string.SET_MATHS_COMPOSER), true);
|
||||
|
||||
if (mathsComposer) {
|
||||
holder.binding.buttonMathsComposer.setVisibility(View.VISIBLE);
|
||||
holder.binding.buttonMathsComposer.setOnClickListener(v -> {
|
||||
int cursorPosition = holder.binding.content.getSelectionStart();
|
||||
AlertDialog.Builder builder = new AlertDialog.Builder(context, Helper.dialogStyle());
|
||||
Resources res = context.getResources();
|
||||
String[] formatArr = res.getStringArray(R.array.SET_MATHS_FORMAT);
|
||||
builder.setItems(formatArr, (dialogInterface, i) -> {
|
||||
if (statusDraft.text == null) {
|
||||
statusDraft.text = "";
|
||||
}
|
||||
if (i == 0) {
|
||||
statusDraft.text = new StringBuilder(statusDraft.text).insert(cursorPosition, "\\( \\)").toString();
|
||||
} else {
|
||||
statusDraft.text = new StringBuilder(statusDraft.text).insert(cursorPosition, "\\[ \\]").toString();
|
||||
}
|
||||
statusDraft.cursorPosition = cursorPosition + 3;
|
||||
notifyItemChanged(position);
|
||||
dialogInterface.dismiss();
|
||||
});
|
||||
builder.setNegativeButton(R.string.cancel, (dialog, which) -> dialog.dismiss());
|
||||
builder.create().show();
|
||||
});
|
||||
} else {
|
||||
holder.binding.buttonMathsComposer.setVisibility(View.GONE);
|
||||
}
|
||||
|
||||
holder.binding.buttonEmojiOne.setVisibility(View.VISIBLE);
|
||||
if (extraFeatures) {
|
||||
|
|
|
@ -674,9 +674,10 @@ public class StatusAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder>
|
|||
mathJaxConfig.setTextColor("white");
|
||||
break;
|
||||
case Configuration.UI_MODE_NIGHT_NO:
|
||||
mathJaxConfig.setTextColor("dark");
|
||||
mathJaxConfig.setTextColor("black");
|
||||
break;
|
||||
}
|
||||
mathJaxConfig.setAutomaticLinebreaks(true);
|
||||
status.mathsShown = true;
|
||||
MathJaxView mathview = new MathJaxView(context, mathJaxConfig);
|
||||
holder.binding.statusContentMaths.addView(mathview);
|
||||
|
|
|
@ -32,6 +32,27 @@
|
|||
android:clipToPadding="false"
|
||||
android:orientation="vertical">
|
||||
|
||||
<androidx.core.widget.NestedScrollView
|
||||
android:id="@+id/laTexView_container"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:visibility="gone"
|
||||
app:layout_constraintBottom_toTopOf="@+id/button_emoji"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent">
|
||||
|
||||
<de.timfreiheit.mathjax.android.MathJaxView
|
||||
android:id="@+id/laTexView"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="center"
|
||||
app:automaticLinebreaks="true"
|
||||
app:input="TeX"
|
||||
app:output="SVG" />
|
||||
</androidx.core.widget.NestedScrollView>
|
||||
|
||||
|
||||
<com.google.android.material.textfield.MaterialAutoCompleteTextView
|
||||
android:id="@+id/content_spoiler"
|
||||
android:layout_width="0dp"
|
||||
|
@ -44,7 +65,7 @@
|
|||
android:visibility="gone"
|
||||
app:layout_constraintEnd_toStartOf="@id/button_emoji"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@+id/laTexView_container"
|
||||
tools:visibility="visible" />
|
||||
|
||||
<com.google.android.material.button.MaterialButton
|
||||
|
@ -55,7 +76,7 @@
|
|||
android:contentDescription="@string/add_status"
|
||||
app:icon="@drawable/ic_compose_thread_add_status"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent" />
|
||||
app:layout_constraintTop_toBottomOf="@+id/laTexView_container" />
|
||||
|
||||
<app.fedilab.android.helper.FedilabAutoCompleteTextView
|
||||
android:id="@+id/content"
|
||||
|
@ -103,6 +124,17 @@
|
|||
app:layout_constraintTop_toBottomOf="@id/button_emoji_one"
|
||||
tools:visibility="visible" />
|
||||
|
||||
<com.google.android.material.button.MaterialButton
|
||||
android:id="@+id/button_maths_composer"
|
||||
style="@style/Fedilab.SmallIconButton"
|
||||
android:layout_marginEnd="6dp"
|
||||
android:contentDescription="@string/maths_format"
|
||||
android:visibility="gone"
|
||||
app:icon="@drawable/ic_baseline_functions_24"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@id/button_text_format"
|
||||
tools:visibility="visible" />
|
||||
|
||||
<com.google.android.material.button.MaterialButton
|
||||
android:id="@+id/button_local_only"
|
||||
style="@style/Fedilab.SmallIconButton"
|
||||
|
@ -111,7 +143,7 @@
|
|||
android:visibility="gone"
|
||||
app:icon="@drawable/ic_baseline_remove_red_eye_24"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@id/button_text_format"
|
||||
app:layout_constraintTop_toBottomOf="@id/button_maths_composer"
|
||||
tools:visibility="visible" />
|
||||
|
||||
<com.google.android.material.checkbox.MaterialCheckBox
|
||||
|
|
|
@ -763,6 +763,12 @@
|
|||
<item>Mastalab</item>
|
||||
</string-array>
|
||||
|
||||
|
||||
<string-array name="SET_MATHS_FORMAT">
|
||||
<item>Inline\nNotation that sits inline with other text\n</item>
|
||||
<item>Display-mode\nNotation that sits on its own line\n</item>
|
||||
</string-array>
|
||||
|
||||
<string-array name="SET_POST_FORMAT" translatable="false">
|
||||
<item>text/plain</item>
|
||||
<item>text/html</item>
|
||||
|
@ -1483,6 +1489,7 @@
|
|||
<string name="SET_UNLISTED_REPLIES" translatable="false">SET_UNLISTED_REPLIES</string>
|
||||
<string name="SET_SELECTED_LANGUAGE" translatable="false">SET_SELECTED_LANGUAGE</string>
|
||||
<string name="SET_WATERMARK_TEXT" translatable="false">SET_WATERMARK_TEXT</string>
|
||||
<string name="SET_MATHS_COMPOSER" translatable="false">SET_MATHS_COMPOSER</string>
|
||||
<string name="SET_PROXY_PASSWORD" translatable="false">SET_PROXY_PASSWORD</string>
|
||||
<string name="SET_PROXY_LOGIN" translatable="false">SET_PROXY_LOGIN</string>
|
||||
<string name="SET_ACCOUNTS_PER_CALL" translatable="false">SET_ACCOUNTS_PER_CALL</string>
|
||||
|
@ -2214,4 +2221,6 @@
|
|||
<string name="set_disable_release_notes">Disable release notes</string>
|
||||
<string name="set_disable_release_notes_indication">When a new version is published, you will not be alerted inside the app.</string>
|
||||
<string name="formula">Formula</string>
|
||||
<string name="set_maths_support">Write formula</string>
|
||||
<string name="maths_format">Maths format</string>
|
||||
</resources>
|
|
@ -60,6 +60,12 @@
|
|||
app:key="@string/SET_WATERMARK_TEXT"
|
||||
app:useSimpleSummaryProvider="true" />
|
||||
|
||||
<SwitchPreferenceCompat
|
||||
app:defaultValue="true"
|
||||
app:iconSpaceReserved="false"
|
||||
app:key="@string/SET_MATHS_COMPOSER"
|
||||
app:singleLineTitle="false"
|
||||
app:title="@string/set_maths_support" />
|
||||
|
||||
<SwitchPreferenceCompat
|
||||
app:defaultValue="false"
|
||||
|
|
|
@ -28,6 +28,7 @@ public class MathJaxConfig {
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
public MathJaxConfig(TypedArray attrs) {
|
||||
this();
|
||||
int inputIndex = attrs.getInteger(R.styleable.MathJaxView_input, -1);
|
||||
|
|
|
@ -9,17 +9,13 @@ import android.os.Handler;
|
|||
import android.text.TextUtils;
|
||||
import android.util.AttributeSet;
|
||||
import android.view.Gravity;
|
||||
import android.view.MotionEvent;
|
||||
import android.view.View;
|
||||
import android.view.ViewConfiguration;
|
||||
import android.view.ViewGroup;
|
||||
import android.webkit.WebSettings;
|
||||
import android.webkit.WebView;
|
||||
import android.webkit.WebViewClient;
|
||||
import android.widget.FrameLayout;
|
||||
|
||||
import java.util.concurrent.atomic.AtomicReference;
|
||||
|
||||
|
||||
/**
|
||||
* Containerview for an WebView which renders LaTex using MathJax
|
||||
|
@ -88,20 +84,26 @@ public class MathJaxView extends FrameLayout {
|
|||
this.onMathJaxRenderListener = onMathJaxRenderListener;
|
||||
}
|
||||
|
||||
public void setTextColor(String color) {
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
|
||||
mWebView.evaluateJavascript("document.body.style.color=\"" + color + "\";", null);
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressLint({"SetJavaScriptEnabled", "AddJavascriptInterface"})
|
||||
private void init(Context context, AttributeSet attrSet, MathJaxConfig config) {
|
||||
mWebView = new WebView(context);
|
||||
|
||||
int gravity = Gravity.START;
|
||||
boolean verticalScrollbarsEnabled = false;
|
||||
boolean horizontalScrollbarsEnabled = true;
|
||||
boolean horizontalScrollbarsEnabled = false;
|
||||
String textColor = config != null ? config.getTextColor() : null;
|
||||
|
||||
if (attrSet != null) {
|
||||
TypedArray attrs = context.obtainStyledAttributes(attrSet, R.styleable.MathJaxView);
|
||||
gravity = attrs.getInteger(R.styleable.MathJaxView_android_gravity, Gravity.START);
|
||||
verticalScrollbarsEnabled = attrs.getBoolean(R.styleable.MathJaxView_verticalScrollbarsEnabled, false);
|
||||
horizontalScrollbarsEnabled = attrs.getBoolean(R.styleable.MathJaxView_horizontalScrollbarsEnabled, true);
|
||||
horizontalScrollbarsEnabled = attrs.getBoolean(R.styleable.MathJaxView_horizontalScrollbarsEnabled, false);
|
||||
textColor = attrs.getString(R.styleable.MathJaxView_textColor);
|
||||
config = new MathJaxConfig(attrs);
|
||||
attrs.recycle();
|
||||
|
@ -153,31 +155,6 @@ public class MathJaxView extends FrameLayout {
|
|||
mWebView.setHorizontalScrollBarEnabled(horizontalScrollbarsEnabled);
|
||||
mWebView.setBackgroundColor(0);
|
||||
mWebView.getSettings().setLoadWithOverviewMode(true);
|
||||
float touchSlop = ViewConfiguration.get(getContext()).getScaledTouchSlop();
|
||||
final boolean[] scrollFlag = {true};
|
||||
AtomicReference<Float> downX = new AtomicReference<>((float) 0);
|
||||
AtomicReference<Float> downY = new AtomicReference<>((float) 0);
|
||||
mWebView.setOnTouchListener((View v, MotionEvent event) -> {
|
||||
if (!scrollFlag[0] && event.getY() < getHeight() / 2) {
|
||||
|
||||
switch (event.getAction()) {
|
||||
case MotionEvent.ACTION_DOWN:
|
||||
downX.set(event.getX());
|
||||
downY.set(event.getY());
|
||||
break;
|
||||
case MotionEvent.ACTION_MOVE:
|
||||
if (Math.abs(event.getY() - downY.get()) < touchSlop && Math.abs(event.getX() - downX.get()) > touchSlop) {
|
||||
getParent().requestDisallowInterceptTouchEvent(true);
|
||||
scrollFlag[0] = true;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (event.getAction() == MotionEvent.ACTION_UP)
|
||||
scrollFlag[0] = false;
|
||||
|
||||
return false;
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
Loading…
Reference in a new issue