fixed github readme rendering while fixing image urls and href urls, the content might get currepted.

This commit is contained in:
Kosh 2017-02-23 20:38:24 +08:00
parent 5a18922999
commit 40a22d8dd2
20 changed files with 210 additions and 97 deletions

View File

@ -99,7 +99,6 @@ dependencies {
compile 'com.jakewharton:butterknife:8.4.0'
compile 'frankiesardo:icepick:3.1.0'
compile 'it.sephiroth.android.library.bottomnavigation:bottom-navigation:1.0.7'
compile 'pub.devrel:easypermissions:0.2.1'
compile 'io.reactivex:rxandroid:1.2.1'
compile 'io.reactivex:rxjava:1.2.2'
compile "com.squareup.retrofit2:retrofit:${retrofit}"
@ -108,6 +107,7 @@ dependencies {
compile 'com.squareup.okhttp3:logging-interceptor:3.3.1'
compile 'com.annimon:stream:1.1.4'
compile 'com.commonsware.cwac:anddown:0.3.0'
compile 'com.tapadoo.android:alerter:1.0.1'
provided "org.projectlombok:lombok:1.12.6"
apt "org.projectlombok:lombok:1.12.6"
apt 'frankiesardo:icepick-processor:3.1.0'

View File

@ -1,6 +1,7 @@
<?xml version="1.0" encoding="utf-8"?>
<manifest package="com.fastaccess"
xmlns:android="http://schemas.android.com/apk/res/android">
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools">
<uses-permission android:name="android.permission.INTERNET"/>
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
@ -14,7 +15,8 @@
android:label="@string/app_name"
android:roundIcon="@mipmap/ic_launcher"
android:supportsRtl="true"
android:theme="@style/AppTheme">
android:theme="@style/AppTheme"
tools:replace="android:allowBackup">
<activity
android:name="com.fastaccess.ui.modules.main.MainView">
<intent-filter>

View File

@ -27,8 +27,9 @@ public class NameParser {
if (segments == null || segments.size() < 2) {
return;
}
this.name = segments.get(1);
this.username = segments.get(0);
boolean isFirstPathIsRepo = (segments.get(0).equalsIgnoreCase("repos") || segments.get(0).equalsIgnoreCase("repo"));
this.username = isFirstPathIsRepo ? segments.get(1) : segments.get(0);
this.name = isFirstPathIsRepo ? segments.get(2) : segments.get(1);
}
}

View File

@ -16,4 +16,8 @@ public class PrefGetter {
public static String getToken() {
return PrefHelper.getString(TOKEN);
}
public static void clear() {
PrefHelper.clearPrefs();
}
}

View File

@ -84,7 +84,7 @@ public class NotificationJobTask extends JobService {
Notification notification = new NotificationCompat.Builder(context)
.setSmallIcon(R.drawable.ic_announcement)
.setContentTitle(context.getString(R.string.notifictions))
.setContentText(context.getString(R.string.unread_notification))
.setContentText(context.getString(R.string.unread_notification) + " (" + count + ")")
.setNumber((int) count)
.addAction(R.drawable.ic_github, context.getString(R.string.open), PendingIntent.getActivity(context, 0, new Intent(),
PendingIntent.FLAG_UPDATE_CURRENT))

View File

@ -7,12 +7,10 @@ import android.support.annotation.LayoutRes;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.support.annotation.StringRes;
import android.support.v4.app.Fragment;
import android.support.v7.widget.Toolbar;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.widget.Toast;
import com.fastaccess.BuildConfig;
import com.fastaccess.R;
@ -24,8 +22,8 @@ import com.fastaccess.helper.ViewHelper;
import com.fastaccess.ui.base.mvp.BaseMvp;
import com.fastaccess.ui.base.mvp.presenter.BasePresenter;
import com.fastaccess.ui.modules.login.LoginView;
import com.fastaccess.ui.widgets.dialog.MessageDialogView;
import com.fastaccess.ui.widgets.dialog.ProgressDialogFragment;
import com.tapadoo.alerter.Alerter;
import net.grandcentrix.thirtyinch.TiActivity;
@ -41,8 +39,6 @@ import icepick.State;
public abstract class BaseActivity<V extends BaseMvp.FAView, P extends BasePresenter<V>> extends TiActivity<P, V> implements
BaseMvp.FAView {
private Toast toast;
@State boolean isProgressShowing;
@Nullable @BindView(R.id.toolbar) Toolbar toolbar;
@Nullable @BindView(R.id.toolbarShadow) View shadowView;
@ -111,23 +107,12 @@ public abstract class BaseActivity<V extends BaseMvp.FAView, P extends BasePrese
@Override public void showMessage(@NonNull String titleRes, @NonNull String msgRes) {
hideProgress();
if (!isFinishing()) {
try {
getSupportFragmentManager().executePendingTransactions();
Fragment fragment = AppHelper.getFragmentByTag(getSupportFragmentManager(), "BaseActivity");
if (fragment == null) {
MessageDialogView.newInstance(titleRes, msgRes).show(getSupportFragmentManager(), "BaseActivity");
} else {
MessageDialogView messageDialogView = (MessageDialogView) fragment;
messageDialogView.setArguments(MessageDialogView.getBundle(titleRes, msgRes, false, null));
messageDialogView.initMessage();
}
return;
} catch (Exception ignored) {}
}
if (toast != null) toast.cancel();
toast = Toast.makeText(this, msgRes, Toast.LENGTH_LONG);
toast.show();
Alerter.create(this)
.setTitle(titleRes)
.setText(msgRes)
.setBackgroundColor(titleRes.equals(getString(R.string.success)) ? R.color.material_green_700 : R.color.material_orange_700)
.show();
}
@Override public void showErrorMessage(@NonNull String msgRes) {

View File

@ -3,6 +3,7 @@ package com.fastaccess.ui.modules.login;
import android.content.Intent;
import android.os.Bundle;
import android.support.annotation.NonNull;
import android.webkit.CookieManager;
import android.webkit.WebChromeClient;
import android.webkit.WebView;
import android.webkit.WebViewClient;
@ -58,6 +59,7 @@ public class LoginView extends BaseActivity<LoginMvp.View, LoginPresenter> imple
@Override protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
refresh.setOnRefreshListener(this);
webView.getSettings().setSaveFormData(false);
webView.setWebChromeClient(new WebChromeClient() {
@Override public void onProgressChanged(WebView view, int progress) {
super.onProgressChanged(view, progress);

View File

@ -39,9 +39,11 @@ interface MainMvp {
void onCloseDrawer();
void onOpenSettings();
void onHideShowFab();
void onSubmitFeedback();
void onLogout();
}
interface Presenter extends BaseMvp.FAPresenter, NavigationView.OnNavigationItemSelectedListener,

View File

@ -82,7 +82,16 @@ class MainPresenter extends BasePresenter<MainMvp.View> implements MainMvp.Prese
}
@Override public boolean onNavigationItemSelected(@NonNull MenuItem item) {
if (getView() != null) getView().onCloseDrawer();
if (getView() != null) {
getView().onCloseDrawer();
if (item.getItemId() == R.id.feedback) {
getView().onSubmitFeedback();
return true;
} else if (item.getItemId() == R.id.logout) {
getView().onLogout();
return true;
}
}
return false;
}

View File

@ -13,22 +13,29 @@ import android.support.v4.widget.DrawerLayout;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.webkit.CookieManager;
import android.widget.TextView;
import android.widget.Toast;
import com.fastaccess.BuildConfig;
import com.fastaccess.R;
import com.fastaccess.data.dao.LoginModel;
import com.fastaccess.data.dao.NotificationThreadModel;
import com.fastaccess.helper.AppHelper;
import com.fastaccess.helper.BundleConstant;
import com.fastaccess.helper.Logger;
import com.fastaccess.helper.PrefGetter;
import com.fastaccess.helper.TypeFaceHelper;
import com.fastaccess.helper.ViewHelper;
import com.fastaccess.ui.base.BaseActivity;
import com.fastaccess.ui.modules.feeds.FeedsView;
import com.fastaccess.ui.modules.gists.create.CreateGistView;
import com.fastaccess.ui.modules.notification.NotificationsBottomSheet;
import com.fastaccess.ui.modules.repos.issues.create.CreateIssueView;
import com.fastaccess.ui.modules.search.SearchView;
import com.fastaccess.ui.widgets.AvatarLayout;
import com.fastaccess.ui.widgets.FontTextView;
import com.fastaccess.ui.widgets.SpannableBuilder;
import butterknife.BindView;
import butterknife.OnClick;
@ -43,6 +50,7 @@ public class MainView extends BaseActivity<MainMvp.View, MainPresenter> implemen
@BindView(R.id.bottomNavigation) BottomNavigation bottomNavigation;
@BindView(R.id.navigation) NavigationView navigationView;
@BindView(R.id.drawerLayout) DrawerLayout drawerLayout;
@BindView(R.id.versionText) FontTextView versionText;
private long backPressTimer;
@ -81,6 +89,13 @@ public class MainView extends BaseActivity<MainMvp.View, MainPresenter> implemen
hideShowShadow(navType != MainMvp.PROFILE);
}
@Override protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (resultCode == RESULT_OK && requestCode == BundleConstant.REQUEST_CODE) {
showMessage(R.string.success, R.string.thank_you_for_feedback);
}
}
@Override public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.search_menu, menu);
if (isLoggedIn() && NotificationThreadModel.hasUnreadNotifications()) {
@ -134,10 +149,6 @@ public class MainView extends BaseActivity<MainMvp.View, MainPresenter> implemen
if (drawerLayout != null && drawerLayout.isDrawerOpen(GravityCompat.START)) drawerLayout.closeDrawer(GravityCompat.START);
}
@Override public void onOpenSettings() {
}
@Override public void onHideShowFab() {
if (navType == MainMvp.GISTS) {
fab.show();
@ -146,6 +157,17 @@ public class MainView extends BaseActivity<MainMvp.View, MainPresenter> implemen
}
}
@Override public void onSubmitFeedback() {
CreateIssueView.startForResult(this);
}
@Override public void onLogout() {
CookieManager.getInstance().removeAllCookies(null);
PrefGetter.clear();
LoginModel.deleteTable().execute();
recreate();
}
private boolean canExit() {
if (backPressTimer + 2000 > System.currentTimeMillis()) {
return true;
@ -178,6 +200,11 @@ public class MainView extends BaseActivity<MainMvp.View, MainPresenter> implemen
((TextView) view.findViewById(R.id.email)).setText(userModel.getLogin());
}
}
versionText.setText(SpannableBuilder.builder()
.append(getString(R.string.current_version))
.append("(")
.bold(BuildConfig.VERSION_NAME)
.append(")"));
}
}
}

View File

@ -1,5 +1,6 @@
package com.fastaccess.ui.modules.repos.issues.create;
import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
import android.support.annotation.NonNull;
@ -33,6 +34,7 @@ public class CreateIssueView extends BaseActivity<CreateIssueMvp.View, CreateIss
@BindView(R.id.description) FontTextView description;
@State String repoId;
@State String login;
@State boolean isFeedback;
private CharSequence savedText;
@ -45,6 +47,18 @@ public class CreateIssueView extends BaseActivity<CreateIssueMvp.View, CreateIss
fragment.startActivityForResult(intent, BundleConstant.REQUEST_CODE);
}
public static void startForResult(@NonNull Activity activity) {
String login = "k0shk0sh"; // FIXME: 23/02/2017 hardcoded
String repoId = "FastHub";// FIXME: 23/02/2017 hardcoded
Intent intent = new Intent(activity, CreateIssueView.class);
intent.putExtras(Bundler.start()
.put(BundleConstant.EXTRA, login)
.put(BundleConstant.ID, repoId)
.put(BundleConstant.EXTRA_TWO, true)
.end());
activity.startActivityForResult(intent, BundleConstant.REQUEST_CODE);
}
@Override public void onSetCode(@NonNull CharSequence charSequence) {
this.savedText = charSequence;
MarkDownProvider.setMdText(description, InputHelper.toString(charSequence));
@ -92,7 +106,9 @@ public class CreateIssueView extends BaseActivity<CreateIssueMvp.View, CreateIss
if (savedInstanceState == null) {
login = getIntent().getExtras().getString(BundleConstant.EXTRA);
repoId = getIntent().getExtras().getString(BundleConstant.ID);
isFeedback = getIntent().getExtras().getBoolean(BundleConstant.EXTRA_TWO);
}
if (isFeedback) setTitle(R.string.submit_feedback);
}
@Override protected void onActivityResult(int requestCode, int resultCode, Intent data) {

View File

@ -18,7 +18,9 @@ import android.webkit.WebViewClient;
import com.fastaccess.helper.InputHelper;
import com.fastaccess.helper.Logger;
import com.fastaccess.provider.markdown.MarkDownProvider;
import com.fastaccess.provider.scheme.SchemeParser;
import com.fastaccess.ui.modules.code.CodeViewerView;
import com.prettifier.pretty.callback.MarkDownInterceptorInterface;
import com.prettifier.pretty.helper.GithubHelper;
import com.prettifier.pretty.helper.PrettifyHelper;
@ -147,7 +149,11 @@ public class PrettifyWebView extends NestedWebView {
private void startActivity(Uri url) {
Logger.e(url);
SchemeParser.launchUri(getContext(), url);
if (MarkDownProvider.isImage(url.toString())) {
CodeViewerView.startActivity(getContext(), url.toString());
} else {
SchemeParser.launchUri(getContext(), url);
}
}
private class WebClientCompat extends WebViewClient {
@ -157,5 +163,4 @@ public class PrettifyWebView extends NestedWebView {
}
}
}
}

