Improve code style to be more consistent
This commit is contained in:
parent
819e52cab3
commit
fda5405e48
244 changed files with 10116 additions and 7222 deletions
|
|
@ -4,6 +4,7 @@ import android.content.Intent;
|
|||
import android.os.Build;
|
||||
import android.os.Bundle;
|
||||
import android.provider.Settings;
|
||||
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.preference.Preference;
|
||||
|
||||
|
|
@ -11,48 +12,20 @@ import org.schabi.newpipe.R;
|
|||
import org.schabi.newpipe.util.Constants;
|
||||
|
||||
public class AppearanceSettingsFragment extends BasePreferenceFragment {
|
||||
private final static boolean CAPTIONING_SETTINGS_ACCESSIBLE =
|
||||
private static final boolean CAPTIONING_SETTINGS_ACCESSIBLE =
|
||||
Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT;
|
||||
|
||||
/**
|
||||
* Theme that was applied when the settings was opened (or recreated after a theme change)
|
||||
* Theme that was applied when the settings was opened (or recreated after a theme change).
|
||||
*/
|
||||
private String startThemeKey;
|
||||
private String captionSettingsKey;
|
||||
|
||||
@Override
|
||||
public void onCreate(@Nullable Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
String themeKey = getString(R.string.theme_key);
|
||||
startThemeKey = defaultPreferences.getString(themeKey, getString(R.string.default_theme_value));
|
||||
findPreference(themeKey).setOnPreferenceChangeListener(themePreferenceChange);
|
||||
|
||||
captionSettingsKey = getString(R.string.caption_settings_key);
|
||||
if (!CAPTIONING_SETTINGS_ACCESSIBLE) {
|
||||
final Preference captionSettings = findPreference(captionSettingsKey);
|
||||
getPreferenceScreen().removePreference(captionSettings);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCreatePreferences(Bundle savedInstanceState, String rootKey) {
|
||||
addPreferencesFromResource(R.xml.appearance_settings);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onPreferenceTreeClick(Preference preference) {
|
||||
if (preference.getKey().equals(captionSettingsKey) && CAPTIONING_SETTINGS_ACCESSIBLE) {
|
||||
startActivity(new Intent(Settings.ACTION_CAPTIONING_SETTINGS));
|
||||
}
|
||||
|
||||
return super.onPreferenceTreeClick(preference);
|
||||
}
|
||||
|
||||
private final Preference.OnPreferenceChangeListener themePreferenceChange = new Preference.OnPreferenceChangeListener() {
|
||||
private final Preference.OnPreferenceChangeListener themePreferenceChange
|
||||
= new Preference.OnPreferenceChangeListener() {
|
||||
@Override
|
||||
public boolean onPreferenceChange(Preference preference, Object newValue) {
|
||||
public boolean onPreferenceChange(final Preference preference, final Object newValue) {
|
||||
defaultPreferences.edit().putBoolean(Constants.KEY_THEME_CHANGE, true).apply();
|
||||
defaultPreferences.edit().putString(getString(R.string.theme_key), newValue.toString()).apply();
|
||||
defaultPreferences.edit()
|
||||
.putString(getString(R.string.theme_key), newValue.toString()).apply();
|
||||
|
||||
if (!newValue.equals(startThemeKey) && getActivity() != null) {
|
||||
// If it's not the current theme
|
||||
|
|
@ -62,4 +35,34 @@ public class AppearanceSettingsFragment extends BasePreferenceFragment {
|
|||
return false;
|
||||
}
|
||||
};
|
||||
private String captionSettingsKey;
|
||||
|
||||
@Override
|
||||
public void onCreate(@Nullable final Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
String themeKey = getString(R.string.theme_key);
|
||||
startThemeKey = defaultPreferences
|
||||
.getString(themeKey, getString(R.string.default_theme_value));
|
||||
findPreference(themeKey).setOnPreferenceChangeListener(themePreferenceChange);
|
||||
|
||||
captionSettingsKey = getString(R.string.caption_settings_key);
|
||||
if (!CAPTIONING_SETTINGS_ACCESSIBLE) {
|
||||
final Preference captionSettings = findPreference(captionSettingsKey);
|
||||
getPreferenceScreen().removePreference(captionSettings);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCreatePreferences(final Bundle savedInstanceState, final String rootKey) {
|
||||
addPreferencesFromResource(R.xml.appearance_settings);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onPreferenceTreeClick(final Preference preference) {
|
||||
if (preference.getKey().equals(captionSettingsKey) && CAPTIONING_SETTINGS_ACCESSIBLE) {
|
||||
startActivity(new Intent(Settings.ACTION_CAPTIONING_SETTINGS));
|
||||
}
|
||||
|
||||
return super.onPreferenceTreeClick(preference);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -3,11 +3,12 @@ package org.schabi.newpipe.settings;
|
|||
import android.content.SharedPreferences;
|
||||
import android.os.Bundle;
|
||||
import android.preference.PreferenceManager;
|
||||
import android.view.View;
|
||||
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.appcompat.app.ActionBar;
|
||||
import androidx.appcompat.app.AppCompatActivity;
|
||||
import androidx.preference.PreferenceFragmentCompat;
|
||||
import android.view.View;
|
||||
|
||||
import org.schabi.newpipe.MainActivity;
|
||||
|
||||
|
|
@ -15,16 +16,16 @@ public abstract class BasePreferenceFragment extends PreferenceFragmentCompat {
|
|||
protected final String TAG = getClass().getSimpleName() + "@" + Integer.toHexString(hashCode());
|
||||
protected final boolean DEBUG = MainActivity.DEBUG;
|
||||
|
||||
protected SharedPreferences defaultPreferences;
|
||||
SharedPreferences defaultPreferences;
|
||||
|
||||
@Override
|
||||
public void onCreate(@Nullable Bundle savedInstanceState) {
|
||||
public void onCreate(@Nullable final Bundle savedInstanceState) {
|
||||
defaultPreferences = PreferenceManager.getDefaultSharedPreferences(getActivity());
|
||||
super.onCreate(savedInstanceState);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onViewCreated(View view, @Nullable Bundle savedInstanceState) {
|
||||
public void onViewCreated(final View view, @Nullable final Bundle savedInstanceState) {
|
||||
super.onViewCreated(view, savedInstanceState);
|
||||
setDivider(null);
|
||||
updateTitle();
|
||||
|
|
@ -39,7 +40,9 @@ public abstract class BasePreferenceFragment extends PreferenceFragmentCompat {
|
|||
private void updateTitle() {
|
||||
if (getActivity() instanceof AppCompatActivity) {
|
||||
ActionBar actionBar = ((AppCompatActivity) getActivity()).getSupportActionBar();
|
||||
if (actionBar != null) actionBar.setTitle(getPreferenceScreen().getTitle());
|
||||
if (actionBar != null) {
|
||||
actionBar.setTitle(getPreferenceScreen().getTitle());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -45,16 +45,15 @@ import java.util.zip.ZipOutputStream;
|
|||
import static org.schabi.newpipe.util.Localization.assureCorrectAppLanguage;
|
||||
|
||||
public class ContentSettingsFragment extends BasePreferenceFragment {
|
||||
|
||||
private static final int REQUEST_IMPORT_PATH = 8945;
|
||||
private static final int REQUEST_EXPORT_PATH = 30945;
|
||||
|
||||
private File databasesDir;
|
||||
private File newpipe_db;
|
||||
private File newpipe_db_journal;
|
||||
private File newpipe_db_shm;
|
||||
private File newpipe_db_wal;
|
||||
private File newpipe_settings;
|
||||
private File newpipeDb;
|
||||
private File newpipeDbJournal;
|
||||
private File newpipeDbShm;
|
||||
private File newpipeDbWal;
|
||||
private File newpipeSettings;
|
||||
|
||||
private String thumbnailLoadToggleKey;
|
||||
|
||||
|
|
@ -63,17 +62,20 @@ public class ContentSettingsFragment extends BasePreferenceFragment {
|
|||
private String initialLanguage;
|
||||
|
||||
@Override
|
||||
public void onCreate(@Nullable Bundle savedInstanceState) {
|
||||
public void onCreate(@Nullable final Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
thumbnailLoadToggleKey = getString(R.string.download_thumbnail_key);
|
||||
|
||||
initialSelectedLocalization = org.schabi.newpipe.util.Localization.getPreferredLocalization(requireContext());
|
||||
initialSelectedContentCountry = org.schabi.newpipe.util.Localization.getPreferredContentCountry(requireContext());
|
||||
initialLanguage = PreferenceManager.getDefaultSharedPreferences(getContext()).getString("app_language_key", "en");
|
||||
initialSelectedLocalization = org.schabi.newpipe.util.Localization
|
||||
.getPreferredLocalization(requireContext());
|
||||
initialSelectedContentCountry = org.schabi.newpipe.util.Localization
|
||||
.getPreferredContentCountry(requireContext());
|
||||
initialLanguage = PreferenceManager
|
||||
.getDefaultSharedPreferences(getContext()).getString("app_language_key", "en");
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onPreferenceTreeClick(Preference preference) {
|
||||
public boolean onPreferenceTreeClick(final Preference preference) {
|
||||
if (preference.getKey().equals(thumbnailLoadToggleKey)) {
|
||||
final ImageLoader imageLoader = ImageLoader.getInstance();
|
||||
imageLoader.stop();
|
||||
|
|
@ -88,17 +90,17 @@ public class ContentSettingsFragment extends BasePreferenceFragment {
|
|||
}
|
||||
|
||||
@Override
|
||||
public void onCreatePreferences(Bundle savedInstanceState, String rootKey) {
|
||||
public void onCreatePreferences(final Bundle savedInstanceState, final String rootKey) {
|
||||
|
||||
String homeDir = getActivity().getApplicationInfo().dataDir;
|
||||
databasesDir = new File(homeDir + "/databases");
|
||||
newpipe_db = new File(homeDir + "/databases/newpipe.db");
|
||||
newpipe_db_journal = new File(homeDir + "/databases/newpipe.db-journal");
|
||||
newpipe_db_shm = new File(homeDir + "/databases/newpipe.db-shm");
|
||||
newpipe_db_wal = new File(homeDir + "/databases/newpipe.db-wal");
|
||||
newpipeDb = new File(homeDir + "/databases/newpipe.db");
|
||||
newpipeDbJournal = new File(homeDir + "/databases/newpipe.db-journal");
|
||||
newpipeDbShm = new File(homeDir + "/databases/newpipe.db-shm");
|
||||
newpipeDbWal = new File(homeDir + "/databases/newpipe.db-wal");
|
||||
|
||||
newpipe_settings = new File(homeDir + "/databases/newpipe.settings");
|
||||
newpipe_settings.delete();
|
||||
newpipeSettings = new File(homeDir + "/databases/newpipe.settings");
|
||||
newpipeSettings.delete();
|
||||
|
||||
addPreferencesFromResource(R.xml.content_settings);
|
||||
|
||||
|
|
@ -107,7 +109,8 @@ public class ContentSettingsFragment extends BasePreferenceFragment {
|
|||
Intent i = new Intent(getActivity(), FilePickerActivityHelper.class)
|
||||
.putExtra(FilePickerActivityHelper.EXTRA_ALLOW_MULTIPLE, false)
|
||||
.putExtra(FilePickerActivityHelper.EXTRA_ALLOW_CREATE_DIR, false)
|
||||
.putExtra(FilePickerActivityHelper.EXTRA_MODE, FilePickerActivityHelper.MODE_FILE);
|
||||
.putExtra(FilePickerActivityHelper.EXTRA_MODE,
|
||||
FilePickerActivityHelper.MODE_FILE);
|
||||
startActivityForResult(i, REQUEST_IMPORT_PATH);
|
||||
return true;
|
||||
});
|
||||
|
|
@ -117,7 +120,8 @@ public class ContentSettingsFragment extends BasePreferenceFragment {
|
|||
Intent i = new Intent(getActivity(), FilePickerActivityHelper.class)
|
||||
.putExtra(FilePickerActivityHelper.EXTRA_ALLOW_MULTIPLE, false)
|
||||
.putExtra(FilePickerActivityHelper.EXTRA_ALLOW_CREATE_DIR, true)
|
||||
.putExtra(FilePickerActivityHelper.EXTRA_MODE, FilePickerActivityHelper.MODE_DIR);
|
||||
.putExtra(FilePickerActivityHelper.EXTRA_MODE,
|
||||
FilePickerActivityHelper.MODE_DIR);
|
||||
startActivityForResult(i, REQUEST_EXPORT_PATH);
|
||||
return true;
|
||||
});
|
||||
|
|
@ -131,22 +135,29 @@ public class ContentSettingsFragment extends BasePreferenceFragment {
|
|||
.getPreferredLocalization(requireContext());
|
||||
final ContentCountry selectedContentCountry = org.schabi.newpipe.util.Localization
|
||||
.getPreferredContentCountry(requireContext());
|
||||
final String selectedLanguage = PreferenceManager.getDefaultSharedPreferences(getContext()).getString("app_language_key", "en");
|
||||
final String selectedLanguage = PreferenceManager
|
||||
.getDefaultSharedPreferences(getContext()).getString("app_language_key", "en");
|
||||
|
||||
if (!selectedLocalization.equals(initialSelectedLocalization)
|
||||
|| !selectedContentCountry.equals(initialSelectedContentCountry) || !selectedLanguage.equals(initialLanguage)) {
|
||||
Toast.makeText(requireContext(), R.string.localization_changes_requires_app_restart, Toast.LENGTH_LONG).show();
|
||||
|| !selectedContentCountry.equals(initialSelectedContentCountry)
|
||||
|| !selectedLanguage.equals(initialLanguage)) {
|
||||
Toast.makeText(requireContext(), R.string.localization_changes_requires_app_restart,
|
||||
Toast.LENGTH_LONG).show();
|
||||
|
||||
NewPipe.setupLocalization(selectedLocalization, selectedContentCountry);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onActivityResult(int requestCode, int resultCode, @NonNull Intent data) {
|
||||
public void onActivityResult(final int requestCode, final int resultCode,
|
||||
@NonNull final Intent data) {
|
||||
assureCorrectAppLanguage(getContext());
|
||||
super.onActivityResult(requestCode, resultCode, data);
|
||||
if (DEBUG) {
|
||||
Log.d(TAG, "onActivityResult() called with: requestCode = [" + requestCode + "], resultCode = [" + resultCode + "], data = [" + data + "]");
|
||||
Log.d(TAG, "onActivityResult() called with: "
|
||||
+ "requestCode = [" + requestCode + "], "
|
||||
+ "resultCode = [" + resultCode + "], "
|
||||
+ "data = [" + data + "]");
|
||||
}
|
||||
|
||||
if ((requestCode == REQUEST_IMPORT_PATH || requestCode == REQUEST_EXPORT_PATH)
|
||||
|
|
@ -167,7 +178,7 @@ public class ContentSettingsFragment extends BasePreferenceFragment {
|
|||
}
|
||||
}
|
||||
|
||||
private void exportDatabase(String path) {
|
||||
private void exportDatabase(final String path) {
|
||||
try {
|
||||
//checkpoint before export
|
||||
NewPipeDatabase.checkpoint();
|
||||
|
|
@ -175,10 +186,10 @@ public class ContentSettingsFragment extends BasePreferenceFragment {
|
|||
ZipOutputStream outZip = new ZipOutputStream(
|
||||
new BufferedOutputStream(
|
||||
new FileOutputStream(path)));
|
||||
ZipHelper.addFileToZip(outZip, newpipe_db.getPath(), "newpipe.db");
|
||||
ZipHelper.addFileToZip(outZip, newpipeDb.getPath(), "newpipe.db");
|
||||
|
||||
saveSharedPreferencesToFile(newpipe_settings);
|
||||
ZipHelper.addFileToZip(outZip, newpipe_settings.getPath(), "newpipe.settings");
|
||||
saveSharedPreferencesToFile(newpipeSettings);
|
||||
ZipHelper.addFileToZip(outZip, newpipeSettings.getPath(), "newpipe.settings");
|
||||
|
||||
outZip.close();
|
||||
|
||||
|
|
@ -189,7 +200,7 @@ public class ContentSettingsFragment extends BasePreferenceFragment {
|
|||
}
|
||||
}
|
||||
|
||||
private void saveSharedPreferencesToFile(File dst) {
|
||||
private void saveSharedPreferencesToFile(final File dst) {
|
||||
ObjectOutputStream output = null;
|
||||
try {
|
||||
output = new ObjectOutputStream(new FileOutputStream(dst));
|
||||
|
|
@ -212,7 +223,7 @@ public class ContentSettingsFragment extends BasePreferenceFragment {
|
|||
}
|
||||
}
|
||||
|
||||
private void importDatabase(String filePath) {
|
||||
private void importDatabase(final String filePath) {
|
||||
// check if file is supported
|
||||
ZipFile zipFile = null;
|
||||
try {
|
||||
|
|
@ -224,7 +235,8 @@ public class ContentSettingsFragment extends BasePreferenceFragment {
|
|||
} finally {
|
||||
try {
|
||||
zipFile.close();
|
||||
} catch (Exception ignored){}
|
||||
} catch (Exception ignored) {
|
||||
}
|
||||
}
|
||||
|
||||
try {
|
||||
|
|
@ -233,21 +245,20 @@ public class ContentSettingsFragment extends BasePreferenceFragment {
|
|||
}
|
||||
|
||||
final boolean isDbFileExtracted = ZipHelper.extractFileFromZip(filePath,
|
||||
newpipe_db.getPath(), "newpipe.db");
|
||||
newpipeDb.getPath(), "newpipe.db");
|
||||
|
||||
if (isDbFileExtracted) {
|
||||
newpipe_db_journal.delete();
|
||||
newpipe_db_wal.delete();
|
||||
newpipe_db_shm.delete();
|
||||
|
||||
newpipeDbJournal.delete();
|
||||
newpipeDbWal.delete();
|
||||
newpipeDbShm.delete();
|
||||
} else {
|
||||
|
||||
Toast.makeText(getContext(), R.string.could_not_import_all_files, Toast.LENGTH_LONG)
|
||||
.show();
|
||||
}
|
||||
|
||||
//If settings file exist, ask if it should be imported.
|
||||
if (ZipHelper.extractFileFromZip(filePath, newpipe_settings.getPath(), "newpipe.settings")) {
|
||||
if (ZipHelper.extractFileFromZip(filePath, newpipeSettings.getPath(),
|
||||
"newpipe.settings")) {
|
||||
AlertDialog.Builder alert = new AlertDialog.Builder(getContext());
|
||||
alert.setTitle(R.string.import_settings);
|
||||
|
||||
|
|
@ -258,7 +269,7 @@ public class ContentSettingsFragment extends BasePreferenceFragment {
|
|||
});
|
||||
alert.setPositiveButton(getString(R.string.finish), (dialog, which) -> {
|
||||
dialog.dismiss();
|
||||
loadSharedPreferences(newpipe_settings);
|
||||
loadSharedPreferences(newpipeSettings);
|
||||
// restart app to properly load db
|
||||
System.exit(0);
|
||||
});
|
||||
|
|
@ -267,33 +278,34 @@ public class ContentSettingsFragment extends BasePreferenceFragment {
|
|||
// restart app to properly load db
|
||||
System.exit(0);
|
||||
}
|
||||
|
||||
} catch (Exception e) {
|
||||
onError(e);
|
||||
}
|
||||
}
|
||||
|
||||
private void loadSharedPreferences(File src) {
|
||||
private void loadSharedPreferences(final File src) {
|
||||
ObjectInputStream input = null;
|
||||
try {
|
||||
input = new ObjectInputStream(new FileInputStream(src));
|
||||
SharedPreferences.Editor prefEdit = PreferenceManager.getDefaultSharedPreferences(getContext()).edit();
|
||||
SharedPreferences.Editor prefEdit = PreferenceManager
|
||||
.getDefaultSharedPreferences(getContext()).edit();
|
||||
prefEdit.clear();
|
||||
Map<String, ?> entries = (Map<String, ?>) input.readObject();
|
||||
for (Map.Entry<String, ?> entry : entries.entrySet()) {
|
||||
Object v = entry.getValue();
|
||||
String key = entry.getKey();
|
||||
|
||||
if (v instanceof Boolean)
|
||||
if (v instanceof Boolean) {
|
||||
prefEdit.putBoolean(key, (Boolean) v);
|
||||
else if (v instanceof Float)
|
||||
} else if (v instanceof Float) {
|
||||
prefEdit.putFloat(key, (Float) v);
|
||||
else if (v instanceof Integer)
|
||||
} else if (v instanceof Integer) {
|
||||
prefEdit.putInt(key, (Integer) v);
|
||||
else if (v instanceof Long)
|
||||
} else if (v instanceof Long) {
|
||||
prefEdit.putLong(key, (Long) v);
|
||||
else if (v instanceof String)
|
||||
prefEdit.putString(key, ((String) v));
|
||||
} else if (v instanceof String) {
|
||||
prefEdit.putString(key, (String) v);
|
||||
}
|
||||
}
|
||||
prefEdit.commit();
|
||||
} catch (FileNotFoundException e) {
|
||||
|
|
@ -317,7 +329,7 @@ public class ContentSettingsFragment extends BasePreferenceFragment {
|
|||
// Error
|
||||
//////////////////////////////////////////////////////////////////////////*/
|
||||
|
||||
protected void onError(Throwable e) {
|
||||
protected void onError(final Throwable e) {
|
||||
final Activity activity = getActivity();
|
||||
ErrorActivity.reportError(activity, e,
|
||||
activity.getClass(),
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@ import org.schabi.newpipe.R;
|
|||
|
||||
public class DebugSettingsFragment extends BasePreferenceFragment {
|
||||
@Override
|
||||
public void onCreatePreferences(Bundle savedInstanceState, String rootKey) {
|
||||
public void onCreatePreferences(final Bundle savedInstanceState, final String rootKey) {
|
||||
addPreferencesFromResource(R.xml.debug_settings);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -32,13 +32,12 @@ import us.shandian.giga.io.StoredDirectoryHelper;
|
|||
import static org.schabi.newpipe.util.Localization.assureCorrectAppLanguage;
|
||||
|
||||
public class DownloadSettingsFragment extends BasePreferenceFragment {
|
||||
public static final boolean IGNORE_RELEASE_ON_OLD_PATH = true;
|
||||
private static final int REQUEST_DOWNLOAD_VIDEO_PATH = 0x1235;
|
||||
private static final int REQUEST_DOWNLOAD_AUDIO_PATH = 0x1236;
|
||||
public static final boolean IGNORE_RELEASE_ON_OLD_PATH = true;
|
||||
|
||||
private String DOWNLOAD_PATH_VIDEO_PREFERENCE;
|
||||
private String DOWNLOAD_PATH_AUDIO_PREFERENCE;
|
||||
private String STORAGE_USE_SAF_PREFERENCE;
|
||||
private String downloadPathVideoPreference;
|
||||
private String downloadPathAudioPreference;
|
||||
private String storageUseSafPreference;
|
||||
|
||||
private Preference prefPathVideo;
|
||||
private Preference prefPathAudio;
|
||||
|
|
@ -47,16 +46,16 @@ public class DownloadSettingsFragment extends BasePreferenceFragment {
|
|||
private Context ctx;
|
||||
|
||||
@Override
|
||||
public void onCreate(@Nullable Bundle savedInstanceState) {
|
||||
public void onCreate(@Nullable final Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
|
||||
DOWNLOAD_PATH_VIDEO_PREFERENCE = getString(R.string.download_path_video_key);
|
||||
DOWNLOAD_PATH_AUDIO_PREFERENCE = getString(R.string.download_path_audio_key);
|
||||
STORAGE_USE_SAF_PREFERENCE = getString(R.string.storage_use_saf);
|
||||
downloadPathVideoPreference = getString(R.string.download_path_video_key);
|
||||
downloadPathAudioPreference = getString(R.string.download_path_audio_key);
|
||||
storageUseSafPreference = getString(R.string.storage_use_saf);
|
||||
final String downloadStorageAsk = getString(R.string.downloads_storage_ask);
|
||||
|
||||
prefPathVideo = findPreference(DOWNLOAD_PATH_VIDEO_PREFERENCE);
|
||||
prefPathAudio = findPreference(DOWNLOAD_PATH_AUDIO_PREFERENCE);
|
||||
prefPathVideo = findPreference(downloadPathVideoPreference);
|
||||
prefPathAudio = findPreference(downloadPathAudioPreference);
|
||||
prefStorageAsk = findPreference(downloadStorageAsk);
|
||||
|
||||
updatePreferencesSummary();
|
||||
|
|
@ -66,7 +65,8 @@ public class DownloadSettingsFragment extends BasePreferenceFragment {
|
|||
prefStorageAsk.setSummary(R.string.downloads_storage_ask_summary);
|
||||
}
|
||||
|
||||
if (hasInvalidPath(DOWNLOAD_PATH_VIDEO_PREFERENCE) || hasInvalidPath(DOWNLOAD_PATH_AUDIO_PREFERENCE)) {
|
||||
if (hasInvalidPath(downloadPathVideoPreference)
|
||||
|| hasInvalidPath(downloadPathAudioPreference)) {
|
||||
updatePreferencesSummary();
|
||||
}
|
||||
|
||||
|
|
@ -77,12 +77,12 @@ public class DownloadSettingsFragment extends BasePreferenceFragment {
|
|||
}
|
||||
|
||||
@Override
|
||||
public void onCreatePreferences(Bundle savedInstanceState, String rootKey) {
|
||||
public void onCreatePreferences(final Bundle savedInstanceState, final String rootKey) {
|
||||
addPreferencesFromResource(R.xml.download_settings);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onAttach(Context context) {
|
||||
public void onAttach(final Context context) {
|
||||
super.onAttach(context);
|
||||
ctx = context;
|
||||
}
|
||||
|
|
@ -95,11 +95,14 @@ public class DownloadSettingsFragment extends BasePreferenceFragment {
|
|||
}
|
||||
|
||||
private void updatePreferencesSummary() {
|
||||
showPathInSummary(DOWNLOAD_PATH_VIDEO_PREFERENCE, R.string.download_path_summary, prefPathVideo);
|
||||
showPathInSummary(DOWNLOAD_PATH_AUDIO_PREFERENCE, R.string.download_path_audio_summary, prefPathAudio);
|
||||
showPathInSummary(downloadPathVideoPreference, R.string.download_path_summary,
|
||||
prefPathVideo);
|
||||
showPathInSummary(downloadPathAudioPreference, R.string.download_path_audio_summary,
|
||||
prefPathAudio);
|
||||
}
|
||||
|
||||
private void showPathInSummary(String prefKey, @StringRes int defaultString, Preference target) {
|
||||
private void showPathInSummary(final String prefKey, @StringRes final int defaultString,
|
||||
final Preference target) {
|
||||
String rawUri = defaultPreferences.getString(prefKey, null);
|
||||
if (rawUri == null || rawUri.isEmpty()) {
|
||||
target.setSummary(getString(defaultString));
|
||||
|
|
@ -124,33 +127,36 @@ public class DownloadSettingsFragment extends BasePreferenceFragment {
|
|||
target.setSummary(rawUri);
|
||||
}
|
||||
|
||||
private boolean isFileUri(String path) {
|
||||
private boolean isFileUri(final String path) {
|
||||
return path.charAt(0) == File.separatorChar || path.startsWith(ContentResolver.SCHEME_FILE);
|
||||
}
|
||||
|
||||
private boolean hasInvalidPath(String prefKey) {
|
||||
private boolean hasInvalidPath(final String prefKey) {
|
||||
String value = defaultPreferences.getString(prefKey, null);
|
||||
return value == null || value.isEmpty();
|
||||
}
|
||||
|
||||
private void updatePathPickers(boolean enabled) {
|
||||
private void updatePathPickers(final boolean enabled) {
|
||||
prefPathVideo.setEnabled(enabled);
|
||||
prefPathAudio.setEnabled(enabled);
|
||||
}
|
||||
|
||||
// FIXME: after releasing the old path, all downloads created on the folder becomes inaccessible
|
||||
private void forgetSAFTree(Context ctx, String oldPath) {
|
||||
private void forgetSAFTree(final Context context, final String oldPath) {
|
||||
if (IGNORE_RELEASE_ON_OLD_PATH) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (oldPath == null || oldPath.isEmpty() || isFileUri(oldPath)) return;
|
||||
if (oldPath == null || oldPath.isEmpty() || isFileUri(oldPath)) {
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
Uri uri = Uri.parse(oldPath);
|
||||
|
||||
ctx.getContentResolver().releasePersistableUriPermission(uri, StoredDirectoryHelper.PERMISSION_FLAGS);
|
||||
ctx.revokeUriPermission(uri, StoredDirectoryHelper.PERMISSION_FLAGS);
|
||||
context.getContentResolver()
|
||||
.releasePersistableUriPermission(uri, StoredDirectoryHelper.PERMISSION_FLAGS);
|
||||
context.revokeUriPermission(uri, StoredDirectoryHelper.PERMISSION_FLAGS);
|
||||
|
||||
Log.i(TAG, "Revoke old path permissions success on " + oldPath);
|
||||
} catch (Exception err) {
|
||||
|
|
@ -158,7 +164,7 @@ public class DownloadSettingsFragment extends BasePreferenceFragment {
|
|||
}
|
||||
}
|
||||
|
||||
private void showMessageDialog(@StringRes int title, @StringRes int message) {
|
||||
private void showMessageDialog(@StringRes final int title, @StringRes final int message) {
|
||||
AlertDialog.Builder msg = new AlertDialog.Builder(ctx);
|
||||
msg.setTitle(title);
|
||||
msg.setMessage(message);
|
||||
|
|
@ -167,35 +173,40 @@ public class DownloadSettingsFragment extends BasePreferenceFragment {
|
|||
}
|
||||
|
||||
@Override
|
||||
public boolean onPreferenceTreeClick(Preference preference) {
|
||||
public boolean onPreferenceTreeClick(final Preference preference) {
|
||||
if (DEBUG) {
|
||||
Log.d(TAG, "onPreferenceTreeClick() called with: preference = [" + preference + "]");
|
||||
Log.d(TAG, "onPreferenceTreeClick() called with: "
|
||||
+ "preference = [" + preference + "]");
|
||||
}
|
||||
|
||||
String key = preference.getKey();
|
||||
int request;
|
||||
|
||||
if (key.equals(STORAGE_USE_SAF_PREFERENCE)) {
|
||||
Toast.makeText(getContext(), R.string.download_choose_new_path, Toast.LENGTH_LONG).show();
|
||||
if (key.equals(storageUseSafPreference)) {
|
||||
Toast.makeText(getContext(), R.string.download_choose_new_path,
|
||||
Toast.LENGTH_LONG).show();
|
||||
return true;
|
||||
} else if (key.equals(DOWNLOAD_PATH_VIDEO_PREFERENCE)) {
|
||||
} else if (key.equals(downloadPathVideoPreference)) {
|
||||
request = REQUEST_DOWNLOAD_VIDEO_PATH;
|
||||
} else if (key.equals(DOWNLOAD_PATH_AUDIO_PREFERENCE)) {
|
||||
} else if (key.equals(downloadPathAudioPreference)) {
|
||||
request = REQUEST_DOWNLOAD_AUDIO_PATH;
|
||||
} else {
|
||||
return super.onPreferenceTreeClick(preference);
|
||||
}
|
||||
|
||||
Intent i;
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP && NewPipeSettings.useStorageAccessFramework(ctx)) {
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP
|
||||
&& NewPipeSettings.useStorageAccessFramework(ctx)) {
|
||||
i = new Intent(Intent.ACTION_OPEN_DOCUMENT_TREE)
|
||||
.putExtra("android.content.extra.SHOW_ADVANCED", true)
|
||||
.addFlags(Intent.FLAG_GRANT_PERSISTABLE_URI_PERMISSION | StoredDirectoryHelper.PERMISSION_FLAGS);
|
||||
.addFlags(Intent.FLAG_GRANT_PERSISTABLE_URI_PERMISSION
|
||||
| StoredDirectoryHelper.PERMISSION_FLAGS);
|
||||
} else {
|
||||
i = new Intent(getActivity(), FilePickerActivityHelper.class)
|
||||
.putExtra(FilePickerActivityHelper.EXTRA_ALLOW_MULTIPLE, false)
|
||||
.putExtra(FilePickerActivityHelper.EXTRA_ALLOW_CREATE_DIR, true)
|
||||
.putExtra(FilePickerActivityHelper.EXTRA_MODE, FilePickerActivityHelper.MODE_DIR);
|
||||
.putExtra(FilePickerActivityHelper.EXTRA_MODE,
|
||||
FilePickerActivityHelper.MODE_DIR);
|
||||
}
|
||||
|
||||
startActivityForResult(i, request);
|
||||
|
|
@ -204,24 +215,28 @@ public class DownloadSettingsFragment extends BasePreferenceFragment {
|
|||
}
|
||||
|
||||
@Override
|
||||
public void onActivityResult(int requestCode, int resultCode, Intent data) {
|
||||
public void onActivityResult(final int requestCode, final int resultCode, final Intent data) {
|
||||
assureCorrectAppLanguage(getContext());
|
||||
super.onActivityResult(requestCode, resultCode, data);
|
||||
if (DEBUG) {
|
||||
Log.d(TAG, "onActivityResult() called with: requestCode = [" + requestCode + "], " +
|
||||
"resultCode = [" + resultCode + "], data = [" + data + "]"
|
||||
Log.d(TAG, "onActivityResult() called with: "
|
||||
+ "requestCode = [" + requestCode + "], "
|
||||
+ "resultCode = [" + resultCode + "], data = [" + data + "]"
|
||||
);
|
||||
}
|
||||
|
||||
if (resultCode != Activity.RESULT_OK) return;
|
||||
if (resultCode != Activity.RESULT_OK) {
|
||||
return;
|
||||
}
|
||||
|
||||
String key;
|
||||
if (requestCode == REQUEST_DOWNLOAD_VIDEO_PATH)
|
||||
key = DOWNLOAD_PATH_VIDEO_PREFERENCE;
|
||||
else if (requestCode == REQUEST_DOWNLOAD_AUDIO_PATH)
|
||||
key = DOWNLOAD_PATH_AUDIO_PREFERENCE;
|
||||
else
|
||||
if (requestCode == REQUEST_DOWNLOAD_VIDEO_PATH) {
|
||||
key = downloadPathVideoPreference;
|
||||
} else if (requestCode == REQUEST_DOWNLOAD_AUDIO_PATH) {
|
||||
key = downloadPathAudioPreference;
|
||||
} else {
|
||||
return;
|
||||
}
|
||||
|
||||
Uri uri = data.getData();
|
||||
if (uri == null) {
|
||||
|
|
@ -231,23 +246,28 @@ public class DownloadSettingsFragment extends BasePreferenceFragment {
|
|||
|
||||
|
||||
// revoke permissions on the old save path (required for SAF only)
|
||||
final Context ctx = getContext();
|
||||
if (ctx == null) throw new NullPointerException("getContext()");
|
||||
final Context context = getContext();
|
||||
if (context == null) {
|
||||
throw new NullPointerException("getContext()");
|
||||
}
|
||||
|
||||
forgetSAFTree(ctx, defaultPreferences.getString(key, ""));
|
||||
forgetSAFTree(context, defaultPreferences.getString(key, ""));
|
||||
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP && !FilePickerActivityHelper.isOwnFileUri(ctx, uri)) {
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP
|
||||
&& !FilePickerActivityHelper.isOwnFileUri(context, uri)) {
|
||||
// steps to acquire the selected path:
|
||||
// 1. acquire permissions on the new save path
|
||||
// 2. save the new path, if step(2) was successful
|
||||
try {
|
||||
ctx.grantUriPermission(ctx.getPackageName(), uri, StoredDirectoryHelper.PERMISSION_FLAGS);
|
||||
context.grantUriPermission(context.getPackageName(), uri,
|
||||
StoredDirectoryHelper.PERMISSION_FLAGS);
|
||||
|
||||
StoredDirectoryHelper mainStorage = new StoredDirectoryHelper(ctx, uri, null);
|
||||
StoredDirectoryHelper mainStorage = new StoredDirectoryHelper(context, uri, null);
|
||||
Log.i(TAG, "Acquiring tree success from " + uri.toString());
|
||||
|
||||
if (!mainStorage.canWrite())
|
||||
if (!mainStorage.canWrite()) {
|
||||
throw new IOException("No write permissions on " + uri.toString());
|
||||
}
|
||||
} catch (IOException err) {
|
||||
Log.e(TAG, "Error acquiring tree from " + uri.toString(), err);
|
||||
showMessageDialog(R.string.general_error, R.string.no_available_dir);
|
||||
|
|
@ -256,7 +276,8 @@ public class DownloadSettingsFragment extends BasePreferenceFragment {
|
|||
} else {
|
||||
File target = Utils.getFileForUri(uri);
|
||||
if (!target.canWrite()) {
|
||||
showMessageDialog(R.string.download_to_sdcard_error_title, R.string.download_to_sdcard_error_message);
|
||||
showMessageDialog(R.string.download_to_sdcard_error_title,
|
||||
R.string.download_to_sdcard_error_message);
|
||||
return;
|
||||
}
|
||||
uri = Uri.fromFile(target);
|
||||
|
|
|
|||
|
|
@ -1,10 +1,11 @@
|
|||
package org.schabi.newpipe.settings;
|
||||
|
||||
import android.os.Bundle;
|
||||
import android.widget.Toast;
|
||||
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.appcompat.app.AlertDialog;
|
||||
import androidx.preference.Preference;
|
||||
import android.widget.Toast;
|
||||
|
||||
import org.schabi.newpipe.R;
|
||||
import org.schabi.newpipe.local.history.HistoryRecordManager;
|
||||
|
|
@ -25,7 +26,7 @@ public class HistorySettingsFragment extends BasePreferenceFragment {
|
|||
private CompositeDisposable disposables;
|
||||
|
||||
@Override
|
||||
public void onCreate(@Nullable Bundle savedInstanceState) {
|
||||
public void onCreate(@Nullable final Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
cacheWipeKey = getString(R.string.metadata_cache_wipe_key);
|
||||
viewsHistoryClearKey = getString(R.string.clear_views_history_key);
|
||||
|
|
@ -36,12 +37,12 @@ public class HistorySettingsFragment extends BasePreferenceFragment {
|
|||
}
|
||||
|
||||
@Override
|
||||
public void onCreatePreferences(Bundle savedInstanceState, String rootKey) {
|
||||
public void onCreatePreferences(final Bundle savedInstanceState, final String rootKey) {
|
||||
addPreferencesFromResource(R.xml.history_settings);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onPreferenceTreeClick(Preference preference) {
|
||||
public boolean onPreferenceTreeClick(final Preference preference) {
|
||||
if (preference.getKey().equals(cacheWipeKey)) {
|
||||
InfoCache.getInstance().clearCache();
|
||||
Toast.makeText(preference.getContext(), R.string.metadata_cache_wipe_complete_notice,
|
||||
|
|
@ -53,7 +54,8 @@ public class HistorySettingsFragment extends BasePreferenceFragment {
|
|||
.setTitle(R.string.delete_view_history_alert)
|
||||
.setNegativeButton(R.string.cancel, ((dialog, which) -> dialog.dismiss()))
|
||||
.setPositiveButton(R.string.delete, ((dialog, which) -> {
|
||||
final Disposable onDeletePlaybackStates = recordManager.deleteCompelteStreamStateHistory()
|
||||
final Disposable onDeletePlaybackStates
|
||||
= recordManager.deleteCompelteStreamStateHistory()
|
||||
.observeOn(AndroidSchedulers.mainThread())
|
||||
.subscribe(
|
||||
howManyDeleted -> Toast.makeText(getActivity(),
|
||||
|
|
@ -86,7 +88,8 @@ public class HistorySettingsFragment extends BasePreferenceFragment {
|
|||
final Disposable onClearOrphans = recordManager.removeOrphanedRecords()
|
||||
.observeOn(AndroidSchedulers.mainThread())
|
||||
.subscribe(
|
||||
howManyDeleted -> {},
|
||||
howManyDeleted -> {
|
||||
},
|
||||
throwable -> ErrorActivity.reportError(getContext(),
|
||||
throwable,
|
||||
SettingsActivity.class, null,
|
||||
|
|
@ -109,7 +112,8 @@ public class HistorySettingsFragment extends BasePreferenceFragment {
|
|||
.setNegativeButton(R.string.cancel, ((dialog, which) -> dialog.dismiss()))
|
||||
.setPositiveButton(R.string.delete, ((dialog, which) -> {
|
||||
|
||||
final Disposable onDeletePlaybackStates = recordManager.deleteCompelteStreamStateHistory()
|
||||
final Disposable onDeletePlaybackStates
|
||||
= recordManager.deleteCompelteStreamStateHistory()
|
||||
.observeOn(AndroidSchedulers.mainThread())
|
||||
.subscribe(
|
||||
howManyDeleted -> Toast.makeText(getActivity(),
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
package org.schabi.newpipe.settings;
|
||||
|
||||
import android.os.Bundle;
|
||||
|
||||
import androidx.preference.Preference;
|
||||
|
||||
import org.schabi.newpipe.BuildConfig;
|
||||
|
|
@ -11,7 +12,7 @@ public class MainSettingsFragment extends BasePreferenceFragment {
|
|||
public static final boolean DEBUG = !BuildConfig.BUILD_TYPE.equals("release");
|
||||
|
||||
@Override
|
||||
public void onCreatePreferences(Bundle savedInstanceState, String rootKey) {
|
||||
public void onCreatePreferences(final Bundle savedInstanceState, final String rootKey) {
|
||||
addPreferencesFromResource(R.xml.main_settings);
|
||||
|
||||
if (!CheckForNewAppVersionTask.isGithubApk()) {
|
||||
|
|
|
|||
|
|
@ -1,3 +1,16 @@
|
|||
package org.schabi.newpipe.settings;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.SharedPreferences;
|
||||
import android.os.Environment;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.preference.PreferenceManager;
|
||||
|
||||
import org.schabi.newpipe.R;
|
||||
|
||||
import java.io.File;
|
||||
|
||||
/*
|
||||
* Created by k3b on 07.01.2016.
|
||||
*
|
||||
|
|
@ -18,46 +31,13 @@
|
|||
* along with NewPipe. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package org.schabi.newpipe.settings;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.SharedPreferences;
|
||||
import android.os.Environment;
|
||||
import androidx.preference.PreferenceManager;
|
||||
import androidx.annotation.NonNull;
|
||||
|
||||
import org.schabi.newpipe.R;
|
||||
|
||||
import java.io.File;
|
||||
|
||||
/**
|
||||
* Helper for global settings
|
||||
* Helper class for global settings.
|
||||
*/
|
||||
public final class NewPipeSettings {
|
||||
private NewPipeSettings() { }
|
||||
|
||||
/*
|
||||
* Copyright (C) Christian Schabesberger 2016 <chris.schabesberger@mailbox.org>
|
||||
* NewPipeSettings.java is part of NewPipe.
|
||||
*
|
||||
* NewPipe is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* NewPipe is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with NewPipe. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
public class NewPipeSettings {
|
||||
|
||||
private NewPipeSettings() {
|
||||
}
|
||||
|
||||
public static void initSettings(Context context) {
|
||||
public static void initSettings(final Context context) {
|
||||
PreferenceManager.setDefaultValues(context, R.xml.appearance_settings, true);
|
||||
PreferenceManager.setDefaultValues(context, R.xml.content_settings, true);
|
||||
PreferenceManager.setDefaultValues(context, R.xml.download_settings, true);
|
||||
|
|
@ -70,19 +50,22 @@ public class NewPipeSettings {
|
|||
getAudioDownloadFolder(context);
|
||||
}
|
||||
|
||||
private static void getVideoDownloadFolder(Context context) {
|
||||
private static void getVideoDownloadFolder(final Context context) {
|
||||
getDir(context, R.string.download_path_video_key, Environment.DIRECTORY_MOVIES);
|
||||
}
|
||||
|
||||
private static void getAudioDownloadFolder(Context context) {
|
||||
private static void getAudioDownloadFolder(final Context context) {
|
||||
getDir(context, R.string.download_path_audio_key, Environment.DIRECTORY_MUSIC);
|
||||
}
|
||||
|
||||
private static void getDir(Context context, int keyID, String defaultDirectoryName) {
|
||||
private static void getDir(final Context context, final int keyID,
|
||||
final String defaultDirectoryName) {
|
||||
SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(context);
|
||||
final String key = context.getString(keyID);
|
||||
String downloadPath = prefs.getString(key, null);
|
||||
if ((downloadPath != null) && (!downloadPath.isEmpty())) return;
|
||||
if ((downloadPath != null) && (!downloadPath.isEmpty())) {
|
||||
return;
|
||||
}
|
||||
|
||||
SharedPreferences.Editor spEditor = prefs.edit();
|
||||
spEditor.putString(key, getNewPipeChildFolderPathForDir(getDir(defaultDirectoryName)));
|
||||
|
|
@ -90,15 +73,15 @@ public class NewPipeSettings {
|
|||
}
|
||||
|
||||
@NonNull
|
||||
public static File getDir(String defaultDirectoryName) {
|
||||
public static File getDir(final String defaultDirectoryName) {
|
||||
return new File(Environment.getExternalStorageDirectory(), defaultDirectoryName);
|
||||
}
|
||||
|
||||
private static String getNewPipeChildFolderPathForDir(File dir) {
|
||||
private static String getNewPipeChildFolderPathForDir(final File dir) {
|
||||
return new File(dir, "NewPipe").toURI().toString();
|
||||
}
|
||||
|
||||
public static boolean useStorageAccessFramework(Context context) {
|
||||
public static boolean useStorageAccessFramework(final Context context) {
|
||||
final String key = context.getString(R.string.storage_use_saf);
|
||||
final SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(context);
|
||||
|
||||
|
|
|
|||
|
|
@ -53,23 +53,21 @@ import io.reactivex.disposables.Disposable;
|
|||
import io.reactivex.schedulers.Schedulers;
|
||||
|
||||
public class PeertubeInstanceListFragment extends Fragment {
|
||||
|
||||
private static final int MENU_ITEM_RESTORE_ID = 123456;
|
||||
public InstanceListAdapter instanceListAdapter;
|
||||
private List<PeertubeInstance> instanceList = new ArrayList<>();
|
||||
private PeertubeInstance selectedInstance;
|
||||
private String savedInstanceListKey;
|
||||
public InstanceListAdapter instanceListAdapter;
|
||||
|
||||
private ProgressBar progressBar;
|
||||
private SharedPreferences sharedPreferences;
|
||||
|
||||
private CompositeDisposable disposables = new CompositeDisposable();
|
||||
|
||||
/*//////////////////////////////////////////////////////////////////////////
|
||||
// Lifecycle
|
||||
//////////////////////////////////////////////////////////////////////////*/
|
||||
private CompositeDisposable disposables = new CompositeDisposable();
|
||||
|
||||
@Override
|
||||
public void onCreate(@Nullable Bundle savedInstanceState) {
|
||||
public void onCreate(@Nullable final Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
|
||||
sharedPreferences = PreferenceManager.getDefaultSharedPreferences(requireContext());
|
||||
|
|
@ -81,20 +79,23 @@ public class PeertubeInstanceListFragment extends Fragment {
|
|||
}
|
||||
|
||||
@Override
|
||||
public View onCreateView(@NonNull LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
|
||||
public View onCreateView(@NonNull final LayoutInflater inflater, final ViewGroup container,
|
||||
final Bundle savedInstanceState) {
|
||||
return inflater.inflate(R.layout.fragment_instance_list, container, false);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onViewCreated(@NonNull View rootView, @Nullable Bundle savedInstanceState) {
|
||||
public void onViewCreated(@NonNull final View rootView,
|
||||
@Nullable final Bundle savedInstanceState) {
|
||||
super.onViewCreated(rootView, savedInstanceState);
|
||||
|
||||
initViews(rootView);
|
||||
}
|
||||
|
||||
private void initViews(@NonNull View rootView) {
|
||||
private void initViews(@NonNull final View rootView) {
|
||||
TextView instanceHelpTV = rootView.findViewById(R.id.instanceHelpTV);
|
||||
instanceHelpTV.setText(getString(R.string.peertube_instance_url_help, getString(R.string.peertube_instance_list_url)));
|
||||
instanceHelpTV.setText(getString(R.string.peertube_instance_url_help,
|
||||
getString(R.string.peertube_instance_list_url)));
|
||||
|
||||
initButton(rootView);
|
||||
|
||||
|
|
@ -121,32 +122,34 @@ public class PeertubeInstanceListFragment extends Fragment {
|
|||
super.onPause();
|
||||
saveChanges();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDestroy() {
|
||||
super.onDestroy();
|
||||
if (disposables != null) disposables.clear();
|
||||
disposables = null;
|
||||
}
|
||||
/*//////////////////////////////////////////////////////////////////////////
|
||||
// Menu
|
||||
//////////////////////////////////////////////////////////////////////////*/
|
||||
|
||||
private final int MENU_ITEM_RESTORE_ID = 123456;
|
||||
@Override
|
||||
public void onDestroy() {
|
||||
super.onDestroy();
|
||||
if (disposables != null) {
|
||||
disposables.clear();
|
||||
}
|
||||
disposables = null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
|
||||
public void onCreateOptionsMenu(final Menu menu, final MenuInflater inflater) {
|
||||
super.onCreateOptionsMenu(menu, inflater);
|
||||
|
||||
final MenuItem restoreItem = menu.add(Menu.NONE, MENU_ITEM_RESTORE_ID, Menu.NONE, R.string.restore_defaults);
|
||||
final MenuItem restoreItem = menu
|
||||
.add(Menu.NONE, MENU_ITEM_RESTORE_ID, Menu.NONE, R.string.restore_defaults);
|
||||
restoreItem.setShowAsAction(MenuItem.SHOW_AS_ACTION_ALWAYS);
|
||||
|
||||
final int restoreIcon = ThemeHelper.resolveResourceIdFromAttr(requireContext(), R.attr.ic_restore_defaults);
|
||||
final int restoreIcon = ThemeHelper
|
||||
.resolveResourceIdFromAttr(requireContext(), R.attr.ic_restore_defaults);
|
||||
restoreItem.setIcon(AppCompatResources.getDrawable(requireContext(), restoreIcon));
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onOptionsItemSelected(MenuItem item) {
|
||||
public boolean onOptionsItemSelected(final MenuItem item) {
|
||||
if (item.getItemId() == MENU_ITEM_RESTORE_ID) {
|
||||
restoreDefaults();
|
||||
return true;
|
||||
|
|
@ -164,7 +167,7 @@ public class PeertubeInstanceListFragment extends Fragment {
|
|||
instanceList.addAll(PeertubeHelper.getInstanceList(requireContext()));
|
||||
}
|
||||
|
||||
private void selectInstance(PeertubeInstance instance) {
|
||||
private void selectInstance(final PeertubeInstance instance) {
|
||||
selectedInstance = PeertubeHelper.selectInstance(instance, requireContext());
|
||||
sharedPreferences.edit().putBoolean(Constants.KEY_MAIN_PAGE_CHANGE, true).apply();
|
||||
}
|
||||
|
|
@ -172,7 +175,9 @@ public class PeertubeInstanceListFragment extends Fragment {
|
|||
private void updateTitle() {
|
||||
if (getActivity() instanceof AppCompatActivity) {
|
||||
ActionBar actionBar = ((AppCompatActivity) getActivity()).getSupportActionBar();
|
||||
if (actionBar != null) actionBar.setTitle(R.string.peertube_instance_url_title);
|
||||
if (actionBar != null) {
|
||||
actionBar.setTitle(R.string.peertube_instance_url_title);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -202,14 +207,14 @@ public class PeertubeInstanceListFragment extends Fragment {
|
|||
.show();
|
||||
}
|
||||
|
||||
private void initButton(View rootView) {
|
||||
private void initButton(final View rootView) {
|
||||
final FloatingActionButton fab = rootView.findViewById(R.id.addInstanceButton);
|
||||
fab.setOnClickListener(v -> {
|
||||
showAddItemDialog(requireContext());
|
||||
});
|
||||
}
|
||||
|
||||
private void showAddItemDialog(Context c) {
|
||||
private void showAddItemDialog(final Context c) {
|
||||
final EditText urlET = new EditText(c);
|
||||
urlET.setInputType(InputType.TYPE_CLASS_TEXT | InputType.TYPE_TEXT_VARIATION_URI);
|
||||
urlET.setHint(R.string.peertube_instance_add_help);
|
||||
|
|
@ -226,46 +231,52 @@ public class PeertubeInstanceListFragment extends Fragment {
|
|||
dialog.show();
|
||||
}
|
||||
|
||||
private void addInstance(String url) {
|
||||
private void addInstance(final String url) {
|
||||
String cleanUrl = cleanUrl(url);
|
||||
if(null == cleanUrl) return;
|
||||
if (cleanUrl == null) {
|
||||
return;
|
||||
}
|
||||
progressBar.setVisibility(View.VISIBLE);
|
||||
Disposable disposable = Single.fromCallable(() -> {
|
||||
PeertubeInstance instance = new PeertubeInstance(cleanUrl);
|
||||
instance.fetchInstanceMetaData();
|
||||
return instance;
|
||||
}).subscribeOn(Schedulers.io()).observeOn(AndroidSchedulers.mainThread()).subscribe((instance) -> {
|
||||
progressBar.setVisibility(View.GONE);
|
||||
add(instance);
|
||||
}, e -> {
|
||||
progressBar.setVisibility(View.GONE);
|
||||
Toast.makeText(getActivity(), R.string.peertube_instance_add_fail, Toast.LENGTH_SHORT).show();
|
||||
});
|
||||
}).subscribeOn(Schedulers.io()).observeOn(AndroidSchedulers.mainThread())
|
||||
.subscribe((instance) -> {
|
||||
progressBar.setVisibility(View.GONE);
|
||||
add(instance);
|
||||
}, e -> {
|
||||
progressBar.setVisibility(View.GONE);
|
||||
Toast.makeText(getActivity(), R.string.peertube_instance_add_fail,
|
||||
Toast.LENGTH_SHORT).show();
|
||||
});
|
||||
disposables.add(disposable);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private String cleanUrl(String url){
|
||||
url = url.trim();
|
||||
private String cleanUrl(final String url) {
|
||||
String cleanUrl = url.trim();
|
||||
// if protocol not present, add https
|
||||
if(!url.startsWith("http")){
|
||||
url = "https://" + url;
|
||||
if (!cleanUrl.startsWith("http")) {
|
||||
cleanUrl = "https://" + cleanUrl;
|
||||
}
|
||||
// remove trailing slash
|
||||
url = url.replaceAll("/$", "");
|
||||
cleanUrl = cleanUrl.replaceAll("/$", "");
|
||||
// only allow https
|
||||
if (!url.startsWith("https://")) {
|
||||
Toast.makeText(getActivity(), R.string.peertube_instance_add_https_only, Toast.LENGTH_SHORT).show();
|
||||
if (!cleanUrl.startsWith("https://")) {
|
||||
Toast.makeText(getActivity(), R.string.peertube_instance_add_https_only,
|
||||
Toast.LENGTH_SHORT).show();
|
||||
return null;
|
||||
}
|
||||
// only allow if not already exists
|
||||
for (PeertubeInstance instance : instanceList) {
|
||||
if (instance.getUrl().equals(url)) {
|
||||
Toast.makeText(getActivity(), R.string.peertube_instance_add_exists, Toast.LENGTH_SHORT).show();
|
||||
if (instance.getUrl().equals(cleanUrl)) {
|
||||
Toast.makeText(getActivity(), R.string.peertube_instance_add_exists,
|
||||
Toast.LENGTH_SHORT).show();
|
||||
return null;
|
||||
}
|
||||
}
|
||||
return url;
|
||||
return cleanUrl;
|
||||
}
|
||||
|
||||
private void add(final PeertubeInstance instance) {
|
||||
|
|
@ -277,30 +288,93 @@ public class PeertubeInstanceListFragment extends Fragment {
|
|||
// List Handling
|
||||
//////////////////////////////////////////////////////////////////////////*/
|
||||
|
||||
private class InstanceListAdapter extends RecyclerView.Adapter<InstanceListAdapter.TabViewHolder> {
|
||||
private ItemTouchHelper itemTouchHelper;
|
||||
private ItemTouchHelper.SimpleCallback getItemTouchCallback() {
|
||||
return new ItemTouchHelper.SimpleCallback(ItemTouchHelper.UP | ItemTouchHelper.DOWN,
|
||||
ItemTouchHelper.START | ItemTouchHelper.END) {
|
||||
@Override
|
||||
public int interpolateOutOfBoundsScroll(final RecyclerView recyclerView,
|
||||
final int viewSize,
|
||||
final int viewSizeOutOfBounds,
|
||||
final int totalSize,
|
||||
final long msSinceStartScroll) {
|
||||
final int standardSpeed = super.interpolateOutOfBoundsScroll(recyclerView, viewSize,
|
||||
viewSizeOutOfBounds, totalSize, msSinceStartScroll);
|
||||
final int minimumAbsVelocity = Math.max(12,
|
||||
Math.abs(standardSpeed));
|
||||
return minimumAbsVelocity * (int) Math.signum(viewSizeOutOfBounds);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onMove(final RecyclerView recyclerView,
|
||||
final RecyclerView.ViewHolder source,
|
||||
final RecyclerView.ViewHolder target) {
|
||||
if (source.getItemViewType() != target.getItemViewType()
|
||||
|| instanceListAdapter == null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
final int sourceIndex = source.getAdapterPosition();
|
||||
final int targetIndex = target.getAdapterPosition();
|
||||
instanceListAdapter.swapItems(sourceIndex, targetIndex);
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isLongPressDragEnabled() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isItemViewSwipeEnabled() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onSwiped(final RecyclerView.ViewHolder viewHolder, final int swipeDir) {
|
||||
int position = viewHolder.getAdapterPosition();
|
||||
// do not allow swiping the selected instance
|
||||
if (instanceList.get(position).getUrl().equals(selectedInstance.getUrl())) {
|
||||
instanceListAdapter.notifyItemChanged(position);
|
||||
return;
|
||||
}
|
||||
instanceList.remove(position);
|
||||
instanceListAdapter.notifyItemRemoved(position);
|
||||
|
||||
if (instanceList.isEmpty()) {
|
||||
instanceList.add(selectedInstance);
|
||||
instanceListAdapter.notifyItemInserted(0);
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
private class InstanceListAdapter
|
||||
extends RecyclerView.Adapter<InstanceListAdapter.TabViewHolder> {
|
||||
private final LayoutInflater inflater;
|
||||
private ItemTouchHelper itemTouchHelper;
|
||||
private RadioButton lastChecked;
|
||||
|
||||
InstanceListAdapter(Context context, ItemTouchHelper itemTouchHelper) {
|
||||
InstanceListAdapter(final Context context, final ItemTouchHelper itemTouchHelper) {
|
||||
this.itemTouchHelper = itemTouchHelper;
|
||||
this.inflater = LayoutInflater.from(context);
|
||||
}
|
||||
|
||||
public void swapItems(int fromPosition, int toPosition) {
|
||||
public void swapItems(final int fromPosition, final int toPosition) {
|
||||
Collections.swap(instanceList, fromPosition, toPosition);
|
||||
notifyItemMoved(fromPosition, toPosition);
|
||||
}
|
||||
|
||||
@NonNull
|
||||
@Override
|
||||
public InstanceListAdapter.TabViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
|
||||
public InstanceListAdapter.TabViewHolder onCreateViewHolder(@NonNull final ViewGroup parent,
|
||||
final int viewType) {
|
||||
View view = inflater.inflate(R.layout.item_instance, parent, false);
|
||||
return new InstanceListAdapter.TabViewHolder(view);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onBindViewHolder(@NonNull InstanceListAdapter.TabViewHolder holder, int position) {
|
||||
public void onBindViewHolder(@NonNull final InstanceListAdapter.TabViewHolder holder,
|
||||
final int position) {
|
||||
holder.bind(position, holder);
|
||||
}
|
||||
|
||||
|
|
@ -316,7 +390,7 @@ public class PeertubeInstanceListFragment extends Fragment {
|
|||
private RadioButton instanceRB;
|
||||
private ImageView handle;
|
||||
|
||||
TabViewHolder(View itemView) {
|
||||
TabViewHolder(final View itemView) {
|
||||
super(itemView);
|
||||
|
||||
instanceIconView = itemView.findViewById(R.id.instanceIcon);
|
||||
|
|
@ -327,7 +401,7 @@ public class PeertubeInstanceListFragment extends Fragment {
|
|||
}
|
||||
|
||||
@SuppressLint("ClickableViewAccessibility")
|
||||
void bind(int position, TabViewHolder holder) {
|
||||
void bind(final int position, final TabViewHolder holder) {
|
||||
handle.setOnTouchListener(getOnTouchListener(holder));
|
||||
|
||||
final PeertubeInstance instance = instanceList.get(position);
|
||||
|
|
@ -367,61 +441,4 @@ public class PeertubeInstanceListFragment extends Fragment {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
private ItemTouchHelper.SimpleCallback getItemTouchCallback() {
|
||||
return new ItemTouchHelper.SimpleCallback(ItemTouchHelper.UP | ItemTouchHelper.DOWN,
|
||||
ItemTouchHelper.START | ItemTouchHelper.END) {
|
||||
@Override
|
||||
public int interpolateOutOfBoundsScroll(RecyclerView recyclerView, int viewSize,
|
||||
int viewSizeOutOfBounds, int totalSize,
|
||||
long msSinceStartScroll) {
|
||||
final int standardSpeed = super.interpolateOutOfBoundsScroll(recyclerView, viewSize,
|
||||
viewSizeOutOfBounds, totalSize, msSinceStartScroll);
|
||||
final int minimumAbsVelocity = Math.max(12,
|
||||
Math.abs(standardSpeed));
|
||||
return minimumAbsVelocity * (int) Math.signum(viewSizeOutOfBounds);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onMove(RecyclerView recyclerView, RecyclerView.ViewHolder source,
|
||||
RecyclerView.ViewHolder target) {
|
||||
if (source.getItemViewType() != target.getItemViewType() ||
|
||||
instanceListAdapter == null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
final int sourceIndex = source.getAdapterPosition();
|
||||
final int targetIndex = target.getAdapterPosition();
|
||||
instanceListAdapter.swapItems(sourceIndex, targetIndex);
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isLongPressDragEnabled() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isItemViewSwipeEnabled() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onSwiped(RecyclerView.ViewHolder viewHolder, int swipeDir) {
|
||||
int position = viewHolder.getAdapterPosition();
|
||||
// do not allow swiping the selected instance
|
||||
if(instanceList.get(position).getUrl().equals(selectedInstance.getUrl())) {
|
||||
instanceListAdapter.notifyItemChanged(position);
|
||||
return;
|
||||
}
|
||||
instanceList.remove(position);
|
||||
instanceListAdapter.notifyItemRemoved(position);
|
||||
|
||||
if (instanceList.isEmpty()) {
|
||||
instanceList.add(selectedInstance);
|
||||
instanceListAdapter.notifyItemInserted(0);
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -3,16 +3,17 @@ package org.schabi.newpipe.settings;
|
|||
import android.app.Activity;
|
||||
import android.content.DialogInterface;
|
||||
import android.os.Bundle;
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.fragment.app.DialogFragment;
|
||||
import androidx.recyclerview.widget.LinearLayoutManager;
|
||||
import androidx.recyclerview.widget.RecyclerView;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.ProgressBar;
|
||||
import android.widget.TextView;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.fragment.app.DialogFragment;
|
||||
import androidx.recyclerview.widget.LinearLayoutManager;
|
||||
import androidx.recyclerview.widget.RecyclerView;
|
||||
|
||||
import com.nostra13.universalimageloader.core.DisplayImageOptions;
|
||||
import com.nostra13.universalimageloader.core.ImageLoader;
|
||||
|
||||
|
|
@ -31,61 +32,56 @@ import io.reactivex.android.schedulers.AndroidSchedulers;
|
|||
import io.reactivex.disposables.Disposable;
|
||||
import io.reactivex.schedulers.Schedulers;
|
||||
|
||||
|
||||
/**
|
||||
* Created by Christian Schabesberger on 26.09.17.
|
||||
* SelectChannelFragment.java is part of NewPipe.
|
||||
*
|
||||
* <p>
|
||||
* NewPipe is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* </p>
|
||||
* <p>
|
||||
* NewPipe is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* </p>
|
||||
* <p>
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with NewPipe. If not, see <http://www.gnu.org/licenses/>.
|
||||
* </p>
|
||||
*/
|
||||
|
||||
public class SelectChannelFragment extends DialogFragment {
|
||||
/**
|
||||
* This contains the base display options for images.
|
||||
*/
|
||||
public static final DisplayImageOptions DISPLAY_IMAGE_OPTIONS
|
||||
= new DisplayImageOptions.Builder().cacheInMemory(true).build();
|
||||
private final ImageLoader imageLoader = ImageLoader.getInstance();
|
||||
|
||||
OnSelectedLisener onSelectedLisener = null;
|
||||
OnCancelListener onCancelListener = null;
|
||||
private ProgressBar progressBar;
|
||||
private TextView emptyView;
|
||||
private RecyclerView recyclerView;
|
||||
|
||||
private List<SubscriptionEntity> subscriptions = new Vector<>();
|
||||
|
||||
/*//////////////////////////////////////////////////////////////////////////
|
||||
// Interfaces
|
||||
//////////////////////////////////////////////////////////////////////////*/
|
||||
private TextView emptyView;
|
||||
private RecyclerView recyclerView;
|
||||
private List<SubscriptionEntity> subscriptions = new Vector<>();
|
||||
|
||||
public interface OnSelectedLisener {
|
||||
void onChannelSelected(int serviceId, String url, String name);
|
||||
}
|
||||
OnSelectedLisener onSelectedLisener = null;
|
||||
public void setOnSelectedLisener(OnSelectedLisener listener) {
|
||||
public void setOnSelectedLisener(final OnSelectedLisener listener) {
|
||||
onSelectedLisener = listener;
|
||||
}
|
||||
|
||||
public interface OnCancelListener {
|
||||
void onCancel();
|
||||
}
|
||||
OnCancelListener onCancelListener = null;
|
||||
public void setOnCancelListener(OnCancelListener listener) {
|
||||
public void setOnCancelListener(final OnCancelListener listener) {
|
||||
onCancelListener = listener;
|
||||
}
|
||||
|
||||
/*//////////////////////////////////////////////////////////////////////////
|
||||
// Init
|
||||
//////////////////////////////////////////////////////////////////////////*/
|
||||
|
||||
|
||||
@Override
|
||||
public View onCreateView(@NonNull LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
|
||||
public View onCreateView(@NonNull final LayoutInflater inflater, final ViewGroup container,
|
||||
final Bundle savedInstanceState) {
|
||||
View v = inflater.inflate(R.layout.select_channel_fragment, container, false);
|
||||
recyclerView = v.findViewById(R.id.items_list);
|
||||
recyclerView.setLayoutManager(new LinearLayoutManager(getContext()));
|
||||
|
|
@ -108,35 +104,36 @@ public class SelectChannelFragment extends DialogFragment {
|
|||
return v;
|
||||
}
|
||||
|
||||
|
||||
/*//////////////////////////////////////////////////////////////////////////
|
||||
// Handle actions
|
||||
// Init
|
||||
//////////////////////////////////////////////////////////////////////////*/
|
||||
|
||||
@Override
|
||||
public void onCancel(final DialogInterface dialogInterface) {
|
||||
super.onCancel(dialogInterface);
|
||||
if(onCancelListener != null) {
|
||||
if (onCancelListener != null) {
|
||||
onCancelListener.onCancel();
|
||||
}
|
||||
}
|
||||
|
||||
private void clickedItem(int position) {
|
||||
if(onSelectedLisener != null) {
|
||||
|
||||
/*//////////////////////////////////////////////////////////////////////////
|
||||
// Handle actions
|
||||
//////////////////////////////////////////////////////////////////////////*/
|
||||
|
||||
private void clickedItem(final int position) {
|
||||
if (onSelectedLisener != null) {
|
||||
SubscriptionEntity entry = subscriptions.get(position);
|
||||
onSelectedLisener.onChannelSelected(entry.getServiceId(), entry.getUrl(), entry.getName());
|
||||
onSelectedLisener
|
||||
.onChannelSelected(entry.getServiceId(), entry.getUrl(), entry.getName());
|
||||
}
|
||||
dismiss();
|
||||
}
|
||||
|
||||
/*//////////////////////////////////////////////////////////////////////////
|
||||
// Item handling
|
||||
//////////////////////////////////////////////////////////////////////////*/
|
||||
|
||||
private void displayChannels(List<SubscriptionEntity> subscriptions) {
|
||||
this.subscriptions = subscriptions;
|
||||
private void displayChannels(final List<SubscriptionEntity> newSubscriptions) {
|
||||
this.subscriptions = newSubscriptions;
|
||||
progressBar.setVisibility(View.GONE);
|
||||
if(subscriptions.isEmpty()) {
|
||||
if (newSubscriptions.isEmpty()) {
|
||||
emptyView.setVisibility(View.VISIBLE);
|
||||
return;
|
||||
}
|
||||
|
|
@ -144,49 +141,75 @@ public class SelectChannelFragment extends DialogFragment {
|
|||
|
||||
}
|
||||
|
||||
/*//////////////////////////////////////////////////////////////////////////
|
||||
// Item handling
|
||||
//////////////////////////////////////////////////////////////////////////*/
|
||||
|
||||
private Observer<List<SubscriptionEntity>> getSubscriptionObserver() {
|
||||
return new Observer<List<SubscriptionEntity>>() {
|
||||
@Override
|
||||
public void onSubscribe(Disposable d) {
|
||||
public void onSubscribe(final Disposable d) { }
|
||||
|
||||
@Override
|
||||
public void onNext(final List<SubscriptionEntity> newSubscriptions) {
|
||||
displayChannels(newSubscriptions);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onNext(List<SubscriptionEntity> subscriptions) {
|
||||
displayChannels(subscriptions);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onError(Throwable exception) {
|
||||
public void onError(final Throwable exception) {
|
||||
SelectChannelFragment.this.onError(exception);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onComplete() {
|
||||
}
|
||||
public void onComplete() { }
|
||||
};
|
||||
}
|
||||
|
||||
private class SelectChannelAdapter extends
|
||||
RecyclerView.Adapter<SelectChannelAdapter.SelectChannelItemHolder> {
|
||||
protected void onError(final Throwable e) {
|
||||
final Activity activity = getActivity();
|
||||
ErrorActivity.reportError(activity, e, activity.getClass(), null, ErrorActivity.ErrorInfo
|
||||
.make(UserAction.UI_ERROR, "none", "", R.string.app_ui_crash));
|
||||
}
|
||||
|
||||
public interface OnSelectedLisener {
|
||||
void onChannelSelected(int serviceId, String url, String name);
|
||||
}
|
||||
|
||||
/*//////////////////////////////////////////////////////////////////////////
|
||||
// Error
|
||||
//////////////////////////////////////////////////////////////////////////*/
|
||||
|
||||
public interface OnCancelListener {
|
||||
void onCancel();
|
||||
}
|
||||
|
||||
|
||||
/*//////////////////////////////////////////////////////////////////////////
|
||||
// ImageLoaderOptions
|
||||
//////////////////////////////////////////////////////////////////////////*/
|
||||
|
||||
private class SelectChannelAdapter
|
||||
extends RecyclerView.Adapter<SelectChannelAdapter.SelectChannelItemHolder> {
|
||||
@Override
|
||||
public SelectChannelItemHolder onCreateViewHolder(ViewGroup parent, int viewType) {
|
||||
public SelectChannelItemHolder onCreateViewHolder(final ViewGroup parent,
|
||||
final int viewType) {
|
||||
View item = LayoutInflater.from(parent.getContext())
|
||||
.inflate(R.layout.select_channel_item, parent, false);
|
||||
return new SelectChannelItemHolder(item);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onBindViewHolder(SelectChannelItemHolder holder, final int position) {
|
||||
public void onBindViewHolder(final SelectChannelItemHolder holder, final int position) {
|
||||
SubscriptionEntity entry = subscriptions.get(position);
|
||||
holder.titleView.setText(entry.getName());
|
||||
holder.view.setOnClickListener(new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View view) {
|
||||
public void onClick(final View view) {
|
||||
clickedItem(position);
|
||||
}
|
||||
});
|
||||
imageLoader.displayImage(entry.getAvatarUrl(), holder.thumbnailView, DISPLAY_IMAGE_OPTIONS);
|
||||
imageLoader.displayImage(entry.getAvatarUrl(), holder.thumbnailView,
|
||||
DISPLAY_IMAGE_OPTIONS);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
@ -195,41 +218,15 @@ public class SelectChannelFragment extends DialogFragment {
|
|||
}
|
||||
|
||||
public class SelectChannelItemHolder extends RecyclerView.ViewHolder {
|
||||
public SelectChannelItemHolder(View v) {
|
||||
public final View view;
|
||||
public final CircleImageView thumbnailView;
|
||||
public final TextView titleView;
|
||||
SelectChannelItemHolder(final View v) {
|
||||
super(v);
|
||||
this.view = v;
|
||||
thumbnailView = v.findViewById(R.id.itemThumbnailView);
|
||||
titleView = v.findViewById(R.id.itemTitleView);
|
||||
}
|
||||
public final View view;
|
||||
public final CircleImageView thumbnailView;
|
||||
public final TextView titleView;
|
||||
}
|
||||
}
|
||||
|
||||
/*//////////////////////////////////////////////////////////////////////////
|
||||
// Error
|
||||
//////////////////////////////////////////////////////////////////////////*/
|
||||
|
||||
protected void onError(Throwable e) {
|
||||
final Activity activity = getActivity();
|
||||
ErrorActivity.reportError(activity, e,
|
||||
activity.getClass(),
|
||||
null,
|
||||
ErrorActivity.ErrorInfo.make(UserAction.UI_ERROR,
|
||||
"none", "", R.string.app_ui_crash));
|
||||
}
|
||||
|
||||
|
||||
/*//////////////////////////////////////////////////////////////////////////
|
||||
// ImageLoaderOptions
|
||||
//////////////////////////////////////////////////////////////////////////*/
|
||||
|
||||
/**
|
||||
* Base display options
|
||||
*/
|
||||
public static final DisplayImageOptions DISPLAY_IMAGE_OPTIONS =
|
||||
new DisplayImageOptions.Builder()
|
||||
.cacheInMemory(true)
|
||||
.build();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -3,17 +3,17 @@ package org.schabi.newpipe.settings;
|
|||
import android.app.Activity;
|
||||
import android.content.DialogInterface;
|
||||
import android.os.Bundle;
|
||||
import androidx.fragment.app.DialogFragment;
|
||||
import androidx.core.content.ContextCompat;
|
||||
import androidx.recyclerview.widget.LinearLayoutManager;
|
||||
import androidx.recyclerview.widget.RecyclerView;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.ImageView;
|
||||
import android.widget.TextView;
|
||||
|
||||
import org.schabi.newpipe.MainActivity;
|
||||
import androidx.core.content.ContextCompat;
|
||||
import androidx.fragment.app.DialogFragment;
|
||||
import androidx.recyclerview.widget.LinearLayoutManager;
|
||||
import androidx.recyclerview.widget.RecyclerView;
|
||||
|
||||
import org.schabi.newpipe.R;
|
||||
import org.schabi.newpipe.extractor.NewPipe;
|
||||
import org.schabi.newpipe.extractor.StreamingService;
|
||||
|
|
@ -28,51 +28,45 @@ import java.util.Vector;
|
|||
/**
|
||||
* Created by Christian Schabesberger on 09.10.17.
|
||||
* SelectKioskFragment.java is part of NewPipe.
|
||||
*
|
||||
* <p>
|
||||
* NewPipe is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* </p>
|
||||
* <p>
|
||||
* NewPipe is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* </p>
|
||||
* <p>
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with NewPipe. If not, see <http://www.gnu.org/licenses/>.
|
||||
* along with NewPipe. If not, see <http://www.gnu.org/licenses/>.
|
||||
* </p>
|
||||
*/
|
||||
|
||||
public class SelectKioskFragment extends DialogFragment {
|
||||
private RecyclerView recyclerView = null;
|
||||
private SelectKioskAdapter selectKioskAdapter = null;
|
||||
|
||||
private static final boolean DEBUG = MainActivity.DEBUG;
|
||||
|
||||
RecyclerView recyclerView = null;
|
||||
SelectKioskAdapter selectKioskAdapter = null;
|
||||
|
||||
/*//////////////////////////////////////////////////////////////////////////
|
||||
/*//////////////////////////////////////////////////////////////////////////
|
||||
// Interfaces
|
||||
//////////////////////////////////////////////////////////////////////////*/
|
||||
private OnSelectedLisener onSelectedLisener = null;
|
||||
private OnCancelListener onCancelListener = null;
|
||||
|
||||
public interface OnSelectedLisener {
|
||||
void onKioskSelected(int serviceId, String kioskId, String kioskName);
|
||||
}
|
||||
|
||||
OnSelectedLisener onSelectedLisener = null;
|
||||
public void setOnSelectedLisener(OnSelectedLisener listener) {
|
||||
public void setOnSelectedLisener(final OnSelectedLisener listener) {
|
||||
onSelectedLisener = listener;
|
||||
}
|
||||
|
||||
public interface OnCancelListener {
|
||||
void onCancel();
|
||||
}
|
||||
OnCancelListener onCancelListener = null;
|
||||
public void setOnCancelListener(OnCancelListener listener) {
|
||||
public void setOnCancelListener(final OnCancelListener listener) {
|
||||
onCancelListener = listener;
|
||||
}
|
||||
|
||||
@Override
|
||||
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
|
||||
public View onCreateView(final LayoutInflater inflater, final ViewGroup container,
|
||||
final Bundle savedInstanceState) {
|
||||
View v = inflater.inflate(R.layout.select_kiosk_fragment, container, false);
|
||||
recyclerView = v.findViewById(R.id.items_list);
|
||||
recyclerView.setLayoutManager(new LinearLayoutManager(getContext()));
|
||||
|
|
@ -86,52 +80,55 @@ public class SelectKioskFragment extends DialogFragment {
|
|||
return v;
|
||||
}
|
||||
|
||||
/*//////////////////////////////////////////////////////////////////////////
|
||||
// Handle actions
|
||||
//////////////////////////////////////////////////////////////////////////*/
|
||||
|
||||
@Override
|
||||
public void onCancel(final DialogInterface dialogInterface) {
|
||||
super.onCancel(dialogInterface);
|
||||
if(onCancelListener != null) {
|
||||
if (onCancelListener != null) {
|
||||
onCancelListener.onCancel();
|
||||
}
|
||||
}
|
||||
|
||||
private void clickedItem(SelectKioskAdapter.Entry entry) {
|
||||
if(onSelectedLisener != null) {
|
||||
private void clickedItem(final SelectKioskAdapter.Entry entry) {
|
||||
if (onSelectedLisener != null) {
|
||||
onSelectedLisener.onKioskSelected(entry.serviceId, entry.kioskId, entry.kioskName);
|
||||
}
|
||||
dismiss();
|
||||
}
|
||||
|
||||
/*//////////////////////////////////////////////////////////////////////////
|
||||
// Handle actions
|
||||
//////////////////////////////////////////////////////////////////////////*/
|
||||
|
||||
protected void onError(final Throwable e) {
|
||||
final Activity activity = getActivity();
|
||||
ErrorActivity.reportError(activity, e, activity.getClass(), null, ErrorActivity.ErrorInfo
|
||||
.make(UserAction.UI_ERROR, "none", "", R.string.app_ui_crash));
|
||||
}
|
||||
|
||||
public interface OnSelectedLisener {
|
||||
void onKioskSelected(int serviceId, String kioskId, String kioskName);
|
||||
}
|
||||
|
||||
public interface OnCancelListener {
|
||||
void onCancel();
|
||||
}
|
||||
|
||||
/*//////////////////////////////////////////////////////////////////////////
|
||||
// Error
|
||||
//////////////////////////////////////////////////////////////////////////*/
|
||||
|
||||
private class SelectKioskAdapter
|
||||
extends RecyclerView.Adapter<SelectKioskAdapter.SelectKioskItemHolder> {
|
||||
public class Entry {
|
||||
public Entry (int i, int si, String ki, String kn){
|
||||
icon = i; serviceId=si; kioskId=ki; kioskName = kn;
|
||||
}
|
||||
final int icon;
|
||||
final int serviceId;
|
||||
final String kioskId;
|
||||
final String kioskName;
|
||||
}
|
||||
|
||||
private final List<Entry> kioskList = new Vector<>();
|
||||
|
||||
public SelectKioskAdapter()
|
||||
throws Exception {
|
||||
|
||||
for(StreamingService service : NewPipe.getServices()) {
|
||||
for(String kioskId : service.getKioskList().getAvailableKiosks()) {
|
||||
SelectKioskAdapter() throws Exception {
|
||||
for (StreamingService service : NewPipe.getServices()) {
|
||||
for (String kioskId : service.getKioskList().getAvailableKiosks()) {
|
||||
String name = String.format(getString(R.string.service_kiosk_string),
|
||||
service.getServiceInfo().getName(),
|
||||
KioskTranslator.getTranslatedKioskName(kioskId, getContext()));
|
||||
kioskList.add(new Entry(
|
||||
ServiceHelper.getIcon(service.getServiceId()),
|
||||
service.getServiceId(),
|
||||
kioskId,
|
||||
name));
|
||||
kioskList.add(new Entry(ServiceHelper.getIcon(service.getServiceId()),
|
||||
service.getServiceId(), kioskId, name));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -140,47 +137,50 @@ public class SelectKioskFragment extends DialogFragment {
|
|||
return kioskList.size();
|
||||
}
|
||||
|
||||
public SelectKioskItemHolder onCreateViewHolder(ViewGroup parent, int type) {
|
||||
public SelectKioskItemHolder onCreateViewHolder(final ViewGroup parent, final int type) {
|
||||
View item = LayoutInflater.from(parent.getContext())
|
||||
.inflate(R.layout.select_kiosk_item, parent, false);
|
||||
return new SelectKioskItemHolder(item);
|
||||
}
|
||||
|
||||
public void onBindViewHolder(final SelectKioskItemHolder holder, final int position) {
|
||||
final Entry entry = kioskList.get(position);
|
||||
holder.titleView.setText(entry.kioskName);
|
||||
holder.thumbnailView
|
||||
.setImageDrawable(ContextCompat.getDrawable(getContext(), entry.icon));
|
||||
holder.view.setOnClickListener(new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(final View view) {
|
||||
clickedItem(entry);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
class Entry {
|
||||
final int icon;
|
||||
final int serviceId;
|
||||
final String kioskId;
|
||||
final String kioskName;
|
||||
|
||||
Entry(final int i, final int si, final String ki, final String kn) {
|
||||
icon = i;
|
||||
serviceId = si;
|
||||
kioskId = ki;
|
||||
kioskName = kn;
|
||||
}
|
||||
}
|
||||
|
||||
public class SelectKioskItemHolder extends RecyclerView.ViewHolder {
|
||||
public SelectKioskItemHolder(View v) {
|
||||
public final View view;
|
||||
final ImageView thumbnailView;
|
||||
final TextView titleView;
|
||||
|
||||
SelectKioskItemHolder(final View v) {
|
||||
super(v);
|
||||
this.view = v;
|
||||
thumbnailView = v.findViewById(R.id.itemThumbnailView);
|
||||
titleView = v.findViewById(R.id.itemTitleView);
|
||||
}
|
||||
public final View view;
|
||||
public final ImageView thumbnailView;
|
||||
public final TextView titleView;
|
||||
}
|
||||
|
||||
public void onBindViewHolder(SelectKioskItemHolder holder, final int position) {
|
||||
final Entry entry = kioskList.get(position);
|
||||
holder.titleView.setText(entry.kioskName);
|
||||
holder.thumbnailView.setImageDrawable(ContextCompat.getDrawable(getContext(), entry.icon));
|
||||
holder.view.setOnClickListener(new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View view) {
|
||||
clickedItem(entry);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
/*//////////////////////////////////////////////////////////////////////////
|
||||
// Error
|
||||
//////////////////////////////////////////////////////////////////////////*/
|
||||
|
||||
protected void onError(Throwable e) {
|
||||
final Activity activity = getActivity();
|
||||
ErrorActivity.reportError(activity, e,
|
||||
activity.getClass(),
|
||||
null,
|
||||
ErrorActivity.ErrorInfo.make(UserAction.UI_ERROR,
|
||||
"none", "", R.string.app_ui_crash));
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2,15 +2,16 @@ package org.schabi.newpipe.settings;
|
|||
|
||||
import android.content.Context;
|
||||
import android.os.Bundle;
|
||||
import androidx.fragment.app.Fragment;
|
||||
import androidx.appcompat.app.ActionBar;
|
||||
import androidx.appcompat.app.AppCompatActivity;
|
||||
import androidx.preference.Preference;
|
||||
import androidx.preference.PreferenceFragmentCompat;
|
||||
import androidx.appcompat.widget.Toolbar;
|
||||
import android.view.Menu;
|
||||
import android.view.MenuItem;
|
||||
|
||||
import androidx.appcompat.app.ActionBar;
|
||||
import androidx.appcompat.app.AppCompatActivity;
|
||||
import androidx.appcompat.widget.Toolbar;
|
||||
import androidx.fragment.app.Fragment;
|
||||
import androidx.preference.Preference;
|
||||
import androidx.preference.PreferenceFragmentCompat;
|
||||
|
||||
import org.schabi.newpipe.R;
|
||||
import org.schabi.newpipe.util.ThemeHelper;
|
||||
|
||||
|
|
@ -36,14 +37,15 @@ import static org.schabi.newpipe.util.Localization.assureCorrectAppLanguage;
|
|||
* along with NewPipe. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
public class SettingsActivity extends AppCompatActivity implements BasePreferenceFragment.OnPreferenceStartFragmentCallback {
|
||||
public class SettingsActivity extends AppCompatActivity
|
||||
implements BasePreferenceFragment.OnPreferenceStartFragmentCallback {
|
||||
|
||||
public static void initSettings(Context context) {
|
||||
public static void initSettings(final Context context) {
|
||||
NewPipeSettings.initSettings(context);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onCreate(Bundle savedInstanceBundle) {
|
||||
protected void onCreate(final Bundle savedInstanceBundle) {
|
||||
setTheme(ThemeHelper.getSettingsThemeStyle(this));
|
||||
assureCorrectAppLanguage(this);
|
||||
super.onCreate(savedInstanceBundle);
|
||||
|
|
@ -60,7 +62,7 @@ public class SettingsActivity extends AppCompatActivity implements BasePreferenc
|
|||
}
|
||||
|
||||
@Override
|
||||
public boolean onCreateOptionsMenu(Menu menu) {
|
||||
public boolean onCreateOptionsMenu(final Menu menu) {
|
||||
ActionBar actionBar = getSupportActionBar();
|
||||
if (actionBar != null) {
|
||||
actionBar.setDisplayHomeAsUpEnabled(true);
|
||||
|
|
@ -71,22 +73,27 @@ public class SettingsActivity extends AppCompatActivity implements BasePreferenc
|
|||
}
|
||||
|
||||
@Override
|
||||
public boolean onOptionsItemSelected(MenuItem item) {
|
||||
public boolean onOptionsItemSelected(final MenuItem item) {
|
||||
int id = item.getItemId();
|
||||
if (id == android.R.id.home) {
|
||||
if (getSupportFragmentManager().getBackStackEntryCount() == 0) {
|
||||
finish();
|
||||
} else getSupportFragmentManager().popBackStack();
|
||||
} else {
|
||||
getSupportFragmentManager().popBackStack();
|
||||
}
|
||||
}
|
||||
|
||||
return super.onOptionsItemSelected(item);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onPreferenceStartFragment(PreferenceFragmentCompat caller, Preference preference) {
|
||||
Fragment fragment = Fragment.instantiate(this, preference.getFragment(), preference.getExtras());
|
||||
public boolean onPreferenceStartFragment(final PreferenceFragmentCompat caller,
|
||||
final Preference preference) {
|
||||
Fragment fragment = Fragment
|
||||
.instantiate(this, preference.getFragment(), preference.getExtras());
|
||||
getSupportFragmentManager().beginTransaction()
|
||||
.setCustomAnimations(R.animator.custom_fade_in, R.animator.custom_fade_out, R.animator.custom_fade_in, R.animator.custom_fade_out)
|
||||
.setCustomAnimations(R.animator.custom_fade_in, R.animator.custom_fade_out,
|
||||
R.animator.custom_fade_in, R.animator.custom_fade_out)
|
||||
.replace(R.id.fragment_holder, fragment)
|
||||
.addToBackStack(null)
|
||||
.commit();
|
||||
|
|
|
|||
|
|
@ -1,15 +1,22 @@
|
|||
package org.schabi.newpipe.settings;
|
||||
|
||||
import android.os.Bundle;
|
||||
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.preference.Preference;
|
||||
|
||||
import org.schabi.newpipe.R;
|
||||
|
||||
public class UpdateSettingsFragment extends BasePreferenceFragment {
|
||||
private Preference.OnPreferenceChangeListener updatePreferenceChange
|
||||
= (preference, newValue) -> {
|
||||
defaultPreferences.edit()
|
||||
.putBoolean(getString(R.string.update_app_key), (boolean) newValue).apply();
|
||||
return true;
|
||||
};
|
||||
|
||||
@Override
|
||||
public void onCreate(@Nullable Bundle savedInstanceState) {
|
||||
public void onCreate(@Nullable final Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
|
||||
String updateToggleKey = getString(R.string.update_app_key);
|
||||
|
|
@ -17,16 +24,7 @@ public class UpdateSettingsFragment extends BasePreferenceFragment {
|
|||
}
|
||||
|
||||
@Override
|
||||
public void onCreatePreferences(Bundle savedInstanceState, String rootKey) {
|
||||
public void onCreatePreferences(final Bundle savedInstanceState, final String rootKey) {
|
||||
addPreferencesFromResource(R.xml.update_settings);
|
||||
}
|
||||
|
||||
private Preference.OnPreferenceChangeListener updatePreferenceChange
|
||||
= (preference, newValue) -> {
|
||||
|
||||
defaultPreferences.edit().putBoolean(getString(R.string.update_app_key),
|
||||
(boolean) newValue).apply();
|
||||
|
||||
return true;
|
||||
};
|
||||
}
|
||||
|
|
|
|||
|
|
@ -5,44 +5,45 @@ import android.content.res.Resources;
|
|||
import android.os.Build;
|
||||
import android.os.Bundle;
|
||||
import android.provider.Settings;
|
||||
|
||||
import android.text.format.DateUtils;
|
||||
import android.widget.Toast;
|
||||
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.preference.ListPreference;
|
||||
|
||||
import com.google.android.material.snackbar.Snackbar;
|
||||
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import org.schabi.newpipe.R;
|
||||
import org.schabi.newpipe.util.PermissionHelper;
|
||||
|
||||
public class VideoAudioSettingsFragment extends BasePreferenceFragment {
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
|
||||
public class VideoAudioSettingsFragment extends BasePreferenceFragment {
|
||||
private SharedPreferences.OnSharedPreferenceChangeListener listener;
|
||||
|
||||
@Override
|
||||
public void onCreate(@Nullable Bundle savedInstanceState) {
|
||||
public void onCreate(@Nullable final Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
|
||||
updateSeekOptions();
|
||||
|
||||
listener = (sharedPreferences, s) -> {
|
||||
|
||||
// on M and above, if user chooses to minimise to popup player on exit and the app doesn't have
|
||||
// display over other apps permission, show a snackbar to let the user give permission
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M &&
|
||||
s.equals(getString(R.string.minimize_on_exit_key))) {
|
||||
|
||||
// on M and above, if user chooses to minimise to popup player on exit
|
||||
// and the app doesn't have display over other apps permission,
|
||||
// show a snackbar to let the user give permission
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M
|
||||
&& s.equals(getString(R.string.minimize_on_exit_key))) {
|
||||
String newSetting = sharedPreferences.getString(s, null);
|
||||
if (newSetting != null
|
||||
&& newSetting.equals(getString(R.string.minimize_on_exit_popup_key))
|
||||
&& !Settings.canDrawOverlays(getContext())) {
|
||||
|
||||
Snackbar.make(getListView(), R.string.permission_display_over_apps, Snackbar.LENGTH_INDEFINITE)
|
||||
.setAction(R.string.settings,
|
||||
view -> PermissionHelper.checkSystemAlertWindowPermission(getContext()))
|
||||
Snackbar.make(getListView(), R.string.permission_display_over_apps,
|
||||
Snackbar.LENGTH_INDEFINITE)
|
||||
.setAction(R.string.settings, view ->
|
||||
PermissionHelper.checkSystemAlertWindowPermission(getContext()))
|
||||
.show();
|
||||
|
||||
}
|
||||
|
|
@ -53,22 +54,23 @@ public class VideoAudioSettingsFragment extends BasePreferenceFragment {
|
|||
}
|
||||
|
||||
/**
|
||||
* Update fast-forward/-rewind seek duration options according to language and inexact seek setting.
|
||||
* Update fast-forward/-rewind seek duration options
|
||||
* according to language and inexact seek setting.
|
||||
* Exoplayer can't seek 5 seconds in audio when using inexact seek.
|
||||
*/
|
||||
private void updateSeekOptions() {
|
||||
//initializing R.array.seek_duration_description to display the translation of seconds
|
||||
// initializing R.array.seek_duration_description to display the translation of seconds
|
||||
final Resources res = getResources();
|
||||
final String[] durationsValues = res.getStringArray(R.array.seek_duration_value);
|
||||
final List<String> displayedDurationValues = new LinkedList<>();
|
||||
final List<String> displayedDescriptionValues = new LinkedList<>();
|
||||
int currentDurationValue;
|
||||
final boolean inexactSeek = getPreferenceManager().getSharedPreferences()
|
||||
.getBoolean(res.getString(R.string.use_inexact_seek_key), false);
|
||||
.getBoolean(res.getString(R.string.use_inexact_seek_key), false);
|
||||
|
||||
for (String durationsValue : durationsValues) {
|
||||
currentDurationValue =
|
||||
Integer.parseInt(durationsValue) / (int) DateUtils.SECOND_IN_MILLIS;
|
||||
Integer.parseInt(durationsValue) / (int) DateUtils.SECOND_IN_MILLIS;
|
||||
if (inexactSeek && currentDurationValue % 10 == 5) {
|
||||
continue;
|
||||
}
|
||||
|
|
@ -76,15 +78,17 @@ public class VideoAudioSettingsFragment extends BasePreferenceFragment {
|
|||
displayedDurationValues.add(durationsValue);
|
||||
try {
|
||||
displayedDescriptionValues.add(String.format(
|
||||
res.getQuantityString(R.plurals.seconds,
|
||||
currentDurationValue),
|
||||
currentDurationValue));
|
||||
res.getQuantityString(R.plurals.seconds,
|
||||
currentDurationValue),
|
||||
currentDurationValue));
|
||||
} catch (Resources.NotFoundException ignored) {
|
||||
//if this happens, the translation is missing, and the english string will be displayed instead
|
||||
// if this happens, the translation is missing,
|
||||
// and the english string will be displayed instead
|
||||
}
|
||||
}
|
||||
|
||||
final ListPreference durations = (ListPreference) findPreference(getString(R.string.seek_duration_key));
|
||||
final ListPreference durations = (ListPreference) findPreference(
|
||||
getString(R.string.seek_duration_key));
|
||||
durations.setEntryValues(displayedDurationValues.toArray(new CharSequence[0]));
|
||||
durations.setEntries(displayedDescriptionValues.toArray(new CharSequence[0]));
|
||||
final int selectedDuration = Integer.parseInt(durations.getValue());
|
||||
|
|
@ -93,28 +97,30 @@ public class VideoAudioSettingsFragment extends BasePreferenceFragment {
|
|||
durations.setValue(Integer.toString(newDuration * (int) DateUtils.SECOND_IN_MILLIS));
|
||||
|
||||
Toast toast = Toast
|
||||
.makeText(getContext(),
|
||||
getString(R.string.new_seek_duration_toast, newDuration),
|
||||
Toast.LENGTH_LONG);
|
||||
.makeText(getContext(),
|
||||
getString(R.string.new_seek_duration_toast, newDuration),
|
||||
Toast.LENGTH_LONG);
|
||||
toast.show();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCreatePreferences(Bundle savedInstanceState, String rootKey) {
|
||||
public void onCreatePreferences(final Bundle savedInstanceState, final String rootKey) {
|
||||
addPreferencesFromResource(R.xml.video_audio_settings);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onResume() {
|
||||
super.onResume();
|
||||
getPreferenceManager().getSharedPreferences().registerOnSharedPreferenceChangeListener(listener);
|
||||
getPreferenceManager().getSharedPreferences()
|
||||
.registerOnSharedPreferenceChangeListener(listener);
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPause() {
|
||||
super.onPause();
|
||||
getPreferenceManager().getSharedPreferences().unregisterOnSharedPreferenceChangeListener(listener);
|
||||
getPreferenceManager().getSharedPreferences()
|
||||
.unregisterOnSharedPreferenceChangeListener(listener);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -3,23 +3,23 @@ package org.schabi.newpipe.settings.tabs;
|
|||
import android.app.AlertDialog;
|
||||
import android.content.Context;
|
||||
import android.content.DialogInterface;
|
||||
import androidx.annotation.DrawableRes;
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.appcompat.widget.AppCompatImageView;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.BaseAdapter;
|
||||
import android.widget.TextView;
|
||||
|
||||
import androidx.annotation.DrawableRes;
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.appcompat.widget.AppCompatImageView;
|
||||
|
||||
import org.schabi.newpipe.R;
|
||||
import org.schabi.newpipe.util.ThemeHelper;
|
||||
|
||||
public class AddTabDialog {
|
||||
public final class AddTabDialog {
|
||||
private final AlertDialog dialog;
|
||||
|
||||
AddTabDialog(@NonNull final Context context,
|
||||
@NonNull final ChooseTabListItem[] items,
|
||||
AddTabDialog(@NonNull final Context context, @NonNull final ChooseTabListItem[] items,
|
||||
@NonNull final DialogInterface.OnClickListener actions) {
|
||||
|
||||
dialog = new AlertDialog.Builder(context)
|
||||
|
|
@ -32,29 +32,32 @@ public class AddTabDialog {
|
|||
dialog.show();
|
||||
}
|
||||
|
||||
public static final class ChooseTabListItem {
|
||||
static final class ChooseTabListItem {
|
||||
final int tabId;
|
||||
final String itemName;
|
||||
@DrawableRes final int itemIcon;
|
||||
@DrawableRes
|
||||
final int itemIcon;
|
||||
|
||||
ChooseTabListItem(Context context, Tab tab) {
|
||||
ChooseTabListItem(final Context context, final Tab tab) {
|
||||
this(tab.getTabId(), tab.getTabName(context), tab.getTabIconRes(context));
|
||||
}
|
||||
|
||||
ChooseTabListItem(int tabId, String itemName, @DrawableRes int itemIcon) {
|
||||
ChooseTabListItem(final int tabId, final String itemName,
|
||||
@DrawableRes final int itemIcon) {
|
||||
this.tabId = tabId;
|
||||
this.itemName = itemName;
|
||||
this.itemIcon = itemIcon;
|
||||
}
|
||||
}
|
||||
|
||||
private static class DialogListAdapter extends BaseAdapter {
|
||||
private static final class DialogListAdapter extends BaseAdapter {
|
||||
private final LayoutInflater inflater;
|
||||
private final ChooseTabListItem[] items;
|
||||
|
||||
@DrawableRes private final int fallbackIcon;
|
||||
@DrawableRes
|
||||
private final int fallbackIcon;
|
||||
|
||||
private DialogListAdapter(Context context, ChooseTabListItem[] items) {
|
||||
private DialogListAdapter(final Context context, final ChooseTabListItem[] items) {
|
||||
this.inflater = LayoutInflater.from(context);
|
||||
this.items = items;
|
||||
this.fallbackIcon = ThemeHelper.resolveResourceIdFromAttr(context, R.attr.ic_hot);
|
||||
|
|
@ -66,17 +69,18 @@ public class AddTabDialog {
|
|||
}
|
||||
|
||||
@Override
|
||||
public ChooseTabListItem getItem(int position) {
|
||||
public ChooseTabListItem getItem(final int position) {
|
||||
return items[position];
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getItemId(int position) {
|
||||
public long getItemId(final int position) {
|
||||
return getItem(position).tabId;
|
||||
}
|
||||
|
||||
@Override
|
||||
public View getView(int position, View convertView, ViewGroup parent) {
|
||||
public View getView(final int position, final View view, final ViewGroup parent) {
|
||||
View convertView = view;
|
||||
if (convertView == null) {
|
||||
convertView = inflater.inflate(R.layout.list_choose_tabs_dialog, parent, false);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -4,18 +4,6 @@ import android.annotation.SuppressLint;
|
|||
import android.app.Dialog;
|
||||
import android.content.Context;
|
||||
import android.os.Bundle;
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
import com.google.android.material.floatingactionbutton.FloatingActionButton;
|
||||
import androidx.fragment.app.Fragment;
|
||||
import androidx.appcompat.app.ActionBar;
|
||||
import androidx.appcompat.app.AlertDialog;
|
||||
import androidx.appcompat.app.AppCompatActivity;
|
||||
import androidx.appcompat.content.res.AppCompatResources;
|
||||
import androidx.appcompat.widget.AppCompatImageView;
|
||||
import androidx.recyclerview.widget.LinearLayoutManager;
|
||||
import androidx.recyclerview.widget.RecyclerView;
|
||||
import androidx.recyclerview.widget.ItemTouchHelper;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.Menu;
|
||||
import android.view.MenuInflater;
|
||||
|
|
@ -26,6 +14,20 @@ import android.view.ViewGroup;
|
|||
import android.widget.ImageView;
|
||||
import android.widget.TextView;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.appcompat.app.ActionBar;
|
||||
import androidx.appcompat.app.AlertDialog;
|
||||
import androidx.appcompat.app.AppCompatActivity;
|
||||
import androidx.appcompat.content.res.AppCompatResources;
|
||||
import androidx.appcompat.widget.AppCompatImageView;
|
||||
import androidx.fragment.app.Fragment;
|
||||
import androidx.recyclerview.widget.ItemTouchHelper;
|
||||
import androidx.recyclerview.widget.LinearLayoutManager;
|
||||
import androidx.recyclerview.widget.RecyclerView;
|
||||
|
||||
import com.google.android.material.floatingactionbutton.FloatingActionButton;
|
||||
|
||||
import org.schabi.newpipe.R;
|
||||
import org.schabi.newpipe.extractor.NewPipe;
|
||||
import org.schabi.newpipe.report.ErrorActivity;
|
||||
|
|
@ -42,17 +44,18 @@ import java.util.List;
|
|||
import static org.schabi.newpipe.settings.tabs.Tab.typeFrom;
|
||||
|
||||
public class ChooseTabsFragment extends Fragment {
|
||||
|
||||
private static final int MENU_ITEM_RESTORE_ID = 123456;
|
||||
private ChooseTabsFragment.SelectedTabsAdapter selectedTabsAdapter;
|
||||
private TabsManager tabsManager;
|
||||
|
||||
private List<Tab> tabList = new ArrayList<>();
|
||||
public ChooseTabsFragment.SelectedTabsAdapter selectedTabsAdapter;
|
||||
|
||||
/*//////////////////////////////////////////////////////////////////////////
|
||||
// Lifecycle
|
||||
//////////////////////////////////////////////////////////////////////////*/
|
||||
|
||||
@Override
|
||||
public void onCreate(@Nullable Bundle savedInstanceState) {
|
||||
public void onCreate(@Nullable final Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
|
||||
tabsManager = TabsManager.getManager(requireContext());
|
||||
|
|
@ -62,12 +65,14 @@ public class ChooseTabsFragment extends Fragment {
|
|||
}
|
||||
|
||||
@Override
|
||||
public View onCreateView(@NonNull LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
|
||||
public View onCreateView(@NonNull final LayoutInflater inflater, final ViewGroup container,
|
||||
final Bundle savedInstanceState) {
|
||||
return inflater.inflate(R.layout.fragment_choose_tabs, container, false);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onViewCreated(@NonNull View rootView, @Nullable Bundle savedInstanceState) {
|
||||
public void onViewCreated(@NonNull final View rootView,
|
||||
@Nullable final Bundle savedInstanceState) {
|
||||
super.onViewCreated(rootView, savedInstanceState);
|
||||
|
||||
initButton(rootView);
|
||||
|
|
@ -88,31 +93,31 @@ public class ChooseTabsFragment extends Fragment {
|
|||
updateTitle();
|
||||
}
|
||||
|
||||
/*//////////////////////////////////////////////////////////////////////////
|
||||
// Menu
|
||||
//////////////////////////////////////////////////////////////////////////*/
|
||||
|
||||
@Override
|
||||
public void onPause() {
|
||||
super.onPause();
|
||||
saveChanges();
|
||||
}
|
||||
|
||||
/*//////////////////////////////////////////////////////////////////////////
|
||||
// Menu
|
||||
//////////////////////////////////////////////////////////////////////////*/
|
||||
|
||||
private final int MENU_ITEM_RESTORE_ID = 123456;
|
||||
|
||||
@Override
|
||||
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
|
||||
public void onCreateOptionsMenu(final Menu menu, final MenuInflater inflater) {
|
||||
super.onCreateOptionsMenu(menu, inflater);
|
||||
|
||||
final MenuItem restoreItem = menu.add(Menu.NONE, MENU_ITEM_RESTORE_ID, Menu.NONE, R.string.restore_defaults);
|
||||
final MenuItem restoreItem = menu.add(Menu.NONE, MENU_ITEM_RESTORE_ID, Menu.NONE,
|
||||
R.string.restore_defaults);
|
||||
restoreItem.setShowAsAction(MenuItem.SHOW_AS_ACTION_ALWAYS);
|
||||
|
||||
final int restoreIcon = ThemeHelper.resolveResourceIdFromAttr(requireContext(), R.attr.ic_restore_defaults);
|
||||
final int restoreIcon = ThemeHelper.resolveResourceIdFromAttr(requireContext(),
|
||||
R.attr.ic_restore_defaults);
|
||||
restoreItem.setIcon(AppCompatResources.getDrawable(requireContext(), restoreIcon));
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onOptionsItemSelected(MenuItem item) {
|
||||
public boolean onOptionsItemSelected(final MenuItem item) {
|
||||
if (item.getItemId() == MENU_ITEM_RESTORE_ID) {
|
||||
restoreDefaults();
|
||||
return true;
|
||||
|
|
@ -133,7 +138,9 @@ public class ChooseTabsFragment extends Fragment {
|
|||
private void updateTitle() {
|
||||
if (getActivity() instanceof AppCompatActivity) {
|
||||
ActionBar actionBar = ((AppCompatActivity) getActivity()).getSupportActionBar();
|
||||
if (actionBar != null) actionBar.setTitle(R.string.main_page_content);
|
||||
if (actionBar != null) {
|
||||
actionBar.setTitle(R.string.main_page_content);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -154,7 +161,7 @@ public class ChooseTabsFragment extends Fragment {
|
|||
.show();
|
||||
}
|
||||
|
||||
private void initButton(View rootView) {
|
||||
private void initButton(final View rootView) {
|
||||
final FloatingActionButton fab = rootView.findViewById(R.id.addTabsButton);
|
||||
fab.setOnClickListener(v -> {
|
||||
final ChooseTabListItem[] availableTabs = getAvailableTabs(requireContext());
|
||||
|
|
@ -179,37 +186,37 @@ public class ChooseTabsFragment extends Fragment {
|
|||
selectedTabsAdapter.notifyDataSetChanged();
|
||||
}
|
||||
|
||||
private void addTab(int tabId) {
|
||||
private void addTab(final int tabId) {
|
||||
final Tab.Type type = typeFrom(tabId);
|
||||
|
||||
if (type == null) {
|
||||
ErrorActivity.reportError(requireContext(), new IllegalStateException("Tab id not found: " + tabId), null, null,
|
||||
ErrorActivity.ErrorInfo.make(UserAction.SOMETHING_ELSE, "none", "Choosing tabs on settings", 0));
|
||||
ErrorActivity.reportError(requireContext(),
|
||||
new IllegalStateException("Tab id not found: " + tabId), null, null,
|
||||
ErrorActivity.ErrorInfo.make(UserAction.SOMETHING_ELSE, "none",
|
||||
"Choosing tabs on settings", 0));
|
||||
return;
|
||||
}
|
||||
|
||||
switch (type) {
|
||||
case KIOSK: {
|
||||
SelectKioskFragment selectFragment = new SelectKioskFragment();
|
||||
selectFragment.setOnSelectedLisener((serviceId, kioskId, kioskName) ->
|
||||
case KIOSK:
|
||||
SelectKioskFragment selectKioskFragment = new SelectKioskFragment();
|
||||
selectKioskFragment.setOnSelectedLisener((serviceId, kioskId, kioskName) ->
|
||||
addTab(new Tab.KioskTab(serviceId, kioskId)));
|
||||
selectFragment.show(requireFragmentManager(), "select_kiosk");
|
||||
selectKioskFragment.show(requireFragmentManager(), "select_kiosk");
|
||||
return;
|
||||
}
|
||||
case CHANNEL: {
|
||||
SelectChannelFragment selectFragment = new SelectChannelFragment();
|
||||
selectFragment.setOnSelectedLisener((serviceId, url, name) ->
|
||||
case CHANNEL:
|
||||
SelectChannelFragment selectChannelFragment = new SelectChannelFragment();
|
||||
selectChannelFragment.setOnSelectedLisener((serviceId, url, name) ->
|
||||
addTab(new Tab.ChannelTab(serviceId, url, name)));
|
||||
selectFragment.show(requireFragmentManager(), "select_channel");
|
||||
selectChannelFragment.show(requireFragmentManager(), "select_channel");
|
||||
return;
|
||||
}
|
||||
default:
|
||||
addTab(type.getTab());
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
public ChooseTabListItem[] getAvailableTabs(Context context) {
|
||||
public ChooseTabListItem[] getAvailableTabs(final Context context) {
|
||||
final ArrayList<ChooseTabListItem> returnList = new ArrayList<>();
|
||||
|
||||
for (Tab.Type type : Tab.Type.values()) {
|
||||
|
|
@ -217,21 +224,25 @@ public class ChooseTabsFragment extends Fragment {
|
|||
switch (type) {
|
||||
case BLANK:
|
||||
if (!tabList.contains(tab)) {
|
||||
returnList.add(new ChooseTabListItem(tab.getTabId(), getString(R.string.blank_page_summary),
|
||||
returnList.add(new ChooseTabListItem(tab.getTabId(),
|
||||
getString(R.string.blank_page_summary),
|
||||
tab.getTabIconRes(context)));
|
||||
}
|
||||
break;
|
||||
case KIOSK:
|
||||
returnList.add(new ChooseTabListItem(tab.getTabId(), getString(R.string.kiosk_page_summary),
|
||||
returnList.add(new ChooseTabListItem(tab.getTabId(),
|
||||
getString(R.string.kiosk_page_summary),
|
||||
ThemeHelper.resolveResourceIdFromAttr(context, R.attr.ic_hot)));
|
||||
break;
|
||||
case CHANNEL:
|
||||
returnList.add(new ChooseTabListItem(tab.getTabId(), getString(R.string.channel_page_summary),
|
||||
returnList.add(new ChooseTabListItem(tab.getTabId(),
|
||||
getString(R.string.channel_page_summary),
|
||||
tab.getTabIconRes(context)));
|
||||
break;
|
||||
case DEFAULT_KIOSK:
|
||||
if (!tabList.contains(tab)) {
|
||||
returnList.add(new ChooseTabListItem(tab.getTabId(), getString(R.string.default_kiosk_page_summary),
|
||||
returnList.add(new ChooseTabListItem(tab.getTabId(),
|
||||
getString(R.string.default_kiosk_page_summary),
|
||||
ThemeHelper.resolveResourceIdFromAttr(context, R.attr.ic_hot)));
|
||||
}
|
||||
break;
|
||||
|
|
@ -250,29 +261,88 @@ public class ChooseTabsFragment extends Fragment {
|
|||
// List Handling
|
||||
//////////////////////////////////////////////////////////////////////////*/
|
||||
|
||||
private class SelectedTabsAdapter extends RecyclerView.Adapter<ChooseTabsFragment.SelectedTabsAdapter.TabViewHolder> {
|
||||
private ItemTouchHelper itemTouchHelper;
|
||||
private final LayoutInflater inflater;
|
||||
private ItemTouchHelper.SimpleCallback getItemTouchCallback() {
|
||||
return new ItemTouchHelper.SimpleCallback(ItemTouchHelper.UP | ItemTouchHelper.DOWN,
|
||||
ItemTouchHelper.START | ItemTouchHelper.END) {
|
||||
@Override
|
||||
public int interpolateOutOfBoundsScroll(final RecyclerView recyclerView,
|
||||
final int viewSize,
|
||||
final int viewSizeOutOfBounds,
|
||||
final int totalSize,
|
||||
final long msSinceStartScroll) {
|
||||
final int standardSpeed = super.interpolateOutOfBoundsScroll(recyclerView, viewSize,
|
||||
viewSizeOutOfBounds, totalSize, msSinceStartScroll);
|
||||
final int minimumAbsVelocity = Math.max(12,
|
||||
Math.abs(standardSpeed));
|
||||
return minimumAbsVelocity * (int) Math.signum(viewSizeOutOfBounds);
|
||||
}
|
||||
|
||||
SelectedTabsAdapter(Context context, ItemTouchHelper itemTouchHelper) {
|
||||
@Override
|
||||
public boolean onMove(final RecyclerView recyclerView,
|
||||
final RecyclerView.ViewHolder source,
|
||||
final RecyclerView.ViewHolder target) {
|
||||
if (source.getItemViewType() != target.getItemViewType()
|
||||
|| selectedTabsAdapter == null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
final int sourceIndex = source.getAdapterPosition();
|
||||
final int targetIndex = target.getAdapterPosition();
|
||||
selectedTabsAdapter.swapItems(sourceIndex, targetIndex);
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isLongPressDragEnabled() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isItemViewSwipeEnabled() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onSwiped(final RecyclerView.ViewHolder viewHolder, final int swipeDir) {
|
||||
int position = viewHolder.getAdapterPosition();
|
||||
tabList.remove(position);
|
||||
selectedTabsAdapter.notifyItemRemoved(position);
|
||||
|
||||
if (tabList.isEmpty()) {
|
||||
tabList.add(Tab.Type.BLANK.getTab());
|
||||
selectedTabsAdapter.notifyItemInserted(0);
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
private class SelectedTabsAdapter
|
||||
extends RecyclerView.Adapter<ChooseTabsFragment.SelectedTabsAdapter.TabViewHolder> {
|
||||
private final LayoutInflater inflater;
|
||||
private ItemTouchHelper itemTouchHelper;
|
||||
|
||||
SelectedTabsAdapter(final Context context, final ItemTouchHelper itemTouchHelper) {
|
||||
this.itemTouchHelper = itemTouchHelper;
|
||||
this.inflater = LayoutInflater.from(context);
|
||||
}
|
||||
|
||||
public void swapItems(int fromPosition, int toPosition) {
|
||||
public void swapItems(final int fromPosition, final int toPosition) {
|
||||
Collections.swap(tabList, fromPosition, toPosition);
|
||||
notifyItemMoved(fromPosition, toPosition);
|
||||
}
|
||||
|
||||
@NonNull
|
||||
@Override
|
||||
public ChooseTabsFragment.SelectedTabsAdapter.TabViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
|
||||
public ChooseTabsFragment.SelectedTabsAdapter.TabViewHolder onCreateViewHolder(
|
||||
@NonNull final ViewGroup parent, final int viewType) {
|
||||
View view = inflater.inflate(R.layout.list_choose_tabs, parent, false);
|
||||
return new ChooseTabsFragment.SelectedTabsAdapter.TabViewHolder(view);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onBindViewHolder(@NonNull ChooseTabsFragment.SelectedTabsAdapter.TabViewHolder holder, int position) {
|
||||
public void onBindViewHolder(
|
||||
@NonNull final ChooseTabsFragment.SelectedTabsAdapter.TabViewHolder holder,
|
||||
final int position) {
|
||||
holder.bind(position, holder);
|
||||
}
|
||||
|
||||
|
|
@ -286,7 +356,7 @@ public class ChooseTabsFragment extends Fragment {
|
|||
private TextView tabNameView;
|
||||
private ImageView handle;
|
||||
|
||||
TabViewHolder(View itemView) {
|
||||
TabViewHolder(final View itemView) {
|
||||
super(itemView);
|
||||
|
||||
tabNameView = itemView.findViewById(R.id.tabName);
|
||||
|
|
@ -295,7 +365,7 @@ public class ChooseTabsFragment extends Fragment {
|
|||
}
|
||||
|
||||
@SuppressLint("ClickableViewAccessibility")
|
||||
void bind(int position, TabViewHolder holder) {
|
||||
void bind(final int position, final TabViewHolder holder) {
|
||||
handle.setOnTouchListener(getOnTouchListener(holder));
|
||||
|
||||
final Tab tab = tabList.get(position);
|
||||
|
|
@ -314,10 +384,12 @@ public class ChooseTabsFragment extends Fragment {
|
|||
tabName = getString(R.string.default_kiosk_page_summary);
|
||||
break;
|
||||
case KIOSK:
|
||||
tabName = NewPipe.getNameOfService(((Tab.KioskTab) tab).getKioskServiceId()) + "/" + tab.getTabName(requireContext());
|
||||
tabName = NewPipe.getNameOfService(((Tab.KioskTab) tab)
|
||||
.getKioskServiceId()) + "/" + tab.getTabName(requireContext());
|
||||
break;
|
||||
case CHANNEL:
|
||||
tabName = NewPipe.getNameOfService(((Tab.ChannelTab) tab).getChannelServiceId()) + "/" + tab.getTabName(requireContext());
|
||||
tabName = NewPipe.getNameOfService(((Tab.ChannelTab) tab)
|
||||
.getChannelServiceId()) + "/" + tab.getTabName(requireContext());
|
||||
break;
|
||||
default:
|
||||
tabName = tab.getTabName(requireContext());
|
||||
|
|
@ -342,56 +414,4 @@ public class ChooseTabsFragment extends Fragment {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
private ItemTouchHelper.SimpleCallback getItemTouchCallback() {
|
||||
return new ItemTouchHelper.SimpleCallback(ItemTouchHelper.UP | ItemTouchHelper.DOWN,
|
||||
ItemTouchHelper.START | ItemTouchHelper.END) {
|
||||
@Override
|
||||
public int interpolateOutOfBoundsScroll(RecyclerView recyclerView, int viewSize,
|
||||
int viewSizeOutOfBounds, int totalSize,
|
||||
long msSinceStartScroll) {
|
||||
final int standardSpeed = super.interpolateOutOfBoundsScroll(recyclerView, viewSize,
|
||||
viewSizeOutOfBounds, totalSize, msSinceStartScroll);
|
||||
final int minimumAbsVelocity = Math.max(12,
|
||||
Math.abs(standardSpeed));
|
||||
return minimumAbsVelocity * (int) Math.signum(viewSizeOutOfBounds);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onMove(RecyclerView recyclerView, RecyclerView.ViewHolder source,
|
||||
RecyclerView.ViewHolder target) {
|
||||
if (source.getItemViewType() != target.getItemViewType() ||
|
||||
selectedTabsAdapter == null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
final int sourceIndex = source.getAdapterPosition();
|
||||
final int targetIndex = target.getAdapterPosition();
|
||||
selectedTabsAdapter.swapItems(sourceIndex, targetIndex);
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isLongPressDragEnabled() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isItemViewSwipeEnabled() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onSwiped(RecyclerView.ViewHolder viewHolder, int swipeDir) {
|
||||
int position = viewHolder.getAdapterPosition();
|
||||
tabList.remove(position);
|
||||
selectedTabsAdapter.notifyItemRemoved(position);
|
||||
|
||||
if (tabList.isEmpty()) {
|
||||
tabList.add(Tab.Type.BLANK.getTab());
|
||||
selectedTabsAdapter.notifyItemInserted(0);
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -31,59 +31,16 @@ import org.schabi.newpipe.util.ThemeHelper;
|
|||
import java.util.Objects;
|
||||
|
||||
public abstract class Tab {
|
||||
Tab() {
|
||||
}
|
||||
private static final String JSON_TAB_ID_KEY = "tab_id";
|
||||
|
||||
Tab(@NonNull JsonObject jsonObject) {
|
||||
Tab() { }
|
||||
|
||||
Tab(@NonNull final JsonObject jsonObject) {
|
||||
readDataFromJson(jsonObject);
|
||||
}
|
||||
|
||||
public abstract int getTabId();
|
||||
public abstract String getTabName(Context context);
|
||||
@DrawableRes public abstract int getTabIconRes(Context context);
|
||||
|
||||
/**
|
||||
* Return a instance of the fragment that this tab represent.
|
||||
*/
|
||||
public abstract Fragment getFragment(Context context) throws ExtractionException;
|
||||
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
if (obj == this) return true;
|
||||
|
||||
return obj instanceof Tab && obj.getClass().equals(this.getClass())
|
||||
&& ((Tab) obj).getTabId() == this.getTabId();
|
||||
}
|
||||
|
||||
/*//////////////////////////////////////////////////////////////////////////
|
||||
// JSON Handling
|
||||
//////////////////////////////////////////////////////////////////////////*/
|
||||
|
||||
private static final String JSON_TAB_ID_KEY = "tab_id";
|
||||
|
||||
public void writeJsonOn(JsonSink jsonSink) {
|
||||
jsonSink.object();
|
||||
|
||||
jsonSink.value(JSON_TAB_ID_KEY, getTabId());
|
||||
writeDataToJson(jsonSink);
|
||||
|
||||
jsonSink.end();
|
||||
}
|
||||
|
||||
protected void writeDataToJson(JsonSink writerSink) {
|
||||
// No-op
|
||||
}
|
||||
|
||||
protected void readDataFromJson(JsonObject jsonObject) {
|
||||
// No-op
|
||||
}
|
||||
|
||||
/*//////////////////////////////////////////////////////////////////////////
|
||||
// Tab Handling
|
||||
//////////////////////////////////////////////////////////////////////////*/
|
||||
|
||||
@Nullable
|
||||
public static Tab from(@NonNull JsonObject jsonObject) {
|
||||
public static Tab from(@NonNull final JsonObject jsonObject) {
|
||||
final int tabId = jsonObject.getInt(Tab.JSON_TAB_ID_KEY, -1);
|
||||
|
||||
if (tabId == -1) {
|
||||
|
|
@ -99,7 +56,7 @@ public abstract class Tab {
|
|||
}
|
||||
|
||||
@Nullable
|
||||
public static Type typeFrom(int tabId) {
|
||||
public static Type typeFrom(final int tabId) {
|
||||
for (Type available : Type.values()) {
|
||||
if (available.getTabId() == tabId) {
|
||||
return available;
|
||||
|
|
@ -109,7 +66,7 @@ public abstract class Tab {
|
|||
}
|
||||
|
||||
@Nullable
|
||||
private static Tab from(final int tabId, @Nullable JsonObject jsonObject) {
|
||||
private static Tab from(final int tabId, @Nullable final JsonObject jsonObject) {
|
||||
final Type type = typeFrom(tabId);
|
||||
|
||||
if (type == null) {
|
||||
|
|
@ -128,6 +85,56 @@ public abstract class Tab {
|
|||
return type.getTab();
|
||||
}
|
||||
|
||||
/*//////////////////////////////////////////////////////////////////////////
|
||||
// JSON Handling
|
||||
//////////////////////////////////////////////////////////////////////////*/
|
||||
|
||||
public abstract int getTabId();
|
||||
|
||||
public abstract String getTabName(Context context);
|
||||
|
||||
@DrawableRes
|
||||
public abstract int getTabIconRes(Context context);
|
||||
|
||||
/**
|
||||
* Return a instance of the fragment that this tab represent.
|
||||
*
|
||||
* @param context Android app context
|
||||
* @return the fragment this tab represents
|
||||
*/
|
||||
public abstract Fragment getFragment(Context context) throws ExtractionException;
|
||||
|
||||
/*//////////////////////////////////////////////////////////////////////////
|
||||
// Tab Handling
|
||||
//////////////////////////////////////////////////////////////////////////*/
|
||||
|
||||
@Override
|
||||
public boolean equals(final Object obj) {
|
||||
if (obj == this) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return obj instanceof Tab && obj.getClass().equals(this.getClass())
|
||||
&& ((Tab) obj).getTabId() == this.getTabId();
|
||||
}
|
||||
|
||||
public void writeJsonOn(final JsonSink jsonSink) {
|
||||
jsonSink.object();
|
||||
|
||||
jsonSink.value(JSON_TAB_ID_KEY, getTabId());
|
||||
writeDataToJson(jsonSink);
|
||||
|
||||
jsonSink.end();
|
||||
}
|
||||
|
||||
protected void writeDataToJson(final JsonSink writerSink) {
|
||||
// No-op
|
||||
}
|
||||
|
||||
protected void readDataFromJson(final JsonObject jsonObject) {
|
||||
// No-op
|
||||
}
|
||||
|
||||
/*//////////////////////////////////////////////////////////////////////////
|
||||
// Implementations
|
||||
//////////////////////////////////////////////////////////////////////////*/
|
||||
|
|
@ -144,7 +151,7 @@ public abstract class Tab {
|
|||
|
||||
private Tab tab;
|
||||
|
||||
Type(Tab tab) {
|
||||
Type(final Tab tab) {
|
||||
this.tab = tab;
|
||||
}
|
||||
|
||||
|
|
@ -166,18 +173,18 @@ public abstract class Tab {
|
|||
}
|
||||
|
||||
@Override
|
||||
public String getTabName(Context context) {
|
||||
public String getTabName(final Context context) {
|
||||
return "NewPipe"; //context.getString(R.string.blank_page_summary);
|
||||
}
|
||||
|
||||
@DrawableRes
|
||||
@Override
|
||||
public int getTabIconRes(Context context) {
|
||||
public int getTabIconRes(final Context context) {
|
||||
return ThemeHelper.resolveResourceIdFromAttr(context, R.attr.ic_blank_page);
|
||||
}
|
||||
|
||||
@Override
|
||||
public BlankFragment getFragment(Context context) {
|
||||
public BlankFragment getFragment(final Context context) {
|
||||
return new BlankFragment();
|
||||
}
|
||||
}
|
||||
|
|
@ -191,18 +198,18 @@ public abstract class Tab {
|
|||
}
|
||||
|
||||
@Override
|
||||
public String getTabName(Context context) {
|
||||
public String getTabName(final Context context) {
|
||||
return context.getString(R.string.tab_subscriptions);
|
||||
}
|
||||
|
||||
@DrawableRes
|
||||
@Override
|
||||
public int getTabIconRes(Context context) {
|
||||
public int getTabIconRes(final Context context) {
|
||||
return ThemeHelper.resolveResourceIdFromAttr(context, R.attr.ic_channel);
|
||||
}
|
||||
|
||||
@Override
|
||||
public SubscriptionFragment getFragment(Context context) {
|
||||
public SubscriptionFragment getFragment(final Context context) {
|
||||
return new SubscriptionFragment();
|
||||
}
|
||||
|
||||
|
|
@ -217,18 +224,18 @@ public abstract class Tab {
|
|||
}
|
||||
|
||||
@Override
|
||||
public String getTabName(Context context) {
|
||||
public String getTabName(final Context context) {
|
||||
return context.getString(R.string.fragment_feed_title);
|
||||
}
|
||||
|
||||
@DrawableRes
|
||||
@Override
|
||||
public int getTabIconRes(Context context) {
|
||||
public int getTabIconRes(final Context context) {
|
||||
return ThemeHelper.resolveResourceIdFromAttr(context, R.attr.rss);
|
||||
}
|
||||
|
||||
@Override
|
||||
public FeedFragment getFragment(Context context) {
|
||||
public FeedFragment getFragment(final Context context) {
|
||||
return new FeedFragment();
|
||||
}
|
||||
}
|
||||
|
|
@ -242,18 +249,18 @@ public abstract class Tab {
|
|||
}
|
||||
|
||||
@Override
|
||||
public String getTabName(Context context) {
|
||||
public String getTabName(final Context context) {
|
||||
return context.getString(R.string.tab_bookmarks);
|
||||
}
|
||||
|
||||
@DrawableRes
|
||||
@Override
|
||||
public int getTabIconRes(Context context) {
|
||||
public int getTabIconRes(final Context context) {
|
||||
return ThemeHelper.resolveResourceIdFromAttr(context, R.attr.ic_bookmark);
|
||||
}
|
||||
|
||||
@Override
|
||||
public BookmarkFragment getFragment(Context context) {
|
||||
public BookmarkFragment getFragment(final Context context) {
|
||||
return new BookmarkFragment();
|
||||
}
|
||||
}
|
||||
|
|
@ -267,41 +274,39 @@ public abstract class Tab {
|
|||
}
|
||||
|
||||
@Override
|
||||
public String getTabName(Context context) {
|
||||
public String getTabName(final Context context) {
|
||||
return context.getString(R.string.title_activity_history);
|
||||
}
|
||||
|
||||
@DrawableRes
|
||||
@Override
|
||||
public int getTabIconRes(Context context) {
|
||||
public int getTabIconRes(final Context context) {
|
||||
return ThemeHelper.resolveResourceIdFromAttr(context, R.attr.history);
|
||||
}
|
||||
|
||||
@Override
|
||||
public StatisticsPlaylistFragment getFragment(Context context) {
|
||||
public StatisticsPlaylistFragment getFragment(final Context context) {
|
||||
return new StatisticsPlaylistFragment();
|
||||
}
|
||||
}
|
||||
|
||||
public static class KioskTab extends Tab {
|
||||
public static final int ID = 5;
|
||||
|
||||
private int kioskServiceId;
|
||||
private String kioskId;
|
||||
|
||||
private static final String JSON_KIOSK_SERVICE_ID_KEY = "service_id";
|
||||
private static final String JSON_KIOSK_ID_KEY = "kiosk_id";
|
||||
private int kioskServiceId;
|
||||
private String kioskId;
|
||||
|
||||
private KioskTab() {
|
||||
this(-1, "<no-id>");
|
||||
}
|
||||
|
||||
public KioskTab(int kioskServiceId, String kioskId) {
|
||||
public KioskTab(final int kioskServiceId, final String kioskId) {
|
||||
this.kioskServiceId = kioskServiceId;
|
||||
this.kioskId = kioskId;
|
||||
}
|
||||
|
||||
public KioskTab(JsonObject jsonObject) {
|
||||
public KioskTab(final JsonObject jsonObject) {
|
||||
super(jsonObject);
|
||||
}
|
||||
|
||||
|
|
@ -311,13 +316,13 @@ public abstract class Tab {
|
|||
}
|
||||
|
||||
@Override
|
||||
public String getTabName(Context context) {
|
||||
public String getTabName(final Context context) {
|
||||
return KioskTranslator.getTranslatedKioskName(kioskId, context);
|
||||
}
|
||||
|
||||
@DrawableRes
|
||||
@Override
|
||||
public int getTabIconRes(Context context) {
|
||||
public int getTabIconRes(final Context context) {
|
||||
final int kioskIcon = KioskTranslator.getKioskIcons(kioskId, context);
|
||||
|
||||
if (kioskIcon <= 0) {
|
||||
|
|
@ -328,26 +333,25 @@ public abstract class Tab {
|
|||
}
|
||||
|
||||
@Override
|
||||
public KioskFragment getFragment(Context context) throws ExtractionException {
|
||||
public KioskFragment getFragment(final Context context) throws ExtractionException {
|
||||
return KioskFragment.getInstance(kioskServiceId, kioskId);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void writeDataToJson(JsonSink writerSink) {
|
||||
protected void writeDataToJson(final JsonSink writerSink) {
|
||||
writerSink.value(JSON_KIOSK_SERVICE_ID_KEY, kioskServiceId)
|
||||
.value(JSON_KIOSK_ID_KEY, kioskId);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void readDataFromJson(JsonObject jsonObject) {
|
||||
protected void readDataFromJson(final JsonObject jsonObject) {
|
||||
kioskServiceId = jsonObject.getInt(JSON_KIOSK_SERVICE_ID_KEY, -1);
|
||||
kioskId = jsonObject.getString(JSON_KIOSK_ID_KEY, "<no-id>");
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
return super.equals(obj) &&
|
||||
kioskServiceId == ((KioskTab) obj).kioskServiceId
|
||||
public boolean equals(final Object obj) {
|
||||
return super.equals(obj) && kioskServiceId == ((KioskTab) obj).kioskServiceId
|
||||
&& Objects.equals(kioskId, ((KioskTab) obj).kioskId);
|
||||
}
|
||||
|
||||
|
|
@ -362,26 +366,25 @@ public abstract class Tab {
|
|||
|
||||
public static class ChannelTab extends Tab {
|
||||
public static final int ID = 6;
|
||||
|
||||
private int channelServiceId;
|
||||
private String channelUrl;
|
||||
private String channelName;
|
||||
|
||||
private static final String JSON_CHANNEL_SERVICE_ID_KEY = "channel_service_id";
|
||||
private static final String JSON_CHANNEL_URL_KEY = "channel_url";
|
||||
private static final String JSON_CHANNEL_NAME_KEY = "channel_name";
|
||||
private int channelServiceId;
|
||||
private String channelUrl;
|
||||
private String channelName;
|
||||
|
||||
private ChannelTab() {
|
||||
this(-1, "<no-url>", "<no-name>");
|
||||
}
|
||||
|
||||
public ChannelTab(int channelServiceId, String channelUrl, String channelName) {
|
||||
public ChannelTab(final int channelServiceId, final String channelUrl,
|
||||
final String channelName) {
|
||||
this.channelServiceId = channelServiceId;
|
||||
this.channelUrl = channelUrl;
|
||||
this.channelName = channelName;
|
||||
}
|
||||
|
||||
public ChannelTab(JsonObject jsonObject) {
|
||||
public ChannelTab(final JsonObject jsonObject) {
|
||||
super(jsonObject);
|
||||
}
|
||||
|
||||
|
|
@ -391,39 +394,38 @@ public abstract class Tab {
|
|||
}
|
||||
|
||||
@Override
|
||||
public String getTabName(Context context) {
|
||||
public String getTabName(final Context context) {
|
||||
return channelName;
|
||||
}
|
||||
|
||||
@DrawableRes
|
||||
@Override
|
||||
public int getTabIconRes(Context context) {
|
||||
public int getTabIconRes(final Context context) {
|
||||
return ThemeHelper.resolveResourceIdFromAttr(context, R.attr.ic_channel);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ChannelFragment getFragment(Context context) {
|
||||
public ChannelFragment getFragment(final Context context) {
|
||||
return ChannelFragment.getInstance(channelServiceId, channelUrl, channelName);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void writeDataToJson(JsonSink writerSink) {
|
||||
protected void writeDataToJson(final JsonSink writerSink) {
|
||||
writerSink.value(JSON_CHANNEL_SERVICE_ID_KEY, channelServiceId)
|
||||
.value(JSON_CHANNEL_URL_KEY, channelUrl)
|
||||
.value(JSON_CHANNEL_NAME_KEY, channelName);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void readDataFromJson(JsonObject jsonObject) {
|
||||
protected void readDataFromJson(final JsonObject jsonObject) {
|
||||
channelServiceId = jsonObject.getInt(JSON_CHANNEL_SERVICE_ID_KEY, -1);
|
||||
channelUrl = jsonObject.getString(JSON_CHANNEL_URL_KEY, "<no-url>");
|
||||
channelName = jsonObject.getString(JSON_CHANNEL_NAME_KEY, "<no-name>");
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
return super.equals(obj) &&
|
||||
channelServiceId == ((ChannelTab) obj).channelServiceId
|
||||
public boolean equals(final Object obj) {
|
||||
return super.equals(obj) && channelServiceId == ((ChannelTab) obj).channelServiceId
|
||||
&& Objects.equals(channelUrl, ((ChannelTab) obj).channelUrl)
|
||||
&& Objects.equals(channelName, ((ChannelTab) obj).channelName);
|
||||
}
|
||||
|
|
@ -450,22 +452,22 @@ public abstract class Tab {
|
|||
}
|
||||
|
||||
@Override
|
||||
public String getTabName(Context context) {
|
||||
public String getTabName(final Context context) {
|
||||
return KioskTranslator.getTranslatedKioskName(getDefaultKioskId(context), context);
|
||||
}
|
||||
|
||||
@DrawableRes
|
||||
@Override
|
||||
public int getTabIconRes(Context context) {
|
||||
public int getTabIconRes(final Context context) {
|
||||
return KioskTranslator.getKioskIcons(getDefaultKioskId(context), context);
|
||||
}
|
||||
|
||||
@Override
|
||||
public DefaultKioskFragment getFragment(Context context) throws ExtractionException {
|
||||
public DefaultKioskFragment getFragment(final Context context) {
|
||||
return new DefaultKioskFragment();
|
||||
}
|
||||
|
||||
private String getDefaultKioskId(Context context) {
|
||||
private String getDefaultKioskId(final Context context) {
|
||||
final int kioskServiceId = ServiceHelper.getSelectedServiceId(context);
|
||||
|
||||
String kioskId = "";
|
||||
|
|
@ -474,7 +476,8 @@ public abstract class Tab {
|
|||
kioskId = service.getKioskList().getDefaultKioskId();
|
||||
} catch (ExtractionException e) {
|
||||
ErrorActivity.reportError(context, e, null, null,
|
||||
ErrorActivity.ErrorInfo.make(UserAction.REQUESTED_KIOSK, "none", "Loading default kiosk from selected service", 0));
|
||||
ErrorActivity.ErrorInfo.make(UserAction.REQUESTED_KIOSK, "none",
|
||||
"Loading default kiosk from selected service", 0));
|
||||
}
|
||||
return kioskId;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,5 +1,7 @@
|
|||
package org.schabi.newpipe.settings.tabs;
|
||||
|
||||
import androidx.annotation.Nullable;
|
||||
|
||||
import com.grack.nanojson.JsonArray;
|
||||
import com.grack.nanojson.JsonObject;
|
||||
import com.grack.nanojson.JsonParser;
|
||||
|
|
@ -12,33 +14,19 @@ import java.util.Arrays;
|
|||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
import androidx.annotation.Nullable;
|
||||
|
||||
/**
|
||||
* Class to get a JSON representation of a list of tabs, and the other way around.
|
||||
*/
|
||||
public class TabsJsonHelper {
|
||||
public final class TabsJsonHelper {
|
||||
private static final String JSON_TABS_ARRAY_KEY = "tabs";
|
||||
|
||||
private static final List<Tab> FALLBACK_INITIAL_TABS_LIST = Collections.unmodifiableList(Arrays.asList(
|
||||
Tab.Type.DEFAULT_KIOSK.getTab(),
|
||||
Tab.Type.SUBSCRIPTIONS.getTab(),
|
||||
Tab.Type.BOOKMARKS.getTab()
|
||||
));
|
||||
private static final List<Tab> FALLBACK_INITIAL_TABS_LIST = Collections.unmodifiableList(
|
||||
Arrays.asList(
|
||||
Tab.Type.DEFAULT_KIOSK.getTab(),
|
||||
Tab.Type.SUBSCRIPTIONS.getTab(),
|
||||
Tab.Type.BOOKMARKS.getTab()));
|
||||
|
||||
public static class InvalidJsonException extends Exception {
|
||||
private InvalidJsonException() {
|
||||
super();
|
||||
}
|
||||
|
||||
private InvalidJsonException(String message) {
|
||||
super(message);
|
||||
}
|
||||
|
||||
private InvalidJsonException(Throwable cause) {
|
||||
super(cause);
|
||||
}
|
||||
}
|
||||
private TabsJsonHelper() { }
|
||||
|
||||
/**
|
||||
* Try to reads the passed JSON and returns the list of tabs if no error were encountered.
|
||||
|
|
@ -52,7 +40,8 @@ public class TabsJsonHelper {
|
|||
* @return a list of {@link Tab tabs}.
|
||||
* @throws InvalidJsonException if the JSON string is not valid
|
||||
*/
|
||||
public static List<Tab> getTabsFromJson(@Nullable String tabsJson) throws InvalidJsonException {
|
||||
public static List<Tab> getTabsFromJson(@Nullable final String tabsJson)
|
||||
throws InvalidJsonException {
|
||||
if (tabsJson == null || tabsJson.isEmpty()) {
|
||||
return getDefaultTabs();
|
||||
}
|
||||
|
|
@ -65,11 +54,14 @@ public class TabsJsonHelper {
|
|||
final JsonArray tabsArray = outerJsonObject.getArray(JSON_TABS_ARRAY_KEY);
|
||||
|
||||
if (tabsArray == null) {
|
||||
throw new InvalidJsonException("JSON doesn't contain \"" + JSON_TABS_ARRAY_KEY + "\" array");
|
||||
throw new InvalidJsonException("JSON doesn't contain \"" + JSON_TABS_ARRAY_KEY
|
||||
+ "\" array");
|
||||
}
|
||||
|
||||
for (Object o : tabsArray) {
|
||||
if (!(o instanceof JsonObject)) continue;
|
||||
if (!(o instanceof JsonObject)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
final Tab tab = Tab.from((JsonObject) o);
|
||||
|
||||
|
|
@ -94,13 +86,15 @@ public class TabsJsonHelper {
|
|||
* @param tabList a list of {@link Tab tabs}.
|
||||
* @return a JSON string representing the list of tabs
|
||||
*/
|
||||
public static String getJsonToSave(@Nullable List<Tab> tabList) {
|
||||
public static String getJsonToSave(@Nullable final List<Tab> tabList) {
|
||||
final JsonStringWriter jsonWriter = JsonWriter.string();
|
||||
jsonWriter.object();
|
||||
|
||||
jsonWriter.array(JSON_TABS_ARRAY_KEY);
|
||||
if (tabList != null) for (Tab tab : tabList) {
|
||||
tab.writeJsonOn(jsonWriter);
|
||||
if (tabList != null) {
|
||||
for (Tab tab : tabList) {
|
||||
tab.writeJsonOn(jsonWriter);
|
||||
}
|
||||
}
|
||||
jsonWriter.end();
|
||||
|
||||
|
|
@ -108,7 +102,21 @@ public class TabsJsonHelper {
|
|||
return jsonWriter.done();
|
||||
}
|
||||
|
||||
public static List<Tab> getDefaultTabs(){
|
||||
public static List<Tab> getDefaultTabs() {
|
||||
return FALLBACK_INITIAL_TABS_LIST;
|
||||
}
|
||||
}
|
||||
|
||||
public static final class InvalidJsonException extends Exception {
|
||||
private InvalidJsonException() {
|
||||
super();
|
||||
}
|
||||
|
||||
private InvalidJsonException(final String message) {
|
||||
super(message);
|
||||
}
|
||||
|
||||
private InvalidJsonException(final Throwable cause) {
|
||||
super(cause);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -9,21 +9,23 @@ import org.schabi.newpipe.R;
|
|||
|
||||
import java.util.List;
|
||||
|
||||
public class TabsManager {
|
||||
public final class TabsManager {
|
||||
private final SharedPreferences sharedPreferences;
|
||||
private final String savedTabsKey;
|
||||
private final Context context;
|
||||
private SavedTabsChangeListener savedTabsChangeListener;
|
||||
private SharedPreferences.OnSharedPreferenceChangeListener preferenceChangeListener;
|
||||
|
||||
public static TabsManager getManager(Context context) {
|
||||
return new TabsManager(context);
|
||||
}
|
||||
|
||||
private TabsManager(Context context) {
|
||||
private TabsManager(final Context context) {
|
||||
this.context = context;
|
||||
this.sharedPreferences = PreferenceManager.getDefaultSharedPreferences(context);
|
||||
this.savedTabsKey = context.getString(R.string.saved_tabs_key);
|
||||
}
|
||||
|
||||
public static TabsManager getManager(final Context context) {
|
||||
return new TabsManager(context);
|
||||
}
|
||||
|
||||
public List<Tab> getTabs() {
|
||||
final String savedJson = sharedPreferences.getString(savedTabsKey, null);
|
||||
try {
|
||||
|
|
@ -34,11 +36,15 @@ public class TabsManager {
|
|||
}
|
||||
}
|
||||
|
||||
public void saveTabs(List<Tab> tabList) {
|
||||
public void saveTabs(final List<Tab> tabList) {
|
||||
final String jsonToSave = TabsJsonHelper.getJsonToSave(tabList);
|
||||
sharedPreferences.edit().putString(savedTabsKey, jsonToSave).apply();
|
||||
}
|
||||
|
||||
/*//////////////////////////////////////////////////////////////////////////
|
||||
// Listener
|
||||
//////////////////////////////////////////////////////////////////////////*/
|
||||
|
||||
public void resetTabs() {
|
||||
sharedPreferences.edit().remove(savedTabsKey).apply();
|
||||
}
|
||||
|
|
@ -47,18 +53,7 @@ public class TabsManager {
|
|||
return TabsJsonHelper.getDefaultTabs();
|
||||
}
|
||||
|
||||
/*//////////////////////////////////////////////////////////////////////////
|
||||
// Listener
|
||||
//////////////////////////////////////////////////////////////////////////*/
|
||||
|
||||
public interface SavedTabsChangeListener {
|
||||
void onTabsChanged();
|
||||
}
|
||||
|
||||
private SavedTabsChangeListener savedTabsChangeListener;
|
||||
private SharedPreferences.OnSharedPreferenceChangeListener preferenceChangeListener;
|
||||
|
||||
public void setSavedTabsListener(SavedTabsChangeListener listener) {
|
||||
public void setSavedTabsListener(final SavedTabsChangeListener listener) {
|
||||
if (preferenceChangeListener != null) {
|
||||
sharedPreferences.unregisterOnSharedPreferenceChangeListener(preferenceChangeListener);
|
||||
}
|
||||
|
|
@ -76,13 +71,19 @@ public class TabsManager {
|
|||
}
|
||||
|
||||
private SharedPreferences.OnSharedPreferenceChangeListener getPreferenceChangeListener() {
|
||||
return (sharedPreferences, key) -> {
|
||||
return (sp, key) -> {
|
||||
if (key.equals(savedTabsKey)) {
|
||||
if (savedTabsChangeListener != null) savedTabsChangeListener.onTabsChanged();
|
||||
if (savedTabsChangeListener != null) {
|
||||
savedTabsChangeListener.onTabsChanged();
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
public interface SavedTabsChangeListener {
|
||||
void onTabsChanged();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue