From d931edad724bf22228e11998d9aa599cf5e1e0ad Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Denis=20=C3=87erri?=
<64997243+deniscerri@users.noreply.github.com>
Date: Tue, 13 Sep 2022 00:01:22 +0200
Subject: [PATCH] new settings features
implemented alot of sponsorblock and ytdlp features as settings
moved settings fragment to a different activity
added boilerplate bottom nav pages that will be added later
---
.idea/assetWizardSettings.xml | 5 +-
.idea/misc.xml | 20 +-
app/build.gradle | 3 +
app/src/main/AndroidManifest.xml | 4 +
.../main/java/com/deniscerri/ytdl/App.java | 5 +-
.../ytdl/{service => }/DownloaderService.java | 6 +-
.../com/deniscerri/ytdl/MainActivity.java | 15 -
.../ytdl/{util => }/NotificationUtil.java | 4 +-
.../deniscerri/ytdl/page/HomeFragment.java | 58 ++-
.../ytdl/page/SettingsFragment.java | 184 ----------
.../ytdl/page/settings/SettingsActivity.java | 46 +++
.../ytdl/page/settings/SettingsFragment.java | 341 ++++++++++++++++++
app/src/main/res/drawable/ic_back.xml | 5 +
app/src/main/res/drawable/ic_chapters.xml | 8 +
app/src/main/res/drawable/ic_down.xml | 5 +
app/src/main/res/drawable/ic_image.xml | 5 +
app/src/main/res/drawable/ic_lines.xml | 5 +
app/src/main/res/drawable/ic_more.xml | 5 +
app/src/main/res/drawable/ic_music.xml | 4 +-
app/src/main/res/drawable/ic_subtitles.xml | 5 +
app/src/main/res/drawable/ic_update_app.xml | 5 +
app/src/main/res/drawable/ic_video.xml | 4 +-
app/src/main/res/layout/activity_main.xml | 1 +
app/src/main/res/layout/activity_settings.xml | 39 ++
app/src/main/res/layout/fragment_settings.xml | 2 +-
app/src/main/res/menu/bottom_nav_menu.xml | 12 +-
app/src/main/res/menu/main_menu.xml | 7 +-
app/src/main/res/values/arrays.xml | 17 +
app/src/main/res/values/strings.xml | 5 +
app/src/main/res/xml/root_preferences.xml | 153 ++++++--
30 files changed, 714 insertions(+), 264 deletions(-)
rename app/src/main/java/com/deniscerri/ytdl/{service => }/DownloaderService.java (88%)
rename app/src/main/java/com/deniscerri/ytdl/{util => }/NotificationUtil.java (97%)
delete mode 100644 app/src/main/java/com/deniscerri/ytdl/page/SettingsFragment.java
create mode 100644 app/src/main/java/com/deniscerri/ytdl/page/settings/SettingsActivity.java
create mode 100644 app/src/main/java/com/deniscerri/ytdl/page/settings/SettingsFragment.java
create mode 100644 app/src/main/res/drawable/ic_back.xml
create mode 100644 app/src/main/res/drawable/ic_chapters.xml
create mode 100644 app/src/main/res/drawable/ic_down.xml
create mode 100644 app/src/main/res/drawable/ic_image.xml
create mode 100644 app/src/main/res/drawable/ic_lines.xml
create mode 100644 app/src/main/res/drawable/ic_more.xml
create mode 100644 app/src/main/res/drawable/ic_subtitles.xml
create mode 100644 app/src/main/res/drawable/ic_update_app.xml
create mode 100644 app/src/main/res/layout/activity_settings.xml
diff --git a/.idea/assetWizardSettings.xml b/.idea/assetWizardSettings.xml
index 3bd69647..cd6d91a3 100644
--- a/.idea/assetWizardSettings.xml
+++ b/.idea/assetWizardSettings.xml
@@ -23,7 +23,7 @@
@@ -33,9 +33,8 @@
diff --git a/.idea/misc.xml b/.idea/misc.xml
index 469d480c..53c71f02 100644
--- a/.idea/misc.xml
+++ b/.idea/misc.xml
@@ -36,25 +36,34 @@
+
+
+
+
+
+
+
+
+
-
+
@@ -65,9 +74,14 @@
-
+
-
+
+
+
+
+
+
diff --git a/app/build.gradle b/app/build.gradle
index 6debe2a7..80581e87 100644
--- a/app/build.gradle
+++ b/app/build.gradle
@@ -65,6 +65,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"
@@ -78,4 +80,5 @@ dependencies {
implementation 'androidx.coordinatorlayout:coordinatorlayout:1.2.0'
implementation 'com.facebook.shimmer:shimmer:0.5.0'
+
}
diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml
index 1fdcb393..5e51f8c2 100644
--- a/app/src/main/AndroidManifest.xml
+++ b/app/src/main/AndroidManifest.xml
@@ -28,6 +28,10 @@
+
0) contentText += queue + " items left\n";
+ if (queue > 1) contentText += queue + " items left\n";
contentText += desc.replaceAll("\\[.*?\\]", "");
notificationBuilder.setProgress(100, (int) progress, false)
diff --git a/app/src/main/java/com/deniscerri/ytdl/page/HomeFragment.java b/app/src/main/java/com/deniscerri/ytdl/page/HomeFragment.java
index 0d425211..fe614efa 100644
--- a/app/src/main/java/com/deniscerri/ytdl/page/HomeFragment.java
+++ b/app/src/main/java/com/deniscerri/ytdl/page/HomeFragment.java
@@ -39,7 +39,8 @@ import com.deniscerri.ytdl.adapter.HomeRecyclerViewAdapter;
import com.deniscerri.ytdl.api.YoutubeAPIManager;
import com.deniscerri.ytdl.database.DBManager;
import com.deniscerri.ytdl.database.Video;
-import com.deniscerri.ytdl.util.NotificationUtil;
+import com.deniscerri.ytdl.NotificationUtil;
+import com.deniscerri.ytdl.page.settings.SettingsActivity;
import com.facebook.shimmer.ShimmerFrameLayout;
import com.google.android.material.appbar.AppBarLayout;
import com.google.android.material.appbar.MaterialToolbar;
@@ -249,6 +250,10 @@ public class HomeFragment extends Fragment implements HomeRecyclerViewAdapter.On
case R.id.refresh_results:
recyclerView.removeAllViews();
initCards();
+ return true;
+ case R.id.open_settings:
+ Intent intent = new Intent(context, SettingsActivity.class);
+ startActivity(intent);
}
return true;
});
@@ -445,7 +450,7 @@ public class HomeFragment extends Fragment implements HomeRecyclerViewAdapter.On
}
try {
- video = videos.remove();
+ video = videos.peek();
} catch (Exception e) {
return;
}
@@ -466,24 +471,57 @@ public class HomeFragment extends Fragment implements HomeRecyclerViewAdapter.On
MaterialButton clickedButton = null;
+ SharedPreferences sharedPreferences = context.getSharedPreferences("root_preferences", Activity.MODE_PRIVATE);
+
+ int concurrentFragments = sharedPreferences.getInt("concurrent_fragments", 1);
+ request.addOption("-N", concurrentFragments);
+
+ String limitRate = sharedPreferences.getString("limit_rate", "");
+ if(!limitRate.equals("")){
+ request.addOption("-r", limitRate);
+ }
+
+ boolean writeThumbnail = sharedPreferences.getBoolean("write_thumbnail", false);
+ if(writeThumbnail){
+ request.addOption("--write-thumbnail");
+ }
+
if (type.equals("mp3")) {
- request.addOption("--embed-thumbnail");
- request.addOption("--sponsorblock-remove", "all");
+ boolean embedThumb = sharedPreferences.getBoolean("embed_thumbnail", false);
+ if(embedThumb){
+ request.addOption("--embed-thumbnail");
+ }
+ boolean removeNonMusic = sharedPreferences.getBoolean("remove_non_music", false);
+ if(removeNonMusic){
+ request.addOption("--sponsorblock-remove", "all");
+ }
request.addOption("--postprocessor-args", "-write_id3v1 1 -id3v2_version 3");
request.addOption("--add-metadata");
request.addOption("--no-mtime");
request.addOption("-x");
- request.addOption("--audio-format", "mp3");
+ String format = sharedPreferences.getString("audio_format", "");
+ request.addOption("--audio-format", format);
clickedButton = recyclerView.findViewWithTag(id + "##mp3");
} else if (type.equals("mp4")) {
- request.addOption("--embed-thumbnail");
- request.addOption("--sponsorblock-mark", "all");
- request.addOption("--embed-subs", "");
- request.addOption("-f", "bestvideo[ext=mp4]+bestaudio[ext=m4a]/best[ext=mp4]/best");
+ boolean embedThumb = sharedPreferences.getBoolean("embed_thumbnail", false);
+ if(embedThumb){
+ request.addOption("--embed-thumbnail");
+ }
+ boolean addChapters = sharedPreferences.getBoolean("add_chapters", false);
+ if(addChapters){
+ request.addOption("--sponsorblock-mark", "all");
+ }
+ boolean embedSubs = sharedPreferences.getBoolean("embed_subtitles", false);
+ if(embedSubs){
+ request.addOption("--embed-subs", "");
+ }
+ String format = sharedPreferences.getString("video_format", "");
+ request.addOption("-f", "bestvideo[ext="+format+"]+bestaudio[ext=m4a]/best[ext="+format+"]/best");
clickedButton = recyclerView.findViewWithTag(id + "##mp4");
}
+
request.addOption("-o", youtubeDLDir.getAbsolutePath() + "/%(title)s.%(ext)s");
progressBar = fragmentView.findViewWithTag(id + "##progress");
@@ -524,6 +562,7 @@ public class HomeFragment extends Fragment implements HomeRecyclerViewAdapter.On
MediaScannerConnection.scanFile(context, new String[]{youtubeDLDir.getAbsolutePath()}, null, null);
// SCAN NEXT IN QUEUE
+ videos.remove();
startDownload(videos);
}, e -> {
if (BuildConfig.DEBUG) Log.e(TAG, getString(R.string.failed_download), e);
@@ -535,6 +574,7 @@ public class HomeFragment extends Fragment implements HomeRecyclerViewAdapter.On
downloading = false;
// SCAN NEXT IN QUEUE
+ videos.remove();
startDownload(videos);
});
compositeDisposable.add(disposable);
diff --git a/app/src/main/java/com/deniscerri/ytdl/page/SettingsFragment.java b/app/src/main/java/com/deniscerri/ytdl/page/SettingsFragment.java
deleted file mode 100644
index c955f714..00000000
--- a/app/src/main/java/com/deniscerri/ytdl/page/SettingsFragment.java
+++ /dev/null
@@ -1,184 +0,0 @@
-package com.deniscerri.ytdl.page;
-
-import android.app.Activity;
-import android.content.Intent;
-import android.content.SharedPreferences;
-import android.os.Bundle;
-import android.util.Log;
-import android.widget.Toast;
-
-import androidx.activity.result.ActivityResult;
-import androidx.activity.result.ActivityResultCallback;
-import androidx.activity.result.ActivityResultLauncher;
-import androidx.activity.result.contract.ActivityResultContracts;
-import androidx.preference.Preference;
-import androidx.preference.PreferenceFragmentCompat;
-
-import com.deniscerri.ytdl.BuildConfig;
-import com.deniscerri.ytdl.R;
-import com.yausername.youtubedl_android.YoutubeDL;
-import java.nio.charset.StandardCharsets;
-import io.reactivex.Observable;
-import io.reactivex.android.schedulers.AndroidSchedulers;
-import io.reactivex.disposables.CompositeDisposable;
-import io.reactivex.disposables.Disposable;
-import io.reactivex.schedulers.Schedulers;
-
-public class SettingsFragment extends PreferenceFragmentCompat {
-
- Preference musicPath;
- Preference videoPath;
- Preference update;
- public static final int MUSIC_PATH_CODE = 33333;
- public static final int VIDEO_PATH_CODE = 55555;
- public static boolean updating;
-
- private static final String TAG = "SettingsFragment";
- private final CompositeDisposable compositeDisposable = new CompositeDisposable();
-
-
- @Override
- public void onCreatePreferences(Bundle savedInstanceState, String rootKey) {
- setPreferencesFromResource(R.xml.root_preferences, rootKey);
-
- musicPath = findPreference("music_path");
- videoPath = findPreference("video_path");
-
- SharedPreferences preferences = requireContext().getSharedPreferences("root_preferences", Activity.MODE_PRIVATE);
- String music_path = preferences.getString("music_path", "");
- String video_path = preferences.getString("video_path", "");
-
- if(music_path.isEmpty()){
- SharedPreferences.Editor editor = preferences.edit();
- editor.putString("music_path", "/storage/emulated/0/Music/");
- editor.apply();
- music_path = preferences.getString("music_path", "");
- }
- musicPath.setSummary(music_path);
- musicPath.setOnPreferenceClickListener(preference -> {
- Intent intent = new Intent(Intent.ACTION_OPEN_DOCUMENT_TREE);
- musicPathResultLauncher.launch(intent);
- return true;
- });
-
-
- if(video_path.isEmpty()){
- SharedPreferences.Editor editor = preferences.edit();
- editor.putString("video_path", "/storage/emulated/0/Movies/");
- editor.apply();
- video_path = preferences.getString("video_path", "");
- }
- videoPath.setSummary(video_path);
- videoPath.setOnPreferenceClickListener(preference -> {
- Intent intent = new Intent(Intent.ACTION_OPEN_DOCUMENT_TREE);
- videoPathResultLauncher.launch(intent);
- return true;
- });
-
- update = findPreference("update");
- if(update != null){
- update.setOnPreferenceClickListener(preference -> {
- updateYoutubeDL();
- return true;
- });
- }
-
-
- }
-
- ActivityResultLauncher musicPathResultLauncher = registerForActivityResult(
- new ActivityResultContracts.StartActivityForResult(),
- new ActivityResultCallback() {
- @Override
- public void onActivityResult(ActivityResult result) {
- if (result.getResultCode() == Activity.RESULT_OK) {
- changePath(musicPath, result.getData(), MUSIC_PATH_CODE);
- }
- }
- });
-
- ActivityResultLauncher videoPathResultLauncher = registerForActivityResult(
- new ActivityResultContracts.StartActivityForResult(),
- new ActivityResultCallback() {
- @Override
- public void onActivityResult(ActivityResult result) {
- if (result.getResultCode() == Activity.RESULT_OK) {
- changePath(videoPath, result.getData(), VIDEO_PATH_CODE);
- }
- }
- });
-
- public void changePath(Preference p, Intent data, int requestCode){
- Log.e("TEST", data.toUri(0));
- String dataValue = data.getData().toString();
- dataValue = dataValue.replace("content://com.android.externalstorage.documents/tree/", "");
- dataValue = dataValue.replaceAll("%3A", "/");
-
- try{
- dataValue = java.net.URLDecoder.decode(dataValue, StandardCharsets.UTF_8.name());
- }catch(Exception ignored){}
-
- String[] pieces = dataValue.split("/");
-
- int index = 1;
- StringBuilder path = new StringBuilder("/storage/");
- if(pieces[0].equals("primary")){
- path.append("emulated/0/");
- }else{
- path.append(pieces[0]).append("/");
- }
-
- for(int i = index; i < pieces.length; i++){
- path.append(pieces[i]).append("/");
- }
-
- Log.e("TEST", path.toString());
- p.setSummary(path.toString());
- SharedPreferences sharedPreferences = requireContext().getSharedPreferences("root_preferences", Activity.MODE_PRIVATE);
- SharedPreferences.Editor editor = sharedPreferences.edit();
- switch (requestCode){
- case MUSIC_PATH_CODE:
- editor.putString("music_path", path.toString());
- break;
- case VIDEO_PATH_CODE:
- editor.putString("video_path", path.toString());
- break;
- }
- editor.apply();
- }
-
- private void updateYoutubeDL() {
- if (updating) {
- Toast.makeText(getContext(), getString(R.string.ytdl_already_updating), Toast.LENGTH_LONG).show();
- return;
- }
-
- Toast.makeText(getContext(), getString(R.string.ytdl_updating_started), Toast.LENGTH_SHORT).show();
-
- updating = true;
- Disposable disposable = Observable.fromCallable(() -> YoutubeDL.getInstance().updateYoutubeDL(getContext()))
- .subscribeOn(Schedulers.newThread())
- .observeOn(AndroidSchedulers.mainThread())
- .subscribe(status -> {
- switch (status) {
- case DONE:
- Toast.makeText(getContext(), getString(R.string.ytld_update_success), Toast.LENGTH_LONG).show();
- break;
- case ALREADY_UP_TO_DATE:
- Toast.makeText(getContext(), getString(R.string.you_are_in_latest_version), Toast.LENGTH_LONG).show();
- break;
- default:
- Toast.makeText(getContext(), status.toString(), Toast.LENGTH_LONG).show();
- break;
- }
- updating = false;
- }, e -> {
- if(BuildConfig.DEBUG) Log.e(TAG, getString(R.string.ytdl_update_failed), e);
- Toast.makeText(getContext(), getString(R.string.ytdl_update_failed), Toast.LENGTH_LONG).show();
- updating = false;
- });
- compositeDisposable.add(disposable);
- }
-
-
-}
\ No newline at end of file
diff --git a/app/src/main/java/com/deniscerri/ytdl/page/settings/SettingsActivity.java b/app/src/main/java/com/deniscerri/ytdl/page/settings/SettingsActivity.java
new file mode 100644
index 00000000..da1eb781
--- /dev/null
+++ b/app/src/main/java/com/deniscerri/ytdl/page/settings/SettingsActivity.java
@@ -0,0 +1,46 @@
+package com.deniscerri.ytdl.page.settings;
+
+import android.content.Context;
+import android.content.Intent;
+import android.os.Bundle;
+import android.text.InputType;
+import android.view.MenuItem;
+import android.view.View;
+
+import androidx.appcompat.app.ActionBar;
+import androidx.appcompat.app.AppCompatActivity;
+import androidx.appcompat.widget.SearchView;
+import androidx.fragment.app.FragmentManager;
+
+
+import com.deniscerri.ytdl.R;
+import com.google.android.material.appbar.MaterialToolbar;
+
+
+public class SettingsActivity extends AppCompatActivity{
+
+ private FragmentManager fm;
+ private MaterialToolbar topAppBar;
+ Context context;
+
+ @Override
+ public void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ setContentView(R.layout.activity_settings);
+ context = getBaseContext();
+ topAppBar = findViewById(R.id.settings_toolbar);
+ topAppBar.setNavigationOnClickListener(view -> onBackPressed());
+
+ fm = getSupportFragmentManager();
+
+ fm.beginTransaction()
+ .replace(R.id.settings_frame_layout, new SettingsFragment())
+ .commit();
+
+ }
+
+ @Override
+ public void onBackPressed() {
+ super.onBackPressed();
+ }
+}
diff --git a/app/src/main/java/com/deniscerri/ytdl/page/settings/SettingsFragment.java b/app/src/main/java/com/deniscerri/ytdl/page/settings/SettingsFragment.java
new file mode 100644
index 00000000..4be31ff2
--- /dev/null
+++ b/app/src/main/java/com/deniscerri/ytdl/page/settings/SettingsFragment.java
@@ -0,0 +1,341 @@
+package com.deniscerri.ytdl.page.settings;
+
+import android.app.Activity;
+import android.content.Intent;
+import android.content.SharedPreferences;
+import android.os.Bundle;
+import android.util.Log;
+import android.widget.Toast;
+
+import androidx.activity.result.ActivityResult;
+import androidx.activity.result.ActivityResultCallback;
+import androidx.activity.result.ActivityResultLauncher;
+import androidx.activity.result.contract.ActivityResultContracts;
+import androidx.annotation.NonNull;
+import androidx.preference.EditTextPreference;
+import androidx.preference.ListPreference;
+import androidx.preference.Preference;
+import androidx.preference.PreferenceFragmentCompat;
+import androidx.preference.SeekBarPreference;
+import androidx.preference.SwitchPreferenceCompat;
+import com.deniscerri.ytdl.BuildConfig;
+import com.deniscerri.ytdl.R;
+import com.yausername.youtubedl_android.YoutubeDL;
+import java.nio.charset.StandardCharsets;
+
+import io.reactivex.Observable;
+import io.reactivex.android.schedulers.AndroidSchedulers;
+import io.reactivex.disposables.CompositeDisposable;
+import io.reactivex.disposables.Disposable;
+import io.reactivex.schedulers.Schedulers;
+
+public class SettingsFragment extends PreferenceFragmentCompat {
+
+ Preference musicPath;
+ Preference videoPath;
+
+ SeekBarPreference concurrentFragments;
+ EditTextPreference limitRate;
+
+ SwitchPreferenceCompat removeNonMusic;
+ SwitchPreferenceCompat embedSubtitles;
+ SwitchPreferenceCompat embedThumbnail;
+ SwitchPreferenceCompat addChapters;
+ SwitchPreferenceCompat writeThumbnail;
+ ListPreference audioFormat;
+ ListPreference videoFormat;
+ SeekBarPreference audioQuality;
+
+ Preference updateYTDL;
+ Preference updateApp;
+
+ public static final int MUSIC_PATH_CODE = 33333;
+ public static final int VIDEO_PATH_CODE = 55555;
+ public static boolean updatingYTDL;
+ public static boolean updatingApp;
+ private static boolean firstRun = true;
+
+ private static final String TAG = "SettingsFragment";
+ private final CompositeDisposable compositeDisposable = new CompositeDisposable();
+
+
+ @Override
+ public void onCreatePreferences(Bundle savedInstanceState, String rootKey) {
+ setPreferencesFromResource(R.xml.root_preferences, rootKey);
+
+ musicPath = findPreference("music_path");
+ videoPath = findPreference("video_path");
+
+ concurrentFragments = findPreference("concurrent_fragments");
+ limitRate = findPreference("limit_rate");
+
+ removeNonMusic = findPreference("remove_non_music");
+ embedSubtitles = findPreference("embed_subtitles");
+ embedThumbnail = findPreference("embed_thumbnail");
+ addChapters = findPreference("add_chapters");
+ writeThumbnail = findPreference("write_thumbnail");
+ audioFormat = findPreference("audio_format");
+ videoFormat = findPreference("video_format");
+ audioQuality = findPreference("audio_quality");
+
+
+ updateYTDL = findPreference("update_ytdl");
+ updateApp = findPreference("update_app");
+
+ if(firstRun){
+ initPreferences();
+ }
+ initListeners();
+ }
+
+ private void initPreferences(){
+ SharedPreferences preferences = requireContext().getSharedPreferences("root_preferences", Activity.MODE_PRIVATE);
+ SharedPreferences.Editor editor = preferences.edit();
+
+ if(preferences.getString("music_path", "").isEmpty()){
+ editor.putString("music_path", "/storage/emulated/0/Music/");
+ }
+ if(preferences.getString("video_path", "").isEmpty()){
+ editor.putString("video_path", "/storage/emulated/0/Movies/");
+ }
+
+ editor.putInt("concurrent_fragments", concurrentFragments.getValue());
+ editor.putString("limit_rate", limitRate.getText());
+ editor.putBoolean("remove_non_music", removeNonMusic.isChecked());
+ editor.putBoolean("embed_subtitles", embedSubtitles.isChecked());
+ editor.putBoolean("embed_thumbnail", embedThumbnail.isChecked());
+ editor.putBoolean("add_chapters", addChapters.isChecked());
+ editor.putBoolean("write_thumbnail", writeThumbnail.isChecked());
+ editor.putString("audio_format", audioFormat.getValue());
+ editor.putString("video_format", videoFormat.getValue());
+ editor.putInt("audio_quality", audioQuality.getValue());
+
+ editor.apply();
+ firstRun = false;
+ }
+
+ private void initListeners(){
+ SharedPreferences preferences = requireContext().getSharedPreferences("root_preferences", Activity.MODE_PRIVATE);
+ SharedPreferences.Editor editor = preferences.edit();
+
+ musicPath.setSummary(preferences.getString("music_path", ""));
+ musicPath.setOnPreferenceClickListener(preference -> {
+ Intent intent = new Intent(Intent.ACTION_OPEN_DOCUMENT_TREE);
+ musicPathResultLauncher.launch(intent);
+ return true;
+ });
+
+ videoPath.setSummary(preferences.getString("video_path", ""));
+ videoPath.setOnPreferenceClickListener(preference -> {
+ Intent intent = new Intent(Intent.ACTION_OPEN_DOCUMENT_TREE);
+ videoPathResultLauncher.launch(intent);
+ return true;
+ });
+
+ concurrentFragments.setOnPreferenceChangeListener((preference, newValue) -> {
+ int value = Integer.parseInt(String.valueOf(newValue));
+ editor.putInt("concurrent_fragments", value);
+ editor.apply();
+ return true;
+ });
+
+ limitRate.setOnPreferenceChangeListener((preference, newValue) -> {
+ editor.putString("limit_rate", String.valueOf(newValue));
+ editor.apply();
+ return true;
+ });
+
+ removeNonMusic.setOnPreferenceChangeListener((preference, newValue) -> {
+ boolean remove = (Boolean) newValue;
+ editor.putBoolean("remove_non_music", remove);
+ editor.apply();
+ return true;
+ });
+
+ embedSubtitles.setOnPreferenceChangeListener((preference, newValue) -> {
+ boolean embed = (Boolean) newValue;
+ editor.putBoolean("embed_subtitles", embed);
+ editor.apply();
+ return true;
+ });
+
+ embedThumbnail.setOnPreferenceChangeListener((preference, newValue) -> {
+ boolean embed = (Boolean) newValue;
+ editor.putBoolean("embed_thumbnail", embed);
+ editor.apply();
+ return true;
+ });
+
+ addChapters.setOnPreferenceChangeListener((preference, newValue) -> {
+ boolean add = (Boolean) newValue;
+ editor.putBoolean("add_chapters", add);
+ editor.apply();
+ return true;
+ });
+
+ writeThumbnail.setOnPreferenceChangeListener((preference, newValue) -> {
+ boolean write = (Boolean) newValue;
+ editor.putBoolean("write_thumbnail", write);
+ editor.apply();
+ return true;
+ });
+
+ audioFormat.setOnPreferenceChangeListener((preference, newValue) -> {
+ editor.putString("audio_format", String.valueOf(newValue));
+ editor.apply();
+ return true;
+ });
+
+ videoFormat.setOnPreferenceChangeListener((preference, newValue) -> {
+ editor.putString("video_format", String.valueOf(newValue));
+ editor.apply();
+ return true;
+ });
+
+ audioQuality.setOnPreferenceChangeListener((preference, newValue) -> {
+ editor.putInt("audio_format", Integer.parseInt(String.valueOf(newValue)));
+ editor.apply();
+ return true;
+ });
+
+ updateYTDL.setOnPreferenceClickListener(preference -> {
+ updateYoutubeDL();
+ return true;
+ });
+
+ updateApp.setOnPreferenceClickListener(preference -> {
+ updateApp();
+ return true;
+ });
+ }
+
+ ActivityResultLauncher musicPathResultLauncher = registerForActivityResult(
+ new ActivityResultContracts.StartActivityForResult(),
+ new ActivityResultCallback() {
+ @Override
+ public void onActivityResult(ActivityResult result) {
+ if (result.getResultCode() == Activity.RESULT_OK) {
+ changePath(musicPath, result.getData(), MUSIC_PATH_CODE);
+ }
+ }
+ });
+
+ ActivityResultLauncher videoPathResultLauncher = registerForActivityResult(
+ new ActivityResultContracts.StartActivityForResult(),
+ new ActivityResultCallback() {
+ @Override
+ public void onActivityResult(ActivityResult result) {
+ if (result.getResultCode() == Activity.RESULT_OK) {
+ changePath(videoPath, result.getData(), VIDEO_PATH_CODE);
+ }
+ }
+ });
+
+ public void changePath(Preference p, Intent data, int requestCode){
+ Log.e("TEST", data.toUri(0));
+ String dataValue = data.getData().toString();
+ dataValue = dataValue.replace("content://com.android.externalstorage.documents/tree/", "");
+ dataValue = dataValue.replaceAll("%3A", "/");
+
+ try{
+ dataValue = java.net.URLDecoder.decode(dataValue, StandardCharsets.UTF_8.name());
+ }catch(Exception ignored){}
+
+ String[] pieces = dataValue.split("/");
+
+ int index = 1;
+ StringBuilder path = new StringBuilder("/storage/");
+ if(pieces[0].equals("primary")){
+ path.append("emulated/0/");
+ }else{
+ path.append(pieces[0]).append("/");
+ }
+
+ for(int i = index; i < pieces.length; i++){
+ path.append(pieces[i]).append("/");
+ }
+
+ Log.e("TEST", path.toString());
+ p.setSummary(path.toString());
+ SharedPreferences sharedPreferences = requireContext().getSharedPreferences("root_preferences", Activity.MODE_PRIVATE);
+ SharedPreferences.Editor editor = sharedPreferences.edit();
+ switch (requestCode){
+ case MUSIC_PATH_CODE:
+ editor.putString("music_path", path.toString());
+ break;
+ case VIDEO_PATH_CODE:
+ editor.putString("video_path", path.toString());
+ break;
+ }
+ editor.apply();
+ }
+
+ private void updateYoutubeDL() {
+ if (updatingYTDL) {
+ Toast.makeText(getContext(), getString(R.string.ytdl_already_updating), Toast.LENGTH_LONG).show();
+ return;
+ }
+
+ Toast.makeText(getContext(), getString(R.string.ytdl_updating_started), Toast.LENGTH_SHORT).show();
+
+ updatingYTDL = true;
+ Disposable disposable = Observable.fromCallable(() -> YoutubeDL.getInstance().updateYoutubeDL(getContext()))
+ .subscribeOn(Schedulers.newThread())
+ .observeOn(AndroidSchedulers.mainThread())
+ .subscribe(status -> {
+ switch (status) {
+ case DONE:
+ Toast.makeText(getContext(), getString(R.string.ytld_update_success), Toast.LENGTH_LONG).show();
+ break;
+ case ALREADY_UP_TO_DATE:
+ Toast.makeText(getContext(), getString(R.string.you_are_in_latest_version), Toast.LENGTH_LONG).show();
+ break;
+ default:
+ Toast.makeText(getContext(), status.toString(), Toast.LENGTH_LONG).show();
+ break;
+ }
+ updatingYTDL = false;
+ }, e -> {
+ if(BuildConfig.DEBUG) Log.e(TAG, getString(R.string.ytdl_update_failed), e);
+ Toast.makeText(getContext(), getString(R.string.ytdl_update_failed), Toast.LENGTH_LONG).show();
+ updatingYTDL = false;
+ });
+ compositeDisposable.add(disposable);
+ }
+
+
+ private void updateApp(){
+ if (updatingApp) {
+ Toast.makeText(getContext(), getString(R.string.ytdl_already_updating), Toast.LENGTH_LONG).show();
+ return;
+ }
+
+ Toast.makeText(getContext(), getString(R.string.ytdl_updating_started), Toast.LENGTH_SHORT).show();
+
+ updatingApp = true;
+ Disposable disposable = Observable.fromCallable(() -> YoutubeDL.getInstance().updateYoutubeDL(getContext()))
+ .subscribeOn(Schedulers.newThread())
+ .observeOn(AndroidSchedulers.mainThread())
+ .subscribe(status -> {
+ switch (status) {
+ case DONE:
+ Toast.makeText(getContext(), getString(R.string.ytld_update_success), Toast.LENGTH_LONG).show();
+ break;
+ case ALREADY_UP_TO_DATE:
+ Toast.makeText(getContext(), getString(R.string.you_are_in_latest_version), Toast.LENGTH_LONG).show();
+ break;
+ default:
+ Toast.makeText(getContext(), status.toString(), Toast.LENGTH_LONG).show();
+ break;
+ }
+ updatingApp = false;
+ }, e -> {
+ if(BuildConfig.DEBUG) Log.e(TAG, getString(R.string.ytdl_update_failed), e);
+ Toast.makeText(getContext(), getString(R.string.ytdl_update_failed), Toast.LENGTH_LONG).show();
+ updatingApp = false;
+ });
+ compositeDisposable.add(disposable);
+ }
+
+
+}
\ No newline at end of file
diff --git a/app/src/main/res/drawable/ic_back.xml b/app/src/main/res/drawable/ic_back.xml
new file mode 100644
index 00000000..7747a65b
--- /dev/null
+++ b/app/src/main/res/drawable/ic_back.xml
@@ -0,0 +1,5 @@
+
+
+
diff --git a/app/src/main/res/drawable/ic_chapters.xml b/app/src/main/res/drawable/ic_chapters.xml
new file mode 100644
index 00000000..eb5255ab
--- /dev/null
+++ b/app/src/main/res/drawable/ic_chapters.xml
@@ -0,0 +1,8 @@
+
+
+
+
+
+
diff --git a/app/src/main/res/drawable/ic_down.xml b/app/src/main/res/drawable/ic_down.xml
new file mode 100644
index 00000000..f28b21bd
--- /dev/null
+++ b/app/src/main/res/drawable/ic_down.xml
@@ -0,0 +1,5 @@
+
+
+
diff --git a/app/src/main/res/drawable/ic_image.xml b/app/src/main/res/drawable/ic_image.xml
new file mode 100644
index 00000000..3707acfa
--- /dev/null
+++ b/app/src/main/res/drawable/ic_image.xml
@@ -0,0 +1,5 @@
+
+
+
diff --git a/app/src/main/res/drawable/ic_lines.xml b/app/src/main/res/drawable/ic_lines.xml
new file mode 100644
index 00000000..f651d834
--- /dev/null
+++ b/app/src/main/res/drawable/ic_lines.xml
@@ -0,0 +1,5 @@
+
+
+
diff --git a/app/src/main/res/drawable/ic_more.xml b/app/src/main/res/drawable/ic_more.xml
new file mode 100644
index 00000000..1fde2cbb
--- /dev/null
+++ b/app/src/main/res/drawable/ic_more.xml
@@ -0,0 +1,5 @@
+
+
+
diff --git a/app/src/main/res/drawable/ic_music.xml b/app/src/main/res/drawable/ic_music.xml
index d11f93ce..86999d4a 100644
--- a/app/src/main/res/drawable/ic_music.xml
+++ b/app/src/main/res/drawable/ic_music.xml
@@ -1,5 +1,5 @@
-
-
+
diff --git a/app/src/main/res/drawable/ic_subtitles.xml b/app/src/main/res/drawable/ic_subtitles.xml
new file mode 100644
index 00000000..74cbbd08
--- /dev/null
+++ b/app/src/main/res/drawable/ic_subtitles.xml
@@ -0,0 +1,5 @@
+
+
+
diff --git a/app/src/main/res/drawable/ic_update_app.xml b/app/src/main/res/drawable/ic_update_app.xml
new file mode 100644
index 00000000..e6b23ed5
--- /dev/null
+++ b/app/src/main/res/drawable/ic_update_app.xml
@@ -0,0 +1,5 @@
+
+
+
diff --git a/app/src/main/res/drawable/ic_video.xml b/app/src/main/res/drawable/ic_video.xml
index dde24fa0..d631aa70 100644
--- a/app/src/main/res/drawable/ic_video.xml
+++ b/app/src/main/res/drawable/ic_video.xml
@@ -1,5 +1,5 @@
-
-
+
diff --git a/app/src/main/res/layout/activity_main.xml b/app/src/main/res/layout/activity_main.xml
index 03576714..855ed964 100644
--- a/app/src/main/res/layout/activity_main.xml
+++ b/app/src/main/res/layout/activity_main.xml
@@ -19,6 +19,7 @@
android:id="@+id/bottomNavigationView"
android:layout_width="match_parent"
android:layout_height="wrap_content"
+ app:labelVisibilityMode="labeled"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0.0"
diff --git a/app/src/main/res/layout/activity_settings.xml b/app/src/main/res/layout/activity_settings.xml
new file mode 100644
index 00000000..16c742ef
--- /dev/null
+++ b/app/src/main/res/layout/activity_settings.xml
@@ -0,0 +1,39 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/layout/fragment_settings.xml b/app/src/main/res/layout/fragment_settings.xml
index b5653fac..522b9976 100644
--- a/app/src/main/res/layout/fragment_settings.xml
+++ b/app/src/main/res/layout/fragment_settings.xml
@@ -1,7 +1,7 @@
diff --git a/app/src/main/res/menu/bottom_nav_menu.xml b/app/src/main/res/menu/bottom_nav_menu.xml
index 9d6d3778..e50f391f 100644
--- a/app/src/main/res/menu/bottom_nav_menu.xml
+++ b/app/src/main/res/menu/bottom_nav_menu.xml
@@ -7,7 +7,13 @@
-
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/menu/main_menu.xml b/app/src/main/res/menu/main_menu.xml
index 75af3be6..00455c66 100644
--- a/app/src/main/res/menu/main_menu.xml
+++ b/app/src/main/res/menu/main_menu.xml
@@ -14,12 +14,17 @@
android:id="@+id/refresh_results"
android:icon="@drawable/ic_refresh"
android:title="@string/refresh_results"
- app:showAsAction="ifRoom" />
+ app:showAsAction="never" />
+
+
diff --git a/app/src/main/res/values/arrays.xml b/app/src/main/res/values/arrays.xml
index a082d2e0..d3e2922a 100644
--- a/app/src/main/res/values/arrays.xml
+++ b/app/src/main/res/values/arrays.xml
@@ -1,4 +1,21 @@
+
+ - mp3
+ - m4a
+ - aac
+ - alac
+ - flac
+ - opus
+ - vorbis
+ - wav
+
+
+
+ - mp4
+ - mkv
+ - mov
+ - webm
+
\ 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 6f71400e..7f0e5038 100644
--- a/app/src/main/res/values/strings.xml
+++ b/app/src/main/res/values/strings.xml
@@ -42,4 +42,9 @@
Confirm
Search from History
No Results
+ TAG Editor
+ Commands
+ More
+ Update App
+ Download the latest version of the app
diff --git a/app/src/main/res/xml/root_preferences.xml b/app/src/main/res/xml/root_preferences.xml
index 87987d5a..f3f3226c 100644
--- a/app/src/main/res/xml/root_preferences.xml
+++ b/app/src/main/res/xml/root_preferences.xml
@@ -3,39 +3,130 @@
xmlns:app="http://schemas.android.com/apk/res-auto"
>
-
+
+
-
+
+
-
-
-
-
-
-
-
-
+
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file