Use README.md in details for repo

This commit is contained in:
topjohnwu
2017-02-16 05:45:31 +08:00
parent d1c939f48a
commit a03bb90754
25 changed files with 147 additions and 347 deletions

View File

@ -87,7 +87,7 @@ public class InstallFragment extends Fragment implements CallbackEvent.Listener<
},
getApplication().magiskLink,
Utils.getLegalFilename(filename)))
.setNeutralButton(R.string.check_release_notes, (dialog, which) -> {
.setNeutralButton(R.string.release_notes, (dialog, which) -> {
getActivity().startActivity(new Intent(Intent.ACTION_VIEW, Uri.parse(getApplication().releaseNoteLink)));
})
.setNegativeButton(R.string.no_thanks, null)

View File

@ -242,7 +242,7 @@ public class StatusFragment extends Fragment implements CallbackEvent.Listener<V
transaction.replace(R.id.content_frame, new InstallFragment(), "install").commit();
} catch (IllegalStateException ignored) {}
})
.setNeutralButton(R.string.check_release_notes, (dialog, which) -> {
.setNeutralButton(R.string.release_notes, (dialog, which) -> {
getActivity().startActivity(new Intent(Intent.ACTION_VIEW, Uri.parse(getApplication().releaseNoteLink)));
})
.setNegativeButton(R.string.no_thanks, null)

View File

@ -1,17 +1,12 @@
package com.topjohnwu.magisk.adapters;
import android.animation.Animator;
import android.animation.ObjectAnimator;
import android.animation.ValueAnimator;
import android.content.Context;
import android.content.Intent;
import android.net.Uri;
import android.support.v7.widget.RecyclerView;
import android.text.TextUtils;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.view.ViewTreeObserver;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.TextView;
@ -19,14 +14,12 @@ import android.widget.TextView;
import com.topjohnwu.magisk.R;
import com.topjohnwu.magisk.asyncs.ProcessRepoZip;
import com.topjohnwu.magisk.components.AlertDialogBuilder;
import com.topjohnwu.magisk.components.MarkDownWindow;
import com.topjohnwu.magisk.module.Repo;
import com.topjohnwu.magisk.receivers.DownloadReceiver;
import com.topjohnwu.magisk.utils.Utils;
import com.topjohnwu.magisk.utils.WebWindow;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import butterknife.BindView;
import butterknife.ButterKnife;
@ -34,7 +27,7 @@ import butterknife.ButterKnife;
public class ReposAdapter extends RecyclerView.Adapter<ReposAdapter.ViewHolder> {
private List<Repo> mUpdateRepos, mInstalledRepos, mOthersRepos;
private Set<Repo> expandList = new HashSet<>();
private Context mContext;
public ReposAdapter(List<Repo> update, List<Repo> installed, List<Repo> others) {
mUpdateRepos = update;
@ -44,45 +37,31 @@ public class ReposAdapter extends RecyclerView.Adapter<ReposAdapter.ViewHolder>
@Override
public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View v = LayoutInflater.from(parent.getContext()).inflate(R.layout.list_item_repo, parent, false);
mContext = parent.getContext();
View v = LayoutInflater.from(mContext).inflate(R.layout.list_item_repo, parent, false);
return new ViewHolder(v);
}
@Override
public void onBindViewHolder(final ViewHolder holder, int position) {
Context context = holder.itemView.getContext();
Repo repo = getItem(position);
holder.title.setText(repo.getName());
holder.versionName.setText(repo.getVersion());
String author = repo.getAuthor();
holder.author.setText(TextUtils.isEmpty(author) ? null : context.getString(R.string.author, author));
holder.author.setText(TextUtils.isEmpty(author) ? null : mContext.getString(R.string.author, author));
holder.description.setText(repo.getDescription());
holder.setExpanded(expandList.contains(repo));
holder.infoLayout.setOnClickListener(v -> new MarkDownWindow(null, repo.getDetailUrl(), mContext));
holder.itemView.setOnClickListener(view -> {
if (holder.mExpanded) {
holder.collapse();
expandList.remove(repo);
} else {
holder.expand();
expandList.add(repo);
}
});
holder.changeLog.setOnClickListener(view -> {
if (!TextUtils.isEmpty(repo.getLogUrl())) {
new WebWindow(context.getString(R.string.changelog), repo.getLogUrl(), context);
}
});
holder.updateImage.setOnClickListener(view -> {
holder.downloadImage.setOnClickListener(v -> {
String filename = repo.getName() + "-" + repo.getVersion() + ".zip";
new AlertDialogBuilder(context)
.setTitle(context.getString(R.string.repo_install_title, repo.getName()))
.setMessage(context.getString(R.string.repo_install_msg, filename))
new AlertDialogBuilder(mContext)
.setTitle(mContext.getString(R.string.repo_install_title, repo.getName()))
.setMessage(mContext.getString(R.string.repo_install_msg, filename))
.setCancelable(true)
.setPositiveButton(R.string.download_install, (dialogInterface, i) -> Utils.dlAndReceive(
context,
mContext,
new DownloadReceiver() {
@Override
public void onDownloadDone(Uri uri) {
@ -94,16 +73,6 @@ public class ReposAdapter extends RecyclerView.Adapter<ReposAdapter.ViewHolder>
.setNegativeButton(R.string.no_thanks, null)
.show();
});
holder.authorLink.setOnClickListener(view -> {
if (!TextUtils.isEmpty(repo.getDonateUrl())) {
context.startActivity(new Intent(Intent.ACTION_VIEW, Uri.parse(repo.getDonateUrl())));
}
});
holder.supportLink.setOnClickListener(view -> {
if (!TextUtils.isEmpty(repo.getSupportUrl())) {
context.startActivity(new Intent(Intent.ACTION_VIEW, Uri.parse(repo.getSupportUrl())));
}
});
}
@Override
@ -131,97 +100,12 @@ public class ReposAdapter extends RecyclerView.Adapter<ReposAdapter.ViewHolder>
@BindView(R.id.version_name) TextView versionName;
@BindView(R.id.description) TextView description;
@BindView(R.id.author) TextView author;
@BindView(R.id.expand_layout) LinearLayout expandLayout;
@BindView(R.id.update) ImageView updateImage;
@BindView(R.id.changeLog) ImageView changeLog;
@BindView(R.id.authorLink) ImageView authorLink;
@BindView(R.id.supportLink) ImageView supportLink;
private ValueAnimator mAnimator;
private ObjectAnimator animY2;
private boolean mExpanded = false;
private static int expandHeight = 0;
@BindView(R.id.info_layout) LinearLayout infoLayout;
@BindView(R.id.download) ImageView downloadImage;
ViewHolder(View itemView) {
super(itemView);
ButterKnife.bind(this, itemView);
expandLayout.getViewTreeObserver().addOnPreDrawListener(
new ViewTreeObserver.OnPreDrawListener() {
@Override
public boolean onPreDraw() {
if (expandHeight == 0) {
final int widthSpec = View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED);
final int heightSpec = View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED);
expandLayout.measure(widthSpec, heightSpec);
expandHeight = expandLayout.getMeasuredHeight();
}
expandLayout.getViewTreeObserver().removeOnPreDrawListener(this);
expandLayout.setVisibility(View.GONE);
mAnimator = slideAnimator(0, expandHeight);
animY2 = ObjectAnimator.ofFloat(updateImage, "translationY", expandHeight / 2);
return true;
}
});
}
private void setExpanded(boolean expanded) {
mExpanded = expanded;
ViewGroup.LayoutParams layoutParams = expandLayout.getLayoutParams();
layoutParams.height = expanded ? expandHeight : 0;
expandLayout.setLayoutParams(layoutParams);
expandLayout.setVisibility(expanded ? View.VISIBLE : View.GONE);
if (expanded) {
updateImage.setTranslationY(expandHeight / 2);
} else {
updateImage.setTranslationY(0);
}
}
private void expand() {
expandLayout.setVisibility(View.VISIBLE);
mAnimator.start();
animY2.start();
mExpanded = true;
}
private void collapse() {
if (!mExpanded) return;
int finalHeight = expandLayout.getHeight();
ValueAnimator mAnimator = slideAnimator(finalHeight, 0);
mAnimator.addListener(new Animator.AnimatorListener() {
@Override
public void onAnimationEnd(Animator animator) {
expandLayout.setVisibility(View.GONE);
}
@Override
public void onAnimationStart(Animator animator) {}
@Override
public void onAnimationCancel(Animator animator) {}
@Override
public void onAnimationRepeat(Animator animator) {}
});
mAnimator.start();
animY2.reverse();
mExpanded = false;
}
private ValueAnimator slideAnimator(int start, int end) {
ValueAnimator animator = ValueAnimator.ofInt(start, end);
animator.addUpdateListener(valueAnimator -> {
int value = (Integer) valueAnimator.getAnimatedValue();
ViewGroup.LayoutParams layoutParams = expandLayout.getLayoutParams();
layoutParams.height = value;
expandLayout.setLayoutParams(layoutParams);
});
return animator;
}
}

View File

@ -6,7 +6,6 @@ import android.net.Uri;
import android.widget.Toast;
import com.topjohnwu.magisk.R;
import com.topjohnwu.magisk.utils.ByteArrayInOutStream;
import com.topjohnwu.magisk.utils.Logger;
import com.topjohnwu.magisk.utils.Shell;
import com.topjohnwu.magisk.utils.Utils;

View File

@ -9,7 +9,10 @@ import android.support.annotation.StyleRes;
import android.support.v7.app.AlertDialog;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.view.ViewStub;
import android.widget.Button;
import android.widget.LinearLayout;
import android.widget.TextView;
import com.topjohnwu.magisk.R;
@ -19,10 +22,14 @@ import butterknife.ButterKnife;
public class AlertDialogBuilder extends AlertDialog.Builder {
@BindView(R.id.button_panel) LinearLayout buttons;
@BindView(R.id.message_panel) LinearLayout messagePanel;
@BindView(R.id.negative) Button negative;
@BindView(R.id.positive) Button positive;
@BindView(R.id.neutral) Button neutral;
@BindView(R.id.message) TextView messageView;
@BindView(R.id.custom_view) ViewStub custom;
private DialogInterface.OnClickListener positiveListener;
private DialogInterface.OnClickListener negativeListener;
@ -47,11 +54,30 @@ public class AlertDialogBuilder extends AlertDialog.Builder {
negative.setVisibility(View.GONE);
positive.setVisibility(View.GONE);
neutral.setVisibility(View.GONE);
buttons.setVisibility(View.GONE);
messagePanel.setVisibility(View.GONE);
}
@Override
public AlertDialog.Builder setView(int layoutResId) {
custom.setLayoutResource(layoutResId);
custom.inflate();
return this;
}
@Override
public AlertDialog.Builder setView(View view) {
ViewGroup parent = (ViewGroup) custom.getParent();
int idx = parent.indexOfChild(custom);
parent.removeView(custom);
parent.addView(view, idx);
return this;
}
@Override
public AlertDialog.Builder setMessage(@Nullable CharSequence message) {
messageView.setText(message);
messagePanel.setVisibility(View.VISIBLE);
return this;
}
@ -62,6 +88,7 @@ public class AlertDialogBuilder extends AlertDialog.Builder {
@Override
public AlertDialog.Builder setPositiveButton(CharSequence text, DialogInterface.OnClickListener listener) {
buttons.setVisibility(View.VISIBLE);
positive.setVisibility(View.VISIBLE);
positive.setText(text);
positiveListener = listener;
@ -80,6 +107,7 @@ public class AlertDialogBuilder extends AlertDialog.Builder {
@Override
public AlertDialog.Builder setNegativeButton(CharSequence text, DialogInterface.OnClickListener listener) {
buttons.setVisibility(View.VISIBLE);
negative.setVisibility(View.VISIBLE);
negative.setText(text);
negativeListener = listener;
@ -98,6 +126,7 @@ public class AlertDialogBuilder extends AlertDialog.Builder {
@Override
public AlertDialog.Builder setNeutralButton(CharSequence text, DialogInterface.OnClickListener listener) {
buttons.setVisibility(View.VISIBLE);
neutral.setVisibility(View.VISIBLE);
neutral.setText(text);
neutralListener = listener;

View File

@ -0,0 +1,27 @@
package com.topjohnwu.magisk.components;
import android.content.Context;
import android.support.v7.app.AlertDialog;
import com.topjohnwu.magisk.R;
import com.topjohnwu.magisk.utils.Logger;
import us.feras.mdv.MarkdownView;
public class MarkDownWindow {
public MarkDownWindow(String title, String url, Context context) {
AlertDialog.Builder alert = new AlertDialogBuilder(context);
alert.setTitle(title);
Logger.dev("WebView: URL = " + url);
MarkdownView md = new MarkdownView(context);
md.loadMarkdownFile(url);
alert.setView(md);
alert.setNegativeButton(R.string.close, (dialog, id) -> dialog.dismiss());
alert.show();
}
}

View File

@ -9,8 +9,7 @@ import java.util.List;
public abstract class BaseModule implements Comparable<BaseModule> {
protected String mId, mName, mVersion, mAuthor, mDescription, mSupportUrl, mDonateUrl;
protected boolean mIsCacheModule = false;
protected String mId, mName, mVersion, mAuthor, mDescription;
protected int mVersionCode = 0;
protected void parseProps(List<String> props) throws CacheModException { parseProps(props.toArray(new String[props.size()])); }
@ -48,21 +47,14 @@ public abstract class BaseModule implements Comparable<BaseModule> {
case "description":
this.mDescription = prop[1];
break;
case "support":
this.mSupportUrl = prop[1];
break;
case "donate":
this.mDonateUrl = prop[1];
break;
case "cacheModule":
this.mIsCacheModule = Boolean.parseBoolean(prop[1]);
if (Boolean.parseBoolean(prop[1]))
throw new CacheModException(mId);
break;
default:
break;
}
}
if (mIsCacheModule)
throw new CacheModException(mId);
}
public String getName() {
@ -77,7 +69,9 @@ public abstract class BaseModule implements Comparable<BaseModule> {
return mAuthor;
}
public String getId() {return mId; }
public String getId() {
return mId;
}
public String getDescription() {
return mDescription;
@ -87,14 +81,6 @@ public abstract class BaseModule implements Comparable<BaseModule> {
return mVersionCode;
}
public String getDonateUrl() {
return mDonateUrl;
}
public String getSupportUrl() {
return mSupportUrl;
}
public static class CacheModException extends Exception {
public CacheModException(String id) {
Logger.error("Cache mods are no longer supported! id: " + id);

View File

@ -42,8 +42,6 @@ public class Repo extends BaseModule {
public void update(Date lastUpdate) throws CacheModException {
Logger.dev("Repo: Local: " + mLastUpdate + " Remote: " + lastUpdate);
if (mIsCacheModule)
throw new CacheModException(mId);
if (lastUpdate.after(mLastUpdate)) {
mLastUpdate = lastUpdate;
update();
@ -75,6 +73,10 @@ public class Repo extends BaseModule {
return String.format(FILE_URL, repoName, "module.prop");
}
public String getDetailUrl() {
return String.format(FILE_URL, repoName, "README.md");
}
public Date getLastUpdate() {
return mLastUpdate;
}

View File

@ -1,34 +0,0 @@
package com.topjohnwu.magisk.utils;
import android.content.Context;
import android.support.v7.app.AlertDialog;
import android.webkit.WebResourceRequest;
import android.webkit.WebView;
import android.webkit.WebViewClient;
import com.topjohnwu.magisk.components.AlertDialogBuilder;
public class WebWindow {
public WebWindow(String title, String url, Context context) {
AlertDialog.Builder alert = new AlertDialogBuilder(context);
alert.setTitle(title);
Logger.dev("WebView: URL = " + url);
WebView wv = new WebView(context);
wv.loadUrl(url);
wv.setWebViewClient(new WebViewClient() {
@Override
public boolean shouldOverrideUrlLoading(WebView view, WebResourceRequest request) {
view.loadUrl(url);
return true;
}
});
alert.setView(wv);
alert.setNegativeButton("Close", (dialog, id) -> dialog.dismiss());
alert.show();
}
}