View File

@ -1,12 +1,12 @@
package com.prettifier.pretty.helper;
import android.net.Uri;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import com.fastaccess.BuildConfig;
import com.fastaccess.data.dao.NameParser;
import com.fastaccess.helper.Logger;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
@ -17,13 +17,8 @@ import java.util.regex.Pattern;
*/
public class GithubHelper {
private static Matcher IMAGE_TAG_MATCHER = Pattern.compile("<(img|IMG)(.*?)>").matcher("");
private static Matcher IMAGE_SRC_MATCHER = Pattern.compile("(src|SRC)=\"(.*?)\"").matcher("");
private static Matcher LINK_TAG_MATCHER = Pattern.compile("<(a|A)(.*?)>").matcher("");
private static Matcher HREF_MATCHER = Pattern.compile("(href)=\"(.*?)\"").matcher("");
private static Pattern LINK_TAG_MATCHER = Pattern.compile("href=\"(.*?)\"");
private static Pattern IMAGE_TAG_MATCHER = Pattern.compile("src=\"(.*?)\"");
@NonNull public static String generateContent(@NonNull String source, @Nullable String baseUrl) {
if (baseUrl == null) {
@ -34,47 +29,35 @@ public class GithubHelper {
}
@NonNull private static String validateImageBaseUrl(@NonNull String source, @NonNull String baseUrl) {
Uri uri = Uri.parse(baseUrl);
List<String> segments = uri.getPathSegments();
if (segments == null || segments.size() < 2) return source;
String owner = segments.get(0);
String repoName = segments.get(1);
Matcher matcher = IMAGE_TAG_MATCHER.reset(source);
NameParser nameParser = new NameParser(baseUrl);
String owner = nameParser.getUsername();
String repoName = nameParser.getName();
Matcher matcher = IMAGE_TAG_MATCHER.matcher(source);
while (matcher.find()) {
String image = matcher.group(2).trim();
IMAGE_SRC_MATCHER.reset(image);
String src = null;
if (IMAGE_SRC_MATCHER.find()) {
src = IMAGE_SRC_MATCHER.group(2).trim();
}
if (src == null || src.startsWith("http://") || src.startsWith("https://")) {
String src = matcher.group(1).trim();
if (src.startsWith("http://") || src.startsWith("https://")) {
continue;
}
Logger.e(src);
String finalSrc = "https://raw.githubusercontent.com/" + owner + "/" + repoName + "/master/" + src;
source = source.replace(src, finalSrc);
source = source.replace("src=\"" + src + "\"", "src=\"" + finalSrc + "\"");
}
return validateLinks(source, baseUrl);
}
private static String validateLinks(@NonNull String source, @NonNull String baseUrl) {
Uri uri = Uri.parse(baseUrl);
List<String> segments = uri.getPathSegments();
if (segments == null || segments.size() < 2) return source;
String owner = segments.get(0);
String repoName = segments.get(1);
Matcher matcher = LINK_TAG_MATCHER.reset(source);
NameParser nameParser = new NameParser(baseUrl);
String owner = nameParser.getUsername();
String repoName = nameParser.getName();
Matcher matcher = LINK_TAG_MATCHER.matcher(source);
while (matcher.find()) {
String link = matcher.group(2).trim();
HREF_MATCHER.reset(link);
String href = null;
if (HREF_MATCHER.find()) {
href = HREF_MATCHER.group(2).trim();
}
if (href == null || href.startsWith("http://") || href.startsWith("https://") || href.startsWith("mailto:")) {
String href = matcher.group(1).trim();
if (href.startsWith("#") || href.startsWith("http://") || href.startsWith("https://") || href.startsWith("mailto:")) {
continue;
}
Logger.e(href);
String finalSrc = BuildConfig.REST_URL + "repos/" + owner + "/" + repoName + "/contents/" + href;
source = source.replace(href, finalSrc);
source = source.replace("href=\"" + href + "\"", "href=\"" + finalSrc + "\"");
}
return source;
}

View File

@ -0,0 +1,9 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="24.0"
android:viewportHeight="24.0">
<path
android:fillColor="#FF000000"
android:pathData="M10.09,15.59L11.5,17l5,-5 -5,-5 -1.41,1.41L12.67,11H3v2h9.67l-2.58,2.59zM19,3H5c-1.11,0 -2,0.9 -2,2v4h2V5h14v14H5v-4H3v4c0,1.1 0.89,2 2,2h14c1.1,0 2,-0.9 2,-2V5c0,-1.1 -0.9,-2 -2,-2z"/>
</vector>

View File

@ -48,8 +48,37 @@
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:layout_gravity="start"
android:clipToPadding="false"
android:fitsSystemWindows="true"
android:paddingBottom="76dp"
app:headerLayout="@layout/drawer_header"
app:itemIconTint="?colorAccent"
app:itemTextColor="?colorAccent"/>
app:itemTextColor="?colorAccent"
app:menu="@menu/drawer_menu">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="bottom"
android:layout_marginBottom="-76dp"
android:orientation="vertical"
android:paddingBottom="@dimen/spacing_xs_large">
<com.fastaccess.ui.widgets.FontTextView
style="@style/TextAppearance.AppCompat.Title"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center"
android:text="@string/app_name"/>
<com.fastaccess.ui.widgets.FontTextView
android:id="@+id/versionText"
style="@style/TextAppearance.AppCompat.Medium"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center"/>
</LinearLayout>
</android.support.design.widget.NavigationView>
</android.support.v4.widget.DrawerLayout>

View File

@ -3,30 +3,48 @@
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@drawable/header_background"
android:gravity="bottom"
android:minHeight="172dp"
android:orientation="vertical"
android:padding="@dimen/spacing_xs_large">
android:orientation="vertical">
<com.fastaccess.ui.widgets.AvatarLayout
android:id="@+id/avatarLayout"
android:layout_width="@dimen/header_icon_zie"
android:layout_height="@dimen/header_icon_zie"
android:layout_marginBottom="@dimen/spacing_normal"/>
<com.fastaccess.ui.widgets.FontTextView
android:id="@+id/username"
style="@style/TextAppearance.AppCompat.Title.Inverse"
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="@string/app_name"/>
android:layout_marginTop="@dimen/spacing_xs_large"
android:orientation="horizontal"
android:padding="@dimen/spacing_xs_large">
<com.fastaccess.ui.widgets.FontTextView
android:id="@+id/email"
style="@style/TextAppearance.AppCompat.Medium.Inverse"
<com.fastaccess.ui.widgets.AvatarLayout
android:id="@+id/avatarLayout"
android:layout_width="@dimen/header_icon_zie"
android:layout_height="@dimen/header_icon_zie"/>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:layout_marginStart="@dimen/spacing_xs_large"
android:orientation="vertical">
<com.fastaccess.ui.widgets.FontTextView
android:id="@+id/username"
style="@style/TextAppearance.AppCompat.Title"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:maxLines="1"
android:text="@string/app_name"/>
<com.fastaccess.ui.widgets.FontTextView
android:id="@+id/email"
style="@style/TextAppearance.AppCompat.Medium"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:maxLines="1"
android:text="@string/app_name"/>
</LinearLayout>
</LinearLayout>
<View
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="@string/app_name"/>
android:layout_height="4dp"
android:background="@drawable/toolbar_shadow"/>
</LinearLayout>

View File

@ -0,0 +1,17 @@
<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android">
<group android:checkableBehavior="none">
<item
android:id="@+id/feedback"
android:icon="@drawable/ic_announcement"
android:title="@string/submit_feedback"/>
<item
android:id="@+id/logout"
android:icon="@drawable/ic_logout"
android:title="@string/logout"/>
</group>
</menu>

View File

@ -4,7 +4,7 @@
<item
android:id="@+id/notifications"
android:icon="@drawable/ic_notifications"
android:icon="@drawable/ic_ring"
android:title="@string/notifictions"
app:showAsAction="ifRoom"/>

View File

@ -149,4 +149,8 @@
<string name="labels">Labels</string>
<string name="no_labels">No Labels</string>
<string name="labels_added_successfully">Labels Added Successfully</string>
<string name="submit_feedback">Submit Feedback</string>
<string name="logout">Logout</string>
<string name="thank_you_for_feedback">Thanks for your feedback.</string>
<string name="current_version">Current Version</string>
</resources>