[app] Add info
This commit is contained in:
parent
ddd082e17d
commit
2f0d6da850
|
|
@ -35,7 +35,7 @@ public class Collaborator implements Serializable, Parcelable {
|
||||||
private String login;
|
private String login;
|
||||||
@SerializedName("name")
|
@SerializedName("name")
|
||||||
@Expose
|
@Expose
|
||||||
private Object name;
|
private String name;
|
||||||
public final static Creator<Collaborator> CREATOR = new Creator<Collaborator>() {
|
public final static Creator<Collaborator> CREATOR = new Creator<Collaborator>() {
|
||||||
|
|
||||||
public Collaborator createFromParcel(Parcel in) {
|
public Collaborator createFromParcel(Parcel in) {
|
||||||
|
|
@ -51,7 +51,7 @@ public class Collaborator implements Serializable, Parcelable {
|
||||||
|
|
||||||
protected Collaborator(Parcel in) {
|
protected Collaborator(Parcel in) {
|
||||||
this.login = ((String) in.readValue((String.class.getClassLoader())));
|
this.login = ((String) in.readValue((String.class.getClassLoader())));
|
||||||
this.name = in.readValue((Object.class.getClassLoader()));
|
this.name = ((String) in.readValue((String.class.getClassLoader())));
|
||||||
}
|
}
|
||||||
|
|
||||||
public Collaborator() {
|
public Collaborator() {
|
||||||
|
|
@ -65,11 +65,11 @@ public class Collaborator implements Serializable, Parcelable {
|
||||||
this.login = login;
|
this.login = login;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Object getName() {
|
public String getName() {
|
||||||
return name;
|
return name;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setName(Object name) {
|
public void setName(String name) {
|
||||||
this.name = name;
|
this.name = name;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -68,6 +68,15 @@ public class OnlineModule implements Serializable, Parcelable {
|
||||||
@SerializedName("additionalAuthors")
|
@SerializedName("additionalAuthors")
|
||||||
@Expose
|
@Expose
|
||||||
private List<Object> additionalAuthors = null;
|
private List<Object> additionalAuthors = null;
|
||||||
|
@SerializedName("updatedAt")
|
||||||
|
@Expose
|
||||||
|
private String updatedAt;
|
||||||
|
@SerializedName("createdAt")
|
||||||
|
@Expose
|
||||||
|
private String createdAt;
|
||||||
|
@SerializedName("stargazerCount")
|
||||||
|
@Expose
|
||||||
|
private Integer stargazerCount;
|
||||||
public final static Creator<OnlineModule> CREATOR = new Creator<OnlineModule>() {
|
public final static Creator<OnlineModule> CREATOR = new Creator<OnlineModule>() {
|
||||||
|
|
||||||
public OnlineModule createFromParcel(Parcel in) {
|
public OnlineModule createFromParcel(Parcel in) {
|
||||||
|
|
@ -79,7 +88,7 @@ public class OnlineModule implements Serializable, Parcelable {
|
||||||
}
|
}
|
||||||
|
|
||||||
};
|
};
|
||||||
private final static long serialVersionUID = -2294634398588027071L;
|
private final static long serialVersionUID = 3372849627722130087L;
|
||||||
|
|
||||||
protected OnlineModule(Parcel in) {
|
protected OnlineModule(Parcel in) {
|
||||||
this.name = ((String) in.readValue((String.class.getClassLoader())));
|
this.name = ((String) in.readValue((String.class.getClassLoader())));
|
||||||
|
|
@ -94,6 +103,9 @@ public class OnlineModule implements Serializable, Parcelable {
|
||||||
this.sourceUrl = ((String) in.readValue((String.class.getClassLoader())));
|
this.sourceUrl = ((String) in.readValue((String.class.getClassLoader())));
|
||||||
this.hide = ((Boolean) in.readValue((Boolean.class.getClassLoader())));
|
this.hide = ((Boolean) in.readValue((Boolean.class.getClassLoader())));
|
||||||
in.readList(this.additionalAuthors, (Object.class.getClassLoader()));
|
in.readList(this.additionalAuthors, (Object.class.getClassLoader()));
|
||||||
|
this.updatedAt = ((String) in.readValue((String.class.getClassLoader())));
|
||||||
|
this.createdAt = ((String) in.readValue((String.class.getClassLoader())));
|
||||||
|
this.stargazerCount = ((Integer) in.readValue((Integer.class.getClassLoader())));
|
||||||
}
|
}
|
||||||
|
|
||||||
public OnlineModule() {
|
public OnlineModule() {
|
||||||
|
|
@ -179,7 +191,7 @@ public class OnlineModule implements Serializable, Parcelable {
|
||||||
this.sourceUrl = sourceUrl;
|
this.sourceUrl = sourceUrl;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Boolean getHide() {
|
public Boolean isHide() {
|
||||||
return hide;
|
return hide;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -195,6 +207,30 @@ public class OnlineModule implements Serializable, Parcelable {
|
||||||
this.additionalAuthors = additionalAuthors;
|
this.additionalAuthors = additionalAuthors;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public String getUpdatedAt() {
|
||||||
|
return updatedAt;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setUpdatedAt(String updatedAt) {
|
||||||
|
this.updatedAt = updatedAt;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getCreatedAt() {
|
||||||
|
return createdAt;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setCreatedAt(String createdAt) {
|
||||||
|
this.createdAt = createdAt;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Integer getStargazerCount() {
|
||||||
|
return stargazerCount;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setStargazerCount(Integer stargazerCount) {
|
||||||
|
this.stargazerCount = stargazerCount;
|
||||||
|
}
|
||||||
|
|
||||||
public void writeToParcel(Parcel dest, int flags) {
|
public void writeToParcel(Parcel dest, int flags) {
|
||||||
dest.writeValue(name);
|
dest.writeValue(name);
|
||||||
dest.writeValue(description);
|
dest.writeValue(description);
|
||||||
|
|
@ -208,6 +244,9 @@ public class OnlineModule implements Serializable, Parcelable {
|
||||||
dest.writeValue(sourceUrl);
|
dest.writeValue(sourceUrl);
|
||||||
dest.writeValue(hide);
|
dest.writeValue(hide);
|
||||||
dest.writeList(additionalAuthors);
|
dest.writeList(additionalAuthors);
|
||||||
|
dest.writeValue(updatedAt);
|
||||||
|
dest.writeValue(createdAt);
|
||||||
|
dest.writeValue(stargazerCount);
|
||||||
}
|
}
|
||||||
|
|
||||||
public int describeContents() {
|
public int describeContents() {
|
||||||
|
|
|
||||||
|
|
@ -43,6 +43,7 @@ import java.util.ArrayList;
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
import io.github.lsposed.manager.R;
|
import io.github.lsposed.manager.R;
|
||||||
import io.github.lsposed.manager.databinding.ActivityAppListBinding;
|
import io.github.lsposed.manager.databinding.ActivityAppListBinding;
|
||||||
|
|
@ -168,6 +169,7 @@ public class RepoActivity extends BaseActivity implements RepoLoader.Listener {
|
||||||
|
|
||||||
public void setData(Collection<OnlineModule> modules) {
|
public void setData(Collection<OnlineModule> modules) {
|
||||||
fullList = new ArrayList<>(modules);
|
fullList = new ArrayList<>(modules);
|
||||||
|
fullList = fullList.stream().filter((onlineModule -> !onlineModule.isHide())).collect(Collectors.toList());
|
||||||
fullList.sort((o1, o2) -> o1.getDescription().compareToIgnoreCase(o2.getDescription()));
|
fullList.sort((o1, o2) -> o1.getDescription().compareToIgnoreCase(o2.getDescription()));
|
||||||
String queryStr = searchView != null ? searchView.getQuery().toString() : "";
|
String queryStr = searchView != null ? searchView.getQuery().toString() : "";
|
||||||
runOnUiThread(() -> getFilter().filter(queryStr));
|
runOnUiThread(() -> getFilter().filter(queryStr));
|
||||||
|
|
|
||||||
|
|
@ -22,6 +22,9 @@ package io.github.lsposed.manager.ui.activity;
|
||||||
|
|
||||||
import android.os.Build;
|
import android.os.Build;
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
|
import android.text.Spannable;
|
||||||
|
import android.text.SpannableStringBuilder;
|
||||||
|
import android.text.style.ClickableSpan;
|
||||||
import android.text.util.Linkify;
|
import android.text.util.Linkify;
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
import android.view.ViewGroup;
|
import android.view.ViewGroup;
|
||||||
|
|
@ -38,24 +41,31 @@ import androidx.recyclerview.widget.RecyclerView;
|
||||||
import androidx.viewpager2.widget.ViewPager2;
|
import androidx.viewpager2.widget.ViewPager2;
|
||||||
|
|
||||||
import com.google.android.material.dialog.MaterialAlertDialogBuilder;
|
import com.google.android.material.dialog.MaterialAlertDialogBuilder;
|
||||||
|
import com.google.android.material.snackbar.Snackbar;
|
||||||
import com.google.android.material.tabs.TabLayoutMediator;
|
import com.google.android.material.tabs.TabLayoutMediator;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.ListIterator;
|
||||||
|
|
||||||
import io.github.lsposed.manager.R;
|
import io.github.lsposed.manager.R;
|
||||||
import io.github.lsposed.manager.databinding.ActivityModuleDetailBinding;
|
import io.github.lsposed.manager.databinding.ActivityModuleDetailBinding;
|
||||||
import io.github.lsposed.manager.databinding.ItemRepoReadmeBinding;
|
import io.github.lsposed.manager.databinding.ItemRepoReadmeBinding;
|
||||||
import io.github.lsposed.manager.databinding.ItemRepoReleaseBinding;
|
import io.github.lsposed.manager.databinding.ItemRepoRecyclerviewBinding;
|
||||||
import io.github.lsposed.manager.databinding.ItemRepoReleasesBinding;
|
import io.github.lsposed.manager.databinding.ItemRepoTitleDescriptionBinding;
|
||||||
import io.github.lsposed.manager.repo.RepoLoader;
|
import io.github.lsposed.manager.repo.RepoLoader;
|
||||||
|
import io.github.lsposed.manager.repo.model.Collaborator;
|
||||||
import io.github.lsposed.manager.repo.model.OnlineModule;
|
import io.github.lsposed.manager.repo.model.OnlineModule;
|
||||||
import io.github.lsposed.manager.repo.model.Release;
|
import io.github.lsposed.manager.repo.model.Release;
|
||||||
|
import io.github.lsposed.manager.repo.model.ReleaseAsset;
|
||||||
|
import io.github.lsposed.manager.ui.widget.LinkifyTextView;
|
||||||
import io.github.lsposed.manager.util.GlideApp;
|
import io.github.lsposed.manager.util.GlideApp;
|
||||||
import io.github.lsposed.manager.util.LinearLayoutManagerFix;
|
import io.github.lsposed.manager.util.LinearLayoutManagerFix;
|
||||||
import io.github.lsposed.manager.util.NavUtil;
|
import io.github.lsposed.manager.util.NavUtil;
|
||||||
|
import io.github.lsposed.manager.util.chrome.CustomTabsURLSpan;
|
||||||
import io.github.lsposed.manager.util.chrome.LinkTransformationMethod;
|
import io.github.lsposed.manager.util.chrome.LinkTransformationMethod;
|
||||||
import io.noties.markwon.Markwon;
|
import io.noties.markwon.Markwon;
|
||||||
|
import io.noties.markwon.html.HtmlPlugin;
|
||||||
import io.noties.markwon.image.glide.GlideImagesPlugin;
|
import io.noties.markwon.image.glide.GlideImagesPlugin;
|
||||||
import io.noties.markwon.linkify.LinkifyPlugin;
|
import io.noties.markwon.linkify.LinkifyPlugin;
|
||||||
|
|
||||||
|
|
@ -81,6 +91,7 @@ public class RepoItemActivity extends BaseActivity {
|
||||||
markwon = Markwon.builder(this)
|
markwon = Markwon.builder(this)
|
||||||
.usePlugin(GlideImagesPlugin.create(GlideApp.with(this)))
|
.usePlugin(GlideImagesPlugin.create(GlideApp.with(this)))
|
||||||
.usePlugin(LinkifyPlugin.create(Linkify.WEB_URLS))
|
.usePlugin(LinkifyPlugin.create(Linkify.WEB_URLS))
|
||||||
|
.usePlugin(HtmlPlugin.create())
|
||||||
.build();
|
.build();
|
||||||
module = RepoLoader.getInstance().getOnlineModule(modulePackageName);
|
module = RepoLoader.getInstance().getOnlineModule(modulePackageName);
|
||||||
binding.viewPager.setAdapter(new PagerAdapter());
|
binding.viewPager.setAdapter(new PagerAdapter());
|
||||||
|
|
@ -94,7 +105,7 @@ public class RepoItemActivity extends BaseActivity {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
int[] titles = new int[]{R.string.module_readme, R.string.module_releases};
|
int[] titles = new int[]{R.string.module_readme, R.string.module_releases, R.string.module_information};
|
||||||
new TabLayoutMediator(binding.tabLayout, binding.viewPager, (tab, position) -> tab.setText(titles[position])).attach();
|
new TabLayoutMediator(binding.tabLayout, binding.viewPager, (tab, position) -> tab.setText(titles[position])).attach();
|
||||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
|
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
|
||||||
WindowCompat.setDecorFitsSystemWindows(getWindow(), false);
|
WindowCompat.setDecorFitsSystemWindows(getWindow(), false);
|
||||||
|
|
@ -106,7 +117,81 @@ public class RepoItemActivity extends BaseActivity {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private class ReleaseAdapter extends RecyclerView.Adapter<ReleaseAdapter.ViewHolder> {
|
private class InformationAdapter extends RecyclerView.Adapter<TitleDescriptionHolder> {
|
||||||
|
private final OnlineModule module;
|
||||||
|
|
||||||
|
private int rowCount = 0;
|
||||||
|
private int homepageRow = -1;
|
||||||
|
private int collaboratorsRow = -1;
|
||||||
|
private int sourceUrlRow = -1;
|
||||||
|
|
||||||
|
public InformationAdapter(OnlineModule module) {
|
||||||
|
this.module = module;
|
||||||
|
if (module.getHomepageUrl() != null) {
|
||||||
|
homepageRow = rowCount++;
|
||||||
|
}
|
||||||
|
if (module.getCollaborators() != null) {
|
||||||
|
collaboratorsRow = rowCount++;
|
||||||
|
}
|
||||||
|
if (module.getSourceUrl() != null) {
|
||||||
|
sourceUrlRow = rowCount++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@NonNull
|
||||||
|
@Override
|
||||||
|
public TitleDescriptionHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
|
||||||
|
return new TitleDescriptionHolder(ItemRepoTitleDescriptionBinding.inflate(getLayoutInflater(), parent, false));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onBindViewHolder(@NonNull TitleDescriptionHolder holder, int position) {
|
||||||
|
if (position == homepageRow) {
|
||||||
|
holder.title.setText(R.string.module_information_homepage);
|
||||||
|
holder.description.setText(module.getHomepageUrl());
|
||||||
|
} else if (position == collaboratorsRow) {
|
||||||
|
holder.title.setText(R.string.module_information_collaborators);
|
||||||
|
List<Collaborator> collaborators = module.getCollaborators();
|
||||||
|
SpannableStringBuilder sb = new SpannableStringBuilder();
|
||||||
|
ListIterator<Collaborator> iterator = collaborators.listIterator();
|
||||||
|
while (iterator.hasNext()) {
|
||||||
|
Collaborator collaborator = iterator.next();
|
||||||
|
String name = collaborator.getName() == null ? collaborator.getLogin() : collaborator.getName();
|
||||||
|
sb.append(name);
|
||||||
|
CustomTabsURLSpan span = new CustomTabsURLSpan(RepoItemActivity.this, String.format("https://github.com/%s", collaborator.getLogin()));
|
||||||
|
sb.setSpan(span, sb.length() - name.length(), sb.length(), Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
|
||||||
|
if (iterator.hasNext()) {
|
||||||
|
sb.append(", ");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
holder.description.setText(sb);
|
||||||
|
} else if (position == sourceUrlRow) {
|
||||||
|
holder.title.setText(R.string.module_information_source_url);
|
||||||
|
holder.description.setText(module.getSourceUrl());
|
||||||
|
}
|
||||||
|
holder.itemView.setOnClickListener(v -> {
|
||||||
|
if (position == homepageRow) {
|
||||||
|
NavUtil.startURL(RepoItemActivity.this, module.getHomepageUrl());
|
||||||
|
} else if (position == collaboratorsRow) {
|
||||||
|
ClickableSpan span = holder.description.getCurrentSpan();
|
||||||
|
holder.description.clearCurrentSpan();
|
||||||
|
|
||||||
|
if (span instanceof CustomTabsURLSpan) {
|
||||||
|
span.onClick(v);
|
||||||
|
}
|
||||||
|
} else if (position == sourceUrlRow) {
|
||||||
|
NavUtil.startURL(RepoItemActivity.this, module.getSourceUrl());
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getItemCount() {
|
||||||
|
return rowCount;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private class ReleaseAdapter extends RecyclerView.Adapter<TitleDescriptionHolder> {
|
||||||
private final List<Release> items;
|
private final List<Release> items;
|
||||||
|
|
||||||
public ReleaseAdapter(List<Release> items) {
|
public ReleaseAdapter(List<Release> items) {
|
||||||
|
|
@ -115,21 +200,26 @@ public class RepoItemActivity extends BaseActivity {
|
||||||
|
|
||||||
@NonNull
|
@NonNull
|
||||||
@Override
|
@Override
|
||||||
public ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
|
public TitleDescriptionHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
|
||||||
return new ViewHolder(ItemRepoReleaseBinding.inflate(getLayoutInflater(), parent, false));
|
return new TitleDescriptionHolder(ItemRepoTitleDescriptionBinding.inflate(getLayoutInflater(), parent, false));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onBindViewHolder(@NonNull ViewHolder holder, int position) {
|
public void onBindViewHolder(@NonNull TitleDescriptionHolder holder, int position) {
|
||||||
Release release = items.get(position);
|
Release release = items.get(position);
|
||||||
holder.title.setText(release.getName());
|
holder.title.setText(release.getName());
|
||||||
holder.description.setText(release.getDescription());
|
holder.description.setText(release.getDescription());
|
||||||
holder.itemView.setOnClickListener(v -> {
|
holder.itemView.setOnClickListener(v -> {
|
||||||
ArrayList<String> names = new ArrayList<>();
|
List<ReleaseAsset> assets = release.getReleaseAssets();
|
||||||
release.getReleaseAssets().forEach(releaseAsset -> names.add(releaseAsset.getName()));
|
if (assets != null && !assets.isEmpty()) {
|
||||||
new MaterialAlertDialogBuilder(RepoItemActivity.this)
|
ArrayList<String> names = new ArrayList<>();
|
||||||
.setItems(names.toArray(new String[0]), (dialog, which) -> NavUtil.startURL(RepoItemActivity.this, release.getReleaseAssets().get(which).getDownloadUrl()))
|
release.getReleaseAssets().forEach(releaseAsset -> names.add(releaseAsset.getName()));
|
||||||
.show();
|
new MaterialAlertDialogBuilder(RepoItemActivity.this)
|
||||||
|
.setItems(names.toArray(new String[0]), (dialog, which) -> NavUtil.startURL(RepoItemActivity.this, release.getReleaseAssets().get(which).getDownloadUrl()))
|
||||||
|
.show();
|
||||||
|
} else {
|
||||||
|
Snackbar.make(binding.snackbar, "no assets", Snackbar.LENGTH_SHORT).show();
|
||||||
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -137,20 +227,21 @@ public class RepoItemActivity extends BaseActivity {
|
||||||
public int getItemCount() {
|
public int getItemCount() {
|
||||||
return items.size();
|
return items.size();
|
||||||
}
|
}
|
||||||
|
}
|
||||||
class ViewHolder extends RecyclerView.ViewHolder {
|
|
||||||
TextView title;
|
|
||||||
TextView description;
|
|
||||||
|
|
||||||
|
|
||||||
public ViewHolder(ItemRepoReleaseBinding binding) {
|
static class TitleDescriptionHolder extends RecyclerView.ViewHolder {
|
||||||
super(binding.getRoot());
|
TextView title;
|
||||||
title = binding.appName;
|
LinkifyTextView description;
|
||||||
description = binding.description;
|
|
||||||
}
|
public TitleDescriptionHolder(ItemRepoTitleDescriptionBinding binding) {
|
||||||
|
super(binding.getRoot());
|
||||||
|
title = binding.title;
|
||||||
|
description = binding.description;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
private class PagerAdapter extends RecyclerView.Adapter<PagerAdapter.ViewHolder> {
|
private class PagerAdapter extends RecyclerView.Adapter<PagerAdapter.ViewHolder> {
|
||||||
|
|
||||||
@NonNull
|
@NonNull
|
||||||
|
|
@ -159,7 +250,7 @@ public class RepoItemActivity extends BaseActivity {
|
||||||
if (viewType == 0) {
|
if (viewType == 0) {
|
||||||
return new ViewHolder(ItemRepoReadmeBinding.inflate(getLayoutInflater(), parent, false).getRoot(), viewType);
|
return new ViewHolder(ItemRepoReadmeBinding.inflate(getLayoutInflater(), parent, false).getRoot(), viewType);
|
||||||
} else {
|
} else {
|
||||||
return new ViewHolder(ItemRepoReleasesBinding.inflate(getLayoutInflater(), parent, false).getRoot(), viewType);
|
return new ViewHolder(ItemRepoRecyclerviewBinding.inflate(getLayoutInflater(), parent, false).getRoot(), viewType);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -192,24 +283,30 @@ public class RepoItemActivity extends BaseActivity {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (position == 0) {
|
switch (position) {
|
||||||
holder.textView.setTransformationMethod(new LinkTransformationMethod(RepoItemActivity.this));
|
case 0:
|
||||||
markwon.setMarkdown(holder.textView, module.getReadme());
|
holder.textView.setTransformationMethod(new LinkTransformationMethod(RepoItemActivity.this));
|
||||||
} else {
|
markwon.setMarkdown(holder.textView, module.getReadme());
|
||||||
ReleaseAdapter adapter = new ReleaseAdapter(module.getReleases());
|
break;
|
||||||
holder.recyclerView.setAdapter(adapter);
|
case 1:
|
||||||
holder.recyclerView.setLayoutManager(new LinearLayoutManagerFix(RepoItemActivity.this));
|
holder.recyclerView.setAdapter(new ReleaseAdapter(module.getReleases()));
|
||||||
|
holder.recyclerView.setLayoutManager(new LinearLayoutManagerFix(RepoItemActivity.this));
|
||||||
|
break;
|
||||||
|
case 2:
|
||||||
|
holder.recyclerView.setAdapter(new InformationAdapter(module));
|
||||||
|
holder.recyclerView.setLayoutManager(new LinearLayoutManagerFix(RepoItemActivity.this));
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int getItemCount() {
|
public int getItemCount() {
|
||||||
return 2;
|
return 3;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int getItemViewType(int position) {
|
public int getItemViewType(int position) {
|
||||||
return position;
|
return position == 0 ? 0 : 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
class ViewHolder extends RecyclerView.ViewHolder {
|
class ViewHolder extends RecyclerView.ViewHolder {
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,92 @@
|
||||||
|
/*
|
||||||
|
* Copyright 2015 Hippo Seven
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package io.github.lsposed.manager.ui.widget;
|
||||||
|
|
||||||
|
import android.annotation.SuppressLint;
|
||||||
|
import android.content.Context;
|
||||||
|
import android.text.Layout;
|
||||||
|
import android.text.Spanned;
|
||||||
|
import android.text.style.ClickableSpan;
|
||||||
|
import android.util.AttributeSet;
|
||||||
|
import android.view.MotionEvent;
|
||||||
|
|
||||||
|
import androidx.annotation.NonNull;
|
||||||
|
|
||||||
|
public class LinkifyTextView extends androidx.appcompat.widget.AppCompatTextView {
|
||||||
|
|
||||||
|
private ClickableSpan mCurrentSpan;
|
||||||
|
|
||||||
|
public LinkifyTextView(Context context) {
|
||||||
|
super(context);
|
||||||
|
}
|
||||||
|
|
||||||
|
public LinkifyTextView(Context context, AttributeSet attrs) {
|
||||||
|
super(context, attrs);
|
||||||
|
}
|
||||||
|
|
||||||
|
public LinkifyTextView(Context context, AttributeSet attrs, int defStyleAttr) {
|
||||||
|
super(context, attrs, defStyleAttr);
|
||||||
|
}
|
||||||
|
|
||||||
|
public ClickableSpan getCurrentSpan() {
|
||||||
|
return mCurrentSpan;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void clearCurrentSpan() {
|
||||||
|
mCurrentSpan = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@SuppressLint("ClickableViewAccessibility")
|
||||||
|
@Override
|
||||||
|
public boolean onTouchEvent(@NonNull MotionEvent event) {
|
||||||
|
// Let the parent or grandparent of TextView to handles click aciton.
|
||||||
|
// Otherwise click effect like ripple will not work, and if touch area
|
||||||
|
// do not contain a url, the TextView will still get MotionEvent.
|
||||||
|
// onTouchEven must be called with MotionEvent.ACTION_DOWN for each touch
|
||||||
|
// action on it, so we analyze touched url here.
|
||||||
|
if (event.getAction() == MotionEvent.ACTION_DOWN) {
|
||||||
|
mCurrentSpan = null;
|
||||||
|
|
||||||
|
if (getText() instanceof Spanned) {
|
||||||
|
// Get this code from android.text.method.LinkMovementMethod.
|
||||||
|
// Work fine !
|
||||||
|
int x = (int) event.getX();
|
||||||
|
int y = (int) event.getY();
|
||||||
|
|
||||||
|
x -= getTotalPaddingLeft();
|
||||||
|
y -= getTotalPaddingTop();
|
||||||
|
|
||||||
|
x += getScrollX();
|
||||||
|
y += getScrollY();
|
||||||
|
|
||||||
|
Layout layout = getLayout();
|
||||||
|
if (null != layout) {
|
||||||
|
int line = layout.getLineForVertical(y);
|
||||||
|
int off = layout.getOffsetForHorizontal(line, x);
|
||||||
|
|
||||||
|
ClickableSpan[] spans = ((Spanned) getText()).getSpans(off, off, ClickableSpan.class);
|
||||||
|
|
||||||
|
if (spans.length > 0) {
|
||||||
|
mCurrentSpan = spans[0];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return super.onTouchEvent(event);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -30,7 +30,7 @@ public class CustomTabsURLSpan extends URLSpan {
|
||||||
|
|
||||||
private final BaseActivity activity;
|
private final BaseActivity activity;
|
||||||
|
|
||||||
CustomTabsURLSpan(BaseActivity activity, String url) {
|
public CustomTabsURLSpan(BaseActivity activity, String url) {
|
||||||
super(url);
|
super(url);
|
||||||
this.activity = activity;
|
this.activity = activity;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -39,7 +39,7 @@
|
||||||
tools:ignore="RtlSymmetry">
|
tools:ignore="RtlSymmetry">
|
||||||
|
|
||||||
<TextView
|
<TextView
|
||||||
android:id="@+id/app_name"
|
android:id="@+id/title"
|
||||||
android:layout_width="0dp"
|
android:layout_width="0dp"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:textAppearance="?android:attr/textAppearanceListItem"
|
android:textAppearance="?android:attr/textAppearanceListItem"
|
||||||
|
|
@ -50,7 +50,7 @@
|
||||||
app:layout_constraintBottom_toBottomOf="parent"
|
app:layout_constraintBottom_toBottomOf="parent"
|
||||||
tools:text="@tools:sample/lorem" />
|
tools:text="@tools:sample/lorem" />
|
||||||
|
|
||||||
<TextView
|
<io.github.lsposed.manager.ui.widget.LinkifyTextView
|
||||||
android:id="@+id/description"
|
android:id="@+id/description"
|
||||||
android:layout_width="0dp"
|
android:layout_width="0dp"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
|
|
@ -58,8 +58,8 @@
|
||||||
android:textAppearance="?android:attr/textAppearanceSmall"
|
android:textAppearance="?android:attr/textAppearanceSmall"
|
||||||
app:layout_constraintBottom_toBottomOf="parent"
|
app:layout_constraintBottom_toBottomOf="parent"
|
||||||
app:layout_constraintEnd_toEndOf="parent"
|
app:layout_constraintEnd_toEndOf="parent"
|
||||||
app:layout_constraintStart_toStartOf="@+id/app_name"
|
app:layout_constraintStart_toStartOf="@+id/title"
|
||||||
app:layout_constraintTop_toBottomOf="@id/app_name"
|
app:layout_constraintTop_toBottomOf="@id/title"
|
||||||
tools:text="@tools:sample/lorem" />
|
tools:text="@tools:sample/lorem" />
|
||||||
|
|
||||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||||
|
|
@ -150,4 +150,8 @@
|
||||||
<string name="module_repo_summary">repository</string>
|
<string name="module_repo_summary">repository</string>
|
||||||
<string name="module_readme">Readme</string>
|
<string name="module_readme">Readme</string>
|
||||||
<string name="module_releases">Releases</string>
|
<string name="module_releases">Releases</string>
|
||||||
|
<string name="module_information">Info</string>
|
||||||
|
<string name="module_information_homepage">Homepage</string>
|
||||||
|
<string name="module_information_source_url">Source code</string>
|
||||||
|
<string name="module_information_collaborators">Collaborators</string>
|
||||||
</resources>
|
</resources>
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue