diff --git a/app/build.gradle b/app/build.gradle index 4140e140..766f0b2e 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -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' diff --git a/app/src/main/java/io/lbry/browser/FileViewActivity.java b/app/src/main/java/io/lbry/browser/FileViewActivity.java index fa3d8232..1889e41c 100644 --- a/app/src/main/java/io/lbry/browser/FileViewActivity.java +++ b/app/src/main/java/io/lbry/browser/FileViewActivity.java @@ -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,8 +821,10 @@ public class FileViewActivity extends AppCompatActivity { mainActionButton.setText(R.string.download); } - if (claim.isFree() && (claim.isPlayable() || claim.isViewable())) { - onMainActionButtonClicked(); + if (claim.isFree()) { + if (claim.isPlayable() || (claim.isViewable() && Lbry.SDK_READY)) { + onMainActionButtonClicked(); + } } loadRelatedContent(); @@ -1008,32 +1030,39 @@ public class FileViewActivity extends AppCompatActivity { handled = true; } else if (claim.isViewable()) { // check type and display - 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) + 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); + + Glide.with(getApplicationContext()).load(fileUri).centerInside().into(photoView); + hideFloatingWalletBalance(); + container.setVisibility(View.VISIBLE); + } else if (mediaType.startsWith("text")) { + // 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; } - handled = true; } } @@ -1042,6 +1071,57 @@ public class FileViewActivity extends AppCompatActivity { } } + 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 "\n" + + " \n" + + "
\n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + "