mirror of
https://github.com/gsantner/dandelion
synced 2025-09-09 10:19:42 +02:00
Introduce new markdown parser;
Rework existing md files; Show changelog/update dialog
This commit is contained in:
parent
8d6b09c800
commit
101c5f5b7d
16 changed files with 397 additions and 134 deletions
|
@ -265,9 +265,12 @@ public class AboutActivity extends ThemedActivity
|
|||
final Context context = rootView.getContext();
|
||||
accentColor = Helpers.colorToHex(ThemeHelper.getAccentColor());
|
||||
|
||||
maintainers.setTextFormatted(getString(R.string.fragment_license__maintainers_text, getMaintainersHtml(context)));
|
||||
contributors.setTextFormatted(getString(R.string.fragment_license__contributors_thank_you, getContributorsHtml(context)));
|
||||
thirdPartyLibs.setTextFormatted(getLicense3dPartyHtml(context));
|
||||
maintainers.setTextFormatted(getString(R.string.fragment_license__maintainers_text,
|
||||
Helpers.loadMarkdownFromRawForTextView(context, R.raw.maintainers, "")));
|
||||
contributors.setTextFormatted(getString(R.string.fragment_license__contributors_thank_you,
|
||||
Helpers.loadMarkdownFromRawForTextView(context, R.raw.contributors, "* ")));
|
||||
thirdPartyLibs.setTextFormatted(
|
||||
Helpers.loadMarkdownFromRawForTextView(context, R.raw.license_third_party, ""));
|
||||
return rootView;
|
||||
}
|
||||
|
||||
|
@ -283,25 +286,6 @@ public class AboutActivity extends ThemedActivity
|
|||
}
|
||||
}
|
||||
|
||||
public String getContributorsHtml(Context context) {
|
||||
return Helpers.readTextfileFromRawRessource(context, R.raw.contributors,
|
||||
"<font color='" + accentColor + "'><b>*</b></font> ", "<br>");
|
||||
}
|
||||
|
||||
public String getMaintainersHtml(Context context) {
|
||||
String text = Helpers.readTextfileFromRawRessource(context, R.raw.maintainers, "", "<br>");
|
||||
text = text
|
||||
.replace("NEWENTRY", "<font color='" + accentColor + "'><b>*</b></font> ")
|
||||
.replace("SUBTABBY", " ");
|
||||
return text;
|
||||
}
|
||||
|
||||
public String getLicense3dPartyHtml(Context context) {
|
||||
String text = Helpers.readTextfileFromRawRessource(context, R.raw.license_third_party, "", "<br>");
|
||||
text = text.replace("NEWENTRY", "<font color='" + accentColor + "'><b>*</b></font> ");
|
||||
return text;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void applyColorToViews() {
|
||||
ThemeHelper.getInstance(getAppSettings());
|
||||
|
|
|
@ -76,12 +76,16 @@ import com.github.dfa.diaspora_android.ui.theme.ThemedAlertDialogBuilder;
|
|||
import com.github.dfa.diaspora_android.util.AppLog;
|
||||
import com.github.dfa.diaspora_android.util.AppSettings;
|
||||
import com.github.dfa.diaspora_android.util.DiasporaUrlHelper;
|
||||
import com.github.dfa.diaspora_android.util.Helpers;
|
||||
import com.github.dfa.diaspora_android.util.SimpleMarkdownParser;
|
||||
import com.github.dfa.diaspora_android.web.BrowserFragment;
|
||||
import com.github.dfa.diaspora_android.web.ContextMenuWebView;
|
||||
import com.github.dfa.diaspora_android.web.ProxyHandler;
|
||||
import com.github.dfa.diaspora_android.web.WebHelper;
|
||||
import com.github.dfa.diaspora_android.web.custom_tab.CustomTabActivityHelper;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import butterknife.BindView;
|
||||
import butterknife.ButterKnife;
|
||||
import butterknife.OnClick;
|
||||
|
@ -212,6 +216,30 @@ public class MainActivity extends ThemedActivity
|
|||
openDiasporaUrl(urls.getStreamUrl());
|
||||
}
|
||||
}
|
||||
|
||||
// Show first start dialog
|
||||
try {
|
||||
if (appSettings.isAppFirstStart()) {
|
||||
SimpleMarkdownParser smp = new SimpleMarkdownParser().parse(
|
||||
getResources().openRawResource(R.raw.license),
|
||||
SimpleMarkdownParser.FILTER_ANDROID_TEXTVIEW, "");
|
||||
String html = smp.getHtml()
|
||||
+ "<br/><br/><br/>"
|
||||
+ "<h1>" + getString(R.string.fragment_license__thirdparty_libs) + "</h1>"
|
||||
+ smp.parse(getResources().openRawResource(R.raw.license_third_party),
|
||||
SimpleMarkdownParser.FILTER_ANDROID_TEXTVIEW, "");
|
||||
html = smp.setHtml(html).removeMultiNewlines().getHtml();
|
||||
Helpers.showDialogWithHtmlTextView(this, html, R.string.about_activity__title_about_license);
|
||||
appSettings.isAppCurrentVersionFirstStart();
|
||||
} else if (appSettings.isAppCurrentVersionFirstStart()) {
|
||||
SimpleMarkdownParser smp = new SimpleMarkdownParser().parse(
|
||||
getResources().openRawResource(R.raw.changelog),
|
||||
SimpleMarkdownParser.FILTER_ANDROID_TEXTVIEW, "");
|
||||
Helpers.showDialogWithHtmlTextView(this, smp.getHtml(), R.string.changelog);
|
||||
}
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -244,14 +272,14 @@ public class MainActivity extends ThemedActivity
|
|||
moveTaskToBack(true);
|
||||
}
|
||||
});
|
||||
snackbarLastVisitedTimestampInStream =
|
||||
Snackbar.make(fragmentContainer,
|
||||
R.string.jump_to_last_visited_timestamp_in_stream, Snackbar.LENGTH_LONG)
|
||||
.setAction(android.R.string.yes, new View.OnClickListener() {
|
||||
public void onClick(View view) {
|
||||
openDiasporaUrl(urls.getStreamWithTimestampUrl(diasporaUserProfile.getLastVisitedPositionInStream()));
|
||||
}
|
||||
});
|
||||
snackbarLastVisitedTimestampInStream =
|
||||
Snackbar.make(fragmentContainer,
|
||||
R.string.jump_to_last_visited_timestamp_in_stream, Snackbar.LENGTH_LONG)
|
||||
.setAction(android.R.string.yes, new View.OnClickListener() {
|
||||
public void onClick(View view) {
|
||||
openDiasporaUrl(urls.getStreamWithTimestampUrl(diasporaUserProfile.getLastVisitedPositionInStream()));
|
||||
}
|
||||
});
|
||||
snackbarNoInternet = Snackbar.make(fragmentContainer, R.string.no_internet, Snackbar.LENGTH_LONG);
|
||||
|
||||
// Load app settings
|
||||
|
@ -392,8 +420,7 @@ public class MainActivity extends ThemedActivity
|
|||
app.getAvatarImageLoader().startImageDownload(navheaderImage, avatarUrl);
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (BuildConfig.IS_TEST_BUILD){
|
||||
} else if (BuildConfig.IS_TEST_BUILD) {
|
||||
navheaderImage.setImageResource(R.drawable.ic_launcher_test);
|
||||
}
|
||||
updateNavigationViewEntryVisibilities();
|
||||
|
|
|
@ -122,7 +122,7 @@ public class AppSettings {
|
|||
return pref.getString(context.getString(ressourceId), context.getString(ressourceIdDefaultValue));
|
||||
}
|
||||
|
||||
private boolean getBoolean(SharedPreferences pref, int ressourceId, boolean defaultValue) {
|
||||
private boolean getBool(SharedPreferences pref, int ressourceId, boolean defaultValue) {
|
||||
return pref.getBoolean(context.getString(ressourceId), defaultValue);
|
||||
}
|
||||
|
||||
|
@ -164,7 +164,7 @@ public class AppSettings {
|
|||
}
|
||||
|
||||
public boolean isLoadImages() {
|
||||
return getBoolean(prefApp, R.string.pref_key__load_images, true);
|
||||
return getBool(prefApp, R.string.pref_key__load_images, true);
|
||||
}
|
||||
|
||||
public int getMinimumFontSize() {
|
||||
|
@ -277,7 +277,7 @@ public class AppSettings {
|
|||
}
|
||||
|
||||
public boolean isAppendSharedViaApp() {
|
||||
return getBoolean(prefApp, R.string.pref_key__append_shared_via_app, true);
|
||||
return getBool(prefApp, R.string.pref_key__append_shared_via_app, true);
|
||||
}
|
||||
|
||||
@SuppressLint("CommitPrefEdits")
|
||||
|
@ -293,7 +293,7 @@ public class AppSettings {
|
|||
*/
|
||||
public boolean isProxyHttpEnabled() {
|
||||
try {
|
||||
return getBoolean(prefApp, R.string.pref_key__http_proxy_enabled, false);
|
||||
return getBool(prefApp, R.string.pref_key__http_proxy_enabled, false);
|
||||
} catch (ClassCastException e) {
|
||||
setProxyHttpEnabled(false);
|
||||
return false;
|
||||
|
@ -301,7 +301,7 @@ public class AppSettings {
|
|||
}
|
||||
|
||||
public boolean wasProxyEnabled() {
|
||||
return getBoolean(prefApp, R.string.pref_key__proxy_was_enabled, false);
|
||||
return getBool(prefApp, R.string.pref_key__proxy_was_enabled, false);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -353,81 +353,92 @@ public class AppSettings {
|
|||
}
|
||||
|
||||
public boolean isIntellihideToolbars() {
|
||||
return getBoolean(prefApp, R.string.pref_key__intellihide_toolbars, true);
|
||||
return getBool(prefApp, R.string.pref_key__intellihide_toolbars, true);
|
||||
}
|
||||
|
||||
public boolean isChromeCustomTabsEnabled() {
|
||||
return getBoolean(prefApp, R.string.pref_key__chrome_custom_tabs_enabled, true);
|
||||
return getBool(prefApp, R.string.pref_key__chrome_custom_tabs_enabled, true);
|
||||
}
|
||||
|
||||
public boolean isLoggingEnabled() {
|
||||
return getBoolean(prefApp, R.string.pref_key__logging_enabled, false);
|
||||
return getBool(prefApp, R.string.pref_key__logging_enabled, false);
|
||||
}
|
||||
|
||||
public boolean isLoggingSpamEnabled() {
|
||||
return getBoolean(prefApp, R.string.pref_key__logging_spam_enabled, false);
|
||||
return getBool(prefApp, R.string.pref_key__logging_spam_enabled, false);
|
||||
}
|
||||
|
||||
public boolean isVisibleInNavExit() {
|
||||
return getBoolean(prefApp, R.string.pref_key__visibility_nav__exit, false);
|
||||
return getBool(prefApp, R.string.pref_key__visibility_nav__exit, false);
|
||||
}
|
||||
|
||||
public boolean isVisibleInNavHelp_license() {
|
||||
return getBoolean(prefApp, R.string.pref_key__visibility_nav__help_license, true);
|
||||
return getBool(prefApp, R.string.pref_key__visibility_nav__help_license, true);
|
||||
}
|
||||
|
||||
public boolean isVisibleInNavPublic_activities() {
|
||||
return getBoolean(prefApp, R.string.pref_key__visibility_nav__public_activities, false);
|
||||
return getBool(prefApp, R.string.pref_key__visibility_nav__public_activities, false);
|
||||
}
|
||||
|
||||
public boolean isVisibleInNavMentions() {
|
||||
return getBoolean(prefApp, R.string.pref_key__visibility_nav__mentions, false);
|
||||
return getBool(prefApp, R.string.pref_key__visibility_nav__mentions, false);
|
||||
}
|
||||
|
||||
public boolean isVisibleInNavCommented() {
|
||||
return getBoolean(prefApp, R.string.pref_key__visibility_nav__commented, true);
|
||||
return getBool(prefApp, R.string.pref_key__visibility_nav__commented, true);
|
||||
}
|
||||
|
||||
public boolean isVisibleInNavLiked() {
|
||||
return getBoolean(prefApp, R.string.pref_key__visibility_nav__liked, true);
|
||||
return getBool(prefApp, R.string.pref_key__visibility_nav__liked, true);
|
||||
}
|
||||
|
||||
public boolean isVisibleInNavActivities() {
|
||||
return getBoolean(prefApp, R.string.pref_key__visibility_nav__activities, true);
|
||||
return getBool(prefApp, R.string.pref_key__visibility_nav__activities, true);
|
||||
}
|
||||
|
||||
public boolean isVisibleInNavAspects() {
|
||||
return getBoolean(prefApp, R.string.pref_key__visibility_nav__aspects, true);
|
||||
return getBool(prefApp, R.string.pref_key__visibility_nav__aspects, true);
|
||||
}
|
||||
|
||||
public boolean isVisibleInNavFollowed_tags() {
|
||||
return getBoolean(prefApp, R.string.pref_key__visibility_nav__followed_tags, true);
|
||||
return getBool(prefApp, R.string.pref_key__visibility_nav__followed_tags, true);
|
||||
}
|
||||
|
||||
public boolean isVisibleInNavProfile() {
|
||||
return getBoolean(prefApp, R.string.pref_key__visibility_nav__profile, true);
|
||||
return getBool(prefApp, R.string.pref_key__visibility_nav__profile, true);
|
||||
}
|
||||
|
||||
public boolean isVisibleInNavContacts() {
|
||||
return getBoolean(prefApp, R.string.pref_key__visibility_nav__contacts, false);
|
||||
return getBool(prefApp, R.string.pref_key__visibility_nav__contacts, false);
|
||||
}
|
||||
|
||||
public boolean isVisibleInNavReports() {
|
||||
return getBoolean(prefApp, R.string.pref_key__visibility_nav__reports, false);
|
||||
return getBool(prefApp, R.string.pref_key__visibility_nav__reports, false);
|
||||
}
|
||||
|
||||
public boolean isVisibleToggleMobileDesktop() {
|
||||
return getBoolean(prefApp, R.string.pref_key__visibility_nav__toggle_mobile_desktop, false);
|
||||
return getBool(prefApp, R.string.pref_key__visibility_nav__toggle_mobile_desktop, false);
|
||||
}
|
||||
|
||||
public boolean isTopbarStreamShortcutEnabled() {
|
||||
return getBoolean(prefApp, R.string.pref_key__topbar_stream_shortcut, false);
|
||||
return getBool(prefApp, R.string.pref_key__topbar_stream_shortcut, false);
|
||||
}
|
||||
|
||||
public String getScreenRotation() {
|
||||
return getString(prefApp, R.string.pref_key__screen_rotation, R.string.rotation_val_system);
|
||||
}
|
||||
|
||||
public boolean isAppFirstStart(){
|
||||
boolean value = getBool(prefApp, R.string.pref_key__app_first_start, true);
|
||||
setBool(prefApp, R.string.pref_key__app_first_start, false);
|
||||
return value;
|
||||
}
|
||||
|
||||
public boolean isAppCurrentVersionFirstStart(){
|
||||
int value = getInt(prefApp, R.string.pref_key__app_first_start_current_version, -1);
|
||||
setInt(prefApp, R.string.pref_key__app_first_start_current_version, BuildConfig.VERSION_CODE);
|
||||
return value != BuildConfig.VERSION_CODE && !BuildConfig.IS_TEST_BUILD;
|
||||
}
|
||||
|
||||
public long getLastVisitedPositionInStream() {
|
||||
return getLong(prefPod, R.string.pref_key__podprofile_last_stream_position, -1);
|
||||
|
@ -479,6 +490,6 @@ public class AppSettings {
|
|||
}
|
||||
|
||||
public boolean isExtendedNotificationsActivated() {
|
||||
return getBoolean(prefApp, R.string.pref_key__extended_notifications, false);
|
||||
return getBool(prefApp, R.string.pref_key__extended_notifications, false);
|
||||
}
|
||||
}
|
|
@ -18,7 +18,6 @@
|
|||
*/
|
||||
package com.github.dfa.diaspora_android.util;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.content.res.Resources;
|
||||
|
@ -26,11 +25,21 @@ import android.net.Uri;
|
|||
import android.os.Build;
|
||||
import android.os.Bundle;
|
||||
import android.os.Environment;
|
||||
import android.support.annotation.RawRes;
|
||||
import android.support.annotation.StringRes;
|
||||
import android.support.design.widget.Snackbar;
|
||||
import android.support.v4.content.ContextCompat;
|
||||
import android.support.v7.app.AlertDialog;
|
||||
import android.text.Html;
|
||||
import android.text.SpannableString;
|
||||
import android.text.TextUtils;
|
||||
import android.text.method.LinkMovementMethod;
|
||||
import android.util.TypedValue;
|
||||
import android.view.View;
|
||||
import android.widget.LinearLayout;
|
||||
import android.widget.ScrollView;
|
||||
import android.widget.TextView;
|
||||
|
||||
import com.github.dfa.diaspora_android.App;
|
||||
import com.github.dfa.diaspora_android.R;
|
||||
import com.github.dfa.diaspora_android.web.WebHelper;
|
||||
|
||||
|
@ -44,17 +53,6 @@ import java.util.Date;
|
|||
import java.util.Locale;
|
||||
|
||||
public class Helpers {
|
||||
|
||||
public static void animateToActivity(Activity from, Class to, boolean finishFromActivity) {
|
||||
Intent intent = new Intent(from, to);
|
||||
intent.addFlags(Intent.FLAG_ACTIVITY_NO_ANIMATION);
|
||||
from.startActivity(intent);
|
||||
from.overridePendingTransition(R.anim.fadein, R.anim.fadeout);
|
||||
if (finishFromActivity) {
|
||||
from.finish();
|
||||
}
|
||||
}
|
||||
|
||||
public static int getColorFromRessource(Context context, int ressourceId) {
|
||||
Resources res = context.getResources();
|
||||
if (Build.VERSION.SDK_INT >= 23) {
|
||||
|
@ -64,14 +62,6 @@ public class Helpers {
|
|||
}
|
||||
}
|
||||
|
||||
public static void loadUrlInExternalBrowser(Context context, String url) {
|
||||
try {
|
||||
Intent browserIntent = new Intent(Intent.ACTION_VIEW, Uri.parse(url));
|
||||
context.startActivity(browserIntent);
|
||||
} catch (Exception ignored) {
|
||||
}
|
||||
}
|
||||
|
||||
public static File createImageFile() throws IOException {
|
||||
// Create an image file name
|
||||
String timeStamp = new SimpleDateFormat("dd-MM-yy_HH-mm", Locale.getDefault()).format(new Date());
|
||||
|
@ -123,8 +113,41 @@ public class Helpers {
|
|||
return sb.toString();
|
||||
}
|
||||
|
||||
public static String hexColorFromRessourceColor(Context context, int idColor) {
|
||||
return "#" + Integer.toHexString(context.getResources().getColor(idColor) & 0x00ffffff);
|
||||
public static String loadMarkdownFromRawForTextView(Context context, @RawRes int rawMdFile, String prepend) {
|
||||
try {
|
||||
return new SimpleMarkdownParser()
|
||||
.parse(context.getResources().openRawResource(rawMdFile),
|
||||
SimpleMarkdownParser.FILTER_ANDROID_TEXTVIEW, prepend)
|
||||
.replaceColor("#000001", ContextCompat.getColor(context, R.color.accent))
|
||||
.removeMultiNewlines().replaceBulletCharacter("*").getHtml();
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
return "";
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public static void showDialogWithHtmlTextView(Context context, String html, @StringRes int resTitleId) {
|
||||
LinearLayout layout = new LinearLayout(context);
|
||||
TextView textView = new TextView(context);
|
||||
textView.setMovementMethod(LinkMovementMethod.getInstance());
|
||||
ScrollView root = new ScrollView(context);
|
||||
int margin = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 20,
|
||||
context.getResources().getDisplayMetrics());
|
||||
LinearLayout.LayoutParams layoutParams = new LinearLayout.LayoutParams(
|
||||
LinearLayout.LayoutParams.MATCH_PARENT, LinearLayout.LayoutParams.MATCH_PARENT);
|
||||
layoutParams.setMargins(margin, 0, margin, 0);
|
||||
layout.setLayoutParams(layoutParams);
|
||||
|
||||
layout.addView(textView);
|
||||
root.addView(layout);
|
||||
|
||||
textView.setText(new SpannableString(Html.fromHtml(html)));
|
||||
AlertDialog.Builder dialog = new AlertDialog.Builder(context)
|
||||
.setPositiveButton(android.R.string.ok, null)
|
||||
.setTitle(resTitleId)
|
||||
.setView(root);
|
||||
dialog.show();
|
||||
}
|
||||
|
||||
public static String colorToHex(int color) {
|
||||
|
|
|
@ -0,0 +1,202 @@
|
|||
/*
|
||||
* ----------------------------------------------------------------------------
|
||||
* "THE COKE-WARE LIBRARY LICENSE" (Revision 255):
|
||||
* Gregor Santner <gsantner.github.io> wrote this file. You can do whatever
|
||||
* you want with this stuff. If we meet some day, and you think this stuff is
|
||||
* worth it, you can buy me a coke in return. Provided as is without any kind
|
||||
* of warranty. No attribution required. - Gregor Santner
|
||||
* ----------------------------------------------------------------------------
|
||||
*/
|
||||
package com.github.dfa.diaspora_android.util;
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.InputStreamReader;
|
||||
|
||||
/**
|
||||
* Simple Markdown Parser
|
||||
* <p>
|
||||
* Parses most common markdown tags. Only inline tags are supported, multiline/block syntax
|
||||
* is not supported (citation, multiline code, ..). This is intended to stay as easy as possible.
|
||||
* <p>
|
||||
* You can e.g. apply a accent color by replacing #000001 with your accentColor string.
|
||||
* <p>
|
||||
* FILTER_ANDROID_TEXTVIEW output is intended to be used at simple Android TextViews,
|
||||
* were a limited set of html tags is supported. This allow to still display e.g. a simple
|
||||
* CHANGELOG.md file without inlcuding a WebView for showing HTML, or other additional UI-libraries.
|
||||
* <p>
|
||||
* FILTER_HTMLPART is intended to be used at engines understanding most common HTML tags.
|
||||
* <p>
|
||||
* You can use this anywhere you want, no backlink/attribution required, but I would appreciate it.
|
||||
*/
|
||||
@SuppressWarnings({"WeakerAccess", "CaughtExceptionImmediatelyRethrown"})
|
||||
public class SimpleMarkdownParser {
|
||||
public interface SimpleLineFilter {
|
||||
String filterLine(String line);
|
||||
}
|
||||
|
||||
public static final SimpleLineFilter FILTER_ANDROID_TEXTVIEW = new SimpleLineFilter() {
|
||||
@Override
|
||||
public String filterLine(String line) {
|
||||
// TextView supports a limited set of html tags, most notably
|
||||
// a href, b, big, font size&color, i, li, small, u
|
||||
line = line
|
||||
.replace("~°", " ") // double space/half tab
|
||||
.replaceAll("^### ([^<]*)", "<br/><big><b><font color='#000000'>$1</font></b></big> ") // h3
|
||||
.replaceAll("^## ([^<]*)", "<br/><big><big><b><font color='#000000'>$1</font></b></big></big><br/> ") // h2 (DEP: h3)
|
||||
.replaceAll("^# ([^<]*)", "<br/><big><big><big><b><font color='#000000'>$1</font></b></big></big></big><br/> ") // h1 (DEP: h2,h3)
|
||||
.replaceAll("!\\[(.*?)\\]\\((.*?)\\)", "<a href=\\'$2\\'>$1</a>") // img
|
||||
.replaceAll("\\[(.*?)\\]\\((.*?)\\)", "<a href=\\'$2\\'>$1</a>") // a href (DEP: img)
|
||||
.replaceAll("<(http|https):\\/\\/(.*)>", "<a href='$1://$2'>$1://$2</a>") // a href (DEP: img)
|
||||
.replaceAll("^(-|\\*) ([^<]*)", "<font color='#000001'>•</font> $2 ") // unordered list + end line
|
||||
.replaceAll("^ (-|\\*) ([^<]*)", " <font color='#000001'>•</font> $2 ") // unordered list2 + end line
|
||||
.replaceAll("`([^<]*)`", "<font face='monospace'>$1</font>") // code
|
||||
.replace("\\*", "●") // temporary replace escaped star symbol
|
||||
.replaceAll("\\*\\*([^<]*)\\*\\*", "<b>$1</b>") // bold (DEP: temp star)
|
||||
.replaceAll("\\*([^<]*)\\*", "<i>$1</i>") // italic (DEP: temp star code)
|
||||
.replace("●", "*") // restore escaped star symbol (DEP: b,i)
|
||||
.replaceAll(" $", "<br/>") // new line (DEP: ul)
|
||||
;
|
||||
return line.isEmpty() ? line + "<br/>" : line;
|
||||
}
|
||||
};
|
||||
|
||||
public static final SimpleLineFilter FILTER_HTMLPART = new SimpleLineFilter() {
|
||||
@Override
|
||||
public String filterLine(String line) {
|
||||
line = line
|
||||
.replaceAll("~°", " ") // double space/half tab
|
||||
.replaceAll("^### ([^<]*)", "<h3>$1</h3>") // h3
|
||||
.replaceAll("^## ([^<]*)", "<h2>$1</h2>") /// h2 (DEP: h3)
|
||||
.replaceAll("^# ([^<]*)", "<h1>$1</h1>") // h1 (DEP: h2,h3)
|
||||
.replaceAll("!\\[(.*?)\\]\\((.*?)\\)", "<img src=\\'$2\\' alt='$1' />") // img
|
||||
.replaceAll("<(http|https):\\/\\/(.*)>", "<a href='$1://$2'>$1://$2</a>") // a href (DEP: img)
|
||||
.replaceAll("\\[(.*?)\\]\\((.*?)\\)", "<a href=\\'$2\\'>$1</a>") // a href (DEP: img)
|
||||
.replaceAll("^(-|\\*) ([^<]*)", "<font color='#000001'>•</font> $2 ") // unordered list + end line
|
||||
.replaceAll("^ (-|\\*) ([^<]*)", " <font color='#000001'>•</font> $2 ") // unordered list2 + end line
|
||||
.replaceAll("`([^<]*)`", "<code>$1</code>") // code
|
||||
.replace("\\*", "●") // temporary replace escaped star symbol
|
||||
.replaceAll("\\*\\*([^<]*)\\*\\*", "<b>$1</b>") // bold (DEP: temp star)
|
||||
.replaceAll("\\*([^<]*)\\*", "<b>$1</b>") // italic (DEP: temp star)
|
||||
.replace("●", "*") // restore escaped star symbol (DEP: b,i)
|
||||
.replaceAll(" $", "<br/>") // new line (DEP: ul)
|
||||
;
|
||||
return line.isEmpty() ? line + "<br/>" : line;
|
||||
}
|
||||
};
|
||||
|
||||
//########################
|
||||
//##
|
||||
//## Members
|
||||
//##
|
||||
//########################
|
||||
private String html;
|
||||
|
||||
public SimpleMarkdownParser parse(String filepath, SimpleLineFilter simpleLineFilter) throws IOException {
|
||||
return parse(new FileInputStream(filepath), simpleLineFilter, "");
|
||||
}
|
||||
|
||||
public SimpleMarkdownParser parse(InputStream inputStream, SimpleLineFilter simpleLineFilter, String lineMdPrefix) throws IOException {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
BufferedReader br = null;
|
||||
String line;
|
||||
|
||||
try {
|
||||
br = new BufferedReader(new InputStreamReader(inputStream));
|
||||
while ((line = br.readLine()) != null) {
|
||||
sb.append(simpleLineFilter.filterLine(lineMdPrefix + line));
|
||||
sb.append("\n");
|
||||
}
|
||||
} catch (IOException rethrow) {
|
||||
html = "";
|
||||
throw rethrow;
|
||||
} finally {
|
||||
if (br != null) {
|
||||
try {
|
||||
br.close();
|
||||
} catch (IOException ignored) {
|
||||
}
|
||||
}
|
||||
}
|
||||
html = sb.toString().trim();
|
||||
return this;
|
||||
}
|
||||
|
||||
public String getHtml() {
|
||||
return html;
|
||||
}
|
||||
|
||||
public SimpleMarkdownParser setHtml(String html) {
|
||||
this.html = html;
|
||||
return this;
|
||||
}
|
||||
|
||||
public SimpleMarkdownParser removeMultiNewlines() {
|
||||
html = html.replace("\n", "").replaceAll("(<br/>){3,}", "<br/><br/>");
|
||||
return this;
|
||||
}
|
||||
|
||||
public SimpleMarkdownParser replaceBulletCharacter(String replacment) {
|
||||
html = html.replace("•", replacment);
|
||||
return this;
|
||||
}
|
||||
|
||||
public SimpleMarkdownParser replaceColor(String hexColor, int newIntColor) {
|
||||
html = html.replace(hexColor, colorToHexString(newIntColor));
|
||||
return this;
|
||||
}
|
||||
|
||||
public static String colorToHexString(int intColor) {
|
||||
return String.format("#%06X", 0xFFFFFF & intColor);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return html != null ? html : "";
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
// Apply to Android TextView:
|
||||
textView.setText(new SpannableString(Html.fromHtml(htmlFromParser)));
|
||||
|
||||
// As wrapper method, includes applying accent color
|
||||
public static String loadMarkdownFromRawForTextView(Context context, @RawRes int rawMdFile, String prepend) {
|
||||
try {
|
||||
return new SimpleMarkdownParser()
|
||||
.parse(context.getResources().openRawResource(rawMdFile),
|
||||
SimpleMarkdownParser.FILTER_ANDROID_TEXTVIEW, prepend)
|
||||
.replaceColor("#000001", ContextCompat.getColor(context, R.color.accent))
|
||||
.removeMultiNewlines().replaceBulletCharacter("*").getHtml();
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
return "";
|
||||
}
|
||||
}
|
||||
|
||||
// Show HTML a TextView in a scrollable Dialog
|
||||
public static void showDialogWithHtmlTextView(Context context, String html, @StringRes int resTitleId) {
|
||||
LinearLayout layout = new LinearLayout(context);
|
||||
TextView textView = new TextView(context);
|
||||
textView.setMovementMethod(LinkMovementMethod.getInstance());
|
||||
ScrollView root = new ScrollView(context);
|
||||
int margin = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 20,
|
||||
context.getResources().getDisplayMetrics());
|
||||
LinearLayout.LayoutParams layoutParams = new LinearLayout.LayoutParams(
|
||||
LinearLayout.LayoutParams.MATCH_PARENT, LinearLayout.LayoutParams.MATCH_PARENT);
|
||||
layoutParams.setMargins(margin, 0, margin, 0);
|
||||
layout.setLayoutParams(layoutParams);
|
||||
|
||||
layout.addView(textView);
|
||||
root.addView(layout);
|
||||
|
||||
textView.setText(new SpannableString(Html.fromHtml(html)));
|
||||
AlertDialog.Builder dialog = new AlertDialog.Builder(context)
|
||||
.setPositiveButton(android.R.string.ok, null)
|
||||
.setTitle(resTitleId)
|
||||
.setView(root);
|
||||
dialog.show();
|
||||
}
|
||||
*/
|
14
app/src/main/res/raw/license_third_party.md
Normal file
14
app/src/main/res/raw/license_third_party.md
Normal file
|
@ -0,0 +1,14 @@
|
|||
* NetCipher
|
||||
<https://github.com/guardianproject/NetCipher>
|
||||
|
||||
* ButterKnife
|
||||
<https://jakewharton.github.io/butterknife>
|
||||
|
||||
* ShiftColorPicker
|
||||
<https://github.com/DASAR/ShiftColorPicker>
|
||||
|
||||
* Android Support Library
|
||||
<https://developer.android.com/topic/libraries/support-library/index.html>
|
||||
|
||||
* Android Design Library
|
||||
<https://android-developers.blogspot.de/2015/05/android-design-support-library.html>
|
|
@ -1,14 +0,0 @@
|
|||
NEWENTRY NetCipher
|
||||
https://github.com/guardianproject/NetCipher
|
||||
|
||||
NEWENTRY ButterKnife
|
||||
https://jakewharton.github.io/butterknife
|
||||
|
||||
NEWENTRY ShiftColorPicker
|
||||
https://github.com/DASAR/ShiftColorPicker
|
||||
|
||||
NEWENTRY Android Support Library
|
||||
https://developer.android.com/topic/libraries/support-library/index.html
|
||||
|
||||
NEWENTRY Android Design Library
|
||||
https://android-developers.blogspot.de/2015/05/android-design-support-library.html
|
5
app/src/main/res/raw/maintainers.md
Normal file
5
app/src/main/res/raw/maintainers.md
Normal file
|
@ -0,0 +1,5 @@
|
|||
* Gregor Santner (gsantner)
|
||||
~° https://gsantner.github.io
|
||||
|
||||
* Paul Schaub (vanitasvitae)
|
||||
~° https://github.com/vanitasvitae
|
|
@ -1,5 +0,0 @@
|
|||
NEWENTRY Gregor Santner (gsantner)
|
||||
SUBTABBY https://gsantner.github.io
|
||||
|
||||
NEWENTRY Paul Schaub (vanitasvitae)
|
||||
SUBTABBY https://github.com/vanitasvitae
|
|
@ -15,6 +15,8 @@
|
|||
<string name="pref_key__http_proxy_load_tor_preset" translatable="false">pref_key__http_proxy_load_tor_preset</string>
|
||||
<string name="pref_key__extended_notifications" translatable="false">pref_key__extended_notifications</string>
|
||||
<string name="pref_key__topbar_stream_shortcut" translatable="false">pref_key__topbar_stream_shortcut</string>
|
||||
<string name="pref_key__app_first_start" translatable="false">pref_key__app_first_start</string>
|
||||
<string name="pref_key__app_first_start_current_version" translatable="false">pref_key__app_first_start_current_version</string>
|
||||
|
||||
<!-- Themes -->
|
||||
<string name="pref_key__primary_color__preference_click" translatable="false">@string/pref_key__primary_color_shade</string>
|
||||
|
|
|
@ -27,6 +27,7 @@
|
|||
<string name="public_">Public</string>
|
||||
<string name="search">Search</string>
|
||||
<string name="contacts">Contacts</string>
|
||||
<string name="changelog">Changelog</string>
|
||||
<string name="tor" translatable="false">Tor</string>
|
||||
|
||||
<!-- Notifications dropdown menu -->
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue