making java kotlin since 2023(tm)
Signed-off-by: androidacy-user <opensource@androidacy.com>pull/27/head
parent
906a5cbab9
commit
0708c2f7a9
@ -1,254 +1,255 @@
|
|||||||
package com.fox2code.mmm.markdown;
|
package com.fox2code.mmm.markdown
|
||||||
|
|
||||||
import android.content.Intent;
|
import android.content.DialogInterface
|
||||||
import android.content.pm.PackageManager;
|
import android.content.pm.PackageManager
|
||||||
import android.content.res.Configuration;
|
import android.content.res.Configuration
|
||||||
import android.graphics.Color;
|
import android.graphics.Color
|
||||||
import android.os.Build;
|
import android.os.Build
|
||||||
import android.os.Bundle;
|
import android.os.Bundle
|
||||||
import android.view.View;
|
import android.view.MenuItem
|
||||||
import android.view.ViewGroup;
|
import android.view.View
|
||||||
import android.view.WindowManager;
|
import android.view.ViewGroup
|
||||||
import android.widget.TextView;
|
import android.view.WindowManager
|
||||||
import android.widget.Toast;
|
import android.widget.TextView
|
||||||
|
import android.widget.Toast
|
||||||
import androidx.annotation.Nullable;
|
import com.fox2code.foxcompat.app.FoxActivity
|
||||||
|
import com.fox2code.mmm.Constants
|
||||||
import com.fox2code.foxcompat.app.FoxActivity;
|
import com.fox2code.mmm.MainApplication
|
||||||
import com.fox2code.mmm.Constants;
|
import com.fox2code.mmm.R
|
||||||
import com.fox2code.mmm.MainApplication;
|
import com.fox2code.mmm.XHooks
|
||||||
import com.fox2code.mmm.R;
|
import com.fox2code.mmm.utils.IntentHelper
|
||||||
import com.fox2code.mmm.XHooks;
|
import com.fox2code.mmm.utils.io.net.Http
|
||||||
import com.fox2code.mmm.utils.IntentHelper;
|
import com.google.android.material.bottomnavigation.BottomNavigationView
|
||||||
import com.fox2code.mmm.utils.io.net.Http;
|
import com.google.android.material.chip.Chip
|
||||||
import com.google.android.material.bottomnavigation.BottomNavigationView;
|
import com.google.android.material.chip.ChipGroup
|
||||||
import com.google.android.material.chip.Chip;
|
import com.google.android.material.dialog.MaterialAlertDialogBuilder
|
||||||
import com.google.android.material.chip.ChipGroup;
|
import com.topjohnwu.superuser.internal.UiThreadHandler
|
||||||
import com.google.android.material.dialog.MaterialAlertDialogBuilder;
|
import org.matomo.sdk.extra.TrackHelper
|
||||||
import com.topjohnwu.superuser.internal.UiThreadHandler;
|
import timber.log.Timber
|
||||||
|
import java.io.IOException
|
||||||
import org.matomo.sdk.extra.TrackHelper;
|
import java.nio.charset.StandardCharsets
|
||||||
|
|
||||||
import java.io.IOException;
|
class MarkdownActivity : FoxActivity() {
|
||||||
import java.nio.charset.StandardCharsets;
|
private var header: TextView? = null
|
||||||
import java.util.HashMap;
|
private var footer: TextView? = null
|
||||||
import java.util.Objects;
|
override fun onCreate(savedInstanceState: Bundle?) {
|
||||||
|
super.onCreate(savedInstanceState)
|
||||||
import timber.log.Timber;
|
TrackHelper.track().screen(this).with(MainApplication.getINSTANCE().tracker)
|
||||||
|
setDisplayHomeAsUpEnabled(true)
|
||||||
public class MarkdownActivity extends FoxActivity {
|
val intent = this.intent
|
||||||
private static final HashMap<String, String> redirects = new HashMap<>(4);
|
|
||||||
private static final String[] variants = new String[]{"readme.md", "README.MD", ".github/README.md"};
|
|
||||||
private TextView header;
|
|
||||||
private TextView footer;
|
|
||||||
|
|
||||||
private static byte[] getRawMarkdown(String url) throws IOException {
|
|
||||||
String newUrl = redirects.get(url);
|
|
||||||
if (newUrl != null && !newUrl.equals(url)) {
|
|
||||||
return Http.doHttpGet(newUrl, true);
|
|
||||||
}
|
|
||||||
try {
|
|
||||||
return Http.doHttpGet(url, true);
|
|
||||||
} catch (IOException e) {
|
|
||||||
// Workaround GitHub README.md case sensitivity issue
|
|
||||||
if (url.startsWith("https://raw.githubusercontent.com/") && url.endsWith("/README.md")) {
|
|
||||||
String prefix = url.substring(0, url.length() - 9);
|
|
||||||
for (String suffix : variants) {
|
|
||||||
newUrl = prefix + suffix;
|
|
||||||
try { // Try with lowercase version
|
|
||||||
byte[] rawMarkdown = Http.doHttpGet(prefix + suffix, true);
|
|
||||||
redirects.put(url, newUrl); // Avoid retries
|
|
||||||
return rawMarkdown;
|
|
||||||
} catch (IOException ignored) {
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
throw e;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void onCreate(@Nullable Bundle savedInstanceState) {
|
|
||||||
super.onCreate(savedInstanceState);
|
|
||||||
TrackHelper.track().screen(this).with(MainApplication.getINSTANCE().getTracker());
|
|
||||||
this.setDisplayHomeAsUpEnabled(true);
|
|
||||||
Intent intent = this.getIntent();
|
|
||||||
if (!MainApplication.checkSecret(intent)) {
|
if (!MainApplication.checkSecret(intent)) {
|
||||||
Timber.e("Impersonation detected!");
|
Timber.e("Impersonation detected!")
|
||||||
this.forceBackPressed();
|
forceBackPressed()
|
||||||
return;
|
return
|
||||||
}
|
}
|
||||||
String url = Objects.requireNonNull(intent.getExtras()).getString(Constants.EXTRA_MARKDOWN_URL);
|
val url = intent.extras?.getString(Constants.EXTRA_MARKDOWN_URL)
|
||||||
String title = intent.getExtras().getString(Constants.EXTRA_MARKDOWN_TITLE);
|
var title = intent.extras!!.getString(Constants.EXTRA_MARKDOWN_TITLE)
|
||||||
String config = intent.getExtras().getString(Constants.EXTRA_MARKDOWN_CONFIG);
|
val config = intent.extras!!.getString(Constants.EXTRA_MARKDOWN_CONFIG)
|
||||||
boolean change_boot = intent.getExtras().getBoolean(Constants.EXTRA_MARKDOWN_CHANGE_BOOT);
|
val changeBoot = intent.extras!!.getBoolean(Constants.EXTRA_MARKDOWN_CHANGE_BOOT)
|
||||||
boolean needs_ramdisk = intent.getExtras().getBoolean(Constants.EXTRA_MARKDOWN_NEEDS_RAMDISK);
|
val needsRamdisk = intent.extras!!.getBoolean(Constants.EXTRA_MARKDOWN_NEEDS_RAMDISK)
|
||||||
int min_magisk = intent.getExtras().getInt(Constants.EXTRA_MARKDOWN_MIN_MAGISK);
|
val minMagisk = intent.extras!!.getInt(Constants.EXTRA_MARKDOWN_MIN_MAGISK)
|
||||||
int min_api = intent.getExtras().getInt(Constants.EXTRA_MARKDOWN_MIN_API);
|
val minApi = intent.extras!!.getInt(Constants.EXTRA_MARKDOWN_MIN_API)
|
||||||
int max_api = intent.getExtras().getInt(Constants.EXTRA_MARKDOWN_MAX_API);
|
val maxApi = intent.extras!!.getInt(Constants.EXTRA_MARKDOWN_MAX_API)
|
||||||
if (title != null && !title.isEmpty()) {
|
if (!title.isNullOrEmpty()) {
|
||||||
this.setTitle(title);
|
this.title = title
|
||||||
}
|
} else {
|
||||||
setActionBarBackground(null);
|
@Suppress("UNUSED_VALUE")
|
||||||
this.getWindow().setFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_NAVIGATION, 0);
|
title = url
|
||||||
if (config != null && !config.isEmpty()) {
|
}
|
||||||
String configPkg = IntentHelper.getPackageOfConfig(config);
|
setActionBarBackground(null)
|
||||||
|
@Suppress("DEPRECATION")
|
||||||
|
this.window.setFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_NAVIGATION, 0)
|
||||||
|
if (!config.isNullOrEmpty()) {
|
||||||
|
val configPkg = IntentHelper.getPackageOfConfig(config)
|
||||||
try {
|
try {
|
||||||
XHooks.checkConfigTargetExists(this, configPkg, config);
|
XHooks.checkConfigTargetExists(this, configPkg, config)
|
||||||
this.setActionBarExtraMenuButton(R.drawable.ic_baseline_app_settings_alt_24, menu -> {
|
this.setActionBarExtraMenuButton(R.drawable.ic_baseline_app_settings_alt_24) { _: MenuItem? ->
|
||||||
IntentHelper.openConfig(this, config);
|
IntentHelper.openConfig(this, config)
|
||||||
return true;
|
true
|
||||||
});
|
}
|
||||||
} catch (PackageManager.NameNotFoundException e) {
|
} catch (e: PackageManager.NameNotFoundException) {
|
||||||
Timber.w("Config package \"" + configPkg + "\" missing for markdown view");
|
Timber.w("Config package \"$configPkg\" missing for markdown view")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// validate the url won't crash the app
|
// validate the url won't crash the app
|
||||||
if (url == null || url.isEmpty() || url.contains("..")) {
|
if (url.isNullOrEmpty() || url.contains("..")) {
|
||||||
Timber.e("Invalid url %s", String.valueOf(url));
|
Timber.e("Invalid url %s", url.toString())
|
||||||
this.forceBackPressed();
|
forceBackPressed()
|
||||||
return;
|
return
|
||||||
}
|
}
|
||||||
//noinspection UnnecessaryCallToStringValueOf
|
Timber.i("Url for markdown %s", url.toString())
|
||||||
Timber.i("Url for markdown %s", String.valueOf(url));
|
setContentView(R.layout.markdown_view)
|
||||||
setContentView(R.layout.markdown_view);
|
val markdownBackground = findViewById<ViewGroup>(R.id.markdownBackground)
|
||||||
final ViewGroup markdownBackground = findViewById(R.id.markdownBackground);
|
val textView = findViewById<TextView>(R.id.markdownView)
|
||||||
final TextView textView = findViewById(R.id.markdownView);
|
header = findViewById(R.id.markdownHeader)
|
||||||
this.header = findViewById(R.id.markdownHeader);
|
footer = findViewById(R.id.markdownFooter)
|
||||||
this.footer = findViewById(R.id.markdownFooter);
|
updateBlurState()
|
||||||
this.updateBlurState();
|
UiThreadHandler.handler.post { // Fix header/footer height
|
||||||
UiThreadHandler.handler.post(() -> // Fix header/footer height
|
this.updateScreenInsets(this.resources.configuration)
|
||||||
this.updateScreenInsets(this.getResources().getConfiguration()));
|
}
|
||||||
|
|
||||||
// Really bad created (MSG by Der_Googler)
|
// Really bad created (MSG by Der_Googler)
|
||||||
// set "message" to null to disable dialog
|
// set "message" to null to disable dialog
|
||||||
if (change_boot) this.addChip(MarkdownChip.CHANGE_BOOT);
|
if (changeBoot) this.addChip(MarkdownChip.CHANGE_BOOT)
|
||||||
if (needs_ramdisk) this.addChip(MarkdownChip.NEED_RAMDISK);
|
if (needsRamdisk) this.addChip(MarkdownChip.NEED_RAMDISK)
|
||||||
if (min_magisk != 0) this.addChip(MarkdownChip.MIN_MAGISK, String.valueOf(min_magisk));
|
if (minMagisk != 0) this.addChip(MarkdownChip.MIN_MAGISK, minMagisk.toString())
|
||||||
if (min_api != 0) this.addChip(MarkdownChip.MIN_SDK, parseAndroidVersion(min_api));
|
if (minApi != 0) this.addChip(MarkdownChip.MIN_SDK, parseAndroidVersion(minApi))
|
||||||
if (max_api != 0) this.addChip(MarkdownChip.MAX_SDK, parseAndroidVersion(max_api));
|
if (maxApi != 0) this.addChip(MarkdownChip.MAX_SDK, parseAndroidVersion(maxApi))
|
||||||
|
Thread({
|
||||||
new Thread(() -> {
|
|
||||||
try {
|
try {
|
||||||
Timber.i("Downloading");
|
Timber.i("Downloading")
|
||||||
byte[] rawMarkdown = getRawMarkdown(url);
|
val rawMarkdown = getRawMarkdown(url)
|
||||||
Timber.i("Encoding");
|
Timber.i("Encoding")
|
||||||
String markdown = new String(rawMarkdown, StandardCharsets.UTF_8);
|
val markdown = String(rawMarkdown, StandardCharsets.UTF_8)
|
||||||
Timber.i("Done!");
|
Timber.i("Done!")
|
||||||
runOnUiThread(() -> {
|
runOnUiThread {
|
||||||
findViewById(R.id.markdownFooter).setMinimumHeight(this.getNavigationBarHeight());
|
footer?.minimumHeight = this.navigationBarHeight
|
||||||
MainApplication.getINSTANCE().getMarkwon().setMarkdown(textView, MarkdownUrlLinker.urlLinkify(markdown));
|
MainApplication.getINSTANCE().markwon.setMarkdown(
|
||||||
|
textView,
|
||||||
|
MarkdownUrlLinker.urlLinkify(markdown)
|
||||||
|
)
|
||||||
if (markdownBackground != null) {
|
if (markdownBackground != null) {
|
||||||
markdownBackground.setClickable(true);
|
markdownBackground.isClickable = true
|
||||||
|
}
|
||||||
}
|
}
|
||||||
});
|
} catch (e: Exception) {
|
||||||
} catch (Exception e) {
|
Timber.e(e)
|
||||||
Timber.e(e);
|
runOnUiThread {
|
||||||
runOnUiThread(() -> Toast.makeText(this, R.string.failed_download, Toast.LENGTH_SHORT).show());
|
Toast.makeText(this, R.string.failed_download, Toast.LENGTH_SHORT).show()
|
||||||
}
|
}
|
||||||
}, "Markdown load thread").start();
|
}
|
||||||
|
}, "Markdown load thread").start()
|
||||||
}
|
}
|
||||||
|
|
||||||
private void updateBlurState() {
|
private fun updateBlurState() {
|
||||||
if (MainApplication.isBlurEnabled()) {
|
if (MainApplication.isBlurEnabled()) {
|
||||||
// set bottom navigation bar color to transparent blur
|
// set bottom navigation bar color to transparent blur
|
||||||
BottomNavigationView bottomNavigationView = findViewById(R.id.bottom_navigation);
|
val bottomNavigationView = findViewById<BottomNavigationView>(R.id.bottom_navigation)
|
||||||
if (bottomNavigationView != null) {
|
if (bottomNavigationView != null) {
|
||||||
bottomNavigationView.setBackgroundColor(Color.TRANSPARENT);
|
bottomNavigationView.setBackgroundColor(Color.TRANSPARENT)
|
||||||
bottomNavigationView.setAlpha(0.8F);
|
bottomNavigationView.alpha = 0.8f
|
||||||
} else {
|
} else {
|
||||||
Timber.w("Bottom navigation view not found");
|
Timber.w("Bottom navigation view not found")
|
||||||
}
|
}
|
||||||
// set dialogs to have transparent blur
|
// set dialogs to have transparent blur
|
||||||
getWindow().addFlags(WindowManager.LayoutParams.FLAG_BLUR_BEHIND);
|
window.addFlags(WindowManager.LayoutParams.FLAG_BLUR_BEHIND)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void updateScreenInsets() {
|
private fun updateScreenInsets() {
|
||||||
this.runOnUiThread(() -> this.updateScreenInsets(this.getResources().getConfiguration()));
|
runOnUiThread { this.updateScreenInsets(this.resources.configuration) }
|
||||||
}
|
}
|
||||||
|
|
||||||
private void updateScreenInsets(Configuration configuration) {
|
private fun updateScreenInsets(configuration: Configuration) {
|
||||||
boolean landscape = configuration.orientation == Configuration.ORIENTATION_LANDSCAPE;
|
val landscape = configuration.orientation == Configuration.ORIENTATION_LANDSCAPE
|
||||||
int bottomInset = (landscape ? 0 : this.getNavigationBarHeight());
|
val bottomInset = if (landscape) 0 else this.navigationBarHeight
|
||||||
int statusBarHeight = getStatusBarHeight();
|
val statusBarHeight = statusBarHeight
|
||||||
int actionBarHeight = getActionBarHeight();
|
val actionBarHeight = actionBarHeight
|
||||||
int combinedBarsHeight = statusBarHeight + actionBarHeight;
|
val combinedBarsHeight = statusBarHeight + actionBarHeight
|
||||||
this.header.setMinHeight(combinedBarsHeight);
|
header!!.minHeight = combinedBarsHeight
|
||||||
this.footer.setMinHeight(bottomInset);
|
footer!!.minHeight = bottomInset
|
||||||
//this.actionBarBlur.invalidate();
|
//this.actionBarBlur.invalidate();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
override fun refreshUI() {
|
||||||
public void refreshUI() {
|
super.refreshUI()
|
||||||
super.refreshUI();
|
this.updateScreenInsets()
|
||||||
this.updateScreenInsets();
|
updateBlurState()
|
||||||
this.updateBlurState();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
override fun onWindowUpdated() {
|
||||||
protected void onWindowUpdated() {
|
this.updateScreenInsets()
|
||||||
this.updateScreenInsets();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void addChip(MarkdownChip markdownChip) {
|
private fun addChip(markdownChip: MarkdownChip) {
|
||||||
this.makeChip(this.getString(markdownChip.title), markdownChip.desc == 0 ? null : this.getString(markdownChip.desc));
|
makeChip(
|
||||||
|
this.getString(markdownChip.title),
|
||||||
|
if (markdownChip.desc == 0) null else this.getString(markdownChip.desc)
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
private void addChip(MarkdownChip markdownChip, String extra) {
|
private fun addChip(markdownChip: MarkdownChip, extra: String) {
|
||||||
String title = this.getString(markdownChip.title);
|
var title = this.getString(markdownChip.title)
|
||||||
if (title.contains("%s")) {
|
title = if (title.contains("%s")) {
|
||||||
title = title.replace("%s", extra);
|
title.replace("%s", extra)
|
||||||
} else {
|
} else {
|
||||||
title = title + " " + extra;
|
"$title $extra"
|
||||||
}
|
}
|
||||||
this.makeChip(title, markdownChip.desc == 0 ? null : this.getString(markdownChip.desc));
|
makeChip(title, if (markdownChip.desc == 0) null else this.getString(markdownChip.desc))
|
||||||
}
|
}
|
||||||
|
|
||||||
private void makeChip(String title, String message) {
|
private fun makeChip(title: String, message: String?) {
|
||||||
final ChipGroup chip_group_holder = findViewById(R.id.chip_group_holder);
|
val chipGroupHolder = findViewById<ChipGroup>(R.id.chip_group_holder)
|
||||||
Chip chip = new Chip(this);
|
val chip = Chip(this)
|
||||||
chip.setText(title);
|
chip.text = title
|
||||||
chip.setVisibility(View.VISIBLE);
|
chip.visibility = View.VISIBLE
|
||||||
if (message != null) {
|
if (message != null) {
|
||||||
chip.setOnClickListener(_view -> {
|
chip.setOnClickListener { _: View? ->
|
||||||
MaterialAlertDialogBuilder builder = new MaterialAlertDialogBuilder(this);
|
val builder = MaterialAlertDialogBuilder(this)
|
||||||
|
builder.setTitle(title).setMessage(message).setCancelable(true)
|
||||||
builder.setTitle(title).setMessage(message).setCancelable(true).setPositiveButton(R.string.ok, (x, y) -> x.dismiss()).show();
|
.setPositiveButton(R.string.ok) { x: DialogInterface, _: Int -> x.dismiss() }
|
||||||
|
.show()
|
||||||
});
|
}
|
||||||
|
}
|
||||||
|
chipGroupHolder.addView(chip)
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun parseAndroidVersion(version: Int): String {
|
||||||
|
return when (version) {
|
||||||
|
Build.VERSION_CODES.JELLY_BEAN -> "4.1 JellyBean"
|
||||||
|
Build.VERSION_CODES.JELLY_BEAN_MR1 -> "4.2 JellyBean"
|
||||||
|
Build.VERSION_CODES.JELLY_BEAN_MR2 -> "4.3 JellyBean"
|
||||||
|
Build.VERSION_CODES.KITKAT -> "4.4 KitKat"
|
||||||
|
Build.VERSION_CODES.KITKAT_WATCH -> "4.4 KitKat Watch"
|
||||||
|
Build.VERSION_CODES.LOLLIPOP -> "5.0 Lollipop"
|
||||||
|
Build.VERSION_CODES.LOLLIPOP_MR1 -> "5.1 Lollipop"
|
||||||
|
Build.VERSION_CODES.M -> "6.0 Marshmallow"
|
||||||
|
Build.VERSION_CODES.N -> "7.0 Nougat"
|
||||||
|
Build.VERSION_CODES.N_MR1 -> "7.1 Nougat"
|
||||||
|
Build.VERSION_CODES.O -> "8.0 Oreo"
|
||||||
|
Build.VERSION_CODES.O_MR1 -> "8.1 Oreo"
|
||||||
|
Build.VERSION_CODES.P -> "9.0 Pie"
|
||||||
|
Build.VERSION_CODES.Q -> "10 (Q)"
|
||||||
|
Build.VERSION_CODES.R -> "11 (R)"
|
||||||
|
Build.VERSION_CODES.S -> "12 (S)"
|
||||||
|
Build.VERSION_CODES.S_V2 -> "12L"
|
||||||
|
Build.VERSION_CODES.TIRAMISU -> "13 Tiramisu"
|
||||||
|
else -> "Sdk: $version"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onResume() {
|
||||||
|
super.onResume()
|
||||||
|
val footer = findViewById<View>(R.id.markdownFooter)
|
||||||
|
if (footer != null) footer.minimumHeight = this.navigationBarHeight
|
||||||
|
}
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
private val redirects = HashMap<String, String>(4)
|
||||||
|
private val variants = arrayOf("readme.md", "README.MD", ".github/README.md")
|
||||||
|
@Throws(IOException::class)
|
||||||
|
private fun getRawMarkdown(url: String): ByteArray {
|
||||||
|
var newUrl = redirects[url]
|
||||||
|
return if (newUrl != null && newUrl != url) {
|
||||||
|
Http.doHttpGet(newUrl, true)
|
||||||
|
} else try {
|
||||||
|
Http.doHttpGet(url, true)
|
||||||
|
} catch (e: IOException) {
|
||||||
|
// Workaround GitHub README.md case sensitivity issue
|
||||||
|
if (url.startsWith("https://raw.githubusercontent.com/") && url.endsWith("/README.md")) {
|
||||||
|
val prefix = url.substring(0, url.length - 9)
|
||||||
|
for (suffix in variants) {
|
||||||
|
newUrl = prefix + suffix
|
||||||
|
try { // Try with lowercase version
|
||||||
|
val rawMarkdown = Http.doHttpGet(prefix + suffix, true)
|
||||||
|
redirects[url] = newUrl // Avoid retries
|
||||||
|
return rawMarkdown
|
||||||
|
} catch (ignored: IOException) {
|
||||||
}
|
}
|
||||||
chip_group_holder.addView(chip);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private String parseAndroidVersion(int version) {
|
|
||||||
return switch (version) {
|
|
||||||
case Build.VERSION_CODES.JELLY_BEAN -> "4.1 JellyBean";
|
|
||||||
case Build.VERSION_CODES.JELLY_BEAN_MR1 -> "4.2 JellyBean";
|
|
||||||
case Build.VERSION_CODES.JELLY_BEAN_MR2 -> "4.3 JellyBean";
|
|
||||||
case Build.VERSION_CODES.KITKAT -> "4.4 KitKat";
|
|
||||||
case Build.VERSION_CODES.KITKAT_WATCH -> "4.4 KitKat Watch";
|
|
||||||
case Build.VERSION_CODES.LOLLIPOP -> "5.0 Lollipop";
|
|
||||||
case Build.VERSION_CODES.LOLLIPOP_MR1 -> "5.1 Lollipop";
|
|
||||||
case Build.VERSION_CODES.M -> "6.0 Marshmallow";
|
|
||||||
case Build.VERSION_CODES.N -> "7.0 Nougat";
|
|
||||||
case Build.VERSION_CODES.N_MR1 -> "7.1 Nougat";
|
|
||||||
case Build.VERSION_CODES.O -> "8.0 Oreo";
|
|
||||||
case Build.VERSION_CODES.O_MR1 -> "8.1 Oreo";
|
|
||||||
case Build.VERSION_CODES.P -> "9.0 Pie";
|
|
||||||
case Build.VERSION_CODES.Q -> "10 (Q)";
|
|
||||||
case Build.VERSION_CODES.R -> "11 (R)";
|
|
||||||
case Build.VERSION_CODES.S -> "12 (S)";
|
|
||||||
case Build.VERSION_CODES.S_V2 -> "12L";
|
|
||||||
case Build.VERSION_CODES.TIRAMISU -> "13 Tiramisu";
|
|
||||||
default -> "Sdk: " + version;
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
|
throw e
|
||||||
@Override
|
}
|
||||||
protected void onResume() {
|
}
|
||||||
super.onResume();
|
|
||||||
View footer = findViewById(R.id.markdownFooter);
|
|
||||||
if (footer != null) footer.setMinimumHeight(this.getNavigationBarHeight());
|
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -1,19 +1,21 @@
|
|||||||
package com.fox2code.mmm.markdown;
|
package com.fox2code.mmm.markdown
|
||||||
|
|
||||||
import androidx.annotation.StringRes;
|
import androidx.annotation.StringRes
|
||||||
|
import com.fox2code.mmm.R
|
||||||
|
|
||||||
import com.fox2code.mmm.R;
|
enum class MarkdownChip(
|
||||||
|
@field:StringRes @param:StringRes val title: Int,
|
||||||
public enum MarkdownChip {
|
@field:StringRes @param:StringRes val desc: Int
|
||||||
CHANGE_BOOT(R.string.module_can_change_boot, R.string.module_can_change_boot_desc),
|
) {
|
||||||
NEED_RAMDISK(R.string.module_needs_ramdisk, R.string.module_needs_ramdisk_desc),
|
CHANGE_BOOT(
|
||||||
MIN_MAGISK(R.string.module_min_magisk_chip, 0),
|
R.string.module_can_change_boot,
|
||||||
MIN_SDK(R.string.module_min_sdk_chip, 0),
|
R.string.module_can_change_boot_desc
|
||||||
MAX_SDK(R.string.module_max_sdk_chip, 0);
|
),
|
||||||
@StringRes public final int title, desc;
|
NEED_RAMDISK(
|
||||||
|
R.string.module_needs_ramdisk, R.string.module_needs_ramdisk_desc
|
||||||
MarkdownChip(@StringRes int title,@StringRes int desc) {
|
),
|
||||||
this.title = title;
|
MIN_MAGISK(R.string.module_min_magisk_chip, 0), MIN_SDK(
|
||||||
this.desc = desc;
|
R.string.module_min_sdk_chip, 0
|
||||||
}
|
),
|
||||||
|
MAX_SDK(R.string.module_max_sdk_chip, 0)
|
||||||
}
|
}
|
@ -1,57 +1,51 @@
|
|||||||
package com.fox2code.mmm.markdown;
|
package com.fox2code.mmm.markdown
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import timber.log.Timber
|
||||||
|
|
||||||
import timber.log.Timber;
|
enum class MarkdownUrlLinker {
|
||||||
|
|
||||||
public enum MarkdownUrlLinker {
|
|
||||||
;
|
;
|
||||||
|
|
||||||
public static String urlLinkify(String url) {
|
private class LinkifyTask(val start: Int, val end: Int) {
|
||||||
int index = url.indexOf("https://");
|
companion object {
|
||||||
if (index == -1)
|
val NULL = LinkifyTask(0, 0)
|
||||||
return url;
|
}
|
||||||
ArrayList<LinkifyTask> linkifyTasks = new ArrayList<>();
|
}
|
||||||
int extra = 0;
|
|
||||||
|
companion object {
|
||||||
|
@JvmStatic
|
||||||
|
fun urlLinkify(url: String): String {
|
||||||
|
var index = url.indexOf("https://")
|
||||||
|
if (index == -1) return url
|
||||||
|
val linkifyTasks = ArrayList<LinkifyTask>()
|
||||||
|
var extra = 0
|
||||||
while (index != -1) {
|
while (index != -1) {
|
||||||
int end = url.indexOf(' ', index);
|
var end = url.indexOf(' ', index)
|
||||||
end = end == -1 ? url.indexOf('\n', index) : Math.min(url.indexOf('\n', index), end);
|
end = if (end == -1) url.indexOf('\n', index) else url.indexOf('\n', index)
|
||||||
if (end == -1)
|
.coerceAtMost(end)
|
||||||
end = url.length();
|
if (end == -1) end = url.length
|
||||||
if (index == 0 || '\n' == url.charAt(index - 1) || ' ' == url.charAt(index - 1)) {
|
if (index == 0 || '\n' == url[index - 1] || ' ' == url[index - 1]) {
|
||||||
int endDomain = url.indexOf('/', index + 9);
|
val endDomain = url.indexOf('/', index + 9)
|
||||||
char endCh = url.charAt(end - 1);
|
val endCh = url[end - 1]
|
||||||
if (endDomain != -1 && endDomain < end && endCh != '>' && endCh != ')' && endCh != ']') {
|
if (endDomain != -1 && endDomain < end && endCh != '>' && endCh != ')' && endCh != ']') {
|
||||||
linkifyTasks.add(new LinkifyTask(index, end));
|
linkifyTasks.add(LinkifyTask(index, end))
|
||||||
extra += (end - index) + 4;
|
extra += end - index + 4
|
||||||
Timber.d("Linkify url: %s", url.substring(end));
|
Timber.d("Linkify url: %s", url.substring(end))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
index = url.indexOf("https://", end);
|
index = url.indexOf("https://", end)
|
||||||
}
|
}
|
||||||
if (linkifyTasks.isEmpty())
|
if (linkifyTasks.isEmpty()) return url
|
||||||
return url;
|
var prev = LinkifyTask.NULL
|
||||||
LinkifyTask prev = LinkifyTask.NULL;
|
val stringBuilder = StringBuilder(url.length + extra)
|
||||||
StringBuilder stringBuilder = new StringBuilder(url.length() + extra);
|
for (linkifyTask in linkifyTasks) {
|
||||||
for (LinkifyTask linkifyTask : linkifyTasks) {
|
stringBuilder.append(url, prev.end, linkifyTask.start).append('[')
|
||||||
stringBuilder.append(url, prev.end, linkifyTask.start).append('[').append(url, linkifyTask.start, linkifyTask.end).append("](").append(url, linkifyTask.start, linkifyTask.end).append(')');
|
.append(url, linkifyTask.start, linkifyTask.end).append("](")
|
||||||
prev = linkifyTask;
|
.append(url, linkifyTask.start, linkifyTask.end).append(')')
|
||||||
|
prev = linkifyTask
|
||||||
}
|
}
|
||||||
if (prev.end != url.length())
|
if (prev.end != url.length) stringBuilder.append(url, prev.end, url.length)
|
||||||
stringBuilder.append(url, prev.end, url.length());
|
Timber.i("Added Markdown link to " + linkifyTasks.size + " urls")
|
||||||
Timber.i("Added Markdown link to " + linkifyTasks.size() + " urls");
|
return stringBuilder.toString()
|
||||||
return stringBuilder.toString();
|
|
||||||
}
|
|
||||||
|
|
||||||
private static class LinkifyTask {
|
|
||||||
static final LinkifyTask NULL = new LinkifyTask(0, 0);
|
|
||||||
|
|
||||||
private final int start;
|
|
||||||
private final int end;
|
|
||||||
|
|
||||||
private LinkifyTask(int start, int end) {
|
|
||||||
this.start = start;
|
|
||||||
this.end = end;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
Loading…
Reference in New Issue