diff --git a/app/build.gradle b/app/build.gradle index 7bcd9d38a..782634a0b 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -14,12 +14,14 @@ android { testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner" vectorDrawables.useSupportLibrary = true } + buildTypes { release { minifyEnabled true shrinkResources true proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' } + debug { multiDexEnabled true debuggable true @@ -33,6 +35,7 @@ android { // but continue the build even when errors are found: abortOnError false } + compileOptions { sourceCompatibility JavaVersion.VERSION_1_8 targetCompatibility JavaVersion.VERSION_1_8 diff --git a/app/src/main/ic_settings_update_white-web.png b/app/src/main/ic_settings_update_white-web.png new file mode 100644 index 000000000..60383b790 Binary files /dev/null and b/app/src/main/ic_settings_update_white-web.png differ diff --git a/app/src/main/java/org/schabi/newpipe/App.java b/app/src/main/java/org/schabi/newpipe/App.java index 314c95c8d..3ac2d5014 100644 --- a/app/src/main/java/org/schabi/newpipe/App.java +++ b/app/src/main/java/org/schabi/newpipe/App.java @@ -1,5 +1,6 @@ package org.schabi.newpipe; +import android.annotation.TargetApi; import android.app.Application; import android.app.NotificationChannel; import android.app.NotificationManager; @@ -65,6 +66,7 @@ import io.reactivex.plugins.RxJavaPlugins; public class App extends Application { protected static final String TAG = App.class.toString(); private RefWatcher refWatcher; + private static App app; @SuppressWarnings("unchecked") private static final Class[] @@ -88,6 +90,8 @@ public class App extends Application { } refWatcher = installLeakCanary(); + app = this; + // Initialize settings first because others inits can use its values SettingsActivity.initSettings(this); @@ -100,6 +104,9 @@ public class App extends Application { ImageLoader.getInstance().init(getImageLoaderConfigurations(10, 50)); configureRxJavaErrorHandler(); + + // Check for new version + new CheckForNewAppVersionTask().execute(); } protected Downloader getDownloader() { @@ -211,6 +218,31 @@ public class App extends Application { NotificationManager mNotificationManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE); mNotificationManager.createNotificationChannel(mChannel); + + setUpUpdateNotificationChannel(importance); + } + + /** + * Set up notification channel for app update. + * @param importance + */ + @TargetApi(Build.VERSION_CODES.O) + private void setUpUpdateNotificationChannel(int importance) { + + final String appUpdateId + = getString(R.string.app_update_notification_channel_id); + final CharSequence appUpdateName + = getString(R.string.app_update_notification_channel_name); + final String appUpdateDescription + = getString(R.string.app_update_notification_channel_description); + + NotificationChannel appUpdateChannel + = new NotificationChannel(appUpdateId, appUpdateName, importance); + appUpdateChannel.setDescription(appUpdateDescription); + + NotificationManager appUpdateNotificationManager + = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE); + appUpdateNotificationManager.createNotificationChannel(appUpdateChannel); } @Nullable @@ -226,4 +258,8 @@ public class App extends Application { protected boolean isDisposedRxExceptionsReported() { return false; } + + public static App getApp() { + return app; + } } diff --git a/app/src/main/java/org/schabi/newpipe/CheckForNewAppVersionTask.java b/app/src/main/java/org/schabi/newpipe/CheckForNewAppVersionTask.java new file mode 100644 index 000000000..af9b88ac1 --- /dev/null +++ b/app/src/main/java/org/schabi/newpipe/CheckForNewAppVersionTask.java @@ -0,0 +1,230 @@ +package org.schabi.newpipe; + +import android.app.Application; +import android.app.PendingIntent; +import android.content.Intent; +import android.content.SharedPreferences; +import android.content.pm.PackageInfo; +import android.content.pm.PackageManager; +import android.content.pm.Signature; +import android.net.Uri; +import android.os.AsyncTask; +import android.preference.PreferenceManager; +import android.support.v4.app.NotificationCompat; +import android.support.v4.app.NotificationManagerCompat; + +import org.json.JSONException; +import org.json.JSONObject; +import org.schabi.newpipe.report.ErrorActivity; +import org.schabi.newpipe.report.UserAction; + +import java.io.BufferedReader; +import java.io.ByteArrayInputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.net.HttpURLConnection; +import java.net.URL; +import java.security.MessageDigest; +import java.security.NoSuchAlgorithmException; +import java.security.cert.CertificateEncodingException; +import java.security.cert.CertificateException; +import java.security.cert.CertificateFactory; +import java.security.cert.X509Certificate; +import java.util.concurrent.TimeUnit; + +import okhttp3.OkHttpClient; +import okhttp3.Request; +import okhttp3.RequestBody; +import okhttp3.Response; + +/** + * AsyncTask to check if there is a newer version of the NewPipe github apk available or not. + * If there is a newer version we show a notification, informing the user. On tapping + * the notification, the user will be directed to the download link. + */ +public class CheckForNewAppVersionTask extends AsyncTask { + + private static final Application app = App.getApp(); + private static final String GITHUB_APK_SHA1 = "B0:2E:90:7C:1C:D6:FC:57:C3:35:F0:88:D0:8F:50:5F:94:E4:D2:15"; + private static final String newPipeApiUrl = "https://newpipe.schabi.org/api/data.json"; + private static final int timeoutPeriod = 30; + + private SharedPreferences mPrefs; + private OkHttpClient client; + + @Override + protected void onPreExecute() { + + mPrefs = PreferenceManager.getDefaultSharedPreferences(app); + + // Check if user has enabled/ disabled update checking + // and if the current apk is a github one or not. + if (!mPrefs.getBoolean(app.getString(R.string.update_app_key), true) + || !isGithubApk()) { + this.cancel(true); + } + } + + @Override + protected String doInBackground(Void... voids) { + + // Make a network request to get latest NewPipe data. + if (client == null) { + + client = new OkHttpClient + .Builder() + .readTimeout(timeoutPeriod, TimeUnit.SECONDS) + .build(); + } + + Request request = new Request.Builder() + .url(newPipeApiUrl) + .build(); + + try { + Response response = client.newCall(request).execute(); + return response.body().string(); + } catch (IOException ex) { + ErrorActivity.reportError(app, ex, null, null, + ErrorActivity.ErrorInfo.make(UserAction.SOMETHING_ELSE, "none", + "app update API fail", R.string.app_ui_crash)); + } + + return null; + } + + @Override + protected void onPostExecute(String response) { + + // Parse the json from the response. + if (response != null) { + + try { + JSONObject mainObject = new JSONObject(response); + JSONObject flavoursObject = mainObject.getJSONObject("flavors"); + JSONObject githubObject = flavoursObject.getJSONObject("github"); + JSONObject githubStableObject = githubObject.getJSONObject("stable"); + + String versionName = githubStableObject.getString("version"); + String versionCode = githubStableObject.getString("version_code"); + String apkLocationUrl = githubStableObject.getString("apk"); + + compareAppVersionAndShowNotification(versionName, apkLocationUrl, versionCode); + + } catch (JSONException ex) { + ErrorActivity.reportError(app, ex, null, null, + ErrorActivity.ErrorInfo.make(UserAction.SOMETHING_ELSE, "none", + "could not parse app update JSON data", R.string.app_ui_crash)); + } + } + } + + /** + * Method to compare the current and latest available app version. + * If a newer version is available, we show the update notification. + * @param versionName + * @param apkLocationUrl + */ + private void compareAppVersionAndShowNotification(String versionName, + String apkLocationUrl, + String versionCode) { + + int NOTIFICATION_ID = 2000; + + if (BuildConfig.VERSION_CODE < Integer.valueOf(versionCode)) { + + // A pending intent to open the apk location url in the browser. + Intent intent = new Intent(Intent.ACTION_VIEW, Uri.parse(apkLocationUrl)); + PendingIntent pendingIntent + = PendingIntent.getActivity(app, 0, intent, 0); + + NotificationCompat.Builder notificationBuilder = new NotificationCompat + .Builder(app, app.getString(R.string.app_update_notification_channel_id)) + .setSmallIcon(R.drawable.ic_newpipe_update) + .setVisibility(NotificationCompat.VISIBILITY_PUBLIC) + .setContentIntent(pendingIntent) + .setAutoCancel(true) + .setContentTitle(app.getString(R.string.app_update_notification_content_title)) + .setContentText(app.getString(R.string.app_update_notification_content_text) + + " " + versionName); + + NotificationManagerCompat notificationManager = NotificationManagerCompat.from(app); + notificationManager.notify(NOTIFICATION_ID, notificationBuilder.build()); + } + } + + /** + * Method to get the apk's SHA1 key. + * https://stackoverflow.com/questions/9293019/get-certificate-fingerprint-from-android-app#22506133 + */ + private static String getCertificateSHA1Fingerprint() { + + PackageManager pm = app.getPackageManager(); + String packageName = app.getPackageName(); + int flags = PackageManager.GET_SIGNATURES; + PackageInfo packageInfo = null; + + try { + packageInfo = pm.getPackageInfo(packageName, flags); + } catch (PackageManager.NameNotFoundException ex) { + ErrorActivity.reportError(app, ex, null, null, + ErrorActivity.ErrorInfo.make(UserAction.SOMETHING_ELSE, "none", + "Could not find package info", R.string.app_ui_crash)); + } + + Signature[] signatures = packageInfo.signatures; + byte[] cert = signatures[0].toByteArray(); + InputStream input = new ByteArrayInputStream(cert); + + CertificateFactory cf = null; + X509Certificate c = null; + + try { + cf = CertificateFactory.getInstance("X509"); + c = (X509Certificate) cf.generateCertificate(input); + } catch (CertificateException ex) { + ErrorActivity.reportError(app, ex, null, null, + ErrorActivity.ErrorInfo.make(UserAction.SOMETHING_ELSE, "none", + "Certificate error", R.string.app_ui_crash)); + } + + String hexString = null; + + try { + MessageDigest md = MessageDigest.getInstance("SHA1"); + byte[] publicKey = md.digest(c.getEncoded()); + hexString = byte2HexFormatted(publicKey); + } catch (NoSuchAlgorithmException ex1) { + ErrorActivity.reportError(app, ex1, null, null, + ErrorActivity.ErrorInfo.make(UserAction.SOMETHING_ELSE, "none", + "Could not retrieve SHA1 key", R.string.app_ui_crash)); + } catch (CertificateEncodingException ex2) { + ErrorActivity.reportError(app, ex2, null, null, + ErrorActivity.ErrorInfo.make(UserAction.SOMETHING_ELSE, "none", + "Could not retrieve SHA1 key", R.string.app_ui_crash)); + } + + return hexString; + } + + private static String byte2HexFormatted(byte[] arr) { + + StringBuilder str = new StringBuilder(arr.length * 2); + + for (int i = 0; i < arr.length; i++) { + String h = Integer.toHexString(arr[i]); + int l = h.length(); + if (l == 1) h = "0" + h; + if (l > 2) h = h.substring(l - 2, l); + str.append(h.toUpperCase()); + if (i < (arr.length - 1)) str.append(':'); + } + return str.toString(); + } + + public static boolean isGithubApk() { + + return getCertificateSHA1Fingerprint().equals(GITHUB_APK_SHA1); + } +} diff --git a/app/src/main/java/org/schabi/newpipe/settings/MainSettingsFragment.java b/app/src/main/java/org/schabi/newpipe/settings/MainSettingsFragment.java index 5e07e2b12..43270926e 100644 --- a/app/src/main/java/org/schabi/newpipe/settings/MainSettingsFragment.java +++ b/app/src/main/java/org/schabi/newpipe/settings/MainSettingsFragment.java @@ -4,6 +4,7 @@ import android.os.Bundle; import android.support.v7.preference.Preference; import org.schabi.newpipe.BuildConfig; +import org.schabi.newpipe.CheckForNewAppVersionTask; import org.schabi.newpipe.R; public class MainSettingsFragment extends BasePreferenceFragment { @@ -13,6 +14,13 @@ public class MainSettingsFragment extends BasePreferenceFragment { public void onCreatePreferences(Bundle savedInstanceState, String rootKey) { addPreferencesFromResource(R.xml.main_settings); + if (!CheckForNewAppVersionTask.isGithubApk()) { + final Preference update = findPreference(getString(R.string.update_pref_screen_key)); + getPreferenceScreen().removePreference(update); + + defaultPreferences.edit().putBoolean(getString(R.string.update_app_key), false).apply(); + } + if (!DEBUG) { final Preference debug = findPreference(getString(R.string.debug_pref_screen_key)); getPreferenceScreen().removePreference(debug); diff --git a/app/src/main/java/org/schabi/newpipe/settings/UpdateSettingsFragment.java b/app/src/main/java/org/schabi/newpipe/settings/UpdateSettingsFragment.java new file mode 100644 index 000000000..76d887dd1 --- /dev/null +++ b/app/src/main/java/org/schabi/newpipe/settings/UpdateSettingsFragment.java @@ -0,0 +1,33 @@ +package org.schabi.newpipe.settings; + +import android.os.Bundle; +import android.support.annotation.Nullable; +import android.support.v7.preference.Preference; + +import org.schabi.newpipe.CheckForNewAppVersionTask; +import org.schabi.newpipe.R; + +public class UpdateSettingsFragment extends BasePreferenceFragment { + + @Override + public void onCreate(@Nullable Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + + String updateToggleKey = getString(R.string.update_app_key); + findPreference(updateToggleKey).setOnPreferenceChangeListener(updatePreferenceChange); + } + + @Override + public void onCreatePreferences(Bundle savedInstanceState, String rootKey) { + addPreferencesFromResource(R.xml.update_settings); + } + + private Preference.OnPreferenceChangeListener updatePreferenceChange + = (preference, newValue) -> { + + defaultPreferences.edit().putBoolean(getString(R.string.update_app_key), + (boolean) newValue).apply(); + + return true; + }; +} diff --git a/app/src/main/res/drawable-hdpi/ic_newpipe_update.png b/app/src/main/res/drawable-hdpi/ic_newpipe_update.png new file mode 100755 index 000000000..cbf336a1f Binary files /dev/null and b/app/src/main/res/drawable-hdpi/ic_newpipe_update.png differ diff --git a/app/src/main/res/drawable-hdpi/ic_settings_update_black.png b/app/src/main/res/drawable-hdpi/ic_settings_update_black.png new file mode 100755 index 000000000..cdd51d35f Binary files /dev/null and b/app/src/main/res/drawable-hdpi/ic_settings_update_black.png differ diff --git a/app/src/main/res/drawable-hdpi/ic_settings_update_white.png b/app/src/main/res/drawable-hdpi/ic_settings_update_white.png new file mode 100755 index 000000000..544a85c9d Binary files /dev/null and b/app/src/main/res/drawable-hdpi/ic_settings_update_white.png differ diff --git a/app/src/main/res/drawable-ldrtl-mdpi/ic_settings_update_black.png b/app/src/main/res/drawable-ldrtl-mdpi/ic_settings_update_black.png new file mode 100755 index 000000000..d85ec5975 Binary files /dev/null and b/app/src/main/res/drawable-ldrtl-mdpi/ic_settings_update_black.png differ diff --git a/app/src/main/res/drawable-mdpi/ic_newpipe_update.png b/app/src/main/res/drawable-mdpi/ic_newpipe_update.png new file mode 100755 index 000000000..8ab23eb6a Binary files /dev/null and b/app/src/main/res/drawable-mdpi/ic_newpipe_update.png differ diff --git a/app/src/main/res/drawable-mdpi/ic_settings_update_black.png b/app/src/main/res/drawable-mdpi/ic_settings_update_black.png new file mode 100755 index 000000000..964553137 Binary files /dev/null and b/app/src/main/res/drawable-mdpi/ic_settings_update_black.png differ diff --git a/app/src/main/res/drawable-mdpi/ic_settings_update_white.png b/app/src/main/res/drawable-mdpi/ic_settings_update_white.png new file mode 100755 index 000000000..cf4642f97 Binary files /dev/null and b/app/src/main/res/drawable-mdpi/ic_settings_update_white.png differ diff --git a/app/src/main/res/drawable-xhdpi/ic_newpipe_update.png b/app/src/main/res/drawable-xhdpi/ic_newpipe_update.png new file mode 100755 index 000000000..5ee02aaa9 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/ic_newpipe_update.png differ diff --git a/app/src/main/res/drawable-xhdpi/ic_settings_update_black.png b/app/src/main/res/drawable-xhdpi/ic_settings_update_black.png new file mode 100755 index 000000000..0304e6fd1 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/ic_settings_update_black.png differ diff --git a/app/src/main/res/drawable-xhdpi/ic_settings_update_white.png b/app/src/main/res/drawable-xhdpi/ic_settings_update_white.png new file mode 100755 index 000000000..9c71b13f7 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/ic_settings_update_white.png differ diff --git a/app/src/main/res/drawable-xxhdpi/ic_newpipe_update.png b/app/src/main/res/drawable-xxhdpi/ic_newpipe_update.png new file mode 100755 index 000000000..22f0e99d1 Binary files /dev/null and b/app/src/main/res/drawable-xxhdpi/ic_newpipe_update.png differ diff --git a/app/src/main/res/drawable-xxhdpi/ic_settings_update_black.png b/app/src/main/res/drawable-xxhdpi/ic_settings_update_black.png new file mode 100755 index 000000000..7316dbc88 Binary files /dev/null and b/app/src/main/res/drawable-xxhdpi/ic_settings_update_black.png differ diff --git a/app/src/main/res/drawable-xxhdpi/ic_settings_update_white.png b/app/src/main/res/drawable-xxhdpi/ic_settings_update_white.png new file mode 100755 index 000000000..07b1f712d Binary files /dev/null and b/app/src/main/res/drawable-xxhdpi/ic_settings_update_white.png differ diff --git a/app/src/main/res/drawable-xxxhdpi/ic_newpipe_update.png b/app/src/main/res/drawable-xxxhdpi/ic_newpipe_update.png new file mode 100755 index 000000000..1f44c1aaf Binary files /dev/null and b/app/src/main/res/drawable-xxxhdpi/ic_newpipe_update.png differ diff --git a/app/src/main/res/drawable-xxxhdpi/ic_settings_update_black.png b/app/src/main/res/drawable-xxxhdpi/ic_settings_update_black.png new file mode 100755 index 000000000..8186c6f5f Binary files /dev/null and b/app/src/main/res/drawable-xxxhdpi/ic_settings_update_black.png differ diff --git a/app/src/main/res/drawable-xxxhdpi/ic_settings_update_white.png b/app/src/main/res/drawable-xxxhdpi/ic_settings_update_white.png new file mode 100755 index 000000000..8b5e6fa38 Binary files /dev/null and b/app/src/main/res/drawable-xxxhdpi/ic_settings_update_white.png differ diff --git a/app/src/main/res/drawable/drawable-hdpi/ic_settings_update_black.png b/app/src/main/res/drawable/drawable-hdpi/ic_settings_update_black.png new file mode 100755 index 000000000..1e318eecc Binary files /dev/null and b/app/src/main/res/drawable/drawable-hdpi/ic_settings_update_black.png differ diff --git a/app/src/main/res/drawable/drawable-mdpi/ic_settings_update_black.png b/app/src/main/res/drawable/drawable-mdpi/ic_settings_update_black.png new file mode 100755 index 000000000..964553137 Binary files /dev/null and b/app/src/main/res/drawable/drawable-mdpi/ic_settings_update_black.png differ diff --git a/app/src/main/res/drawable/drawable-xhdpi/ic_settings_update_black.png b/app/src/main/res/drawable/drawable-xhdpi/ic_settings_update_black.png new file mode 100755 index 000000000..049edf0d8 Binary files /dev/null and b/app/src/main/res/drawable/drawable-xhdpi/ic_settings_update_black.png differ diff --git a/app/src/main/res/drawable/drawable-xxhdpi/ic_settings_update_black.png b/app/src/main/res/drawable/drawable-xxhdpi/ic_settings_update_black.png new file mode 100755 index 000000000..10ae87bae Binary files /dev/null and b/app/src/main/res/drawable/drawable-xxhdpi/ic_settings_update_black.png differ diff --git a/app/src/main/res/drawable/drawable-xxxhdpi/ic_settings_update_black.png b/app/src/main/res/drawable/drawable-xxxhdpi/ic_settings_update_black.png new file mode 100755 index 000000000..49ac8ea65 Binary files /dev/null and b/app/src/main/res/drawable/drawable-xxxhdpi/ic_settings_update_black.png differ diff --git a/app/src/main/res/drawable/ic_settings_update_black/drawable-hdpi/ic_settings_update_black.png b/app/src/main/res/drawable/ic_settings_update_black/drawable-hdpi/ic_settings_update_black.png new file mode 100755 index 000000000..1e318eecc Binary files /dev/null and b/app/src/main/res/drawable/ic_settings_update_black/drawable-hdpi/ic_settings_update_black.png differ diff --git a/app/src/main/res/drawable/ic_settings_update_black/drawable-mdpi/ic_settings_update_black.png b/app/src/main/res/drawable/ic_settings_update_black/drawable-mdpi/ic_settings_update_black.png new file mode 100755 index 000000000..964553137 Binary files /dev/null and b/app/src/main/res/drawable/ic_settings_update_black/drawable-mdpi/ic_settings_update_black.png differ diff --git a/app/src/main/res/drawable/ic_settings_update_black/drawable-xhdpi/ic_settings_update_black.png b/app/src/main/res/drawable/ic_settings_update_black/drawable-xhdpi/ic_settings_update_black.png new file mode 100755 index 000000000..049edf0d8 Binary files /dev/null and b/app/src/main/res/drawable/ic_settings_update_black/drawable-xhdpi/ic_settings_update_black.png differ diff --git a/app/src/main/res/drawable/ic_settings_update_black/drawable-xxhdpi/ic_settings_update_black.png b/app/src/main/res/drawable/ic_settings_update_black/drawable-xxhdpi/ic_settings_update_black.png new file mode 100755 index 000000000..10ae87bae Binary files /dev/null and b/app/src/main/res/drawable/ic_settings_update_black/drawable-xxhdpi/ic_settings_update_black.png differ diff --git a/app/src/main/res/drawable/ic_settings_update_black/drawable-xxxhdpi/ic_settings_update_black.png b/app/src/main/res/drawable/ic_settings_update_black/drawable-xxxhdpi/ic_settings_update_black.png new file mode 100755 index 000000000..49ac8ea65 Binary files /dev/null and b/app/src/main/res/drawable/ic_settings_update_black/drawable-xxxhdpi/ic_settings_update_black.png differ diff --git a/app/src/main/res/values/attrs.xml b/app/src/main/res/values/attrs.xml index c0e7fa532..865b68c24 100644 --- a/app/src/main/res/values/attrs.xml +++ b/app/src/main/res/values/attrs.xml @@ -41,6 +41,7 @@ + diff --git a/app/src/main/res/values/settings_keys.xml b/app/src/main/res/values/settings_keys.xml index 300217c09..fcc09872e 100644 --- a/app/src/main/res/values/settings_keys.xml +++ b/app/src/main/res/values/settings_keys.xml @@ -222,6 +222,10 @@ @string/always_ask_open_action_key + + update_app_key + update_pref_screen_key + af diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index ec366ebed..e6948bec5 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -112,6 +112,7 @@ Appearance Other Debug + Updates Playing in background Playing in popup mode Queued on background player @@ -153,6 +154,10 @@ NewPipe Notification Notifications for NewPipe background and popup players + newpipeAppUpdate + App Update Notification + Notifications for new NewPipe version + [Unknown] Toggle Orientation @@ -513,6 +518,10 @@ 144p + + Updates + Show a notification to prompt app update when a new version is available + Minimize on app switch Action when switching to other app from main video player — %s @@ -525,16 +534,21 @@ Auto Switch View + + NewPipe Update Available! + Tap to download + + Finished In queue - + paused queued post-processing - + Queue - + Action denied by the system diff --git a/app/src/main/res/values/styles.xml b/app/src/main/res/values/styles.xml index da1ae0e38..8753b9295 100644 --- a/app/src/main/res/values/styles.xml +++ b/app/src/main/res/values/styles.xml @@ -56,6 +56,7 @@ @drawable/ic_list_black_24dp @drawable/ic_grid_black_24dp @drawable/ic_delete_black_24dp + @drawable/ic_settings_update_black @color/light_separator_color @color/light_contrast_background_color @@ -118,6 +119,7 @@ @drawable/ic_list_white_24dp @drawable/ic_grid_white_24dp @drawable/ic_delete_white_24dp + @drawable/ic_settings_update_white @color/dark_separator_color @color/dark_contrast_background_color diff --git a/app/src/main/res/xml/main_settings.xml b/app/src/main/res/xml/main_settings.xml index 4196a98d3..74450f77b 100644 --- a/app/src/main/res/xml/main_settings.xml +++ b/app/src/main/res/xml/main_settings.xml @@ -29,6 +29,12 @@ android:icon="?attr/language" android:title="@string/content"/> + + + + + + +