Fix viewing licenses

This commit is contained in:
wb9688 2020-05-03 14:11:34 +02:00
parent e16a2d7cb6
commit a9697a61ad
2 changed files with 57 additions and 93 deletions

View file

@ -2,8 +2,6 @@ package org.schabi.newpipe.about;
import android.app.Activity; import android.app.Activity;
import android.content.Context; import android.content.Context;
import android.content.Intent;
import android.net.Uri;
import android.os.Bundle; import android.os.Bundle;
import android.view.ContextMenu; import android.view.ContextMenu;
import android.view.LayoutInflater; import android.view.LayoutInflater;
@ -17,9 +15,9 @@ import androidx.annotation.Nullable;
import androidx.fragment.app.Fragment; import androidx.fragment.app.Fragment;
import org.schabi.newpipe.R; import org.schabi.newpipe.R;
import org.schabi.newpipe.util.ShareUtils;
import java.util.Arrays; import java.util.Arrays;
import java.util.Comparator;
/** /**
* Fragment containing the software licenses. * Fragment containing the software licenses.
@ -27,7 +25,7 @@ import java.util.Comparator;
public class LicenseFragment extends Fragment { public class LicenseFragment extends Fragment {
private static final String ARG_COMPONENTS = "components"; private static final String ARG_COMPONENTS = "components";
private SoftwareComponent[] softwareComponents; private SoftwareComponent[] softwareComponents;
private SoftwareComponent mComponentForContextMenu; private SoftwareComponent componentForContextMenu;
public static LicenseFragment newInstance(final SoftwareComponent[] softwareComponents) { public static LicenseFragment newInstance(final SoftwareComponent[] softwareComponents) {
if (softwareComponents == null) { if (softwareComponents == null) {
@ -46,7 +44,7 @@ public class LicenseFragment extends Fragment {
* @param context the context to use * @param context the context to use
* @param license the license to show * @param license the license to show
*/ */
public static void showLicense(final Context context, final License license) { private static void showLicense(final Context context, final License license) {
new LicenseFragmentHelper((Activity) context).execute(license); new LicenseFragmentHelper((Activity) context).execute(license);
} }
@ -57,45 +55,34 @@ public class LicenseFragment extends Fragment {
.getParcelableArray(ARG_COMPONENTS); .getParcelableArray(ARG_COMPONENTS);
// Sort components by name // Sort components by name
Arrays.sort(softwareComponents, new Comparator<SoftwareComponent>() { Arrays.sort(softwareComponents, (o1, o2) -> o1.getName().compareTo(o2.getName()));
@Override
public int compare(final SoftwareComponent o1, final SoftwareComponent o2) {
return o1.getName().compareTo(o2.getName());
}
});
} }
@Nullable @Nullable
@Override @Override
public View onCreateView(final LayoutInflater inflater, @Nullable final ViewGroup container, public View onCreateView(final LayoutInflater inflater, @Nullable final ViewGroup container,
@Nullable final Bundle savedInstanceState) { @Nullable final Bundle savedInstanceState) {
View rootView = inflater.inflate(R.layout.fragment_licenses, container, false); final View rootView = inflater.inflate(R.layout.fragment_licenses, container, false);
ViewGroup softwareComponentsView = rootView.findViewById(R.id.software_components); final ViewGroup softwareComponentsView = rootView.findViewById(R.id.software_components);
View licenseLink = rootView.findViewById(R.id.app_read_license); final View licenseLink = rootView.findViewById(R.id.app_read_license);
licenseLink.setOnClickListener(new OnReadFullLicenseClickListener()); licenseLink.setOnClickListener(v ->
showLicense(getActivity(), StandardLicenses.GPL3));
for (final SoftwareComponent component : softwareComponents) { for (final SoftwareComponent component : softwareComponents) {
View componentView = inflater final View componentView = inflater
.inflate(R.layout.item_software_component, container, false); .inflate(R.layout.item_software_component, container, false);
TextView softwareName = componentView.findViewById(R.id.name); final TextView softwareName = componentView.findViewById(R.id.name);
TextView copyright = componentView.findViewById(R.id.copyright); final TextView copyright = componentView.findViewById(R.id.copyright);
softwareName.setText(component.getName()); softwareName.setText(component.getName());
copyright.setText(getContext().getString(R.string.copyright, copyright.setText(getString(R.string.copyright,
component.getYears(), component.getYears(),
component.getCopyrightOwner(), component.getCopyrightOwner(),
component.getLicense().getAbbreviation())); component.getLicense().getAbbreviation()));
componentView.setTag(component); componentView.setTag(component);
componentView.setOnClickListener(new View.OnClickListener() { componentView.setOnClickListener(v ->
@Override showLicense(getActivity(), component.getLicense()));
public void onClick(final View v) {
Context context = v.getContext();
if (context != null) {
showLicense(context, component.getLicense());
}
}
});
softwareComponentsView.addView(componentView); softwareComponentsView.addView(componentView);
registerForContextMenu(componentView); registerForContextMenu(componentView);
} }
@ -105,40 +92,28 @@ public class LicenseFragment extends Fragment {
@Override @Override
public void onCreateContextMenu(final ContextMenu menu, final View v, public void onCreateContextMenu(final ContextMenu menu, final View v,
final ContextMenu.ContextMenuInfo menuInfo) { final ContextMenu.ContextMenuInfo menuInfo) {
MenuInflater inflater = getActivity().getMenuInflater(); final MenuInflater inflater = getActivity().getMenuInflater();
SoftwareComponent component = (SoftwareComponent) v.getTag(); final SoftwareComponent component = (SoftwareComponent) v.getTag();
menu.setHeaderTitle(component.getName()); menu.setHeaderTitle(component.getName());
inflater.inflate(R.menu.software_component, menu); inflater.inflate(R.menu.software_component, menu);
super.onCreateContextMenu(menu, v, menuInfo); super.onCreateContextMenu(menu, v, menuInfo);
mComponentForContextMenu = (SoftwareComponent) v.getTag(); componentForContextMenu = (SoftwareComponent) v.getTag();
} }
@Override @Override
public boolean onContextItemSelected(final MenuItem item) { public boolean onContextItemSelected(final MenuItem item) {
// item.getMenuInfo() is null so we use the tag of the view // item.getMenuInfo() is null so we use the tag of the view
final SoftwareComponent component = mComponentForContextMenu; final SoftwareComponent component = componentForContextMenu;
if (component == null) { if (component == null) {
return false; return false;
} }
switch (item.getItemId()) { switch (item.getItemId()) {
case R.id.action_website: case R.id.action_website:
openWebsite(component.getLink()); ShareUtils.openUrlInBrowser(getActivity(), component.getLink());
return true; return true;
case R.id.action_show_license: case R.id.action_show_license:
showLicense(getContext(), component.getLicense()); showLicense(getActivity(), component.getLicense());
} }
return false; return false;
} }
private void openWebsite(final String componentLink) {
Intent browserIntent = new Intent(Intent.ACTION_VIEW, Uri.parse(componentLink));
startActivity(browserIntent);
}
private static class OnReadFullLicenseClickListener implements View.OnClickListener {
@Override
public void onClick(final View v) {
LicenseFragment.showLicense(v.getContext(), StandardLicenses.GPL3);
}
}
} }

View file

@ -3,8 +3,10 @@ package org.schabi.newpipe.about;
import android.app.Activity; import android.app.Activity;
import android.content.Context; import android.content.Context;
import android.os.AsyncTask; import android.os.AsyncTask;
import android.util.Base64;
import android.webkit.WebView; import android.webkit.WebView;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable; import androidx.annotation.Nullable;
import androidx.appcompat.app.AlertDialog; import androidx.appcompat.app.AlertDialog;
@ -12,6 +14,7 @@ import org.schabi.newpipe.R;
import org.schabi.newpipe.util.ThemeHelper; import org.schabi.newpipe.util.ThemeHelper;
import java.io.BufferedReader; import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader; import java.io.InputStreamReader;
import java.lang.ref.WeakReference; import java.lang.ref.WeakReference;
import java.nio.charset.StandardCharsets; import java.nio.charset.StandardCharsets;
@ -26,28 +29,18 @@ public class LicenseFragmentHelper extends AsyncTask<Object, Void, Integer> {
weakReference = new WeakReference<>(activity); weakReference = new WeakReference<>(activity);
} }
private static String getFinishString(final Activity activity) {
return activity.getApplicationContext().getResources().getString(R.string.finish);
}
/** /**
* @param context the context to use * @param context the context to use
* @param license the license * @param license the license
* @return String which contains a HTML formatted license page * @return String which contains a HTML formatted license page
* styled according to the context's theme * styled according to the context's theme
*/ */
public static String getFormattedLicense(final Context context, final License license) { private static String getFormattedLicense(@NonNull final Context context,
if (context == null) { @NonNull final License license) {
throw new NullPointerException("context is null"); final StringBuilder licenseContent = new StringBuilder();
} final String webViewData;
if (license == null) {
throw new NullPointerException("license is null");
}
StringBuilder licenseContent = new StringBuilder();
String webViewData;
try { try {
BufferedReader in = new BufferedReader(new InputStreamReader( final BufferedReader in = new BufferedReader(new InputStreamReader(
context.getAssets().open(license.getFilename()), StandardCharsets.UTF_8)); context.getAssets().open(license.getFilename()), StandardCharsets.UTF_8));
String str; String str;
while ((str = in.readLine()) != null) { while ((str = in.readLine()) != null) {
@ -56,13 +49,11 @@ public class LicenseFragmentHelper extends AsyncTask<Object, Void, Integer> {
in.close(); in.close();
// split the HTML file and insert the stylesheet into the HEAD of the file // split the HTML file and insert the stylesheet into the HEAD of the file
String[] insert = licenseContent.toString().split("</head>"); webViewData = licenseContent.toString().replace("</head>",
webViewData = insert[0] + "<style type=\"text/css\">" "<style>" + getLicenseStylesheet(context) + "</style></head>");
+ getLicenseStylesheet(context) + "</style></head>" } catch (IOException e) {
+ insert[1]; throw new IllegalArgumentException(
} catch (Exception e) { "Could not get license file: " + license.getFilename(), e);
throw new NullPointerException("could not get license file:"
+ getLicenseStylesheet(context));
} }
return webViewData; return webViewData;
} }
@ -71,21 +62,19 @@ public class LicenseFragmentHelper extends AsyncTask<Object, Void, Integer> {
* @param context * @param context
* @return String which is a CSS stylesheet according to the context's theme * @return String which is a CSS stylesheet according to the context's theme
*/ */
public static String getLicenseStylesheet(final Context context) { private static String getLicenseStylesheet(final Context context) {
boolean isLightTheme = ThemeHelper.isLightThemeSelected(context); final boolean isLightTheme = ThemeHelper.isLightThemeSelected(context);
return "body{padding:12px 15px;margin:0;background:#" return "body{padding:12px 15px;margin:0;"
+ getHexRGBColor(context, isLightTheme + "background:#" + getHexRGBColor(context, isLightTheme
? R.color.light_license_background_color ? R.color.light_license_background_color
: R.color.dark_license_background_color) : R.color.dark_license_background_color) + ";"
+ ";color:#" + "color:#" + getHexRGBColor(context, isLightTheme
+ getHexRGBColor(context, isLightTheme
? R.color.light_license_text_color ? R.color.light_license_text_color
: R.color.dark_license_text_color) + ";}" : R.color.dark_license_text_color) + "}"
+ "a[href]{color:#" + "a[href]{color:#" + getHexRGBColor(context, isLightTheme
+ getHexRGBColor(context, isLightTheme
? R.color.light_youtube_primary_color ? R.color.light_youtube_primary_color
: R.color.dark_youtube_primary_color) + ";}" : R.color.dark_youtube_primary_color) + "}"
+ "pre{white-space: pre-wrap;}"; + "pre{white-space:pre-wrap}";
} }
/** /**
@ -95,13 +84,13 @@ public class LicenseFragmentHelper extends AsyncTask<Object, Void, Integer> {
* @param color the color number from R.color * @param color the color number from R.color
* @return a six characters long String with hexadecimal RGB values * @return a six characters long String with hexadecimal RGB values
*/ */
public static String getHexRGBColor(final Context context, final int color) { private static String getHexRGBColor(final Context context, final int color) {
return context.getResources().getString(color).substring(3); return context.getResources().getString(color).substring(3);
} }
@Nullable @Nullable
private Activity getActivity() { private Activity getActivity() {
Activity activity = weakReference.get(); final Activity activity = weakReference.get();
if (activity != null && activity.isFinishing()) { if (activity != null && activity.isFinishing()) {
return null; return null;
@ -118,22 +107,22 @@ public class LicenseFragmentHelper extends AsyncTask<Object, Void, Integer> {
@Override @Override
protected void onPostExecute(final Integer result) { protected void onPostExecute(final Integer result) {
Activity activity = getActivity(); final Activity activity = getActivity();
if (activity == null) { if (activity == null) {
return; return;
} }
String webViewData = getFormattedLicense(activity, license); final String webViewData = Base64.encodeToString(getFormattedLicense(activity, license)
AlertDialog.Builder alert = new AlertDialog.Builder(activity); .getBytes(StandardCharsets.UTF_8), Base64.NO_PADDING);
final WebView webView = new WebView(activity);
webView.loadData(webViewData, "text/html; charset=UTF-8", "base64");
final AlertDialog.Builder alert = new AlertDialog.Builder(activity);
alert.setTitle(license.getName()); alert.setTitle(license.getName());
alert.setView(webView);
WebView wv = new WebView(activity); assureCorrectAppLanguage(activity);
wv.loadData(webViewData, "text/html; charset=UTF-8", null); alert.setNegativeButton(activity.getString(R.string.finish),
(dialog, which) -> dialog.dismiss());
alert.setView(wv);
assureCorrectAppLanguage(activity.getApplicationContext());
alert.setNegativeButton(getFinishString(activity), (dialog, which) -> dialog.dismiss());
alert.show(); alert.show();
} }
} }