display text and markdown content
This commit is contained in:
parent
df4785fb5f
commit
6bed7bfd2f
6 changed files with 229 additions and 32 deletions
|
@ -79,6 +79,7 @@ dependencies {
|
|||
implementation 'com.hbb20:ccp:2.3.8'
|
||||
|
||||
implementation 'com.github.chrisbanes:PhotoView:2.3.0'
|
||||
implementation 'com.atlassian.commonmark:commonmark:0.14.0'
|
||||
|
||||
compileOnly 'org.projectlombok:lombok:1.18.10'
|
||||
annotationProcessor 'org.projectlombok:lombok:1.18.10'
|
||||
|
|
|
@ -20,6 +20,10 @@ import android.text.format.DateUtils;
|
|||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.view.WindowManager;
|
||||
import android.webkit.WebResourceRequest;
|
||||
import android.webkit.WebSettings;
|
||||
import android.webkit.WebView;
|
||||
import android.webkit.WebViewClient;
|
||||
import android.widget.ImageView;
|
||||
import android.widget.ProgressBar;
|
||||
import android.widget.RelativeLayout;
|
||||
|
@ -48,6 +52,9 @@ import com.google.android.flexbox.FlexboxLayoutManager;
|
|||
import com.google.android.material.button.MaterialButton;
|
||||
import com.google.android.material.snackbar.Snackbar;
|
||||
|
||||
import org.commonmark.node.Node;
|
||||
import org.commonmark.parser.Parser;
|
||||
import org.commonmark.renderer.html.HtmlRenderer;
|
||||
import org.json.JSONException;
|
||||
import org.json.JSONObject;
|
||||
|
||||
|
@ -56,6 +63,7 @@ import java.math.BigDecimal;
|
|||
import java.text.DecimalFormat;
|
||||
import java.text.NumberFormat;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.Executors;
|
||||
import java.util.concurrent.ScheduledExecutorService;
|
||||
|
@ -74,6 +82,7 @@ import io.lbry.browser.model.LbryFile;
|
|||
import io.lbry.browser.model.Tag;
|
||||
import io.lbry.browser.model.lbryinc.Reward;
|
||||
import io.lbry.browser.model.lbryinc.Subscription;
|
||||
import io.lbry.browser.tasks.ReadTextFileTask;
|
||||
import io.lbry.browser.tasks.claim.ClaimListResultHandler;
|
||||
import io.lbry.browser.tasks.claim.ClaimSearchTask;
|
||||
import io.lbry.browser.tasks.file.DeleteFileTask;
|
||||
|
@ -161,6 +170,7 @@ public class FileViewActivity extends AppCompatActivity {
|
|||
loadFile();
|
||||
}
|
||||
}
|
||||
|
||||
setContentView(R.layout.activity_file_view);
|
||||
checkIsFileComplete();
|
||||
|
||||
|
@ -218,6 +228,14 @@ public class FileViewActivity extends AppCompatActivity {
|
|||
walletBalanceListeners.remove(listener);
|
||||
}
|
||||
|
||||
private void initWebView() {
|
||||
WebView webView = findViewById(R.id.file_view_webview);
|
||||
webView.setWebViewClient(new LbryWebViewClient(this));
|
||||
WebSettings webSettings = webView.getSettings();
|
||||
webSettings.setAllowFileAccess(true);
|
||||
webSettings.setJavaScriptEnabled(true);
|
||||
}
|
||||
|
||||
private void logUrlEvent(String url) {
|
||||
Bundle bundle = new Bundle();
|
||||
bundle.putString("uri", url);
|
||||
|
@ -466,6 +484,8 @@ public class FileViewActivity extends AppCompatActivity {
|
|||
}
|
||||
|
||||
private void initUi() {
|
||||
initWebView();
|
||||
|
||||
findViewById(R.id.file_view_title_area).setOnClickListener(new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View view) {
|
||||
|
@ -788,10 +808,10 @@ public class FileViewActivity extends AppCompatActivity {
|
|||
findViewById(R.id.file_view_fee_container).setVisibility(View.VISIBLE);
|
||||
((TextView) findViewById(R.id.file_view_fee)).setText(Helper.shortCurrencyFormat(Helper.parseDouble(fee.getAmount(), 0)));
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
findViewById(R.id.file_view_icon_follow_unfollow).setVisibility(claim.getSigningChannel() != null ? View.VISIBLE : View.GONE);
|
||||
|
||||
MaterialButton mainActionButton = findViewById(R.id.file_view_main_action_button);
|
||||
if (claim.isPlayable()) {
|
||||
mainActionButton.setText(R.string.play);
|
||||
|
@ -801,9 +821,11 @@ public class FileViewActivity extends AppCompatActivity {
|
|||
mainActionButton.setText(R.string.download);
|
||||
}
|
||||
|
||||
if (claim.isFree() && (claim.isPlayable() || claim.isViewable())) {
|
||||
if (claim.isFree()) {
|
||||
if (claim.isPlayable() || (claim.isViewable() && Lbry.SDK_READY)) {
|
||||
onMainActionButtonClicked();
|
||||
}
|
||||
}
|
||||
|
||||
loadRelatedContent();
|
||||
}
|
||||
|
@ -1008,40 +1030,98 @@ public class FileViewActivity extends AppCompatActivity {
|
|||
handled = true;
|
||||
} else if (claim.isViewable()) {
|
||||
// check type and display
|
||||
boolean fileExists = false;
|
||||
LbryFile claimFile = claim.getFile();
|
||||
Uri fileUri = null;
|
||||
if (claimFile != null && !Helper.isNullOrEmpty(claimFile.getDownloadPath())) {
|
||||
File file = new File(claimFile.getDownloadPath());
|
||||
fileUri = Uri.fromFile(file);
|
||||
fileExists = file.exists();
|
||||
}
|
||||
if (!fileExists) {
|
||||
showError(getString(R.string.claim_file_not_found, claimFile != null ? claimFile.getDownloadPath() : ""));
|
||||
} else if (fileUri != null) {
|
||||
if (mediaType.startsWith("image")) {
|
||||
// display the image
|
||||
View container = findViewById(R.id.file_view_imageviewer_container);
|
||||
PhotoView photoView = findViewById(R.id.file_view_imageviewer);
|
||||
|
||||
boolean fileExists = false;
|
||||
LbryFile claimFile = claim.getFile();
|
||||
if (claimFile != null && !Helper.isNullOrEmpty(claimFile.getDownloadPath())) {
|
||||
File file = new File(claimFile.getDownloadPath());
|
||||
fileExists = file.exists();
|
||||
|
||||
if (fileExists) {
|
||||
Uri fileUri = Uri.fromFile(file);
|
||||
Glide.with(getApplicationContext()).load(fileUri).centerInside().into(photoView);
|
||||
hideFloatingWalletBalance();
|
||||
container.setVisibility(View.VISIBLE);
|
||||
}
|
||||
}
|
||||
|
||||
if (!fileExists) {
|
||||
showError(getString(R.string.claim_file_not_found, claimFile != null ? claimFile.getDownloadPath() : ""));
|
||||
}
|
||||
} else if (mediaType.startsWith("text")) {
|
||||
// show browser (and parse markdown too)
|
||||
// show web view (and parse markdown too)
|
||||
View container = findViewById(R.id.file_view_webview_container);
|
||||
WebView webView = findViewById(R.id.file_view_webview);
|
||||
if (Arrays.asList("text/markdown", "text/md").contains(mediaType.toLowerCase())) {
|
||||
loadMarkdownFromFile(claimFile.getDownloadPath());
|
||||
} else {
|
||||
webView.loadUrl(fileUri.toString());
|
||||
}
|
||||
hideFloatingWalletBalance();
|
||||
container.setVisibility(View.VISIBLE);
|
||||
}
|
||||
handled = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!handled) {
|
||||
showUnsupportedView();
|
||||
}
|
||||
}
|
||||
|
||||
private void loadMarkdownFromFile(String filePath) {
|
||||
ReadTextFileTask task = new ReadTextFileTask(filePath, new ReadTextFileTask.ReadTextFileHandler() {
|
||||
@Override
|
||||
public void onSuccess(String text) {
|
||||
String html = buildMarkdownHtml(text);
|
||||
WebView webView = findViewById(R.id.file_view_webview);
|
||||
webView.loadData(html, "text/html", "utf-8");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onError(Exception error) {
|
||||
showError(error.getMessage());
|
||||
}
|
||||
});
|
||||
task.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
|
||||
}
|
||||
|
||||
private String buildMarkdownHtml(String markdown) {
|
||||
Parser parser = Parser.builder().build();
|
||||
Node document = parser.parse(markdown);
|
||||
HtmlRenderer renderer = HtmlRenderer.builder().build();
|
||||
String markdownHtml = renderer.render(document);
|
||||
|
||||
return "<!doctype html>\n" +
|
||||
" <html>\n" +
|
||||
" <head>\n" +
|
||||
" <meta charset=\"utf-8\"/>\n" +
|
||||
" <meta name=\"viewport\" content=\"width=device-width, user-scalable=no\"/>\n" +
|
||||
" <style type=\"text/css\">\n" +
|
||||
" @font-face {\n" +
|
||||
" font-family: 'Inter';\n" +
|
||||
" src: url('file:///android_res/font/inter_regular.otf');\n" +
|
||||
" font-weight: normal;\n" +
|
||||
" }\n" +
|
||||
" @font-face {\n" +
|
||||
" font-family: 'Inter';\n" +
|
||||
" src: url('file:///android_res/font/inter_bold.otf');\n" +
|
||||
" font-weight: bold;\n" +
|
||||
" }\n" +
|
||||
" body { font-family: 'Inter', sans-serif; margin: 16px }\n" +
|
||||
" img { width: 100%; }\n" +
|
||||
" </style>\n" +
|
||||
" </head>\n" +
|
||||
" <body>\n" +
|
||||
" <div id=\"content\">\n" +
|
||||
markdownHtml +
|
||||
" </div>\n" +
|
||||
" </body>\n" +
|
||||
" </html>";
|
||||
}
|
||||
|
||||
public void showError(String message) {
|
||||
Snackbar.make(findViewById(R.id.file_view_claim_display_area), message, Snackbar.LENGTH_LONG).
|
||||
setTextColor(Color.WHITE).
|
||||
|
@ -1113,6 +1193,14 @@ public class FileViewActivity extends AppCompatActivity {
|
|||
|
||||
if (isImageViewerVisible()) {
|
||||
findViewById(R.id.file_view_imageviewer_container).setVisibility(View.GONE);
|
||||
restoreMainActionButton();
|
||||
showFloatingWalletBalance();
|
||||
return;
|
||||
}
|
||||
if (isWebViewVisible()) {
|
||||
findViewById(R.id.file_view_webview_container).setVisibility(View.GONE);
|
||||
restoreMainActionButton();
|
||||
showFloatingWalletBalance();
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -1127,14 +1215,17 @@ public class FileViewActivity extends AppCompatActivity {
|
|||
}
|
||||
|
||||
private boolean isWebViewVisible() {
|
||||
return false;
|
||||
return findViewById(R.id.file_view_webview_container).getVisibility() == View.VISIBLE;
|
||||
}
|
||||
|
||||
protected void onUserLeaveHint() {
|
||||
if (stopServiceReceived) {
|
||||
if (stopServiceReceived ||
|
||||
claim == null ||
|
||||
!claim.isPlayable()) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
if (startingShareActivity) {
|
||||
// share activity triggered this, so reset the flag at this point
|
||||
new Handler().postDelayed(new Runnable() {
|
||||
|
@ -1145,6 +1236,7 @@ public class FileViewActivity extends AppCompatActivity {
|
|||
}, 1000);
|
||||
return;
|
||||
}
|
||||
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O && !MainActivity.mainActive) {
|
||||
PictureInPictureParams params = new PictureInPictureParams.Builder().build();
|
||||
enterPictureInPictureMode(params);
|
||||
|
@ -1432,6 +1524,9 @@ public class FileViewActivity extends AppCompatActivity {
|
|||
private void hideFloatingWalletBalance() {
|
||||
findViewById(R.id.floating_balance_main_container).setVisibility(View.GONE);
|
||||
}
|
||||
private void showFloatingWalletBalance() {
|
||||
findViewById(R.id.floating_balance_main_container).setVisibility(View.VISIBLE);
|
||||
}
|
||||
|
||||
private void onDownloadAborted() {
|
||||
downloadInProgress = false;
|
||||
|
@ -1451,4 +1546,20 @@ public class FileViewActivity extends AppCompatActivity {
|
|||
findViewById(R.id.file_view_main_action_loading).setVisibility(View.INVISIBLE);
|
||||
findViewById(R.id.file_view_main_action_button).setVisibility(View.VISIBLE);
|
||||
}
|
||||
|
||||
private static class LbryWebViewClient extends WebViewClient {
|
||||
private Context context;
|
||||
public LbryWebViewClient(Context context) {
|
||||
this.context = context;
|
||||
}
|
||||
@Override
|
||||
public boolean shouldOverrideUrlLoading(WebView view, WebResourceRequest request) {
|
||||
Uri url = request.getUrl();
|
||||
if (context != null) {
|
||||
Intent intent = new Intent(Intent.ACTION_VIEW, url);
|
||||
context.startActivity(intent);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -20,6 +20,7 @@ import com.google.firebase.analytics.FirebaseAnalytics;
|
|||
import com.google.firebase.messaging.FirebaseMessagingService;
|
||||
import com.google.firebase.messaging.RemoteMessage;
|
||||
|
||||
import io.lbry.browser.utils.LbryAnalytics;
|
||||
import io.lbry.lbrysdk.LbrynetService;
|
||||
|
||||
import java.io.UnsupportedEncodingException;
|
||||
|
@ -61,7 +62,7 @@ public class LbrynetMessagingService extends FirebaseMessagingService {
|
|||
if (firebaseAnalytics != null) {
|
||||
Bundle bundle = new Bundle();
|
||||
bundle.putString("name", name);
|
||||
firebaseAnalytics.logEvent("lbry_notification_receive", bundle);
|
||||
firebaseAnalytics.logEvent(LbryAnalytics.EVENT_LBRY_NOTIFICATION_RECEIVE, bundle);
|
||||
}
|
||||
|
||||
sendNotification(title, body, type, url, name, contentTitle, channelUrl, publishTime);
|
||||
|
|
|
@ -315,6 +315,7 @@ public class MainActivity extends AppCompatActivity implements SdkStatusListener
|
|||
});
|
||||
|
||||
super.onCreate(savedInstanceState);
|
||||
checkNotificationOpenIntent(getIntent());
|
||||
setContentView(R.layout.activity_main);
|
||||
Toolbar toolbar = findViewById(R.id.toolbar);
|
||||
setSupportActionBar(toolbar);
|
||||
|
@ -441,6 +442,7 @@ public class MainActivity extends AppCompatActivity implements SdkStatusListener
|
|||
protected void onNewIntent(Intent intent) {
|
||||
super.onNewIntent(intent);
|
||||
checkUrlIntent(intent);
|
||||
checkNotificationOpenIntent(intent);
|
||||
}
|
||||
|
||||
public void addSdkStatusListener(SdkStatusListener listener) {
|
||||
|
@ -1837,6 +1839,22 @@ public class MainActivity extends AppCompatActivity implements SdkStatusListener
|
|||
return false;
|
||||
}
|
||||
|
||||
private void checkNotificationOpenIntent(Intent intent) {
|
||||
if (intent != null) {
|
||||
String notificationName = intent.getStringExtra("notification_name");
|
||||
if (notificationName != null) {
|
||||
logNotificationOpen(notificationName);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void logNotificationOpen(String name) {
|
||||
Bundle bundle = new Bundle();
|
||||
bundle.putString("name", name);
|
||||
LbryAnalytics.logEvent(LbryAnalytics.EVENT_LBRY_NOTIFICATION_OPEN, bundle);
|
||||
}
|
||||
|
||||
|
||||
private void registerServiceActionsReceiver() {
|
||||
IntentFilter intentFilter = new IntentFilter();
|
||||
intentFilter.addAction(LbrynetService.LBRY_SDK_SERVICE_STARTED);
|
||||
|
|
|
@ -0,0 +1,55 @@
|
|||
package io.lbry.browser.tasks;
|
||||
|
||||
import android.os.AsyncTask;
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.FileNotFoundException;
|
||||
import java.io.FileReader;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStreamReader;
|
||||
import java.nio.Buffer;
|
||||
|
||||
import io.lbry.browser.utils.Helper;
|
||||
|
||||
public class ReadTextFileTask extends AsyncTask<Void, Void, String> {
|
||||
private String filePath;
|
||||
private Exception error;
|
||||
private ReadTextFileHandler handler;
|
||||
public ReadTextFileTask(String filePath, ReadTextFileHandler handler) {
|
||||
this.filePath = filePath;
|
||||
this.handler = handler;
|
||||
}
|
||||
protected String doInBackground(Void... params) {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
BufferedReader reader = null;
|
||||
try {
|
||||
reader = new BufferedReader(new InputStreamReader(new FileInputStream(filePath)));
|
||||
String line = null;
|
||||
while ((line = reader.readLine()) != null) {
|
||||
sb.append(line).append("\n");
|
||||
}
|
||||
} catch (IOException ex) {
|
||||
error = ex;
|
||||
return null;
|
||||
} finally {
|
||||
Helper.closeCloseable(reader);
|
||||
}
|
||||
|
||||
return sb.toString();
|
||||
}
|
||||
protected void onPostExecute(String text) {
|
||||
if (handler != null) {
|
||||
if (!Helper.isNull(text)) {
|
||||
handler.onSuccess(text);
|
||||
} else {
|
||||
handler.onError(error);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public interface ReadTextFileHandler {
|
||||
void onSuccess(String text);
|
||||
void onError(Exception error);
|
||||
}
|
||||
}
|
|
@ -624,6 +624,17 @@
|
|||
android:layout_height="match_parent" />
|
||||
</RelativeLayout>
|
||||
|
||||
<RelativeLayout
|
||||
android:id="@+id/file_view_webview_container"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:visibility="gone">
|
||||
<WebView
|
||||
android:id="@+id/file_view_webview"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent" />
|
||||
</RelativeLayout>
|
||||
|
||||
<include layout="@layout/floating_wallet_balance" />
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||
</androidx.coordinatorlayout.widget.CoordinatorLayout>
|
Loading…
Reference in a new issue