Fix viewing licenses
This commit is contained in:
parent
e16a2d7cb6
commit
a9697a61ad
2 changed files with 57 additions and 93 deletions
|
@ -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);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -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();
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue