From 3936e8357863381c2d898ad3c2b300af7aed3c7f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Denis=20=C3=87erri?= <64997243+deniscerri@users.noreply.github.com> Date: Sat, 1 Oct 2022 00:18:55 +0200 Subject: [PATCH] new small features made progress bar as thick as the card and somewhat transparent, looks nicer made the download progress not cut off and be seamless when transitioning from intermediate to solid colors renamed history tab to downloads added videopath to downloaded items and if they are not in the filesystem, they are greyed out made updating app as a toggle in the main settings page. moved update ytdl there aswell fixed not getting all playlist items from generic ytdl request brought back the default api key. If the key is throttled, it will try to use the user's custom youtube api key. If that key is throttled too, it will use the generic request as a last resort --- .idea/assetWizardSettings.xml | 4 +- .idea/misc.xml | 5 +- .idea/navEditor.xml | 61 ++++++++ app/build.gradle | 2 + app/src/main/AndroidManifest.xml | 4 + .../com/deniscerri/ytdlnis/MainActivity.java | 14 +- .../adapter/HistoryRecyclerViewAdapter.java | 9 ++ .../deniscerri/ytdlnis/page/HomeFragment.java | 7 +- .../deniscerri/ytdlnis/page/MoreFragment.java | 27 ---- .../page/settings/SettingsFragment.java | 18 ++- .../com/deniscerri/ytdlnis/util/InfoUtil.java | 140 ++++++++---------- app/src/main/res/drawable/ic_app_icon.xml | 15 ++ app/src/main/res/drawable/ic_downloads.xml | 5 + app/src/main/res/drawable/ic_history.xml | 5 - app/src/main/res/layout/fragment_more.xml | 71 ++++++--- app/src/main/res/layout/result_card.xml | 21 +-- app/src/main/res/menu/bottom_nav_menu.xml | 6 +- app/src/main/res/values-sq-rAL/strings.xml | 5 +- app/src/main/res/values/strings.xml | 5 +- app/src/main/res/xml/more_preferences.xml | 36 ++--- app/src/main/res/xml/root_preferences.xml | 17 +++ build.gradle | 2 +- 22 files changed, 294 insertions(+), 185 deletions(-) create mode 100644 .idea/navEditor.xml create mode 100644 app/src/main/res/drawable/ic_app_icon.xml create mode 100644 app/src/main/res/drawable/ic_downloads.xml delete mode 100644 app/src/main/res/drawable/ic_history.xml diff --git a/.idea/assetWizardSettings.xml b/.idea/assetWizardSettings.xml index d1fac0cd..2375cff6 100644 --- a/.idea/assetWizardSettings.xml +++ b/.idea/assetWizardSettings.xml @@ -320,7 +320,7 @@ @@ -331,7 +331,7 @@ diff --git a/.idea/misc.xml b/.idea/misc.xml index be2898d8..d739b9ab 100644 --- a/.idea/misc.xml +++ b/.idea/misc.xml @@ -37,6 +37,7 @@ + @@ -45,6 +46,7 @@ + @@ -70,6 +72,7 @@ + @@ -96,7 +99,7 @@ - + diff --git a/.idea/navEditor.xml b/.idea/navEditor.xml new file mode 100644 index 00000000..8ab47ce5 --- /dev/null +++ b/.idea/navEditor.xml @@ -0,0 +1,61 @@ + + + + + + \ No newline at end of file diff --git a/app/build.gradle b/app/build.gradle index 7cea4b05..960b5f4c 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -68,6 +68,8 @@ dependencies { implementation 'androidx.core:core:1.8.0' implementation 'androidx.recyclerview:recyclerview:1.2.1' implementation 'androidx.preference:preference:1.2.0' + implementation 'androidx.navigation:navigation-fragment:2.5.2' + implementation 'androidx.navigation:navigation-ui:2.5.2' testImplementation "junit:junit:$junitVer" androidTestImplementation "androidx.test.ext:junit:$androidJunitVer" androidTestImplementation "androidx.test.espresso:espresso-core:$espressoVer" diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index 44deca19..bc7b1bbb 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -49,6 +49,10 @@ android:name=".DownloaderService" android:enabled="true" android:exported="false" /> + \ No newline at end of file diff --git a/app/src/main/java/com/deniscerri/ytdlnis/MainActivity.java b/app/src/main/java/com/deniscerri/ytdlnis/MainActivity.java index 7a9622db..e93e94c3 100644 --- a/app/src/main/java/com/deniscerri/ytdlnis/MainActivity.java +++ b/app/src/main/java/com/deniscerri/ytdlnis/MainActivity.java @@ -1,10 +1,12 @@ package com.deniscerri.ytdlnis; +import android.app.Activity; import android.app.ActivityManager; import android.content.ComponentName; import android.content.Context; import android.content.Intent; import android.content.ServiceConnection; +import android.content.SharedPreferences; import android.os.Bundle; import android.os.IBinder; import android.util.Log; @@ -13,7 +15,6 @@ import android.widget.Toast; import androidx.appcompat.app.AppCompatActivity; import androidx.fragment.app.Fragment; import androidx.fragment.app.FragmentManager; - import com.deniscerri.ytdlnis.database.Video; import com.deniscerri.ytdlnis.databinding.ActivityMainBinding; import com.deniscerri.ytdlnis.page.HistoryFragment; @@ -99,11 +100,11 @@ public class MainActivity extends AppCompatActivity{ this.setTitle(R.string.app_name);; } replaceFragment(homeFragment); - }else if(id == R.id.history){ + }else if(id == R.id.downloads){ if(lastFragment == historyFragment){ historyFragment.scrollToTop(); }else { - this.setTitle(getString(R.string.history)); + this.setTitle(getString(R.string.downloads)); } replaceFragment(historyFragment); }else if(id == R.id.more){ @@ -215,8 +216,11 @@ public class MainActivity extends AppCompatActivity{ } private void checkUpdate(){ - UpdateUtil updateUtil = new UpdateUtil(this); - updateUtil.updateApp(); + SharedPreferences preferences = context.getSharedPreferences("root_preferences", Activity.MODE_PRIVATE); + if(preferences.getBoolean("update_app", false)){ + UpdateUtil updateUtil = new UpdateUtil(this); + updateUtil.updateApp(); + } } public void updateHistoryFragment(){ diff --git a/app/src/main/java/com/deniscerri/ytdlnis/adapter/HistoryRecyclerViewAdapter.java b/app/src/main/java/com/deniscerri/ytdlnis/adapter/HistoryRecyclerViewAdapter.java index 3e9267d6..9ded68fb 100644 --- a/app/src/main/java/com/deniscerri/ytdlnis/adapter/HistoryRecyclerViewAdapter.java +++ b/app/src/main/java/com/deniscerri/ytdlnis/adapter/HistoryRecyclerViewAdapter.java @@ -2,6 +2,8 @@ package com.deniscerri.ytdlnis.adapter; import android.content.Context; import android.graphics.Color; +import android.graphics.ColorMatrix; +import android.graphics.ColorMatrixColorFilter; import android.os.Handler; import android.os.Looper; import android.view.LayoutInflater; @@ -21,6 +23,7 @@ import com.deniscerri.ytdlnis.R; import com.deniscerri.ytdlnis.database.Video; import com.squareup.picasso.Picasso; +import java.io.File; import java.util.ArrayList; public class HistoryRecyclerViewAdapter extends RecyclerView.Adapter { @@ -97,6 +100,12 @@ public class HistoryRecyclerViewAdapter extends RecyclerView.Adapter onItemClickListener.onCardClick(position)); } diff --git a/app/src/main/java/com/deniscerri/ytdlnis/page/HomeFragment.java b/app/src/main/java/com/deniscerri/ytdlnis/page/HomeFragment.java index 4b04d397..f3ac6164 100644 --- a/app/src/main/java/com/deniscerri/ytdlnis/page/HomeFragment.java +++ b/app/src/main/java/com/deniscerri/ytdlnis/page/HomeFragment.java @@ -110,10 +110,13 @@ public class HomeFragment extends Fragment implements HomeRecyclerViewAdapter.On public void onDownloadProgress(DownloadInfo info) { activity.runOnUiThread(() -> { try{ + int progress = info.getProgress(); progressBar = fragmentView.findViewWithTag(info.getVideo().getVideoId()+"##progress"); progressBar.setVisibility(View.VISIBLE); - progressBar.setIndeterminate(false); - progressBar.setProgress(info.getProgress()); + if (progress > 1){ + progressBar.setIndeterminate(false); + progressBar.setProgress(info.getProgress()); + } }catch(Exception ignored){} }); } diff --git a/app/src/main/java/com/deniscerri/ytdlnis/page/MoreFragment.java b/app/src/main/java/com/deniscerri/ytdlnis/page/MoreFragment.java index 4a527319..38bf1c6c 100644 --- a/app/src/main/java/com/deniscerri/ytdlnis/page/MoreFragment.java +++ b/app/src/main/java/com/deniscerri/ytdlnis/page/MoreFragment.java @@ -1,40 +1,13 @@ package com.deniscerri.ytdlnis.page; import android.os.Bundle; -import android.widget.Toast; - -import androidx.preference.Preference; import androidx.preference.PreferenceFragmentCompat; - import com.deniscerri.ytdlnis.R; -import com.deniscerri.ytdlnis.util.UpdateUtil; public class MoreFragment extends PreferenceFragmentCompat { - Preference updateYTDL; - Preference updateApp; public static final String TAG = "MoreFragment"; - private UpdateUtil updateUtil; - - @Override public void onCreatePreferences(Bundle savedInstanceState, String rootKey) { setPreferencesFromResource(R.xml.more_preferences, rootKey); - - updateYTDL = findPreference("update_ytdl"); - updateApp = findPreference("update_app"); - - updateUtil = new UpdateUtil(getContext()); - - updateYTDL.setOnPreferenceClickListener(preference -> { - updateUtil.updateYoutubeDL(); - return true; - }); - - updateApp.setOnPreferenceClickListener(preference -> { - if(!updateUtil.updateApp()){ - Toast.makeText(getContext(), R.string.you_are_in_latest_version, Toast.LENGTH_SHORT).show(); - } - return true; - }); } } \ No newline at end of file diff --git a/app/src/main/java/com/deniscerri/ytdlnis/page/settings/SettingsFragment.java b/app/src/main/java/com/deniscerri/ytdlnis/page/settings/SettingsFragment.java index 60820d9d..bd9213b0 100644 --- a/app/src/main/java/com/deniscerri/ytdlnis/page/settings/SettingsFragment.java +++ b/app/src/main/java/com/deniscerri/ytdlnis/page/settings/SettingsFragment.java @@ -43,6 +43,8 @@ public class SettingsFragment extends PreferenceFragmentCompat { ListPreference videoFormat; SeekBarPreference audioQuality; + Preference updateYTDL; + SwitchPreferenceCompat updateApp; Preference version; private UpdateUtil updateUtil; @@ -58,7 +60,6 @@ public class SettingsFragment extends PreferenceFragmentCompat { setPreferencesFromResource(R.xml.root_preferences, rootKey); updateUtil = new UpdateUtil(requireContext()); - initPreferences(); initListeners(); } @@ -85,6 +86,8 @@ public class SettingsFragment extends PreferenceFragmentCompat { videoFormat = findPreference("video_format"); audioQuality = findPreference("audio_quality"); + updateYTDL = findPreference("update_ytdl"); + updateApp = findPreference("update_app"); version = findPreference("version"); version.setSummary(BuildConfig.VERSION_NAME); @@ -110,6 +113,7 @@ public class SettingsFragment extends PreferenceFragmentCompat { editor.putString("audio_format", audioFormat.getValue()); editor.putString("video_format", videoFormat.getValue()); editor.putInt("audio_quality", audioQuality.getValue()); + editor.putBoolean("update_app", updateApp.isChecked()); editor.apply(); } @@ -222,6 +226,18 @@ public class SettingsFragment extends PreferenceFragmentCompat { return true; }); + updateYTDL.setOnPreferenceClickListener(preference -> { + updateUtil.updateYoutubeDL(); + return true; + }); + + updateApp.setOnPreferenceChangeListener((preference, newValue) -> { + boolean enable = (Boolean) newValue; + editor.putBoolean("update_app", enable); + editor.apply(); + return true; + }); + version.setOnPreferenceClickListener(preference -> { if(!updateUtil.updateApp()){ Toast.makeText(getContext(), R.string.you_are_in_latest_version, Toast.LENGTH_SHORT).show(); diff --git a/app/src/main/java/com/deniscerri/ytdlnis/util/InfoUtil.java b/app/src/main/java/com/deniscerri/ytdlnis/util/InfoUtil.java index c05dec88..e996f5b3 100644 --- a/app/src/main/java/com/deniscerri/ytdlnis/util/InfoUtil.java +++ b/app/src/main/java/com/deniscerri/ytdlnis/util/InfoUtil.java @@ -4,6 +4,7 @@ import android.app.Activity; import android.content.Context; import android.content.SharedPreferences; import android.content.pm.ApplicationInfo; +import android.content.pm.PackageManager; import android.text.Html; import android.util.Log; import android.widget.Toast; @@ -35,6 +36,9 @@ public class InfoUtil { try{ SharedPreferences sharedPreferences = context.getSharedPreferences("root_preferences", Activity.MODE_PRIVATE); key = sharedPreferences.getString("api_key", ""); + applicationInfo = context.getPackageManager().getApplicationInfo(context.getPackageName(), PackageManager.GET_META_DATA); + if (key.isEmpty()) key = applicationInfo.metaData.getString("ytAPIkey"); + Log.e(TAG, key); dbManager = new DBManager(context); Thread thread = new Thread(() -> { @@ -60,6 +64,7 @@ public class InfoUtil { videos = new ArrayList<>(); //short data JSONObject res = genericRequest("https://youtube.googleapis.com/youtube/v3/search?part=snippet&q="+query+"&maxResults=25®ionCode="+countryCODE+"&key="+key); + if (!res.has("items")) return getFromYTDL(query); JSONArray dataArray = res.getJSONArray("items"); //extra data @@ -110,6 +115,7 @@ public class InfoUtil { String url = "https://youtube.googleapis.com/youtube/v3/playlistItems?part=snippet&pageToken="+nextPageToken+"&maxResults=50®ionCode="+countryCODE+"&playlistId="+id+"&key="+key; //short data JSONObject res = genericRequest(url); + if (!res.has("items")) return new PlaylistTuple("", getFromYTDL("https://www.youtube.com/playlist?list="+id)); JSONArray dataArray = res.getJSONArray("items"); //extra data @@ -155,6 +161,7 @@ public class InfoUtil { //short data JSONObject res = genericRequest("https://youtube.googleapis.com/youtube/v3/videos?part=snippet,contentDetails&id="+id+"&key="+key); + if (!res.has("items")) return getFromYTDL("https://www.youtube.com/watch?v="+id).get(0); String duration = res.getJSONArray("items").getJSONObject(0).getJSONObject("contentDetails").getString("duration"); duration = formatDuration(duration); @@ -264,59 +271,57 @@ public class InfoUtil { try { YoutubeDLRequest request = new YoutubeDLRequest(query); request.addOption("--flat-playlist"); - request.addOption("-J"); + request.addOption("-j"); request.addOption("--skip-download"); + request.addOption("-R", "1"); + request.addOption("--socket-timeout", "5"); if (!query.contains("http")) request.addOption("--default-search", "ytsearch25"); YoutubeDLResponse youtubeDLResponse = YoutubeDL.getInstance().execute(request); - JSONObject jsonObject = new JSONObject(youtubeDLResponse.getOut()); + String[] results; + try { + results = youtubeDLResponse.getOut().split(System.getProperty("line.separator")); + }catch(Exception e){ + results = new String[]{youtubeDLResponse.getOut()}; + } + + int isPlaylist = 0; + JSONObject pl = new JSONObject(results[0]); + if (pl.has("playlist")){ + if (! pl.getString("playlist").equals(query)) isPlaylist = 1; + } + + for (String result : results) { + JSONObject jsonObject = new JSONObject(result); + if (jsonObject.getString("title").equals("[Private video]")) continue; - if(!jsonObject.has("entries")){ String url = jsonObject.getString("webpage_url"); + String thumb = ""; + if (jsonObject.has("thumbnail")){ + thumb = jsonObject.getString("thumbnail"); + }else { + JSONArray thumbs = jsonObject.getJSONArray("thumbnails"); + thumb = thumbs.getJSONObject(thumbs.length()-1).getString("url"); + } + + String website = ""; + if (jsonObject.has("ie_key")) website = jsonObject.getString("ie_key"); + else website = jsonObject.getString("extractor"); + + videos.add(new Video( jsonObject.getString("id"), url, jsonObject.getString("title"), jsonObject.getString("uploader"), formatIntegerDuration(jsonObject.getInt("duration")), - jsonObject.getString("thumbnail"), + thumb, dbManager.checkDownloaded(url, "audio"), dbManager.checkDownloaded(url, "video"), - 0, - jsonObject.getString("extractor")) + isPlaylist, + website) ); - }else{ - JSONArray jsonArray = jsonObject.getJSONArray("entries"); - - for (int i = 0; i < jsonArray.length(); i++){ - jsonObject = jsonArray.getJSONObject(i); - String url = jsonObject.getString("url"); - String thumb = ""; - if (jsonObject.has("thumbnail")){ - thumb = jsonObject.getString("thumbnail"); - }else { - JSONArray thumbs = jsonObject.getJSONArray("thumbnails"); - thumb = thumbs.getJSONObject(thumbs.length()-1).getString("url"); - } - String website = ""; - if (jsonObject.has("ie_key")) website = jsonObject.getString("ie_key"); - else website = jsonObject.getString("extractor"); - - videos.add(new Video( - jsonObject.getString("id"), - url, - jsonObject.getString("title"), - jsonObject.getString("uploader"), - formatIntegerDuration(jsonObject.getInt("duration")), - thumb, - dbManager.checkDownloaded(url, "audio"), - dbManager.checkDownloaded(url, "video"), - 0, - website) - ); - } } - }catch(Exception e){ e.printStackTrace(); } @@ -335,6 +340,8 @@ public class InfoUtil { //extra data from the same videos JSONObject contentDetails = genericRequest("https://www.googleapis.com/youtube/v3/videos?part=contentDetails&chart=mostPopular&videoCategoryId=10®ionCode="+countryCODE+"&maxResults=25&key="+key); + if(!contentDetails.has("items")) return new ArrayList<>(); + JSONArray dataArray = res.getJSONArray("items"); JSONArray extraDataArray = contentDetails.getJSONArray("items"); for(int i = 0; i < dataArray.length(); i++){ @@ -358,55 +365,30 @@ public class InfoUtil { } public String formatDuration(String dur){ - if(dur.equals("P0D")){ return "LIVE"; } + boolean hours = false; String duration = ""; - String tmp = ""; - String hours = ""; - String minutes = ""; - String seconds = ""; - //removing P - dur = dur.substring(1); - for(int i = 0; i < dur.length(); i++){ - char c = dur.charAt(i); - if(!Character.isDigit(c)){ - int nr = Character.getNumericValue(c); - if(nr < 10){ - tmp = "0" + tmp; - } - if (c == 'D'){ - hours = String.valueOf(Integer.parseInt(tmp) * 24); - }else if(c == 'T'){ - continue; - }else if(c == 'H'){ - hours = tmp; - }else if(c == 'M'){ - minutes = tmp; - }else if(c == 'S'){ - seconds = tmp; - } - tmp = ""; - continue; - } - tmp = tmp + c; + dur = dur.substring(2); + if (dur.contains("H")) { + hours = true; + duration += String.format(Locale.getDefault(), "%02d", Integer.parseInt(dur.substring(0, dur.indexOf("H")))) + ":"; + dur = dur.substring(dur.indexOf("H")+1); + } + if (dur.contains("M")) { + duration += String.format(Locale.getDefault(), "%02d", Integer.parseInt(dur.substring(0, dur.indexOf("M")))) + ":"; + dur = dur.substring(dur.indexOf("M")+1); + }else if(hours) duration += "00:"; + if (dur.contains("S")){ + if(duration.isEmpty()) duration = "00:"; + duration += String.format(Locale.getDefault(), "%02d", Integer.parseInt(dur.substring(0, dur.indexOf("S")))); + }else{ + duration += "00"; } - if(seconds.isEmpty()) seconds = "00"; - else if(Integer.parseInt(seconds) < 10) seconds = "0" + seconds; - if(minutes.isEmpty()){ - minutes = "0"; - } - duration = minutes + ":" + seconds; - - if(!hours.isEmpty()){ - if(Integer.parseInt(minutes) < 10) minutes = "0" + minutes; - duration = hours + ":" + minutes + ":" + seconds; - } - - if(duration.equals("0:00:00")){ + if(duration.equals("00:00")){ duration = ""; } diff --git a/app/src/main/res/drawable/ic_app_icon.xml b/app/src/main/res/drawable/ic_app_icon.xml new file mode 100644 index 00000000..d6a5584c --- /dev/null +++ b/app/src/main/res/drawable/ic_app_icon.xml @@ -0,0 +1,15 @@ + + + diff --git a/app/src/main/res/drawable/ic_downloads.xml b/app/src/main/res/drawable/ic_downloads.xml new file mode 100644 index 00000000..ad08ddb0 --- /dev/null +++ b/app/src/main/res/drawable/ic_downloads.xml @@ -0,0 +1,5 @@ + + + diff --git a/app/src/main/res/drawable/ic_history.xml b/app/src/main/res/drawable/ic_history.xml deleted file mode 100644 index 98a82168..00000000 --- a/app/src/main/res/drawable/ic_history.xml +++ /dev/null @@ -1,5 +0,0 @@ - - - diff --git a/app/src/main/res/layout/fragment_more.xml b/app/src/main/res/layout/fragment_more.xml index ebbe9341..469c74d4 100644 --- a/app/src/main/res/layout/fragment_more.xml +++ b/app/src/main/res/layout/fragment_more.xml @@ -1,27 +1,62 @@ - + android:layout_height="wrap_content"> - + android:layout_height="?attr/actionBarSize" + xmlns:app="http://schemas.android.com/apk/res-auto" + android:id="@+id/preference_coordinatorLayout" + xmlns:android="http://schemas.android.com/apk/res/android"> - + android:layout_height="match_parent" + app:layout_constraintEnd_toEndOf="parent" + app:layout_constraintStart_toStartOf="parent" + app:layout_constraintTop_toTopOf="parent"> - + + + + + + + + + + + + + - \ No newline at end of file + diff --git a/app/src/main/res/layout/result_card.xml b/app/src/main/res/layout/result_card.xml index 43e63b15..74e611a0 100644 --- a/app/src/main/res/layout/result_card.xml +++ b/app/src/main/res/layout/result_card.xml @@ -36,6 +36,17 @@ android:layout_width="match_parent" android:layout_height="match_parent" /> + + - - diff --git a/app/src/main/res/menu/bottom_nav_menu.xml b/app/src/main/res/menu/bottom_nav_menu.xml index 9cd49e2f..73d1eeab 100644 --- a/app/src/main/res/menu/bottom_nav_menu.xml +++ b/app/src/main/res/menu/bottom_nav_menu.xml @@ -4,9 +4,9 @@ - + diff --git a/app/src/main/res/values-sq-rAL/strings.xml b/app/src/main/res/values-sq-rAL/strings.xml index 5de79ea1..42c260ec 100644 --- a/app/src/main/res/values-sq-rAL/strings.xml +++ b/app/src/main/res/values-sq-rAL/strings.xml @@ -45,8 +45,7 @@ Redaktori i Muzikës Komanda Më Shumë - Përditëso Aplikacionin - Shkarko versionin e fundit të aplikacionit + Kontrollo për përditësime Versioni Ekzekuto Komandën Shkruaj komandën yt-dlp @@ -96,4 +95,6 @@ Linku u kopjua Çelësi API i YouTube Përdor një çelës api për të marrë rezultate më të shpejta nga YouTube + Njoftohu kur një përditësim është i vlefshëm + Shkarkimet \ No newline at end of file diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 837f77b6..c22a85b9 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -45,8 +45,7 @@ Music Editor Commands More - Update App - Download the latest version of the app + Check for updates Version Run Custom Command Write yt-dlp command @@ -99,4 +98,6 @@ Link copied to clipboard YouTube API Key Use an api key to get faster results from YouTube + Let you know when updates are available right when you open the application + Downloads diff --git a/app/src/main/res/xml/more_preferences.xml b/app/src/main/res/xml/more_preferences.xml index c622d9ca..f383e16c 100644 --- a/app/src/main/res/xml/more_preferences.xml +++ b/app/src/main/res/xml/more_preferences.xml @@ -4,32 +4,15 @@ - - - - - - - - - - - - + + + - + + + + + + + +