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