package com.prettifier.pretty;
import android.annotation.SuppressLint;
import android.content.Context;
import android.content.res.TypedArray;
import android.net.Uri;
import android.os.Build;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.View;
import android.webkit.WebChromeClient;
import android.webkit.WebResourceRequest;
import android.webkit.WebSettings;
import android.webkit.WebView;
import android.webkit.WebViewClient;
import com.fastaccess.R;
import com.fastaccess.helper.AppHelper;
import com.fastaccess.helper.InputHelper;
import com.fastaccess.helper.Logger;
import com.fastaccess.helper.ViewHelper;
import com.fastaccess.provider.markdown.MarkDownProvider;
import com.fastaccess.provider.scheme.SchemeParser;
import com.fastaccess.ui.modules.code.CodeViewerActivity;
import com.prettifier.pretty.callback.MarkDownInterceptorInterface;
import com.prettifier.pretty.helper.GithubHelper;
import com.prettifier.pretty.helper.PrettifyHelper;
public class PrettifyWebView extends NestedWebView {
private OnContentChangedListener onContentChangedListener;
private boolean interceptTouch;
public interface OnContentChangedListener {
void onContentChanged(int progress);
}
public PrettifyWebView(Context context) {
super(context);
if (isInEditMode()) return;
initView(null);
}
public PrettifyWebView(Context context, AttributeSet attrs) {
super(context, attrs);
initView(attrs);
}
public PrettifyWebView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
initView(attrs);
}
@Override public boolean onInterceptTouchEvent(MotionEvent p_event) {
return true;
}
@SuppressLint("ClickableViewAccessibility") @Override public boolean onTouchEvent(MotionEvent event) {
if (getParent() != null) {
getParent().requestDisallowInterceptTouchEvent(interceptTouch);
}
return super.onTouchEvent(event);
}
@SuppressLint("SetJavaScriptEnabled") private void initView(@Nullable AttributeSet attrs) {
if (isInEditMode()) return;
if (attrs != null) {
TypedArray tp = getContext().obtainStyledAttributes(attrs, R.styleable.PrettifyWebView);
try {
int color = tp.getColor(R.styleable.PrettifyWebView_webview_background, ViewHelper.getWindowBackground(getContext()));
setBackgroundColor(color);
} finally {
tp.recycle();
}
}
setWebChromeClient(new ChromeClient());
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
setWebViewClient(new WebClient());
} else {
setWebViewClient(new WebClientCompat());
}
WebSettings settings = getSettings();
settings.setJavaScriptEnabled(true);
settings.setAppCachePath(getContext().getCacheDir().getPath());
settings.setAppCacheEnabled(true);
settings.setCacheMode(WebSettings.LOAD_CACHE_ELSE_NETWORK);
settings.setDefaultTextEncodingName("utf-8");
settings.setLoadsImagesAutomatically(true);
settings.setBlockNetworkImage(false);
setOnLongClickListener((view) -> {
WebView.HitTestResult result = getHitTestResult();
if (hitLinkResult(result) && !InputHelper.isEmpty(result.getExtra())) {
AppHelper.copyToClipboard(getContext(), result.getExtra());
return true;
}
return false;
});
}
private boolean hitLinkResult(WebView.HitTestResult result) {
return result.getType() == WebView.HitTestResult.SRC_ANCHOR_TYPE || result.getType() == HitTestResult.IMAGE_TYPE ||
result.getType() == HitTestResult.SRC_IMAGE_ANCHOR_TYPE;
}
public void setOnContentChangedListener(@NonNull OnContentChangedListener onContentChangedListener) {
this.onContentChangedListener = onContentChangedListener;
}
public void setSource(@NonNull String source, boolean wrap, @Nullable String url) {
WebSettings settings = getSettings();
settings.setLayoutAlgorithm(WebSettings.LayoutAlgorithm.TEXT_AUTOSIZING);
setScrollBarStyle(View.SCROLLBARS_INSIDE_OVERLAY);
settings.setSupportZoom(!wrap);
settings.setBuiltInZoomControls(!wrap);
if (!wrap) settings.setDisplayZoomControls(false);
if (!InputHelper.isEmpty(source)) {
String page = PrettifyHelper.generateContent(source, AppHelper.isNightMode(getResources()), wrap);
post(() -> loadDataWithBaseURL("file:///android_asset/highlight/", page, "text/html", "utf-8", null));
int lineNo = getLineNo(url);
if (lineNo != 0) {
setOnContentChangedListener(progress -> {
Logger.e(progress);
if (progress == 100) {
if (isAttachedToWindow()) loadUrl("javascript:scrollToLineNumber('" + lineNo + "')");
}
});
}
}
}
private int getLineNo(@Nullable String url) {
int lineNo = 0;
if (url != null) {
try {
Uri uri = Uri.parse(url);
String lineNumber = uri.getEncodedFragment();
Logger.e(lineNumber);
if (lineNumber != null) {
String[] toSplit = lineNumber.split("-");
if (toSplit.length > 1) {
lineNumber = toSplit[toSplit.length - 1];
}
Logger.e(lineNumber);
lineNumber = lineNumber.replace("L", "");
lineNo = Integer.valueOf(lineNumber);
Logger.e(lineNo);
}
} catch (Exception ignored) {}
}
return lineNo;
}
public void setGithubContent(@NonNull String source, @Nullable String baseUrl) {
setGithubContent(source, baseUrl, false);
}
public void setGithubContent(@NonNull String source, @Nullable String baseUrl, boolean wrap) {
if (wrap) {
setScrollbarFadingEnabled(false);
setVerticalScrollBarEnabled(false);
}
if (!InputHelper.isEmpty(source)) {
if (!wrap) addJavascriptInterface(new MarkDownInterceptorInterface(this), "Android");
String page = GithubHelper.generateContent(source, baseUrl, wrap, AppHelper.isNightMode(getResources()));
post(() -> loadDataWithBaseURL("file:///android_asset/md/", page, "text/html", "utf-8", null));
}
}
public void loadImage(@NonNull String url) {
WebSettings settings = getSettings();
settings.setLayoutAlgorithm(WebSettings.LayoutAlgorithm.SINGLE_COLUMN);
setScrollBarStyle(View.SCROLLBARS_INSIDE_OVERLAY);
settings.setSupportZoom(true);
settings.setBuiltInZoomControls(true);
settings.setDisplayZoomControls(false);
String html = "<html><head><style>img{display: inline; height: auto; max-width: 100%;}</style></head><body><img src=\"" + url +
"\"/></body></html>";
loadData(html, "text/html", null);
}
public void setInterceptTouch(boolean interceptTouch) {
this.interceptTouch = interceptTouch;
}
private void startActivity(@Nullable Uri url) {
if (url == null) return;
Logger.e(url);
if (MarkDownProvider.isImage(url.toString())) {
CodeViewerActivity.startActivity(getContext(), url.toString(), url.toString());
} else {
String lastSegment = url.getEncodedFragment();
if (lastSegment != null || url.toString().startsWith("#") || url.toString().indexOf('#') != -1) {
return;
}
SchemeParser.launchUri(getContext(), url, true);
}
}
private class ChromeClient extends WebChromeClient {
@Override public void onProgressChanged(WebView view, int progress) {
super.onProgressChanged(view, progress);
if (onContentChangedListener != null) {
onContentChangedListener.onContentChanged(progress);
}
}
}
private class WebClient extends WebViewClient {
@Override public boolean shouldOverrideUrlLoading(WebView view, WebResourceRequest request) {
startActivity(request.getUrl());
return true;
}
}
private class WebClientCompat extends WebViewClient {
@SuppressWarnings("deprecation") @Override public boolean shouldOverrideUrlLoading(WebView view, String url) {
startActivity(Uri.parse(url));
return true;
}
}
}