Converted the about package to Kotlin
This commit is contained in:
parent
cc72fa4793
commit
fb1aab2a49
|
@ -1,192 +0,0 @@
|
||||||
package org.schabi.newpipe.about;
|
|
||||||
|
|
||||||
import android.content.Context;
|
|
||||||
import android.os.Bundle;
|
|
||||||
import android.view.LayoutInflater;
|
|
||||||
import android.view.MenuItem;
|
|
||||||
import android.view.View;
|
|
||||||
import android.view.ViewGroup;
|
|
||||||
|
|
||||||
import androidx.annotation.NonNull;
|
|
||||||
import androidx.appcompat.app.AppCompatActivity;
|
|
||||||
import androidx.fragment.app.Fragment;
|
|
||||||
import androidx.fragment.app.FragmentActivity;
|
|
||||||
import androidx.viewpager2.adapter.FragmentStateAdapter;
|
|
||||||
|
|
||||||
import com.google.android.material.tabs.TabLayoutMediator;
|
|
||||||
|
|
||||||
import org.schabi.newpipe.BuildConfig;
|
|
||||||
import org.schabi.newpipe.R;
|
|
||||||
import org.schabi.newpipe.databinding.ActivityAboutBinding;
|
|
||||||
import org.schabi.newpipe.databinding.FragmentAboutBinding;
|
|
||||||
import org.schabi.newpipe.util.ThemeHelper;
|
|
||||||
|
|
||||||
import static org.schabi.newpipe.util.Localization.assureCorrectAppLanguage;
|
|
||||||
import static org.schabi.newpipe.util.ShareUtils.openUrlInBrowser;
|
|
||||||
|
|
||||||
public class AboutActivity extends AppCompatActivity {
|
|
||||||
/**
|
|
||||||
* List of all software components.
|
|
||||||
*/
|
|
||||||
private static final SoftwareComponent[] SOFTWARE_COMPONENTS = {
|
|
||||||
new SoftwareComponent("ACRA", "2013", "Kevin Gaudin",
|
|
||||||
"https://github.com/ACRA/acra", StandardLicenses.APACHE2),
|
|
||||||
new SoftwareComponent("AndroidX", "2005 - 2011", "The Android Open Source Project",
|
|
||||||
"https://developer.android.com/jetpack", StandardLicenses.APACHE2),
|
|
||||||
new SoftwareComponent("CircleImageView", "2014 - 2020", "Henning Dodenhof",
|
|
||||||
"https://github.com/hdodenhof/CircleImageView",
|
|
||||||
StandardLicenses.APACHE2),
|
|
||||||
new SoftwareComponent("ExoPlayer", "2014 - 2020", "Google, Inc.",
|
|
||||||
"https://github.com/google/ExoPlayer", StandardLicenses.APACHE2),
|
|
||||||
new SoftwareComponent("GigaGet", "2014 - 2015", "Peter Cai",
|
|
||||||
"https://github.com/PaperAirplane-Dev-Team/GigaGet", StandardLicenses.GPL3),
|
|
||||||
new SoftwareComponent("Groupie", "2016", "Lisa Wray",
|
|
||||||
"https://github.com/lisawray/groupie", StandardLicenses.MIT),
|
|
||||||
new SoftwareComponent("Icepick", "2015", "Frankie Sardo",
|
|
||||||
"https://github.com/frankiesardo/icepick", StandardLicenses.EPL1),
|
|
||||||
new SoftwareComponent("Jsoup", "2009 - 2020", "Jonathan Hedley",
|
|
||||||
"https://github.com/jhy/jsoup", StandardLicenses.MIT),
|
|
||||||
new SoftwareComponent("Markwon", "2019", "Dimitry Ivanov",
|
|
||||||
"https://github.com/noties/Markwon", StandardLicenses.APACHE2),
|
|
||||||
new SoftwareComponent("Material Components for Android", "2016 - 2020", "Google, Inc.",
|
|
||||||
"https://github.com/material-components/material-components-android",
|
|
||||||
StandardLicenses.APACHE2),
|
|
||||||
new SoftwareComponent("NewPipe Extractor", "2017 - 2020", "Christian Schabesberger",
|
|
||||||
"https://github.com/TeamNewPipe/NewPipeExtractor", StandardLicenses.GPL3),
|
|
||||||
new SoftwareComponent("NoNonsense-FilePicker", "2016", "Jonas Kalderstam",
|
|
||||||
"https://github.com/spacecowboy/NoNonsense-FilePicker",
|
|
||||||
StandardLicenses.MPL2),
|
|
||||||
new SoftwareComponent("OkHttp", "2019", "Square, Inc.",
|
|
||||||
"https://square.github.io/okhttp/", StandardLicenses.APACHE2),
|
|
||||||
new SoftwareComponent("PrettyTime", "2012 - 2020", "Lincoln Baxter, III",
|
|
||||||
"https://github.com/ocpsoft/prettytime", StandardLicenses.APACHE2),
|
|
||||||
new SoftwareComponent("RxAndroid", "2015", "The RxAndroid authors",
|
|
||||||
"https://github.com/ReactiveX/RxAndroid", StandardLicenses.APACHE2),
|
|
||||||
new SoftwareComponent("RxBinding", "2015", "Jake Wharton",
|
|
||||||
"https://github.com/JakeWharton/RxBinding", StandardLicenses.APACHE2),
|
|
||||||
new SoftwareComponent("RxJava", "2016 - 2020", "RxJava Contributors",
|
|
||||||
"https://github.com/ReactiveX/RxJava", StandardLicenses.APACHE2),
|
|
||||||
new SoftwareComponent("Universal Image Loader", "2011 - 2015", "Sergey Tarasevich",
|
|
||||||
"https://github.com/nostra13/Android-Universal-Image-Loader",
|
|
||||||
StandardLicenses.APACHE2),
|
|
||||||
};
|
|
||||||
|
|
||||||
private static final int POS_ABOUT = 0;
|
|
||||||
private static final int POS_LICENSE = 1;
|
|
||||||
private static final int TOTAL_COUNT = 2;
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void onCreate(final Bundle savedInstanceState) {
|
|
||||||
assureCorrectAppLanguage(this);
|
|
||||||
super.onCreate(savedInstanceState);
|
|
||||||
ThemeHelper.setTheme(this);
|
|
||||||
setTitle(getString(R.string.title_activity_about));
|
|
||||||
|
|
||||||
final ActivityAboutBinding aboutBinding = ActivityAboutBinding.inflate(getLayoutInflater());
|
|
||||||
setContentView(aboutBinding.getRoot());
|
|
||||||
|
|
||||||
setSupportActionBar(aboutBinding.aboutToolbar);
|
|
||||||
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
|
|
||||||
// Create the adapter that will return a fragment for each of the three
|
|
||||||
// primary sections of the activity.
|
|
||||||
final AboutStateAdapter mAboutStateAdapter = new AboutStateAdapter(this);
|
|
||||||
|
|
||||||
// Set up the ViewPager with the sections adapter.
|
|
||||||
aboutBinding.aboutViewPager2.setAdapter(mAboutStateAdapter);
|
|
||||||
|
|
||||||
new TabLayoutMediator(aboutBinding.aboutTabLayout, aboutBinding.aboutViewPager2, (tab, position) -> {
|
|
||||||
switch (position) {
|
|
||||||
default:
|
|
||||||
case POS_ABOUT:
|
|
||||||
tab.setText(R.string.tab_about);
|
|
||||||
break;
|
|
||||||
case POS_LICENSE:
|
|
||||||
tab.setText(R.string.tab_licenses);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}).attach();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean onOptionsItemSelected(final MenuItem item) {
|
|
||||||
final int id = item.getItemId();
|
|
||||||
|
|
||||||
switch (id) {
|
|
||||||
case android.R.id.home:
|
|
||||||
finish();
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
return super.onOptionsItemSelected(item);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* A placeholder fragment containing a simple view.
|
|
||||||
*/
|
|
||||||
public static class AboutFragment extends Fragment {
|
|
||||||
public AboutFragment() {
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Created a new instance of this fragment for the given section number.
|
|
||||||
*
|
|
||||||
* @return New instance of {@link AboutFragment}
|
|
||||||
*/
|
|
||||||
public static AboutFragment newInstance() {
|
|
||||||
return new AboutFragment();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public View onCreateView(@NonNull final LayoutInflater inflater, final ViewGroup container,
|
|
||||||
final Bundle savedInstanceState) {
|
|
||||||
final FragmentAboutBinding aboutBinding =
|
|
||||||
FragmentAboutBinding.inflate(inflater, container, false);
|
|
||||||
final Context context = getContext();
|
|
||||||
|
|
||||||
aboutBinding.aboutAppVersion.setText(BuildConfig.VERSION_NAME);
|
|
||||||
|
|
||||||
aboutBinding.aboutGithubLink.setOnClickListener(nv ->
|
|
||||||
openUrlInBrowser(context, context.getString(R.string.github_url), false));
|
|
||||||
|
|
||||||
aboutBinding.aboutDonationLink.setOnClickListener(v ->
|
|
||||||
openUrlInBrowser(context, context.getString(R.string.donation_url), false));
|
|
||||||
|
|
||||||
aboutBinding.aboutWebsiteLink.setOnClickListener(nv ->
|
|
||||||
openUrlInBrowser(context, context.getString(R.string.website_url), false));
|
|
||||||
|
|
||||||
aboutBinding.aboutPrivacyPolicyLink.setOnClickListener(v ->
|
|
||||||
openUrlInBrowser(context, context.getString(R.string.privacy_policy_url),
|
|
||||||
false));
|
|
||||||
|
|
||||||
return aboutBinding.getRoot();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* A {@link FragmentStateAdapter} that returns a fragment corresponding to
|
|
||||||
* one of the sections/tabs/pages.
|
|
||||||
*/
|
|
||||||
private static class AboutStateAdapter extends FragmentStateAdapter {
|
|
||||||
AboutStateAdapter(final FragmentActivity fa) {
|
|
||||||
super(fa);
|
|
||||||
}
|
|
||||||
|
|
||||||
@NonNull
|
|
||||||
@Override
|
|
||||||
public Fragment createFragment(final int position) {
|
|
||||||
switch (position) {
|
|
||||||
default:
|
|
||||||
case POS_ABOUT:
|
|
||||||
return AboutFragment.newInstance();
|
|
||||||
case POS_LICENSE:
|
|
||||||
return LicenseFragment.newInstance(SOFTWARE_COMPONENTS);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public int getItemCount() {
|
|
||||||
// Show 2 total pages.
|
|
||||||
return TOTAL_COUNT;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -0,0 +1,204 @@
|
||||||
|
package org.schabi.newpipe.about
|
||||||
|
|
||||||
|
import android.os.Bundle
|
||||||
|
import android.view.LayoutInflater
|
||||||
|
import android.view.MenuItem
|
||||||
|
import android.view.View
|
||||||
|
import android.view.ViewGroup
|
||||||
|
import androidx.appcompat.app.AppCompatActivity
|
||||||
|
import androidx.fragment.app.Fragment
|
||||||
|
import androidx.fragment.app.FragmentActivity
|
||||||
|
import androidx.viewpager2.adapter.FragmentStateAdapter
|
||||||
|
import com.google.android.material.tabs.TabLayout
|
||||||
|
import com.google.android.material.tabs.TabLayoutMediator
|
||||||
|
import org.schabi.newpipe.BuildConfig
|
||||||
|
import org.schabi.newpipe.R
|
||||||
|
import org.schabi.newpipe.databinding.ActivityAboutBinding
|
||||||
|
import org.schabi.newpipe.databinding.FragmentAboutBinding
|
||||||
|
import org.schabi.newpipe.util.Localization
|
||||||
|
import org.schabi.newpipe.util.ShareUtils
|
||||||
|
import org.schabi.newpipe.util.ThemeHelper
|
||||||
|
|
||||||
|
class AboutActivity : AppCompatActivity() {
|
||||||
|
override fun onCreate(savedInstanceState: Bundle?) {
|
||||||
|
Localization.assureCorrectAppLanguage(this)
|
||||||
|
super.onCreate(savedInstanceState)
|
||||||
|
ThemeHelper.setTheme(this)
|
||||||
|
title = getString(R.string.title_activity_about)
|
||||||
|
val aboutBinding = ActivityAboutBinding.inflate(layoutInflater)
|
||||||
|
setContentView(aboutBinding.root)
|
||||||
|
setSupportActionBar(aboutBinding.aboutToolbar)
|
||||||
|
supportActionBar!!.setDisplayHomeAsUpEnabled(true)
|
||||||
|
// Create the adapter that will return a fragment for each of the three
|
||||||
|
// primary sections of the activity.
|
||||||
|
val mAboutStateAdapter = AboutStateAdapter(this)
|
||||||
|
|
||||||
|
// Set up the ViewPager with the sections adapter.
|
||||||
|
aboutBinding.aboutViewPager2.adapter = mAboutStateAdapter
|
||||||
|
TabLayoutMediator(
|
||||||
|
aboutBinding.aboutTabLayout,
|
||||||
|
aboutBinding.aboutViewPager2
|
||||||
|
) { tab: TabLayout.Tab, position: Int ->
|
||||||
|
when (position) {
|
||||||
|
POS_ABOUT -> tab.setText(R.string.tab_about)
|
||||||
|
POS_LICENSE -> tab.setText(R.string.tab_licenses)
|
||||||
|
else -> throw IllegalArgumentException("Unknown position for ViewPager2")
|
||||||
|
}
|
||||||
|
}.attach()
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onOptionsItemSelected(item: MenuItem): Boolean {
|
||||||
|
if (item.itemId == android.R.id.home) {
|
||||||
|
finish()
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
return super.onOptionsItemSelected(item)
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A placeholder fragment containing a simple view.
|
||||||
|
*/
|
||||||
|
class AboutFragment : Fragment() {
|
||||||
|
override fun onCreateView(
|
||||||
|
inflater: LayoutInflater,
|
||||||
|
container: ViewGroup?,
|
||||||
|
savedInstanceState: Bundle?
|
||||||
|
): View {
|
||||||
|
val aboutBinding = FragmentAboutBinding.inflate(inflater, container, false)
|
||||||
|
val context = context
|
||||||
|
aboutBinding.aboutAppVersion.text = BuildConfig.VERSION_NAME
|
||||||
|
aboutBinding.aboutGithubLink.setOnClickListener {
|
||||||
|
ShareUtils.openUrlInBrowser(
|
||||||
|
context,
|
||||||
|
context!!.getString(R.string.github_url),
|
||||||
|
false
|
||||||
|
)
|
||||||
|
}
|
||||||
|
aboutBinding.aboutDonationLink.setOnClickListener {
|
||||||
|
ShareUtils.openUrlInBrowser(
|
||||||
|
context,
|
||||||
|
context!!.getString(R.string.donation_url),
|
||||||
|
false
|
||||||
|
)
|
||||||
|
}
|
||||||
|
aboutBinding.aboutWebsiteLink.setOnClickListener {
|
||||||
|
ShareUtils.openUrlInBrowser(
|
||||||
|
context,
|
||||||
|
context!!.getString(R.string.website_url),
|
||||||
|
false
|
||||||
|
)
|
||||||
|
}
|
||||||
|
aboutBinding.aboutPrivacyPolicyLink.setOnClickListener {
|
||||||
|
ShareUtils.openUrlInBrowser(
|
||||||
|
context, context!!.getString(R.string.privacy_policy_url),
|
||||||
|
false
|
||||||
|
)
|
||||||
|
}
|
||||||
|
return aboutBinding.root
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A [FragmentStateAdapter] that returns a fragment corresponding to
|
||||||
|
* one of the sections/tabs/pages.
|
||||||
|
*/
|
||||||
|
private class AboutStateAdapter(fa: FragmentActivity) : FragmentStateAdapter(fa) {
|
||||||
|
override fun createFragment(position: Int): Fragment {
|
||||||
|
return when (position) {
|
||||||
|
POS_ABOUT -> AboutFragment()
|
||||||
|
POS_LICENSE -> LicenseFragment.newInstance(SOFTWARE_COMPONENTS)
|
||||||
|
else -> throw IllegalArgumentException("Unknown position for ViewPager2")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun getItemCount(): Int {
|
||||||
|
// Show 2 total pages.
|
||||||
|
return TOTAL_COUNT
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
/**
|
||||||
|
* List of all software components.
|
||||||
|
*/
|
||||||
|
private val SOFTWARE_COMPONENTS = arrayOf(
|
||||||
|
SoftwareComponent(
|
||||||
|
"ACRA", "2013", "Kevin Gaudin",
|
||||||
|
"https://github.com/ACRA/acra", StandardLicenses.APACHE2
|
||||||
|
),
|
||||||
|
SoftwareComponent(
|
||||||
|
"AndroidX", "2005 - 2011", "The Android Open Source Project",
|
||||||
|
"https://developer.android.com/jetpack", StandardLicenses.APACHE2
|
||||||
|
),
|
||||||
|
SoftwareComponent(
|
||||||
|
"CircleImageView", "2014 - 2020", "Henning Dodenhof",
|
||||||
|
"https://github.com/hdodenhof/CircleImageView", StandardLicenses.APACHE2
|
||||||
|
),
|
||||||
|
SoftwareComponent(
|
||||||
|
"ExoPlayer", "2014 - 2020", "Google, Inc.",
|
||||||
|
"https://github.com/google/ExoPlayer", StandardLicenses.APACHE2
|
||||||
|
),
|
||||||
|
SoftwareComponent(
|
||||||
|
"GigaGet", "2014 - 2015", "Peter Cai",
|
||||||
|
"https://github.com/PaperAirplane-Dev-Team/GigaGet", StandardLicenses.GPL3
|
||||||
|
),
|
||||||
|
SoftwareComponent(
|
||||||
|
"Groupie", "2016", "Lisa Wray",
|
||||||
|
"https://github.com/lisawray/groupie", StandardLicenses.MIT
|
||||||
|
),
|
||||||
|
SoftwareComponent(
|
||||||
|
"Icepick", "2015", "Frankie Sardo",
|
||||||
|
"https://github.com/frankiesardo/icepick", StandardLicenses.EPL1
|
||||||
|
),
|
||||||
|
SoftwareComponent(
|
||||||
|
"Jsoup", "2009 - 2020", "Jonathan Hedley",
|
||||||
|
"https://github.com/jhy/jsoup", StandardLicenses.MIT
|
||||||
|
),
|
||||||
|
SoftwareComponent(
|
||||||
|
"Markwon", "2019", "Dimitry Ivanov",
|
||||||
|
"https://github.com/noties/Markwon", StandardLicenses.APACHE2
|
||||||
|
),
|
||||||
|
SoftwareComponent(
|
||||||
|
"Material Components for Android", "2016 - 2020", "Google, Inc.",
|
||||||
|
"https://github.com/material-components/material-components-android",
|
||||||
|
StandardLicenses.APACHE2
|
||||||
|
),
|
||||||
|
SoftwareComponent(
|
||||||
|
"NewPipe Extractor", "2017 - 2020", "Christian Schabesberger",
|
||||||
|
"https://github.com/TeamNewPipe/NewPipeExtractor", StandardLicenses.GPL3
|
||||||
|
),
|
||||||
|
SoftwareComponent(
|
||||||
|
"NoNonsense-FilePicker", "2016", "Jonas Kalderstam",
|
||||||
|
"https://github.com/spacecowboy/NoNonsense-FilePicker", StandardLicenses.MPL2
|
||||||
|
),
|
||||||
|
SoftwareComponent(
|
||||||
|
"OkHttp", "2019", "Square, Inc.",
|
||||||
|
"https://square.github.io/okhttp/", StandardLicenses.APACHE2
|
||||||
|
),
|
||||||
|
SoftwareComponent(
|
||||||
|
"PrettyTime", "2012 - 2020", "Lincoln Baxter, III",
|
||||||
|
"https://github.com/ocpsoft/prettytime", StandardLicenses.APACHE2
|
||||||
|
),
|
||||||
|
SoftwareComponent(
|
||||||
|
"RxAndroid", "2015", "The RxAndroid authors",
|
||||||
|
"https://github.com/ReactiveX/RxAndroid", StandardLicenses.APACHE2
|
||||||
|
),
|
||||||
|
SoftwareComponent(
|
||||||
|
"RxBinding", "2015", "Jake Wharton",
|
||||||
|
"https://github.com/JakeWharton/RxBinding", StandardLicenses.APACHE2
|
||||||
|
),
|
||||||
|
SoftwareComponent(
|
||||||
|
"RxJava", "2016 - 2020", "RxJava Contributors",
|
||||||
|
"https://github.com/ReactiveX/RxJava", StandardLicenses.APACHE2
|
||||||
|
),
|
||||||
|
SoftwareComponent(
|
||||||
|
"Universal Image Loader", "2011 - 2015", "Sergey Tarasevich",
|
||||||
|
"https://github.com/nostra13/Android-Universal-Image-Loader",
|
||||||
|
StandardLicenses.APACHE2
|
||||||
|
)
|
||||||
|
)
|
||||||
|
private const val POS_ABOUT = 0
|
||||||
|
private const val POS_LICENSE = 1
|
||||||
|
private const val TOTAL_COUNT = 2
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,145 +0,0 @@
|
||||||
package org.schabi.newpipe.about;
|
|
||||||
|
|
||||||
import android.os.Bundle;
|
|
||||||
import android.view.ContextMenu;
|
|
||||||
import android.view.LayoutInflater;
|
|
||||||
import android.view.MenuInflater;
|
|
||||||
import android.view.MenuItem;
|
|
||||||
import android.view.View;
|
|
||||||
import android.view.ViewGroup;
|
|
||||||
|
|
||||||
import androidx.annotation.NonNull;
|
|
||||||
import androidx.annotation.Nullable;
|
|
||||||
import androidx.fragment.app.Fragment;
|
|
||||||
|
|
||||||
import org.schabi.newpipe.R;
|
|
||||||
import org.schabi.newpipe.databinding.FragmentLicensesBinding;
|
|
||||||
import org.schabi.newpipe.databinding.ItemSoftwareComponentBinding;
|
|
||||||
import org.schabi.newpipe.util.ShareUtils;
|
|
||||||
|
|
||||||
import java.io.Serializable;
|
|
||||||
import java.util.Arrays;
|
|
||||||
import java.util.Comparator;
|
|
||||||
import java.util.Objects;
|
|
||||||
|
|
||||||
import io.reactivex.rxjava3.disposables.CompositeDisposable;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Fragment containing the software licenses.
|
|
||||||
*/
|
|
||||||
public class LicenseFragment extends Fragment {
|
|
||||||
private static final String ARG_COMPONENTS = "components";
|
|
||||||
private static final String LICENSE_KEY = "ACTIVE_LICENSE";
|
|
||||||
|
|
||||||
private SoftwareComponent[] softwareComponents;
|
|
||||||
private SoftwareComponent componentForContextMenu;
|
|
||||||
private License activeLicense;
|
|
||||||
private final CompositeDisposable compositeDisposable = new CompositeDisposable();
|
|
||||||
|
|
||||||
public static LicenseFragment newInstance(final SoftwareComponent[] softwareComponents) {
|
|
||||||
final Bundle bundle = new Bundle();
|
|
||||||
bundle.putParcelableArray(ARG_COMPONENTS, Objects.requireNonNull(softwareComponents));
|
|
||||||
final LicenseFragment fragment = new LicenseFragment();
|
|
||||||
fragment.setArguments(bundle);
|
|
||||||
return fragment;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onCreate(@Nullable final Bundle savedInstanceState) {
|
|
||||||
super.onCreate(savedInstanceState);
|
|
||||||
softwareComponents = (SoftwareComponent[]) getArguments()
|
|
||||||
.getParcelableArray(ARG_COMPONENTS);
|
|
||||||
|
|
||||||
if (savedInstanceState != null) {
|
|
||||||
final Serializable license = savedInstanceState.getSerializable(LICENSE_KEY);
|
|
||||||
if (license != null) {
|
|
||||||
activeLicense = (License) license;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// Sort components by name
|
|
||||||
Arrays.sort(softwareComponents, Comparator.comparing(SoftwareComponent::getName));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onDestroy() {
|
|
||||||
compositeDisposable.dispose();
|
|
||||||
super.onDestroy();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Nullable
|
|
||||||
@Override
|
|
||||||
public View onCreateView(@NonNull final LayoutInflater inflater,
|
|
||||||
@Nullable final ViewGroup container,
|
|
||||||
@Nullable final Bundle savedInstanceState) {
|
|
||||||
final FragmentLicensesBinding binding = FragmentLicensesBinding
|
|
||||||
.inflate(inflater, container, false);
|
|
||||||
|
|
||||||
binding.licensesAppReadLicense.setOnClickListener(v -> {
|
|
||||||
activeLicense = StandardLicenses.GPL3;
|
|
||||||
compositeDisposable.add(LicenseFragmentHelper.showLicense(getActivity(),
|
|
||||||
StandardLicenses.GPL3));
|
|
||||||
});
|
|
||||||
|
|
||||||
for (final SoftwareComponent component : softwareComponents) {
|
|
||||||
final ItemSoftwareComponentBinding componentBinding = ItemSoftwareComponentBinding
|
|
||||||
.inflate(inflater, container, false);
|
|
||||||
componentBinding.name.setText(component.getName());
|
|
||||||
componentBinding.copyright.setText(getString(R.string.copyright,
|
|
||||||
component.getYears(),
|
|
||||||
component.getCopyrightOwner(),
|
|
||||||
component.getLicense().getAbbreviation()));
|
|
||||||
|
|
||||||
final View root = componentBinding.getRoot();
|
|
||||||
root.setTag(component);
|
|
||||||
root.setOnClickListener(v -> {
|
|
||||||
activeLicense = component.getLicense();
|
|
||||||
compositeDisposable.add(LicenseFragmentHelper.showLicense(getActivity(),
|
|
||||||
component.getLicense()));
|
|
||||||
});
|
|
||||||
binding.licensesSoftwareComponents.addView(root);
|
|
||||||
registerForContextMenu(root);
|
|
||||||
}
|
|
||||||
if (activeLicense != null) {
|
|
||||||
compositeDisposable.add(LicenseFragmentHelper.showLicense(getActivity(),
|
|
||||||
activeLicense));
|
|
||||||
}
|
|
||||||
return binding.getRoot();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onCreateContextMenu(final ContextMenu menu, final View v,
|
|
||||||
final ContextMenu.ContextMenuInfo menuInfo) {
|
|
||||||
final MenuInflater inflater = getActivity().getMenuInflater();
|
|
||||||
final SoftwareComponent component = (SoftwareComponent) v.getTag();
|
|
||||||
menu.setHeaderTitle(component.getName());
|
|
||||||
inflater.inflate(R.menu.software_component, menu);
|
|
||||||
super.onCreateContextMenu(menu, v, menuInfo);
|
|
||||||
componentForContextMenu = (SoftwareComponent) v.getTag();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean onContextItemSelected(@NonNull final MenuItem item) {
|
|
||||||
// item.getMenuInfo() is null so we use the tag of the view
|
|
||||||
final SoftwareComponent component = componentForContextMenu;
|
|
||||||
if (component == null) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
switch (item.getItemId()) {
|
|
||||||
case R.id.menu_software_website:
|
|
||||||
ShareUtils.openUrlInBrowser(getActivity(), component.getLink());
|
|
||||||
return true;
|
|
||||||
case R.id.menu_software_show_license:
|
|
||||||
compositeDisposable.add(LicenseFragmentHelper.showLicense(getActivity(),
|
|
||||||
component.getLicense()));
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onSaveInstanceState(@NonNull final Bundle savedInstanceState) {
|
|
||||||
super.onSaveInstanceState(savedInstanceState);
|
|
||||||
if (activeLicense != null) {
|
|
||||||
savedInstanceState.putSerializable(LICENSE_KEY, activeLicense);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -0,0 +1,131 @@
|
||||||
|
package org.schabi.newpipe.about
|
||||||
|
|
||||||
|
import android.os.Bundle
|
||||||
|
import android.view.ContextMenu
|
||||||
|
import android.view.ContextMenu.ContextMenuInfo
|
||||||
|
import android.view.LayoutInflater
|
||||||
|
import android.view.MenuItem
|
||||||
|
import android.view.View
|
||||||
|
import android.view.ViewGroup
|
||||||
|
import androidx.core.os.bundleOf
|
||||||
|
import androidx.fragment.app.Fragment
|
||||||
|
import io.reactivex.rxjava3.disposables.CompositeDisposable
|
||||||
|
import org.schabi.newpipe.R
|
||||||
|
import org.schabi.newpipe.about.LicenseFragmentHelper.showLicense
|
||||||
|
import org.schabi.newpipe.databinding.FragmentLicensesBinding
|
||||||
|
import org.schabi.newpipe.databinding.ItemSoftwareComponentBinding
|
||||||
|
import org.schabi.newpipe.util.ShareUtils
|
||||||
|
import java.util.Arrays
|
||||||
|
import java.util.Objects
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Fragment containing the software licenses.
|
||||||
|
*/
|
||||||
|
class LicenseFragment : Fragment() {
|
||||||
|
private lateinit var softwareComponents: Array<SoftwareComponent>
|
||||||
|
private var componentForContextMenu: SoftwareComponent? = null
|
||||||
|
private var activeLicense: License? = null
|
||||||
|
private val compositeDisposable = CompositeDisposable()
|
||||||
|
|
||||||
|
override fun onCreate(savedInstanceState: Bundle?) {
|
||||||
|
super.onCreate(savedInstanceState)
|
||||||
|
softwareComponents =
|
||||||
|
arguments?.getParcelableArray(ARG_COMPONENTS) as Array<SoftwareComponent>
|
||||||
|
if (savedInstanceState != null) {
|
||||||
|
val license = savedInstanceState.getSerializable(LICENSE_KEY)
|
||||||
|
if (license != null) {
|
||||||
|
activeLicense = license as License?
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Sort components by name
|
||||||
|
Arrays.sort(softwareComponents, Comparator.comparing(SoftwareComponent::name))
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onDestroy() {
|
||||||
|
compositeDisposable.dispose()
|
||||||
|
super.onDestroy()
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onCreateView(
|
||||||
|
inflater: LayoutInflater,
|
||||||
|
container: ViewGroup?,
|
||||||
|
savedInstanceState: Bundle?
|
||||||
|
): View {
|
||||||
|
val binding = FragmentLicensesBinding.inflate(inflater, container, false)
|
||||||
|
binding.licensesAppReadLicense.setOnClickListener {
|
||||||
|
activeLicense = StandardLicenses.GPL3
|
||||||
|
compositeDisposable.add(
|
||||||
|
showLicense(activity, StandardLicenses.GPL3)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
for (component in softwareComponents) {
|
||||||
|
val componentBinding = ItemSoftwareComponentBinding
|
||||||
|
.inflate(inflater, container, false)
|
||||||
|
componentBinding.name.text = component.name
|
||||||
|
componentBinding.copyright.text = getString(
|
||||||
|
R.string.copyright,
|
||||||
|
component.years,
|
||||||
|
component.copyrightOwner,
|
||||||
|
component.license.abbreviation
|
||||||
|
)
|
||||||
|
val root: View = componentBinding.root
|
||||||
|
root.tag = component
|
||||||
|
root.setOnClickListener {
|
||||||
|
activeLicense = component.license
|
||||||
|
compositeDisposable.add(
|
||||||
|
showLicense(activity, component.license)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
binding.licensesSoftwareComponents.addView(root)
|
||||||
|
registerForContextMenu(root)
|
||||||
|
}
|
||||||
|
if (activeLicense != null) {
|
||||||
|
compositeDisposable.add(
|
||||||
|
showLicense(activity, activeLicense!!)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
return binding.root
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onCreateContextMenu(menu: ContextMenu, v: View, menuInfo: ContextMenuInfo?) {
|
||||||
|
val inflater = requireActivity().menuInflater
|
||||||
|
val component = v.tag as SoftwareComponent
|
||||||
|
menu.setHeaderTitle(component.name)
|
||||||
|
inflater.inflate(R.menu.software_component, menu)
|
||||||
|
super.onCreateContextMenu(menu, v, menuInfo)
|
||||||
|
componentForContextMenu = component
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onContextItemSelected(item: MenuItem): Boolean {
|
||||||
|
// item.getMenuInfo() is null so we use the tag of the view
|
||||||
|
val component = componentForContextMenu ?: return false
|
||||||
|
when (item.itemId) {
|
||||||
|
R.id.menu_software_website -> {
|
||||||
|
ShareUtils.openUrlInBrowser(activity, component.link)
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
R.id.menu_software_show_license -> compositeDisposable.add(
|
||||||
|
showLicense(activity, component.license)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onSaveInstanceState(savedInstanceState: Bundle) {
|
||||||
|
super.onSaveInstanceState(savedInstanceState)
|
||||||
|
if (activeLicense != null) {
|
||||||
|
savedInstanceState.putSerializable(LICENSE_KEY, activeLicense)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
private const val ARG_COMPONENTS = "components"
|
||||||
|
private const val LICENSE_KEY = "ACTIVE_LICENSE"
|
||||||
|
fun newInstance(softwareComponents: Array<SoftwareComponent>): LicenseFragment {
|
||||||
|
val fragment = LicenseFragment()
|
||||||
|
fragment.arguments =
|
||||||
|
bundleOf(ARG_COMPONENTS to Objects.requireNonNull(softwareComponents))
|
||||||
|
return fragment
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,109 +0,0 @@
|
||||||
package org.schabi.newpipe.about;
|
|
||||||
|
|
||||||
import android.content.Context;
|
|
||||||
import android.util.Base64;
|
|
||||||
import android.webkit.WebView;
|
|
||||||
|
|
||||||
import androidx.annotation.NonNull;
|
|
||||||
import androidx.annotation.Nullable;
|
|
||||||
import androidx.appcompat.app.AlertDialog;
|
|
||||||
|
|
||||||
import org.schabi.newpipe.R;
|
|
||||||
import org.schabi.newpipe.util.ThemeHelper;
|
|
||||||
|
|
||||||
import java.io.BufferedReader;
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.io.InputStreamReader;
|
|
||||||
import java.nio.charset.StandardCharsets;
|
|
||||||
|
|
||||||
import io.reactivex.rxjava3.android.schedulers.AndroidSchedulers;
|
|
||||||
import io.reactivex.rxjava3.core.Observable;
|
|
||||||
import io.reactivex.rxjava3.disposables.Disposable;
|
|
||||||
import io.reactivex.rxjava3.schedulers.Schedulers;
|
|
||||||
|
|
||||||
import static org.schabi.newpipe.util.Localization.assureCorrectAppLanguage;
|
|
||||||
|
|
||||||
public final class LicenseFragmentHelper {
|
|
||||||
private LicenseFragmentHelper() { }
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param context the context to use
|
|
||||||
* @param license the license
|
|
||||||
* @return String which contains a HTML formatted license page
|
|
||||||
* styled according to the context's theme
|
|
||||||
*/
|
|
||||||
private static String getFormattedLicense(@NonNull final Context context,
|
|
||||||
@NonNull final License license) {
|
|
||||||
final StringBuilder licenseContent = new StringBuilder();
|
|
||||||
final String webViewData;
|
|
||||||
try (BufferedReader in = new BufferedReader(new InputStreamReader(
|
|
||||||
context.getAssets().open(license.getFilename()), StandardCharsets.UTF_8))) {
|
|
||||||
String str;
|
|
||||||
while ((str = in.readLine()) != null) {
|
|
||||||
licenseContent.append(str);
|
|
||||||
}
|
|
||||||
|
|
||||||
// split the HTML file and insert the stylesheet into the HEAD of the file
|
|
||||||
webViewData = licenseContent.toString().replace("</head>",
|
|
||||||
"<style>" + getLicenseStylesheet(context) + "</style></head>");
|
|
||||||
} catch (final IOException e) {
|
|
||||||
throw new IllegalArgumentException(
|
|
||||||
"Could not get license file: " + license.getFilename(), e);
|
|
||||||
}
|
|
||||||
return webViewData;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param context the Android context
|
|
||||||
* @return String which is a CSS stylesheet according to the context's theme
|
|
||||||
*/
|
|
||||||
private static String getLicenseStylesheet(@NonNull final Context context) {
|
|
||||||
final boolean isLightTheme = ThemeHelper.isLightThemeSelected(context);
|
|
||||||
return "body{padding:12px 15px;margin:0;"
|
|
||||||
+ "background:#" + getHexRGBColor(context, isLightTheme
|
|
||||||
? R.color.light_license_background_color
|
|
||||||
: R.color.dark_license_background_color) + ";"
|
|
||||||
+ "color:#" + getHexRGBColor(context, isLightTheme
|
|
||||||
? R.color.light_license_text_color
|
|
||||||
: R.color.dark_license_text_color) + "}"
|
|
||||||
+ "a[href]{color:#" + getHexRGBColor(context, isLightTheme
|
|
||||||
? R.color.light_youtube_primary_color
|
|
||||||
: R.color.dark_youtube_primary_color) + "}"
|
|
||||||
+ "pre{white-space:pre-wrap}";
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Cast R.color to a hexadecimal color value.
|
|
||||||
*
|
|
||||||
* @param context the context to use
|
|
||||||
* @param color the color number from R.color
|
|
||||||
* @return a six characters long String with hexadecimal RGB values
|
|
||||||
*/
|
|
||||||
private static String getHexRGBColor(@NonNull final Context context, final int color) {
|
|
||||||
return context.getResources().getString(color).substring(3);
|
|
||||||
}
|
|
||||||
|
|
||||||
static Disposable showLicense(@Nullable final Context context, @NonNull final License license) {
|
|
||||||
if (context == null) {
|
|
||||||
return Disposable.empty();
|
|
||||||
}
|
|
||||||
|
|
||||||
return Observable.fromCallable(() -> getFormattedLicense(context, license))
|
|
||||||
.subscribeOn(Schedulers.io())
|
|
||||||
.observeOn(AndroidSchedulers.mainThread())
|
|
||||||
.subscribe(formattedLicense -> {
|
|
||||||
final String webViewData = Base64.encodeToString(formattedLicense
|
|
||||||
.getBytes(StandardCharsets.UTF_8), Base64.NO_PADDING);
|
|
||||||
final WebView webView = new WebView(context);
|
|
||||||
webView.loadData(webViewData, "text/html; charset=UTF-8", "base64");
|
|
||||||
|
|
||||||
final AlertDialog.Builder alert = new AlertDialog.Builder(context);
|
|
||||||
alert.setTitle(license.getName());
|
|
||||||
alert.setView(webView);
|
|
||||||
assureCorrectAppLanguage(context);
|
|
||||||
alert.setNegativeButton(context.getString(R.string.finish),
|
|
||||||
(dialog, which) -> dialog.dismiss());
|
|
||||||
alert.show();
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -0,0 +1,114 @@
|
||||||
|
package org.schabi.newpipe.about
|
||||||
|
|
||||||
|
import android.content.Context
|
||||||
|
import android.util.Base64
|
||||||
|
import android.webkit.WebView
|
||||||
|
import androidx.appcompat.app.AlertDialog
|
||||||
|
import io.reactivex.rxjava3.android.schedulers.AndroidSchedulers
|
||||||
|
import io.reactivex.rxjava3.core.Observable
|
||||||
|
import io.reactivex.rxjava3.disposables.Disposable
|
||||||
|
import io.reactivex.rxjava3.schedulers.Schedulers
|
||||||
|
import org.schabi.newpipe.R
|
||||||
|
import org.schabi.newpipe.util.Localization
|
||||||
|
import org.schabi.newpipe.util.ThemeHelper
|
||||||
|
import java.io.BufferedReader
|
||||||
|
import java.io.IOException
|
||||||
|
import java.io.InputStreamReader
|
||||||
|
import java.nio.charset.StandardCharsets
|
||||||
|
|
||||||
|
object LicenseFragmentHelper {
|
||||||
|
/**
|
||||||
|
* @param context the context to use
|
||||||
|
* @param license the license
|
||||||
|
* @return String which contains a HTML formatted license page
|
||||||
|
* styled according to the context's theme
|
||||||
|
*/
|
||||||
|
private fun getFormattedLicense(context: Context, license: License): String {
|
||||||
|
val licenseContent = StringBuilder()
|
||||||
|
val webViewData: String
|
||||||
|
try {
|
||||||
|
BufferedReader(
|
||||||
|
InputStreamReader(
|
||||||
|
context.assets.open(license.filename),
|
||||||
|
StandardCharsets.UTF_8
|
||||||
|
)
|
||||||
|
).use { `in` ->
|
||||||
|
var str: String?
|
||||||
|
while (`in`.readLine().also { str = it } != null) {
|
||||||
|
licenseContent.append(str)
|
||||||
|
}
|
||||||
|
|
||||||
|
// split the HTML file and insert the stylesheet into the HEAD of the file
|
||||||
|
webViewData = "$licenseContent".replace(
|
||||||
|
"</head>",
|
||||||
|
"<style>" + getLicenseStylesheet(context) + "</style></head>"
|
||||||
|
)
|
||||||
|
}
|
||||||
|
} catch (e: IOException) {
|
||||||
|
throw IllegalArgumentException(
|
||||||
|
"Could not get license file: " + license.filename, e
|
||||||
|
)
|
||||||
|
}
|
||||||
|
return webViewData
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param context the Android context
|
||||||
|
* @return String which is a CSS stylesheet according to the context's theme
|
||||||
|
*/
|
||||||
|
private fun getLicenseStylesheet(context: Context): String {
|
||||||
|
val isLightTheme = ThemeHelper.isLightThemeSelected(context)
|
||||||
|
return ("body{padding:12px 15px;margin:0;" + "background:#" + getHexRGBColor(
|
||||||
|
context,
|
||||||
|
if (isLightTheme) R.color.light_license_background_color
|
||||||
|
else R.color.dark_license_background_color
|
||||||
|
) + ";" + "color:#" + getHexRGBColor(
|
||||||
|
context,
|
||||||
|
if (isLightTheme) R.color.light_license_text_color
|
||||||
|
else R.color.dark_license_text_color
|
||||||
|
) + "}" + "a[href]{color:#" + getHexRGBColor(
|
||||||
|
context,
|
||||||
|
if (isLightTheme) R.color.light_youtube_primary_color
|
||||||
|
else R.color.dark_youtube_primary_color
|
||||||
|
) + "}" + "pre{white-space:pre-wrap}")
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Cast R.color to a hexadecimal color value.
|
||||||
|
*
|
||||||
|
* @param context the context to use
|
||||||
|
* @param color the color number from R.color
|
||||||
|
* @return a six characters long String with hexadecimal RGB values
|
||||||
|
*/
|
||||||
|
private fun getHexRGBColor(context: Context, color: Int): String {
|
||||||
|
return context.getString(color).substring(3)
|
||||||
|
}
|
||||||
|
|
||||||
|
@JvmStatic
|
||||||
|
fun showLicense(context: Context?, license: License): Disposable {
|
||||||
|
return if (context == null) {
|
||||||
|
Disposable.empty()
|
||||||
|
} else {
|
||||||
|
Observable.fromCallable { getFormattedLicense(context, license) }
|
||||||
|
.subscribeOn(Schedulers.io())
|
||||||
|
.observeOn(AndroidSchedulers.mainThread())
|
||||||
|
.subscribe { formattedLicense: String ->
|
||||||
|
val webViewData = Base64.encodeToString(
|
||||||
|
formattedLicense
|
||||||
|
.toByteArray(StandardCharsets.UTF_8),
|
||||||
|
Base64.NO_PADDING
|
||||||
|
)
|
||||||
|
val webView = WebView(context)
|
||||||
|
webView.loadData(webViewData, "text/html; charset=UTF-8", "base64")
|
||||||
|
val alert = AlertDialog.Builder(context)
|
||||||
|
alert.setTitle(license.name)
|
||||||
|
alert.setView(webView)
|
||||||
|
Localization.assureCorrectAppLanguage(context)
|
||||||
|
alert.setNegativeButton(
|
||||||
|
context.getString(R.string.finish)
|
||||||
|
) { dialog, _ -> dialog.dismiss() }
|
||||||
|
alert.show()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,19 +0,0 @@
|
||||||
package org.schabi.newpipe.about;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Class containing information about standard software licenses.
|
|
||||||
*/
|
|
||||||
public final class StandardLicenses {
|
|
||||||
public static final License GPL3
|
|
||||||
= new License("GNU General Public License, Version 3.0", "GPLv3", "gpl_3.html");
|
|
||||||
public static final License APACHE2
|
|
||||||
= new License("Apache License, Version 2.0", "ALv2", "apache2.html");
|
|
||||||
public static final License MPL2
|
|
||||||
= new License("Mozilla Public License, Version 2.0", "MPL 2.0", "mpl2.html");
|
|
||||||
public static final License MIT
|
|
||||||
= new License("MIT License", "MIT", "mit.html");
|
|
||||||
public static final License EPL1
|
|
||||||
= new License("Eclipse Public License, Version 1.0", "EPL 1.0", "epl1.html");
|
|
||||||
|
|
||||||
private StandardLicenses() { }
|
|
||||||
}
|
|
|
@ -0,0 +1,21 @@
|
||||||
|
package org.schabi.newpipe.about
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Class containing information about standard software licenses.
|
||||||
|
*/
|
||||||
|
object StandardLicenses {
|
||||||
|
@JvmField
|
||||||
|
val GPL3 = License("GNU General Public License, Version 3.0", "GPLv3", "gpl_3.html")
|
||||||
|
|
||||||
|
@JvmField
|
||||||
|
val APACHE2 = License("Apache License, Version 2.0", "ALv2", "apache2.html")
|
||||||
|
|
||||||
|
@JvmField
|
||||||
|
val MPL2 = License("Mozilla Public License, Version 2.0", "MPL 2.0", "mpl2.html")
|
||||||
|
|
||||||
|
@JvmField
|
||||||
|
val MIT = License("MIT License", "MIT", "mit.html")
|
||||||
|
|
||||||
|
@JvmField
|
||||||
|
val EPL1 = License("Eclipse Public License, Version 1.0", "EPL 1.0", "epl1.html")
|
||||||
|
}
|
Loading…
Reference in New Issue