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
This commit is contained in:
Denis Çerri 2022-09-13 00:01:22 +02:00
parent a061c78ae0
commit d931edad72
No known key found for this signature in database
GPG key ID: 3F50F14A8E7F7A13
30 changed files with 714 additions and 264 deletions

View file

@ -23,7 +23,7 @@
<PersistentState>
<option name="values">
<map>
<entry key="url" value="file:/$USER_HOME$/AppData/Local/Android/Sdk/icons/material/materialicons/delete_sweep/baseline_delete_sweep_24.xml" />
<entry key="url" value="file:/$USER_HOME$/AppData/Local/Android/Sdk/icons/material/materialicons/arrow_downward/baseline_arrow_downward_24.xml" />
</map>
</option>
</PersistentState>
@ -33,9 +33,8 @@
</option>
<option name="values">
<map>
<entry key="assetSourceType" value="FILE" />
<entry key="color" value="00a6ff" />
<entry key="outputName" value="ic_no_results" />
<entry key="outputName" value="ic_down" />
<entry key="sourceFile" value="C:\Users\denis\Desktop\eaKdW401.svg" />
</map>
</option>

View file

@ -36,25 +36,34 @@
<entry key="..\:/Users/denis/Desktop/ytdlnis/ytdlnis/app/src/main/res/xml/root_preferences.xml" value="0.33" />
<entry key="..\:/Users/denis/Desktop/ytdlnis/ytdlnis/app/src/main/res/xml/shortcuts.xml" value="0.13852073535699017" />
<entry key="..\:/Users/denis/Documents/GitHub/ytdlnis/app/src/main/res/drawable/ic_announcement.xml" value="0.1275" />
<entry key="..\:/Users/denis/Documents/GitHub/ytdlnis/app/src/main/res/drawable/ic_back.xml" value="0.109" />
<entry key="..\:/Users/denis/Documents/GitHub/ytdlnis/app/src/main/res/drawable/ic_chapters.xml" value="0.109" />
<entry key="..\:/Users/denis/Documents/GitHub/ytdlnis/app/src/main/res/drawable/ic_cloud_download.xml" value="0.1275" />
<entry key="..\:/Users/denis/Documents/GitHub/ytdlnis/app/src/main/res/drawable/ic_code.xml" value="0.1275" />
<entry key="..\:/Users/denis/Documents/GitHub/ytdlnis/app/src/main/res/drawable/ic_delete_all.xml" value="0.109" />
<entry key="..\:/Users/denis/Documents/GitHub/ytdlnis/app/src/main/res/drawable/ic_down.xml" value="0.109" />
<entry key="..\:/Users/denis/Documents/GitHub/ytdlnis/app/src/main/res/drawable/ic_download.xml" value="0.1275" />
<entry key="..\:/Users/denis/Documents/GitHub/ytdlnis/app/src/main/res/drawable/ic_go_up.xml" value="0.1275" />
<entry key="..\:/Users/denis/Documents/GitHub/ytdlnis/app/src/main/res/drawable/ic_home.xml" value="0.1275" />
<entry key="..\:/Users/denis/Documents/GitHub/ytdlnis/app/src/main/res/drawable/ic_image.xml" value="0.109" />
<entry key="..\:/Users/denis/Documents/GitHub/ytdlnis/app/src/main/res/drawable/ic_lines.xml" value="0.109" />
<entry key="..\:/Users/denis/Documents/GitHub/ytdlnis/app/src/main/res/drawable/ic_more.xml" value="0.109" />
<entry key="..\:/Users/denis/Documents/GitHub/ytdlnis/app/src/main/res/drawable/ic_music.xml" value="0.1275" />
<entry key="..\:/Users/denis/Documents/GitHub/ytdlnis/app/src/main/res/drawable/ic_music_downloaded.xml" value="0.1275" />
<entry key="..\:/Users/denis/Documents/GitHub/ytdlnis/app/src/main/res/drawable/ic_no_results.xml" value="0.109" />
<entry key="..\:/Users/denis/Documents/GitHub/ytdlnis/app/src/main/res/drawable/ic_refresh.xml" value="0.109" />
<entry key="..\:/Users/denis/Documents/GitHub/ytdlnis/app/src/main/res/drawable/ic_search.xml" value="0.1275" />
<entry key="..\:/Users/denis/Documents/GitHub/ytdlnis/app/src/main/res/drawable/ic_subtitles.xml" value="0.109" />
<entry key="..\:/Users/denis/Documents/GitHub/ytdlnis/app/src/main/res/drawable/ic_update.xml" value="0.1275" />
<entry key="..\:/Users/denis/Documents/GitHub/ytdlnis/app/src/main/res/drawable/ic_update_app.xml" value="0.109" />
<entry key="..\:/Users/denis/Documents/GitHub/ytdlnis/app/src/main/res/drawable/ic_video.xml" value="0.1275" />
<entry key="..\:/Users/denis/Documents/GitHub/ytdlnis/app/src/main/res/drawable/ic_video_downloaded.xml" value="0.1275" />
<entry key="..\:/Users/denis/Documents/GitHub/ytdlnis/app/src/main/res/layout/activity_main.xml" value="0.18" />
<entry key="..\:/Users/denis/Documents/GitHub/ytdlnis/app/src/main/res/layout/activity_settings.xml" value="0.16875" />
<entry key="..\:/Users/denis/Documents/GitHub/ytdlnis/app/src/main/res/layout/download_all_card.xml" value="0.3375" />
<entry key="..\:/Users/denis/Documents/GitHub/ytdlnis/app/src/main/res/layout/empty_history_hint.xml" value="0.2" />
<entry key="..\:/Users/denis/Documents/GitHub/ytdlnis/app/src/main/res/layout/fragment_history.xml" value="0.2" />
<entry key="..\:/Users/denis/Documents/GitHub/ytdlnis/app/src/main/res/layout/fragment_home.xml" value="0.1" />
<entry key="..\:/Users/denis/Documents/GitHub/ytdlnis/app/src/main/res/layout/fragment_home.xml" value="0.2" />
<entry key="..\:/Users/denis/Documents/GitHub/ytdlnis/app/src/main/res/layout/fragment_settings.xml" value="0.16875" />
<entry key="..\:/Users/denis/Documents/GitHub/ytdlnis/app/src/main/res/layout/history_bottom_sheet.xml" value="0.16875" />
<entry key="..\:/Users/denis/Documents/GitHub/ytdlnis/app/src/main/res/layout/history_card.xml" value="0.1" />
@ -65,9 +74,14 @@
<entry key="..\:/Users/denis/Documents/GitHub/ytdlnis/app/src/main/res/layout/search_result.xml" value="0.33" />
<entry key="..\:/Users/denis/Documents/GitHub/ytdlnis/app/src/main/res/menu/bottom_nav_menu.xml" value="0.20555555555555555" />
<entry key="..\:/Users/denis/Documents/GitHub/ytdlnis/app/src/main/res/menu/history_menu.xml" value="0.17" />
<entry key="..\:/Users/denis/Documents/GitHub/ytdlnis/app/src/main/res/menu/main_menu.xml" value="0.33" />
<entry key="..\:/Users/denis/Documents/GitHub/ytdlnis/app/src/main/res/menu/main_menu.xml" value="0.25" />
<entry key="..\:/Users/denis/Documents/GitHub/ytdlnis/app/src/main/res/menu/settings_menu.xml" value="0.16875" />
<entry key="..\:/Users/denis/Documents/GitHub/ytdlnis/app/src/main/res/xml/root_preferences.xml" value="0.18" />
<entry key="..\:/Users/denis/Documents/GitHub/ytdlnis/app/src/main/res/xml/about_preferences.xml" value="0.16875" />
<entry key="..\:/Users/denis/Documents/GitHub/ytdlnis/app/src/main/res/xml/display_preferences.xml" value="0.16875" />
<entry key="..\:/Users/denis/Documents/GitHub/ytdlnis/app/src/main/res/xml/download_preferences.xml" value="0.16875" />
<entry key="..\:/Users/denis/Documents/GitHub/ytdlnis/app/src/main/res/xml/notification_preferences.xml" value="0.16875" />
<entry key="..\:/Users/denis/Documents/GitHub/ytdlnis/app/src/main/res/xml/root_preferences.xml" value="0.25" />
<entry key="..\:/Users/denis/Documents/GitHub/ytdlnis/app/src/main/res/xml/update_preferences.xml" value="0.16875" />
</map>
</option>
</component>

View file

@ -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'
}

View file

@ -28,6 +28,10 @@
</intent-filter>
</activity>
<activity
android:name=".page.settings.SettingsActivity"
android:parentActivityName=".MainActivity"
/>
<service
android:name=".DownloaderService"
android:enabled="true"

View file

@ -4,7 +4,6 @@ import android.app.Application;
import android.util.Log;
import android.widget.Toast;
import com.devbrackets.android.exomedia.BuildConfig;
import com.google.android.material.color.DynamicColors;
import com.yausername.ffmpeg.FFmpeg;
import com.yausername.youtubedl_android.YoutubeDL;
@ -17,12 +16,12 @@ import io.reactivex.observers.DisposableCompletableObserver;
import io.reactivex.plugins.RxJavaPlugins;
import io.reactivex.schedulers.Schedulers;
import com.deniscerri.ytdl.util.NotificationUtil;
public class App extends Application {
private static final String TAG = "App";
public static NotificationUtil notificationUtil;
public static String arch = System.getProperty("os.arch");
public static String versionName = BuildConfig.VERSION_NAME;
@Override
public void onCreate() {

View file

@ -1,4 +1,4 @@
package com.deniscerri.ytdl.service;
package com.deniscerri.ytdl;
import android.app.Notification;
import android.app.PendingIntent;
@ -9,10 +9,6 @@ import android.os.IBinder;
import androidx.annotation.Nullable;
import androidx.core.app.NotificationCompat;
import com.deniscerri.ytdl.App;
import com.deniscerri.ytdl.MainActivity;
import com.deniscerri.ytdl.util.NotificationUtil;
public class DownloaderService extends Service {
private LocalBinder binder = new LocalBinder();

View file

@ -4,7 +4,6 @@ import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.ServiceConnection;
import android.os.Binder;
import android.os.Bundle;
import android.os.IBinder;
import android.util.Log;
@ -14,8 +13,6 @@ import androidx.fragment.app.FragmentManager;
import com.deniscerri.ytdl.databinding.ActivityMainBinding;
import com.deniscerri.ytdl.page.HistoryFragment;
import com.deniscerri.ytdl.page.HomeFragment;
import com.deniscerri.ytdl.page.SettingsFragment;
import com.deniscerri.ytdl.service.DownloaderService;
public class MainActivity extends AppCompatActivity{
@ -27,7 +24,6 @@ public class MainActivity extends AppCompatActivity{
private HomeFragment homeFragment;
private HistoryFragment historyFragment;
private SettingsFragment settingsFragment;
private Fragment lastFragment;
private FragmentManager fm;
@ -63,14 +59,11 @@ public class MainActivity extends AppCompatActivity{
homeFragment = new HomeFragment();
historyFragment = new HistoryFragment();
settingsFragment = new SettingsFragment();
fm.beginTransaction()
.replace(R.id.frame_layout, homeFragment)
.add(R.id.frame_layout, historyFragment)
.add(R.id.frame_layout, settingsFragment)
.hide(historyFragment)
.hide(settingsFragment)
.commit();
lastFragment = homeFragment;
@ -93,11 +86,6 @@ public class MainActivity extends AppCompatActivity{
}
replaceFragment(historyFragment);
break;
case R.id.settings:
this.setTitle(getString(R.string.settings));;
replaceFragment(settingsFragment);
break;
}
return true;
});
@ -119,15 +107,12 @@ public class MainActivity extends AppCompatActivity{
homeFragment = new HomeFragment();
historyFragment = new HistoryFragment();
settingsFragment = new SettingsFragment();
homeFragment.handleIntent(intent);
fm.beginTransaction()
.replace(R.id.frame_layout, homeFragment)
.add(R.id.frame_layout, historyFragment)
.add(R.id.frame_layout, settingsFragment)
.hide(historyFragment)
.hide(settingsFragment)
.commit();
lastFragment = homeFragment;

View file

@ -1,4 +1,4 @@
package com.deniscerri.ytdl.util;
package com.deniscerri.ytdl;
import android.app.Notification;
import android.app.NotificationChannel;
@ -62,7 +62,7 @@ public class NotificationUtil {
public void updateDownloadNotification(int id, String desc, int progress, int queue, String title){
String contentText = "";
if (queue > 0) contentText += queue + " items left\n";
if (queue > 1) contentText += queue + " items left\n";
contentText += desc.replaceAll("\\[.*?\\]", "");
notificationBuilder.setProgress(100, (int) progress, false)

View file

@ -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);

View file

@ -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<Intent> musicPathResultLauncher = registerForActivityResult(
new ActivityResultContracts.StartActivityForResult(),
new ActivityResultCallback<ActivityResult>() {
@Override
public void onActivityResult(ActivityResult result) {
if (result.getResultCode() == Activity.RESULT_OK) {
changePath(musicPath, result.getData(), MUSIC_PATH_CODE);
}
}
});
ActivityResultLauncher<Intent> videoPathResultLauncher = registerForActivityResult(
new ActivityResultContracts.StartActivityForResult(),
new ActivityResultCallback<ActivityResult>() {
@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);
}
}

View file

@ -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();
}
}

View file

@ -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<Intent> musicPathResultLauncher = registerForActivityResult(
new ActivityResultContracts.StartActivityForResult(),
new ActivityResultCallback<ActivityResult>() {
@Override
public void onActivityResult(ActivityResult result) {
if (result.getResultCode() == Activity.RESULT_OK) {
changePath(musicPath, result.getData(), MUSIC_PATH_CODE);
}
}
});
ActivityResultLauncher<Intent> videoPathResultLauncher = registerForActivityResult(
new ActivityResultContracts.StartActivityForResult(),
new ActivityResultCallback<ActivityResult>() {
@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);
}
}

View file

@ -0,0 +1,5 @@
<vector android:autoMirrored="true" android:height="24dp"
android:viewportHeight="24"
android:viewportWidth="24" android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
<path android:fillColor="?android:textColorPrimary" android:pathData="M20,11H7.83l5.59,-5.59L12,4l-8,8 8,8 1.41,-1.41L7.83,13H20v-2z"/>
</vector>

View file

@ -0,0 +1,8 @@
<vector android:height="24dp"
android:viewportHeight="24" android:viewportWidth="24"
android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
<path android:fillColor="?android:colorAccent" android:pathData="M21,5c-1.11,-0.35 -2.33,-0.5 -3.5,-0.5c-1.95,0 -4.05,0.4 -5.5,1.5c-1.45,-1.1 -3.55,-1.5 -5.5,-1.5S2.45,4.9 1,6v14.65c0,0.25 0.25,0.5 0.5,0.5c0.1,0 0.15,-0.05 0.25,-0.05C3.1,20.45 5.05,20 6.5,20c1.95,0 4.05,0.4 5.5,1.5c1.35,-0.85 3.8,-1.5 5.5,-1.5c1.65,0 3.35,0.3 4.75,1.05c0.1,0.05 0.15,0.05 0.25,0.05c0.25,0 0.5,-0.25 0.5,-0.5V6C22.4,5.55 21.75,5.25 21,5zM21,18.5c-1.1,-0.35 -2.3,-0.5 -3.5,-0.5c-1.7,0 -4.15,0.65 -5.5,1.5V8c1.35,-0.85 3.8,-1.5 5.5,-1.5c1.2,0 2.4,0.15 3.5,0.5V18.5z"/>
<path android:fillColor="?android:colorAccent" android:pathData="M17.5,10.5c0.88,0 1.73,0.09 2.5,0.26V9.24C19.21,9.09 18.36,9 17.5,9c-1.7,0 -3.24,0.29 -4.5,0.83v1.66C14.13,10.85 15.7,10.5 17.5,10.5z"/>
<path android:fillColor="?android:colorAccent" android:pathData="M13,12.49v1.66c1.13,-0.64 2.7,-0.99 4.5,-0.99c0.88,0 1.73,0.09 2.5,0.26V11.9c-0.79,-0.15 -1.64,-0.24 -2.5,-0.24C15.8,11.66 14.26,11.96 13,12.49z"/>
<path android:fillColor="?android:colorAccent" android:pathData="M17.5,14.33c-1.7,0 -3.24,0.29 -4.5,0.83v1.66c1.13,-0.64 2.7,-0.99 4.5,-0.99c0.88,0 1.73,0.09 2.5,0.26v-1.52C19.21,14.41 18.36,14.33 17.5,14.33z"/>
</vector>

View file

@ -0,0 +1,5 @@
<vector android:height="24dp"
android:viewportHeight="24" android:viewportWidth="24"
android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
<path android:fillColor="?android:colorAccent" android:pathData="M20,12l-1.41,-1.41L13,16.17V4h-2v12.17l-5.58,-5.59L4,12l8,8 8,-8z"/>
</vector>

View file

@ -0,0 +1,5 @@
<vector android:height="24dp"
android:viewportHeight="24" android:viewportWidth="24"
android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
<path android:fillColor="?android:colorAccent" android:pathData="M21,19V5c0,-1.1 -0.9,-2 -2,-2H5c-1.1,0 -2,0.9 -2,2v14c0,1.1 0.9,2 2,2h14c1.1,0 2,-0.9 2,-2zM8.5,13.5l2.5,3.01L14.5,12l4.5,6H5l3.5,-4.5z"/>
</vector>

View file

@ -0,0 +1,5 @@
<vector android:autoMirrored="true" android:height="24dp"
android:viewportHeight="24"
android:viewportWidth="24" android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
<path android:fillColor="?android:colorAccent" android:pathData="M4,22H2V2h2V22zM22,7H6v3h16V7zM16,14H6v3h10V14z"/>
</vector>

View file

@ -0,0 +1,5 @@
<vector android:height="24dp"
android:viewportHeight="24" android:viewportWidth="24"
android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
<path android:fillColor="?android:textColorPrimary" android:pathData="M6,10c-1.1,0 -2,0.9 -2,2s0.9,2 2,2 2,-0.9 2,-2 -0.9,-2 -2,-2zM18,10c-1.1,0 -2,0.9 -2,2s0.9,2 2,2 2,-0.9 2,-2 -0.9,-2 -2,-2zM12,10c-1.1,0 -2,0.9 -2,2s0.9,2 2,2 2,-0.9 2,-2 -0.9,-2 -2,-2z"/>
</vector>

View file

@ -1,5 +1,5 @@
<vector android:height="24dp" android:tint="#FFA600"
<vector android:height="24dp"
android:viewportHeight="24" android:viewportWidth="24"
android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
<path android:fillColor="#fff" android:pathData="M12,3v10.55c-0.59,-0.34 -1.27,-0.55 -2,-0.55 -2.21,0 -4,1.79 -4,4s1.79,4 4,4 4,-1.79 4,-4V7h4V3h-6z"/>
<path android:fillColor="?android:colorAccent" android:pathData="M12,3v10.55c-0.59,-0.34 -1.27,-0.55 -2,-0.55 -2.21,0 -4,1.79 -4,4s1.79,4 4,4 4,-1.79 4,-4V7h4V3h-6z"/>
</vector>

View file

@ -0,0 +1,5 @@
<vector android:height="24dp"
android:viewportHeight="24" android:viewportWidth="24"
android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
<path android:fillColor="?android:colorAccent" android:pathData="M20,4L4,4c-1.1,0 -2,0.9 -2,2v12c0,1.1 0.9,2 2,2h16c1.1,0 2,-0.9 2,-2L22,6c0,-1.1 -0.9,-2 -2,-2zM4,12h4v2L4,14v-2zM14,18L4,18v-2h10v2zM20,18h-4v-2h4v2zM20,14L10,14v-2h10v2z"/>
</vector>

View file

@ -0,0 +1,5 @@
<vector android:height="24dp"
android:viewportHeight="24" android:viewportWidth="24"
android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
<path android:fillColor="?android:colorAccent" android:pathData="M21.81,12.74l-0.82,-0.63v-0.22l0.8,-0.63c0.16,-0.12 0.2,-0.34 0.1,-0.51l-0.85,-1.48c-0.07,-0.13 -0.21,-0.2 -0.35,-0.2 -0.05,0 -0.1,0.01 -0.15,0.03l-0.95,0.38c-0.08,-0.05 -0.11,-0.07 -0.19,-0.11l-0.15,-1.01c-0.03,-0.21 -0.2,-0.36 -0.4,-0.36h-1.71c-0.2,0 -0.37,0.15 -0.4,0.34l-0.14,1.01c-0.03,0.02 -0.07,0.03 -0.1,0.05l-0.09,0.06 -0.95,-0.38c-0.05,-0.02 -0.1,-0.03 -0.15,-0.03 -0.14,0 -0.27,0.07 -0.35,0.2l-0.85,1.48c-0.1,0.17 -0.06,0.39 0.1,0.51l0.8,0.63v0.23l-0.8,0.63c-0.16,0.12 -0.2,0.34 -0.1,0.51l0.85,1.48c0.07,0.13 0.21,0.2 0.35,0.2 0.05,0 0.1,-0.01 0.15,-0.03l0.95,-0.37c0.08,0.05 0.12,0.07 0.2,0.11l0.15,1.01c0.03,0.2 0.2,0.34 0.4,0.34h1.71c0.2,0 0.37,-0.15 0.4,-0.34l0.15,-1.01c0.03,-0.02 0.07,-0.03 0.1,-0.05l0.09,-0.06 0.95,0.38c0.05,0.02 0.1,0.03 0.15,0.03 0.14,0 0.27,-0.07 0.35,-0.2l0.85,-1.48c0.1,-0.17 0.06,-0.39 -0.1,-0.51zM18,13.5c-0.83,0 -1.5,-0.67 -1.5,-1.5s0.67,-1.5 1.5,-1.5 1.5,0.67 1.5,1.5 -0.67,1.5 -1.5,1.5zM17,17h2v4c0,1.1 -0.9,2 -2,2H7c-1.1,0 -2,-0.9 -2,-2V3c0,-1.1 0.9,-2 2,-2h10c1.1,0 2,0.9 2,2v4h-2V6H7v12h10v-1z"/>
</vector>

View file

@ -1,5 +1,5 @@
<vector android:height="24dp" android:tint="#FF4D00"
<vector android:height="24dp"
android:viewportHeight="24" android:viewportWidth="24"
android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
<path android:fillColor="@android:color/white" android:pathData="M17,10.5V7c0,-0.55 -0.45,-1 -1,-1H4c-0.55,0 -1,0.45 -1,1v10c0,0.55 0.45,1 1,1h12c0.55,0 1,-0.45 1,-1v-3.5l4,4v-11l-4,4z"/>
<path android:fillColor="?android:colorAccent" android:pathData="M17,10.5V7c0,-0.55 -0.45,-1 -1,-1H4c-0.55,0 -1,0.45 -1,1v10c0,0.55 0.45,1 1,1h12c0.55,0 1,-0.45 1,-1v-3.5l4,4v-11l-4,4z"/>
</vector>

View file

@ -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"

View file

@ -0,0 +1,39 @@
<?xml version="1.0" encoding="utf-8"?>
<androidx.coordinatorlayout.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context="com.deniscerri.ytdl.page.settings.SettingsActivity">
<FrameLayout
android:id="@+id/settings_frame_layout"
android:layout_width="match_parent"
app:layout_behavior="com.google.android.material.appbar.AppBarLayout$ScrollingViewBehavior"
android:layout_height="match_parent"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<com.google.android.material.appbar.AppBarLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:liftOnScroll="false"
android:background="@android:color/transparent"
android:fitsSystemWindows="true">
<com.google.android.material.appbar.MaterialToolbar
android:id="@+id/settings_toolbar"
android:elevation="0dp"
app:layout_scrollFlags="scroll|enterAlways|snap"
app:title="@string/settings"
android:layout_width="match_parent"
app:navigationIcon="@drawable/ic_back"
android:layout_height="match_parent"/>
</com.google.android.material.appbar.AppBarLayout>
</androidx.coordinatorlayout.widget.CoordinatorLayout>

View file

@ -1,7 +1,7 @@
<?xml version="1.0" encoding="utf-8"?>
<androidx.coordinatorlayout.widget.CoordinatorLayout xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
android:layout_height="match_parent"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:id="@+id/preference_coordinatorLayout"
xmlns:android="http://schemas.android.com/apk/res/android">

View file

@ -7,7 +7,13 @@
<item android:title="@string/history"
android:icon="@drawable/ic_history"
android:id="@+id/history"/>
<item android:title="@string/settings"
android:icon="@drawable/ic_settings"
android:id="@+id/settings"/>
<item android:title="@string/music_editor"
android:icon="@drawable/ic_music_downloaded"
android:id="@+id/music_editor"/>
<item android:title="@string/cli"
android:icon="@drawable/ic_code"
android:id="@+id/cli"/>
<item android:title="@string/more"
android:icon="@drawable/ic_more"
android:id="@+id/more"/>
</menu>

View file

@ -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" />
<item
android:id="@+id/delete_results"
android:title="@string/fshi_rezultatet"
app:showAsAction="never" />
<item
android:id="@+id/open_settings"
android:title="@string/settings"
app:showAsAction="never" />
</menu>

View file

@ -1,4 +1,21 @@
<resources>
<!-- Reply Preference -->
<string-array name="music_formats">
<item>mp3</item>
<item>m4a</item>
<item>aac</item>
<item>alac</item>
<item>flac</item>
<item>opus</item>
<item>vorbis</item>
<item>wav</item>
</string-array>
<string-array name="video_formats">
<item>mp4</item>
<item>mkv</item>
<item>mov</item>
<item>webm</item>
</string-array>
</resources>

View file

@ -42,4 +42,9 @@
<string name="confirm_delete_history">Confirm</string>
<string name="search_history_hint">Search from History</string>
<string name="no_results">No Results</string>
<string name="music_editor">TAG Editor</string>
<string name="cli">Commands</string>
<string name="more">More</string>
<string name="update_app">Update App</string>
<string name="download_latest_version">Download the latest version of the app</string>
</resources>

View file

@ -3,39 +3,130 @@
xmlns:app="http://schemas.android.com/apk/res-auto"
>
<Preference
android:layout="@layout/fragment_settings"/>
<PreferenceCategory android:title="@string/directories">
<Preference
app:key="music_path"
app:icon="@drawable/ic_music_downloaded"
app:title="@string/music_directory" />
<Preference />
<Preference
app:key="video_path"
app:icon="@drawable/ic_video_downloaded"
app:title="@string/video_directory" />
</PreferenceCategory>
<Preference
app:key="music_path"
app:allowDividerAbove="true"
app:icon="@drawable/ic_music_downloaded"
app:title="@string/music_directory" />
<Preference
app:key="video_path"
app:icon="@drawable/ic_video_downloaded"
app:title="@string/video_directory" />
<Preference
app:key="update"
app:allowDividerAbove="true"
app:icon="@drawable/ic_update"
app:summary="@string/ytdl_update_hint"
app:title="@string/update_ytdl" />
<Preference
app:key="rreth"
app:allowDividerAbove="true"
app:icon="@drawable/ic_code"
app:summary="https://github.com/deniscerri/ytdlnis"
app:title="@string/source_code">
<intent
android:action="android.intent.action.VIEW"
android:data="https://github.com/deniscerri/ytdlnis"
<PreferenceCategory app:title="Downloading">
<SeekBarPreference
app:key="concurrent_fragments"
app:title="Concurrent Fragments"
android:icon="@drawable/ic_lines"
app:summary=" Number of fragments of a dash/hlsnative video that should be downloaded concurrently"
android:defaultValue="1"
android:max="10"
app:min="1"
app:showSeekBarValue="true"
/>
</Preference>
<EditTextPreference
app:key="limit_rate"
android:icon="@drawable/ic_down"
app:title="Limit Rate"
app:summary="Maximum download rate in bytes per second, e.g. 50K or 4.2M"
/>
</PreferenceCategory>
<PreferenceCategory android:title="Processing">
<SwitchPreferenceCompat
app:key="remove_non_music"
app:icon="@drawable/ic_music"
app:defaultValue="true"
app:title="Remove non music parts" />
<SwitchPreferenceCompat
app:key="embed_subtitles"
app:defaultValue="true"
app:summary="Embed subtitles in the video (only for mp4,webm and mkv videos)"
app:icon="@drawable/ic_subtitles"
app:title="Embed Subtitles on Videos" />
<SwitchPreferenceCompat
app:key="embed_thumbnail"
app:defaultValue="true"
app:icon="@drawable/ic_image"
app:summary="Embed thumbnail as cover art"
app:title="Embed Thumbnail" />
<SwitchPreferenceCompat
app:key="add_chapters"
app:defaultValue="true"
app:icon="@drawable/ic_chapters"
app:title="Add Chapters on Videos" />
<SwitchPreferenceCompat
app:key="write_thumbnail"
app:defaultValue="false"
app:icon="@drawable/ic_image"
app:title="Write Thumbnail to disk" />
<ListPreference
app:key="audio_format"
app:title="Audio Format"
android:defaultValue="mp3"
android:icon="@drawable/ic_code"
android:entries="@array/music_formats"
android:entryValues="@array/music_formats" />
<ListPreference
app:key="video_format"
app:title="Video Format"
android:defaultValue="mp4"
android:icon="@drawable/ic_code"
android:entries="@array/video_formats"
android:entryValues="@array/video_formats" />
<SeekBarPreference
app:key="audio_quality"
app:title="Audio Quality"
android:icon="@drawable/ic_music"
app:summary="0 (Best) 10 (Worst)"
android:defaultValue="5"
android:max="10"
app:min="0"
app:showSeekBarValue="true"
/>
</PreferenceCategory>
<PreferenceCategory android:title="@string/updating">
<Preference
app:key="update_ytdl"
app:icon="@drawable/ic_update"
app:summary="@string/ytdl_update_hint"
app:title="@string/update_ytdl" />
<Preference
app:key="update_app"
app:icon="@drawable/ic_update_app"
app:summary="@string/download_latest_version"
app:title="@string/update_app" />
</PreferenceCategory>
<PreferenceCategory android:title="@string/about">
<Preference
app:key="rreth"
app:icon="@drawable/ic_code"
app:summary="https://github.com/deniscerri/ytdlnis"
app:title="@string/source_code">
<intent
android:action="android.intent.action.VIEW"
android:data="https://github.com/deniscerri/ytdlnis"
/>
</Preference>
</PreferenceCategory>
</PreferenceScreen>