diff --git a/build.gradle b/build.gradle index 4125ec44..556e0877 100644 --- a/build.gradle +++ b/build.gradle @@ -1,9 +1,7 @@ import com.android.build.gradle.AppExtension import com.android.build.gradle.api.ApkVariantOutput import com.android.build.gradle.api.ApplicationVariant - -apply plugin: 'com.android.application' -apply plugin: 'kotlin-android' +import com.github.jk1.license.render.TextReportRenderer buildscript { ext.kotlin_version = '1.4.21' @@ -19,6 +17,14 @@ buildscript { } } +plugins { + id 'com.github.jk1.dependency-license-report' version '1.16' +} +def licenseResDir = new File("$projectDir/build/dependency-license-res") + +apply plugin: 'com.android.application' +apply plugin: 'kotlin-android' + android { compileSdkVersion 29 defaultConfig { @@ -49,7 +55,7 @@ android { manifest.srcFile 'AndroidManifest.xml' java.srcDirs = ['src'] resources.srcDirs = ['resources'] - res.srcDirs = ['res'] + res.srcDirs = ['res', licenseResDir] assets.srcDirs = ['assets'] } test { @@ -203,3 +209,16 @@ repositories { google() mavenCentral() } + +licenseReport { + configurations = ALL + renderers = [new TextReportRenderer()] +} +generateLicenseReport.doLast { + def target = new File(licenseResDir, "raw/license") + target.parentFile.mkdirs() + target.text = + files("COPYING", "$projectDir/build/reports/dependency-license/THIRD-PARTY-NOTICES.txt") + .collect { it.getText() }.join('\n') +} +preBuild.dependsOn(generateLicenseReport) diff --git a/res/drawable/ic_baseline_attach_money_24.xml b/res/drawable/ic_baseline_attach_money_24.xml new file mode 100644 index 00000000..fecf0313 --- /dev/null +++ b/res/drawable/ic_baseline_attach_money_24.xml @@ -0,0 +1,10 @@ + + + diff --git a/res/drawable/ic_baseline_bug_report_24.xml b/res/drawable/ic_baseline_bug_report_24.xml new file mode 100644 index 00000000..7853f61c --- /dev/null +++ b/res/drawable/ic_baseline_bug_report_24.xml @@ -0,0 +1,10 @@ + + + diff --git a/res/drawable/ic_baseline_code_24.xml b/res/drawable/ic_baseline_code_24.xml new file mode 100644 index 00000000..b97ee53f --- /dev/null +++ b/res/drawable/ic_baseline_code_24.xml @@ -0,0 +1,10 @@ + + + diff --git a/res/drawable/ic_baseline_gavel_24.xml b/res/drawable/ic_baseline_gavel_24.xml new file mode 100644 index 00000000..cbe17b2e --- /dev/null +++ b/res/drawable/ic_baseline_gavel_24.xml @@ -0,0 +1,19 @@ + + + + + + diff --git a/res/values/strings.xml b/res/values/strings.xml index 446bb62c..3c6119a5 100644 --- a/res/values/strings.xml +++ b/res/values/strings.xml @@ -420,5 +420,12 @@ light dark + Report Bug + https://bugs.kde.org/enter_bug.cgi?product=kdeconnect&component=android-application + Donate + https://kde.org/community/donations/?app=kdeconnect-android + Source Code + https://invent.kde.org/network/kdeconnect-android/ + Licenses diff --git a/src/org/kde/kdeconnect/UserInterface/SettingsFragment.java b/src/org/kde/kdeconnect/UserInterface/SettingsFragment.java index 47bd7368..0f7f0adc 100644 --- a/src/org/kde/kdeconnect/UserInterface/SettingsFragment.java +++ b/src/org/kde/kdeconnect/UserInterface/SettingsFragment.java @@ -1,9 +1,11 @@ package org.kde.kdeconnect.UserInterface; +import android.app.AlertDialog; import android.content.Context; import android.content.Intent; import android.content.res.Configuration; import android.graphics.Color; +import android.net.Uri; import android.os.Build; import android.os.Bundle; import android.text.TextUtils; @@ -18,13 +20,45 @@ import androidx.preference.ListPreference; import com.google.android.material.snackbar.Snackbar; +import org.apache.commons.io.IOUtils; import org.kde.kdeconnect.BackgroundService; import org.kde.kdeconnect.Helpers.DeviceHelper; import org.kde.kdeconnect.Helpers.NotificationHelper; import org.kde.kdeconnect_tp.R; +import java.io.IOException; +import java.io.InputStream; +import java.nio.charset.Charset; + public class SettingsFragment extends PreferenceFragmentCompat { + private static class LicenseTextSingleton { + private static volatile String licenseText; + + // Need these separate methods because Context is required to load the string + // Mixing Context and static here is fine because the license + // is a pure function of the project directory (i.e. doesn't depend on language, etc.) + + static synchronized String getOrLoadLicenseText(Context context) { + String licenseText = LicenseTextSingleton.licenseText; + if (licenseText != null) { + return licenseText; + } + try (InputStream is = context.getResources().openRawResource(R.raw.license)) { + licenseText = IOUtils.toString(is, Charset.defaultCharset()); + } catch (IOException ie) { + throw new RuntimeException(ie); + } + return LicenseTextSingleton.licenseText = licenseText; + } + + static synchronized void startLoadingLicenseText(Context context) { + if (licenseText == null) { + new Thread(() -> getOrLoadLicenseText(context)).start(); + } + } + } + private EditTextPreference renameDevice; @Override @@ -153,6 +187,40 @@ public class SettingsFragment extends PreferenceFragmentCompat { moreSettingsText.setSummary(R.string.settings_more_settings_text); screen.addPreference(moreSettingsText); + Preference bug = new Preference(context); + bug.setTitle(R.string.report_bug); + bug.setPersistent(false); + bug.setIcon(R.drawable.ic_baseline_bug_report_24); + bug.setIntent(new Intent(Intent.ACTION_VIEW, Uri.parse(getString(R.string.report_bug_url)))); + screen.addPreference(bug); + + Preference donate = new Preference(context); + donate.setTitle(R.string.donate); + donate.setPersistent(false); + donate.setIcon(R.drawable.ic_baseline_attach_money_24); + donate.setIntent(new Intent(Intent.ACTION_VIEW, Uri.parse(getString(R.string.donate_url)))); + screen.addPreference(donate); + + Preference source = new Preference(context); + source.setTitle(R.string.source_code); + source.setPersistent(false); + source.setIcon(R.drawable.ic_baseline_code_24); + source.setIntent(new Intent(Intent.ACTION_VIEW, Uri.parse(getString(R.string.source_code_url)))); + screen.addPreference(source); + + Preference licences = new Preference(context); + licences.setTitle(R.string.licenses); + licences.setPersistent(false); + licences.setIcon(R.drawable.ic_baseline_gavel_24); + licences.setOnPreferenceClickListener(preference -> { + new AlertDialog.Builder(context) + .setMessage(LicenseTextSingleton.getOrLoadLicenseText(context)) + .create().show(); + return true; + }); + LicenseTextSingleton.startLoadingLicenseText(context); + screen.addPreference(licences); + setPreferenceScreen(screen);