diff --git a/app/src/main/java/org/fdroid/fdroid/views/AppDetailsRecyclerViewAdapter.java b/app/src/main/java/org/fdroid/fdroid/views/AppDetailsRecyclerViewAdapter.java
index 6c8b24cb8..85f9e2dc1 100644
--- a/app/src/main/java/org/fdroid/fdroid/views/AppDetailsRecyclerViewAdapter.java
+++ b/app/src/main/java/org/fdroid/fdroid/views/AppDetailsRecyclerViewAdapter.java
@@ -53,6 +53,7 @@ import org.fdroid.fdroid.data.RepoProvider;
import org.fdroid.fdroid.installer.Installer;
import org.fdroid.fdroid.privileged.views.AppDiff;
import org.fdroid.fdroid.privileged.views.AppSecurityPermissions;
+import org.fdroid.fdroid.views.appdetails.AntiFeaturesListingView;
import org.fdroid.fdroid.views.main.MainActivity;
import java.io.File;
@@ -379,9 +380,10 @@ public class AppDetailsRecyclerViewAdapter
final TextView whatsNewView;
final TextView descriptionView;
final TextView descriptionMoreView;
+ final View antiFeaturesSectionView;
final TextView antiFeaturesLabelView;
- final TextView antiFeaturesView;
final View antiFeaturesWarningView;
+ final AntiFeaturesListingView antiFeaturesListingView;
final View buttonLayout;
final Button buttonPrimaryView;
final Button buttonSecondaryView;
@@ -402,9 +404,10 @@ public class AppDetailsRecyclerViewAdapter
whatsNewView = (TextView) view.findViewById(R.id.whats_new);
descriptionView = (TextView) view.findViewById(R.id.description);
descriptionMoreView = (TextView) view.findViewById(R.id.description_more);
+ antiFeaturesSectionView = view.findViewById(R.id.anti_features_section);
antiFeaturesLabelView = (TextView) view.findViewById(R.id.label_anti_features);
- antiFeaturesView = (TextView) view.findViewById(R.id.text_anti_features);
antiFeaturesWarningView = view.findViewById(R.id.anti_features_warning);
+ antiFeaturesListingView = view.findViewById(R.id.anti_features_full_listing);
buttonLayout = view.findViewById(R.id.button_layout);
buttonPrimaryView = (Button) view.findViewById(R.id.primaryButtonView);
buttonSecondaryView = (Button) view.findViewById(R.id.secondaryButtonView);
@@ -545,23 +548,10 @@ public class AppDetailsRecyclerViewAdapter
}
}
});
- if (app.antiFeatures != null && app.antiFeatures.length > 0) {
- StringBuilder sb = new StringBuilder();
- for (String af : app.antiFeatures) {
- String afdesc = descAntiFeature(af);
- sb.append("
")
- .append(afdesc)
- .append("
");
- }
- antiFeaturesView.setText(trimTrailingNewlines(Html.fromHtml(sb.toString())));
- antiFeaturesView.setMovementMethod(LinkMovementMethod.getInstance());
- } else {
- antiFeaturesView.setVisibility(View.GONE);
- }
+ antiFeaturesListingView.setApp(app);
updateAntiFeaturesWarning();
+
buttonPrimaryView.setText(R.string.menu_install);
buttonPrimaryView.setVisibility(versions.isEmpty() ? View.GONE : View.VISIBLE);
buttonSecondaryView.setText(R.string.menu_uninstall);
@@ -664,41 +654,16 @@ public class AppDetailsRecyclerViewAdapter
}
private void updateAntiFeaturesWarning() {
- if (app.antiFeatures == null || TextUtils.isEmpty(antiFeaturesView.getText())) {
- antiFeaturesLabelView.setVisibility(View.GONE);
- antiFeaturesView.setVisibility(View.GONE);
+ if (app.antiFeatures == null || app.antiFeatures.length == 0) {
+ antiFeaturesSectionView.setVisibility(View.GONE);
+ } else if (descriptionIsExpanded) {
antiFeaturesWarningView.setVisibility(View.GONE);
+ antiFeaturesLabelView.setVisibility(View.VISIBLE);
+ antiFeaturesListingView.setVisibility(View.VISIBLE);
} else {
- antiFeaturesLabelView.setVisibility(descriptionIsExpanded ? View.VISIBLE : View.GONE);
- antiFeaturesView.setVisibility(descriptionIsExpanded ? View.VISIBLE : View.GONE);
- antiFeaturesWarningView.setVisibility(descriptionIsExpanded ? View.GONE : View.VISIBLE);
- }
- }
-
- private String descAntiFeature(String af) {
- switch (af) {
- case "Ads":
- return itemView.getContext().getString(R.string.antiadslist);
- case "Tracking":
- return itemView.getContext().getString(R.string.antitracklist);
- case "NonFreeNet":
- return itemView.getContext().getString(R.string.antinonfreenetlist);
- case "NonFreeAdd":
- return itemView.getContext().getString(R.string.antinonfreeadlist);
- case "NonFreeDep":
- return itemView.getContext().getString(R.string.antinonfreedeplist);
- case "UpstreamNonFree":
- return itemView.getContext().getString(R.string.antiupstreamnonfreelist);
- case "NonFreeAssets":
- return itemView.getContext().getString(R.string.antinonfreeassetslist);
- case "DisabledAlgorithm":
- return itemView.getContext().getString(R.string.antidisabledalgorithmlist);
- case "KnownVuln":
- return itemView.getContext().getString(R.string.antiknownvulnlist);
- case "NoSourceSince":
- return itemView.getContext().getString(R.string.antinosourcesince);
- default:
- return af;
+ antiFeaturesWarningView.setVisibility(View.VISIBLE);
+ antiFeaturesLabelView.setVisibility(View.GONE);
+ antiFeaturesListingView.setVisibility(View.GONE);
}
}
}
diff --git a/app/src/main/java/org/fdroid/fdroid/views/appdetails/AntiFeaturesListingView.java b/app/src/main/java/org/fdroid/fdroid/views/appdetails/AntiFeaturesListingView.java
new file mode 100644
index 000000000..2da361829
--- /dev/null
+++ b/app/src/main/java/org/fdroid/fdroid/views/appdetails/AntiFeaturesListingView.java
@@ -0,0 +1,160 @@
+/*
+ * Copyright (C) 2019 Michael Pöhn
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 3
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+package org.fdroid.fdroid.views.appdetails;
+
+import android.content.Context;
+import android.content.Intent;
+import android.net.Uri;
+import android.os.Build;
+import android.support.annotation.DrawableRes;
+import android.support.annotation.NonNull;
+import android.support.annotation.Nullable;
+import android.support.v4.content.ContextCompat;
+import android.support.v7.widget.LinearLayoutManager;
+import android.support.v7.widget.RecyclerView;
+import android.util.AttributeSet;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.TextView;
+
+import org.fdroid.fdroid.R;
+import org.fdroid.fdroid.data.App;
+
+public class AntiFeaturesListingView extends RecyclerView {
+
+ public AntiFeaturesListingView(Context context, @Nullable AttributeSet attrs) {
+ super(context, attrs);
+ }
+
+ public void setApp(final App app) {
+
+ setHasFixedSize(true);
+
+ LinearLayoutManager layoutManager = new LinearLayoutManager(getContext());
+ setLayoutManager(layoutManager);
+
+ swapAdapter(new RecyclerView.Adapter() {
+
+ @NonNull
+ @Override
+ public AntiFeatureItemViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
+ LayoutInflater inflater = LayoutInflater.from(parent.getContext());
+ View view = inflater.inflate(R.layout.listitem_antifeaturelisting, null);
+ return new AntiFeatureItemViewHolder(view);
+ }
+
+ @Override
+ public void onBindViewHolder(@NonNull AntiFeatureItemViewHolder holder, int position) {
+ final String antiFeatureName = app.antiFeatures[position];
+ holder.antiFeatureIcon.setBackgroundDrawable(
+ ContextCompat.getDrawable(getContext(), antiFeatureIcon(antiFeatureName)));
+ holder.antiFeatureText.setText(
+ getAntiFeatureDescriptionText(holder.antiFeatureText.getContext(), antiFeatureName));
+ holder.entireView.setOnClickListener(new OnClickListener() {
+ @Override
+ public void onClick(View v) {
+ Intent i = new Intent(Intent.ACTION_VIEW);
+ if (Build.VERSION.SDK_INT >= 21) {
+ i.setFlags(Intent.FLAG_ACTIVITY_NEW_DOCUMENT);
+ } else {
+ i.setFlags(Intent.FLAG_ACTIVITY_CLEAR_WHEN_TASK_RESET);
+ }
+ i.setData(Uri.parse("https://f-droid.org/docs/Anti-Features#" + antiFeatureName));
+ getContext().startActivity(i);
+ }
+ });
+ }
+
+ @Override
+ public int getItemCount() {
+ return app == null || app.antiFeatures == null ? 0 : app.antiFeatures.length;
+ }
+ }, false);
+ }
+
+ class AntiFeatureItemViewHolder extends RecyclerView.ViewHolder {
+
+ private final View entireView;
+ private final View antiFeatureIcon;
+ private final TextView antiFeatureText;
+
+ AntiFeatureItemViewHolder(View itemView) {
+ super(itemView);
+ entireView = itemView;
+ antiFeatureIcon = itemView.findViewById(R.id.anti_feature_icon);
+ antiFeatureText = itemView.findViewById(R.id.anti_feature_text);
+ }
+
+ }
+
+ public static String getAntiFeatureDescriptionText(Context context, String antiFeatureName) {
+ switch (antiFeatureName) {
+ case "Ads":
+ return context.getString(R.string.antiadslist);
+ case "Tracking":
+ return context.getString(R.string.antitracklist);
+ case "NonFreeNet":
+ return context.getString(R.string.antinonfreenetlist);
+ case "NonFreeAdd":
+ return context.getString(R.string.antinonfreeadlist);
+ case "NonFreeDep":
+ return context.getString(R.string.antinonfreedeplist);
+ case "UpstreamNonFree":
+ return context.getString(R.string.antiupstreamnonfreelist);
+ case "NonFreeAssets":
+ return context.getString(R.string.antinonfreeassetslist);
+ case "DisabledAlgorithm":
+ return context.getString(R.string.antidisabledalgorithmlist);
+ case "KnownVuln":
+ return context.getString(R.string.antiknownvulnlist);
+ case "NoSourceSince":
+ return context.getString(R.string.antinosourcesince);
+ default:
+ return antiFeatureName;
+ }
+ }
+
+ public static @DrawableRes int antiFeatureIcon(String antiFeatureName) {
+ switch (antiFeatureName) {
+ case "Ads":
+ return R.drawable.ic_antifeature_ads;
+ case "Tracking":
+ return R.drawable.ic_antifeature_tracking;
+ case "NonFreeNet":
+ return R.drawable.ic_antifeature_nonfreenet;
+ case "NonFreeAdd":
+ return R.drawable.ic_antifeature_nonfreeadd;
+ case "NonFreeDep":
+ return R.drawable.ic_antifeature_nonfreedep;
+ case "UpstreamNonFree":
+ return R.drawable.ic_antifeature_upstreamnonfree;
+ case "NonFreeAssets":
+ return R.drawable.ic_antifeature_nonfreeassets;
+ case "DisabledAlgorithm":
+ return R.drawable.ic_antifeature_disabledalgorithm;
+ case "KnownVuln":
+ return R.drawable.ic_antifeature_knownvuln;
+ case "NoSourceSince":
+ return R.drawable.ic_antifeature_nosourcesince;
+ default:
+ return R.drawable.ic_cancel;
+ }
+ }
+}
diff --git a/app/src/main/res/drawable/ic_antifeature_ads.xml b/app/src/main/res/drawable/ic_antifeature_ads.xml
new file mode 100644
index 000000000..0e64a7776
--- /dev/null
+++ b/app/src/main/res/drawable/ic_antifeature_ads.xml
@@ -0,0 +1,5 @@
+
+
+
+
diff --git a/app/src/main/res/drawable/ic_antifeature_disabledalgorithm.xml b/app/src/main/res/drawable/ic_antifeature_disabledalgorithm.xml
new file mode 100644
index 000000000..c44d42931
--- /dev/null
+++ b/app/src/main/res/drawable/ic_antifeature_disabledalgorithm.xml
@@ -0,0 +1,7 @@
+
+
+
+
+
+
diff --git a/app/src/main/res/drawable/ic_antifeature_knownvuln.xml b/app/src/main/res/drawable/ic_antifeature_knownvuln.xml
new file mode 100644
index 000000000..2e52f1d7d
--- /dev/null
+++ b/app/src/main/res/drawable/ic_antifeature_knownvuln.xml
@@ -0,0 +1,5 @@
+
+
+
+
diff --git a/app/src/main/res/drawable/ic_antifeature_nonfreeadd.xml b/app/src/main/res/drawable/ic_antifeature_nonfreeadd.xml
new file mode 100644
index 000000000..880b5efbe
--- /dev/null
+++ b/app/src/main/res/drawable/ic_antifeature_nonfreeadd.xml
@@ -0,0 +1,7 @@
+
+
+
+
+
+
diff --git a/app/src/main/res/drawable/ic_antifeature_nonfreeassets.xml b/app/src/main/res/drawable/ic_antifeature_nonfreeassets.xml
new file mode 100644
index 000000000..f95fb2689
--- /dev/null
+++ b/app/src/main/res/drawable/ic_antifeature_nonfreeassets.xml
@@ -0,0 +1,7 @@
+
+
+
+
+
+
diff --git a/app/src/main/res/drawable/ic_antifeature_nonfreedep.xml b/app/src/main/res/drawable/ic_antifeature_nonfreedep.xml
new file mode 100644
index 000000000..5ae690aa5
--- /dev/null
+++ b/app/src/main/res/drawable/ic_antifeature_nonfreedep.xml
@@ -0,0 +1,8 @@
+
+
+
+
+
+
+
diff --git a/app/src/main/res/drawable/ic_antifeature_nonfreenet.xml b/app/src/main/res/drawable/ic_antifeature_nonfreenet.xml
new file mode 100644
index 000000000..98d48a4e4
--- /dev/null
+++ b/app/src/main/res/drawable/ic_antifeature_nonfreenet.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/app/src/main/res/drawable/ic_antifeature_nosourcesince.xml b/app/src/main/res/drawable/ic_antifeature_nosourcesince.xml
new file mode 100644
index 000000000..1637ee001
--- /dev/null
+++ b/app/src/main/res/drawable/ic_antifeature_nosourcesince.xml
@@ -0,0 +1,6 @@
+
+
+
+
+
diff --git a/app/src/main/res/drawable/ic_antifeature_tracking.xml b/app/src/main/res/drawable/ic_antifeature_tracking.xml
new file mode 100644
index 000000000..f5c38d6b0
--- /dev/null
+++ b/app/src/main/res/drawable/ic_antifeature_tracking.xml
@@ -0,0 +1,8 @@
+
+
+
+
+
+
+
diff --git a/app/src/main/res/drawable/ic_antifeature_upstreamnonfree.xml b/app/src/main/res/drawable/ic_antifeature_upstreamnonfree.xml
new file mode 100644
index 000000000..56cfb73d6
--- /dev/null
+++ b/app/src/main/res/drawable/ic_antifeature_upstreamnonfree.xml
@@ -0,0 +1,7 @@
+
+
+
+
+
+
diff --git a/app/src/main/res/layout/app_details2_header.xml b/app/src/main/res/layout/app_details2_header.xml
index b65d4454e..6785d3e85 100644
--- a/app/src/main/res/layout/app_details2_header.xml
+++ b/app/src/main/res/layout/app_details2_header.xml
@@ -7,14 +7,15 @@
android:layout_margin="@dimen/details_activity_padding"
app:cardBackgroundColor="?attr/appDetailsCardBackground"
app:cardCornerRadius="3dp"
- app:cardElevation="3dp">
+ app:cardElevation="3dp"
+ android:animateLayoutChanges="true">
+ android:paddingBottom="8dp">
+ android:src="@drawable/ic_repo_app_default"
+ android:transitionName="@string/transition_app_item_icon" />
+ android:layout_toLeftOf="@id/progress_cancel"
+ android:textAppearance="@style/TextAppearance.AppCompat.Small"
+ tools:text="500%" />
+ android:layout_alignParentStart="true"
+ android:layout_alignParentLeft="true"
+ android:layout_toStartOf="@id/progress_cancel"
+ android:layout_toLeftOf="@id/progress_cancel" />
@@ -136,10 +137,10 @@
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_below="@id/icon_and_name"
- android:paddingBottom="4dp"
android:clipToPadding="false"
- android:visibility="visible"
- android:gravity="end">
+ android:gravity="end"
+ android:paddingBottom="4dp"
+ android:visibility="visible">
+ tools:text="Uninstall" />
+ tools:text="Open" />
@@ -184,75 +185,73 @@
android:id="@+id/whats_new"
android:layout_width="match_parent"
android:layout_height="wrap_content"
- android:layout_marginTop="2dp"
+ android:background="?attr/detailPanel"
android:paddingStart="8dp"
android:paddingLeft="8dp"
+ android:paddingTop="16dp"
android:paddingEnd="8dp"
android:paddingRight="8dp"
- android:paddingTop="16dp"
android:paddingBottom="16dp"
android:textAppearance="@style/TextAppearance.AppCompat.Body1"
- android:background="?attr/detailPanel"
tools:text="NEW IN VERSION 1.0.2233\n\nA lot has happened since the last build:\n\n\t• Improved UI\n\t• Bug fixes" />
+
-
+ android:layout_marginTop="16dp"
+ android:orientation="vertical">
-
+
-
+
+
+
+
+
+
+
diff --git a/app/src/main/res/layout/listitem_antifeaturelisting.xml b/app/src/main/res/layout/listitem_antifeaturelisting.xml
new file mode 100644
index 000000000..7f0e8c207
--- /dev/null
+++ b/app/src/main/res/layout/listitem_antifeaturelisting.xml
@@ -0,0 +1,28 @@
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/values/attrs.xml b/app/src/main/res/values/attrs.xml
index 34c4a5a03..06d94df96 100644
--- a/app/src/main/res/values/attrs.xml
+++ b/app/src/main/res/values/attrs.xml
@@ -14,5 +14,6 @@
+
diff --git a/app/src/main/res/values/styles.xml b/app/src/main/res/values/styles.xml
index c28975a84..218c2c48f 100644
--- a/app/src/main/res/values/styles.xml
+++ b/app/src/main/res/values/styles.xml
@@ -25,6 +25,7 @@
- @drawable/ic_back_white_24dp
- @drawable/ic_close_white_24dp
- @style/PreferenceThemeOverlay.v14.Material
+ - #ffffff