Merge pull request #13026 from dustdfg/kotlin_merged2
Convert a bunch of files to kotlin
This commit is contained in:
commit
e6e0be772a
@ -1,50 +0,0 @@
|
||||
package org.schabi.newpipe;
|
||||
|
||||
import android.annotation.SuppressLint;
|
||||
import android.app.Activity;
|
||||
import android.content.Intent;
|
||||
import android.os.Bundle;
|
||||
|
||||
import org.schabi.newpipe.util.NavigationHelper;
|
||||
|
||||
/*
|
||||
* Copyright (C) Hans-Christoph Steiner 2016 <hans@eds.org>
|
||||
* ExitActivity.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 ExitActivity extends Activity {
|
||||
|
||||
public static void exitAndRemoveFromRecentApps(final Activity activity) {
|
||||
final Intent intent = new Intent(activity, ExitActivity.class);
|
||||
|
||||
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK
|
||||
| Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS
|
||||
| Intent.FLAG_ACTIVITY_CLEAR_TASK
|
||||
| Intent.FLAG_ACTIVITY_NO_ANIMATION);
|
||||
|
||||
activity.startActivity(intent);
|
||||
}
|
||||
|
||||
@SuppressLint("NewApi")
|
||||
@Override
|
||||
protected void onCreate(final Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
|
||||
finishAndRemoveTask();
|
||||
|
||||
NavigationHelper.restartApp(this);
|
||||
}
|
||||
}
|
||||
36
app/src/main/java/org/schabi/newpipe/ExitActivity.kt
Normal file
36
app/src/main/java/org/schabi/newpipe/ExitActivity.kt
Normal file
@ -0,0 +1,36 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2016-2026 NewPipe contributors <https://newpipe.net>
|
||||
* SPDX-License-Identifier: GPL-3.0-or-later
|
||||
*/
|
||||
|
||||
package org.schabi.newpipe
|
||||
|
||||
import android.annotation.SuppressLint
|
||||
import android.app.Activity
|
||||
import android.content.Intent
|
||||
import android.os.Bundle
|
||||
import org.schabi.newpipe.util.NavigationHelper
|
||||
|
||||
class ExitActivity : Activity() {
|
||||
@SuppressLint("NewApi")
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
finishAndRemoveTask()
|
||||
NavigationHelper.restartApp(this)
|
||||
}
|
||||
|
||||
companion object {
|
||||
@JvmStatic
|
||||
fun exitAndRemoveFromRecentApps(activity: Activity) {
|
||||
val intent = Intent(activity, ExitActivity::class.java)
|
||||
intent.addFlags(
|
||||
Intent.FLAG_ACTIVITY_NEW_TASK
|
||||
or Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS
|
||||
or Intent.FLAG_ACTIVITY_CLEAR_TASK
|
||||
or Intent.FLAG_ACTIVITY_NO_ANIMATION
|
||||
)
|
||||
|
||||
activity.startActivity(intent)
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1,58 +0,0 @@
|
||||
package org.schabi.newpipe.settings.export;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.ObjectInputStream;
|
||||
import java.io.ObjectStreamClass;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* An {@link ObjectInputStream} that only allows preferences-related types to be deserialized, to
|
||||
* prevent injections. The only allowed types are: all primitive types, all boxed primitive types,
|
||||
* null, strings. HashMap, HashSet and arrays of previously defined types are also allowed. Sources:
|
||||
* <a href="https://wiki.sei.cmu.edu/confluence/display/java/SER00-J.+Enable+serialization+compatibility+during+class+evolution">
|
||||
* cmu.edu
|
||||
* </a>,
|
||||
* <a href="https://cheatsheetseries.owasp.org/cheatsheets/Deserialization_Cheat_Sheet.html#harden-your-own-javaioobjectinputstream">
|
||||
* OWASP cheatsheet
|
||||
* </a>,
|
||||
* <a href="https://commons.apache.org/proper/commons-io/apidocs/src-html/org/apache/commons/io/serialization/ValidatingObjectInputStream.html#line-118">
|
||||
* Apache's {@code ValidatingObjectInputStream}
|
||||
* </a>
|
||||
*/
|
||||
public class PreferencesObjectInputStream extends ObjectInputStream {
|
||||
|
||||
/**
|
||||
* Primitive types, strings and other built-in types do not pass through resolveClass() but
|
||||
* instead have a custom encoding; see
|
||||
* <a href="https://docs.oracle.com/javase/6/docs/platform/serialization/spec/protocol.html#10152">
|
||||
* official docs</a>.
|
||||
*/
|
||||
private static final Set<String> CLASS_WHITELIST = Set.of(
|
||||
"java.lang.Boolean",
|
||||
"java.lang.Byte",
|
||||
"java.lang.Character",
|
||||
"java.lang.Short",
|
||||
"java.lang.Integer",
|
||||
"java.lang.Long",
|
||||
"java.lang.Float",
|
||||
"java.lang.Double",
|
||||
"java.lang.Void",
|
||||
"java.util.HashMap",
|
||||
"java.util.HashSet"
|
||||
);
|
||||
|
||||
public PreferencesObjectInputStream(final InputStream in) throws IOException {
|
||||
super(in);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Class<?> resolveClass(final ObjectStreamClass desc)
|
||||
throws ClassNotFoundException, IOException {
|
||||
if (CLASS_WHITELIST.contains(desc.getName())) {
|
||||
return super.resolveClass(desc);
|
||||
} else {
|
||||
throw new ClassNotFoundException("Class not allowed: " + desc.getName());
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,52 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2024-2026 NewPipe contributors <https://newpipe.net>
|
||||
* SPDX-License-Identifier: GPL-3.0-or-later
|
||||
*/
|
||||
|
||||
package org.schabi.newpipe.settings.export
|
||||
|
||||
import java.io.IOException
|
||||
import java.io.InputStream
|
||||
import java.io.ObjectInputStream
|
||||
import java.io.ObjectStreamClass
|
||||
|
||||
/**
|
||||
* An [ObjectInputStream] that only allows preferences-related types to be deserialized, to
|
||||
* prevent injections. The only allowed types are: all primitive types, all boxed primitive types,
|
||||
* null, strings. HashMap, HashSet and arrays of previously defined types are also allowed. Sources:
|
||||
* [cmu.edu](https://wiki.sei.cmu.edu/confluence/display/java/SER00-J.+Enable+serialization+compatibility+during+class+evolution) * ,
|
||||
* [OWASP cheatsheet](https://cheatsheetseries.owasp.org/cheatsheets/Deserialization_Cheat_Sheet.html#harden-your-own-javaioobjectinputstream) * ,
|
||||
* [Apache's `ValidatingObjectInputStream`](https://commons.apache.org/proper/commons-io/apidocs/src-html/org/apache/commons/io/serialization/ValidatingObjectInputStream.html#line-118) *
|
||||
*/
|
||||
class PreferencesObjectInputStream(stream: InputStream) : ObjectInputStream(stream) {
|
||||
@Throws(ClassNotFoundException::class, IOException::class)
|
||||
override fun resolveClass(desc: ObjectStreamClass): Class<*> {
|
||||
if (desc.name in CLASS_WHITELIST) {
|
||||
return super.resolveClass(desc)
|
||||
} else {
|
||||
throw ClassNotFoundException("Class not allowed: $desc.name")
|
||||
}
|
||||
}
|
||||
|
||||
companion object {
|
||||
/**
|
||||
* Primitive types, strings and other built-in types do not pass through resolveClass() but
|
||||
* instead have a custom encoding; see
|
||||
* [
|
||||
* official docs](https://docs.oracle.com/javase/6/docs/platform/serialization/spec/protocol.html#10152).
|
||||
*/
|
||||
private val CLASS_WHITELIST = setOf<String>(
|
||||
"java.lang.Boolean",
|
||||
"java.lang.Byte",
|
||||
"java.lang.Character",
|
||||
"java.lang.Short",
|
||||
"java.lang.Integer",
|
||||
"java.lang.Long",
|
||||
"java.lang.Float",
|
||||
"java.lang.Double",
|
||||
"java.lang.Void",
|
||||
"java.util.HashMap",
|
||||
"java.util.HashSet"
|
||||
)
|
||||
}
|
||||
}
|
||||
@ -1,51 +0,0 @@
|
||||
package org.schabi.newpipe.util;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.SharedPreferences;
|
||||
|
||||
import androidx.preference.PreferenceManager;
|
||||
|
||||
import org.schabi.newpipe.R;
|
||||
|
||||
/**
|
||||
* For preferences with dependencies and multiple use case,
|
||||
* this class can be used to reduce the lines of code.
|
||||
*/
|
||||
public final class DependentPreferenceHelper {
|
||||
|
||||
private DependentPreferenceHelper() {
|
||||
// no instance
|
||||
}
|
||||
|
||||
/**
|
||||
* Option `Resume playback` depends on `Watch history`, this method can be used to retrieve if
|
||||
* `Resume playback` and its dependencies are all enabled.
|
||||
*
|
||||
* @param context the Android context
|
||||
* @return returns true if `Resume playback` and `Watch history` are both enabled
|
||||
*/
|
||||
public static boolean getResumePlaybackEnabled(final Context context) {
|
||||
final SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(context);
|
||||
|
||||
return prefs.getBoolean(context.getString(
|
||||
R.string.enable_watch_history_key), true)
|
||||
&& prefs.getBoolean(context.getString(
|
||||
R.string.enable_playback_resume_key), true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Option `Position in lists` depends on `Watch history`, this method can be used to retrieve if
|
||||
* `Position in lists` and its dependencies are all enabled.
|
||||
*
|
||||
* @param context the Android context
|
||||
* @return returns true if `Positions in lists` and `Watch history` are both enabled
|
||||
*/
|
||||
public static boolean getPositionsInListsEnabled(final Context context) {
|
||||
final SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(context);
|
||||
|
||||
return prefs.getBoolean(context.getString(
|
||||
R.string.enable_watch_history_key), true)
|
||||
&& prefs.getBoolean(context.getString(
|
||||
R.string.enable_playback_state_lists_key), true);
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,46 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2023-2026 NewPipe contributors <https://newpipe.net>
|
||||
* SPDX-License-Identifier: GPL-3.0-or-later
|
||||
*/
|
||||
|
||||
package org.schabi.newpipe.util
|
||||
|
||||
import android.content.Context
|
||||
import androidx.preference.PreferenceManager
|
||||
import org.schabi.newpipe.R
|
||||
|
||||
/**
|
||||
* For preferences with dependencies and multiple use case,
|
||||
* this class can be used to reduce the lines of code.
|
||||
*/
|
||||
object DependentPreferenceHelper {
|
||||
/**
|
||||
* Option `Resume playback` depends on `Watch history`, this method can be used to retrieve if
|
||||
* `Resume playback` and its dependencies are all enabled.
|
||||
*
|
||||
* @param context the Android context
|
||||
* @return returns true if `Resume playback` and `Watch history` are both enabled
|
||||
*/
|
||||
@JvmStatic
|
||||
fun getResumePlaybackEnabled(context: Context): Boolean {
|
||||
val prefs = PreferenceManager.getDefaultSharedPreferences(context)
|
||||
|
||||
return prefs.getBoolean(context.getString(R.string.enable_watch_history_key), true) &&
|
||||
prefs.getBoolean(context.getString(R.string.enable_playback_resume_key), true)
|
||||
}
|
||||
|
||||
/**
|
||||
* Option `Position in lists` depends on `Watch history`, this method can be used to retrieve if
|
||||
* `Position in lists` and its dependencies are all enabled.
|
||||
*
|
||||
* @param context the Android context
|
||||
* @return returns true if `Positions in lists` and `Watch history` are both enabled
|
||||
*/
|
||||
@JvmStatic
|
||||
fun getPositionsInListsEnabled(context: Context): Boolean {
|
||||
val prefs = PreferenceManager.getDefaultSharedPreferences(context)
|
||||
|
||||
return prefs.getBoolean(context.getString(R.string.enable_watch_history_key), true) &&
|
||||
prefs.getBoolean(context.getString(R.string.enable_playback_state_lists_key), true)
|
||||
}
|
||||
}
|
||||
@ -1,61 +0,0 @@
|
||||
package org.schabi.newpipe.util;
|
||||
|
||||
import android.content.Context;
|
||||
import android.text.Selection;
|
||||
import android.text.Spannable;
|
||||
import android.widget.TextView;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
|
||||
import org.schabi.newpipe.util.external_communication.ShareUtils;
|
||||
import org.schabi.newpipe.views.NewPipeEditText;
|
||||
import org.schabi.newpipe.views.NewPipeTextView;
|
||||
|
||||
public final class NewPipeTextViewHelper {
|
||||
private NewPipeTextViewHelper() {
|
||||
}
|
||||
|
||||
/**
|
||||
* Share the selected text of {@link NewPipeTextView NewPipeTextViews} and
|
||||
* {@link NewPipeEditText NewPipeEditTexts} with
|
||||
* {@link ShareUtils#shareText(Context, String, String)}.
|
||||
*
|
||||
* <p>
|
||||
* This allows EMUI users to get the Android share sheet instead of the EMUI share sheet when
|
||||
* using the {@code Share} command of the popup menu which appears when selecting text.
|
||||
* </p>
|
||||
*
|
||||
* @param textView the {@link TextView} on which sharing the selected text. It should be a
|
||||
* {@link NewPipeTextView} or a {@link NewPipeEditText} (even if
|
||||
* {@link TextView standard TextViews} are supported).
|
||||
*/
|
||||
public static void shareSelectedTextWithShareUtils(@NonNull final TextView textView) {
|
||||
final CharSequence textViewText = textView.getText();
|
||||
shareSelectedTextIfNotNullAndNotEmpty(textView, getSelectedText(textView, textViewText));
|
||||
if (textViewText instanceof Spannable) {
|
||||
Selection.setSelection((Spannable) textViewText, textView.getSelectionEnd());
|
||||
}
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private static CharSequence getSelectedText(@NonNull final TextView textView,
|
||||
@Nullable final CharSequence text) {
|
||||
if (!textView.hasSelection() || text == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
final int start = textView.getSelectionStart();
|
||||
final int end = textView.getSelectionEnd();
|
||||
return String.valueOf(start > end ? text.subSequence(end, start)
|
||||
: text.subSequence(start, end));
|
||||
}
|
||||
|
||||
private static void shareSelectedTextIfNotNullAndNotEmpty(
|
||||
@NonNull final TextView textView,
|
||||
@Nullable final CharSequence selectedText) {
|
||||
if (selectedText != null && selectedText.length() != 0) {
|
||||
ShareUtils.shareText(textView.getContext(), "", selectedText.toString());
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,60 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2021-2026 NewPipe contributors <https://newpipe.net>
|
||||
* SPDX-License-Identifier: GPL-3.0-or-later
|
||||
*/
|
||||
|
||||
package org.schabi.newpipe.util
|
||||
|
||||
import android.text.Selection
|
||||
import android.text.Spannable
|
||||
import android.widget.TextView
|
||||
import org.schabi.newpipe.util.external_communication.ShareUtils
|
||||
|
||||
object NewPipeTextViewHelper {
|
||||
/**
|
||||
* Share the selected text of [NewPipeTextViews][org.schabi.newpipe.views.NewPipeTextView] and
|
||||
* [NewPipeEditTexts][org.schabi.newpipe.views.NewPipeEditText] with
|
||||
* [ShareUtils.shareText].
|
||||
*
|
||||
*
|
||||
*
|
||||
* This allows EMUI users to get the Android share sheet instead of the EMUI share sheet when
|
||||
* using the `Share` command of the popup menu which appears when selecting text.
|
||||
*
|
||||
*
|
||||
* @param textView the [TextView] on which sharing the selected text. It should be a
|
||||
* [org.schabi.newpipe.views.NewPipeTextView] or a [org.schabi.newpipe.views.NewPipeEditText]
|
||||
* (even if [standard TextViews][TextView] are supported).
|
||||
*/
|
||||
@JvmStatic
|
||||
fun shareSelectedTextWithShareUtils(textView: TextView) {
|
||||
val textViewText = textView.getText()
|
||||
shareSelectedTextIfNotNullAndNotEmpty(textView, getSelectedText(textView, textViewText))
|
||||
if (textViewText is Spannable) {
|
||||
Selection.setSelection(textViewText, textView.selectionEnd)
|
||||
}
|
||||
}
|
||||
|
||||
private fun getSelectedText(textView: TextView, text: CharSequence?): CharSequence? {
|
||||
if (!textView.hasSelection() || text == null) {
|
||||
return null
|
||||
}
|
||||
|
||||
val start = textView.selectionStart
|
||||
val end = textView.selectionEnd
|
||||
return if (start > end) {
|
||||
text.subSequence(end, start)
|
||||
} else {
|
||||
text.subSequence(start, end)
|
||||
}
|
||||
}
|
||||
|
||||
private fun shareSelectedTextIfNotNullAndNotEmpty(
|
||||
textView: TextView,
|
||||
selectedText: CharSequence?
|
||||
) {
|
||||
if (!selectedText.isNullOrEmpty()) {
|
||||
ShareUtils.shareText(textView.context, "", selectedText.toString())
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1,69 +0,0 @@
|
||||
package org.schabi.newpipe.util;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.SharedPreferences;
|
||||
|
||||
import androidx.preference.PreferenceManager;
|
||||
|
||||
import com.grack.nanojson.JsonArray;
|
||||
import com.grack.nanojson.JsonObject;
|
||||
import com.grack.nanojson.JsonParser;
|
||||
import com.grack.nanojson.JsonParserException;
|
||||
import com.grack.nanojson.JsonStringWriter;
|
||||
import com.grack.nanojson.JsonWriter;
|
||||
|
||||
import org.schabi.newpipe.R;
|
||||
import org.schabi.newpipe.extractor.ServiceList;
|
||||
import org.schabi.newpipe.extractor.services.peertube.PeertubeInstance;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
public final class PeertubeHelper {
|
||||
private PeertubeHelper() { }
|
||||
|
||||
public static List<PeertubeInstance> getInstanceList(final Context context) {
|
||||
final SharedPreferences sharedPreferences = PreferenceManager
|
||||
.getDefaultSharedPreferences(context);
|
||||
final String savedInstanceListKey = context.getString(R.string.peertube_instance_list_key);
|
||||
final String savedJson = sharedPreferences.getString(savedInstanceListKey, null);
|
||||
if (null == savedJson) {
|
||||
return List.of(getCurrentInstance());
|
||||
}
|
||||
|
||||
try {
|
||||
final JsonArray array = JsonParser.object().from(savedJson).getArray("instances");
|
||||
final List<PeertubeInstance> result = new ArrayList<>();
|
||||
for (final Object o : array) {
|
||||
if (o instanceof JsonObject) {
|
||||
final JsonObject instance = (JsonObject) o;
|
||||
final String name = instance.getString("name");
|
||||
final String url = instance.getString("url");
|
||||
result.add(new PeertubeInstance(url, name));
|
||||
}
|
||||
}
|
||||
return result;
|
||||
} catch (final JsonParserException e) {
|
||||
return List.of(getCurrentInstance());
|
||||
}
|
||||
}
|
||||
|
||||
public static PeertubeInstance selectInstance(final PeertubeInstance instance,
|
||||
final Context context) {
|
||||
final SharedPreferences sharedPreferences = PreferenceManager
|
||||
.getDefaultSharedPreferences(context);
|
||||
final String selectedInstanceKey =
|
||||
context.getString(R.string.peertube_selected_instance_key);
|
||||
final JsonStringWriter jsonWriter = JsonWriter.string().object();
|
||||
jsonWriter.value("name", instance.getName());
|
||||
jsonWriter.value("url", instance.getUrl());
|
||||
final String jsonToSave = jsonWriter.end().done();
|
||||
sharedPreferences.edit().putString(selectedInstanceKey, jsonToSave).apply();
|
||||
ServiceList.PeerTube.setInstance(instance);
|
||||
return instance;
|
||||
}
|
||||
|
||||
public static PeertubeInstance getCurrentInstance() {
|
||||
return ServiceList.PeerTube.getInstance();
|
||||
}
|
||||
}
|
||||
52
app/src/main/java/org/schabi/newpipe/util/PeertubeHelper.kt
Normal file
52
app/src/main/java/org/schabi/newpipe/util/PeertubeHelper.kt
Normal file
@ -0,0 +1,52 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2019-2026 NewPipe contributors <https://newpipe.net>
|
||||
* SPDX-License-Identifier: GPL-3.0-or-later
|
||||
*/
|
||||
|
||||
package org.schabi.newpipe.util
|
||||
|
||||
import android.content.Context
|
||||
import androidx.core.content.edit
|
||||
import androidx.preference.PreferenceManager
|
||||
import com.grack.nanojson.JsonObject
|
||||
import com.grack.nanojson.JsonParser
|
||||
import com.grack.nanojson.JsonWriter
|
||||
import org.schabi.newpipe.R
|
||||
import org.schabi.newpipe.extractor.ServiceList
|
||||
import org.schabi.newpipe.extractor.services.peertube.PeertubeInstance
|
||||
|
||||
object PeertubeHelper {
|
||||
|
||||
@JvmStatic
|
||||
val currentInstance: PeertubeInstance
|
||||
get() = ServiceList.PeerTube.instance
|
||||
|
||||
@JvmStatic
|
||||
fun getInstanceList(context: Context): List<PeertubeInstance> {
|
||||
val sharedPreferences = PreferenceManager.getDefaultSharedPreferences(context)
|
||||
val savedInstanceListKey = context.getString(R.string.peertube_instance_list_key)
|
||||
val savedJson = sharedPreferences.getString(savedInstanceListKey, null)
|
||||
?: return listOf(currentInstance)
|
||||
|
||||
return runCatching {
|
||||
JsonParser.`object`().from(savedJson).getArray("instances")
|
||||
.filterIsInstance<JsonObject>()
|
||||
.map { PeertubeInstance(it.getString("url"), it.getString("name")) }
|
||||
}.getOrDefault(listOf(currentInstance))
|
||||
}
|
||||
|
||||
@JvmStatic
|
||||
fun selectInstance(instance: PeertubeInstance, context: Context): PeertubeInstance {
|
||||
val sharedPreferences = PreferenceManager.getDefaultSharedPreferences(context)
|
||||
val selectedInstanceKey = context.getString(R.string.peertube_selected_instance_key)
|
||||
|
||||
val jsonWriter = JsonWriter.string().`object`()
|
||||
jsonWriter.value("name", instance.name)
|
||||
jsonWriter.value("url", instance.url)
|
||||
val jsonToSave = jsonWriter.end().done()
|
||||
|
||||
sharedPreferences.edit { putString(selectedInstanceKey, jsonToSave) }
|
||||
ServiceList.PeerTube.instance = instance
|
||||
return instance
|
||||
}
|
||||
}
|
||||
@ -1,94 +0,0 @@
|
||||
package org.schabi.newpipe.util;
|
||||
|
||||
import android.content.Context;
|
||||
import android.widget.Toast;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.appcompat.app.AppCompatActivity;
|
||||
import androidx.preference.PreferenceManager;
|
||||
|
||||
import org.schabi.newpipe.R;
|
||||
import org.schabi.newpipe.databinding.PlaylistControlBinding;
|
||||
import org.schabi.newpipe.fragments.list.playlist.PlaylistControlViewHolder;
|
||||
import org.schabi.newpipe.player.PlayerType;
|
||||
|
||||
/**
|
||||
* Utility class for play buttons and their respective click listeners.
|
||||
*/
|
||||
public final class PlayButtonHelper {
|
||||
|
||||
private PlayButtonHelper() {
|
||||
// utility class
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialize {@link android.view.View.OnClickListener OnClickListener}
|
||||
* and {@link android.view.View.OnLongClickListener OnLongClickListener} for playlist control
|
||||
* buttons defined in {@link R.layout#playlist_control}.
|
||||
*
|
||||
* @param activity The activity to use for the {@link android.widget.Toast Toast}.
|
||||
* @param playlistControlBinding The binding of the
|
||||
* {@link R.layout#playlist_control playlist control layout}.
|
||||
* @param fragment The fragment to get the play queue from.
|
||||
*/
|
||||
public static void initPlaylistControlClickListener(
|
||||
@NonNull final AppCompatActivity activity,
|
||||
@NonNull final PlaylistControlBinding playlistControlBinding,
|
||||
@NonNull final PlaylistControlViewHolder fragment) {
|
||||
// click listener
|
||||
playlistControlBinding.playlistCtrlPlayAllButton.setOnClickListener(view -> {
|
||||
NavigationHelper.playOnMainPlayer(activity, fragment.getPlayQueue());
|
||||
showHoldToAppendToastIfNeeded(activity);
|
||||
});
|
||||
playlistControlBinding.playlistCtrlPlayPopupButton.setOnClickListener(view -> {
|
||||
NavigationHelper.playOnPopupPlayer(activity, fragment.getPlayQueue(), false);
|
||||
showHoldToAppendToastIfNeeded(activity);
|
||||
});
|
||||
playlistControlBinding.playlistCtrlPlayBgButton.setOnClickListener(view -> {
|
||||
NavigationHelper.playOnBackgroundPlayer(activity, fragment.getPlayQueue(), false);
|
||||
showHoldToAppendToastIfNeeded(activity);
|
||||
});
|
||||
|
||||
// long click listener
|
||||
playlistControlBinding.playlistCtrlPlayAllButton.setOnLongClickListener(view -> {
|
||||
NavigationHelper.enqueueOnPlayer(activity, fragment.getPlayQueue(), PlayerType.MAIN);
|
||||
return true;
|
||||
});
|
||||
playlistControlBinding.playlistCtrlPlayPopupButton.setOnLongClickListener(view -> {
|
||||
NavigationHelper.enqueueOnPlayer(activity, fragment.getPlayQueue(), PlayerType.POPUP);
|
||||
return true;
|
||||
});
|
||||
playlistControlBinding.playlistCtrlPlayBgButton.setOnLongClickListener(view -> {
|
||||
NavigationHelper.enqueueOnPlayer(activity, fragment.getPlayQueue(), PlayerType.AUDIO);
|
||||
return true;
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Show the "hold to append" toast if the corresponding preference is enabled.
|
||||
*
|
||||
* @param context The context to show the toast.
|
||||
*/
|
||||
private static void showHoldToAppendToastIfNeeded(@NonNull final Context context) {
|
||||
if (shouldShowHoldToAppendTip(context)) {
|
||||
Toast.makeText(context, R.string.hold_to_append, Toast.LENGTH_SHORT).show();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if the "hold to append" toast should be shown.
|
||||
*
|
||||
* <p>
|
||||
* The tip is shown if the corresponding preference is enabled.
|
||||
* This is the default behaviour.
|
||||
* </p>
|
||||
*
|
||||
* @param context The context to get the preference.
|
||||
* @return {@code true} if the tip should be shown, {@code false} otherwise.
|
||||
*/
|
||||
public static boolean shouldShowHoldToAppendTip(@NonNull final Context context) {
|
||||
return PreferenceManager.getDefaultSharedPreferences(context)
|
||||
.getBoolean(context.getString(R.string.show_hold_to_append_key), true);
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,96 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2023-2026 NewPipe contributors <https://newpipe.net>
|
||||
* SPDX-License-Identifier: GPL-3.0-or-later
|
||||
*/
|
||||
|
||||
package org.schabi.newpipe.util
|
||||
|
||||
import android.content.Context
|
||||
import android.view.View
|
||||
import android.view.View.OnLongClickListener
|
||||
import android.widget.Toast
|
||||
import androidx.appcompat.app.AppCompatActivity
|
||||
import androidx.preference.PreferenceManager
|
||||
import org.schabi.newpipe.R
|
||||
import org.schabi.newpipe.databinding.PlaylistControlBinding
|
||||
import org.schabi.newpipe.fragments.list.playlist.PlaylistControlViewHolder
|
||||
import org.schabi.newpipe.player.PlayerType
|
||||
|
||||
/**
|
||||
* Utility class for play buttons and their respective click listeners.
|
||||
*/
|
||||
object PlayButtonHelper {
|
||||
/**
|
||||
* Initialize [OnClickListener][View.OnClickListener]
|
||||
* and [OnLongClickListener][OnLongClickListener] for playlist control
|
||||
* buttons defined in [R.layout.playlist_control].
|
||||
*
|
||||
* @param activity The activity to use for the [Toast][Toast].
|
||||
* @param playlistControlBinding The binding of the
|
||||
* [playlist control layout][R.layout.playlist_control].
|
||||
* @param fragment The fragment to get the play queue from.
|
||||
*/
|
||||
@JvmStatic
|
||||
fun initPlaylistControlClickListener(
|
||||
activity: AppCompatActivity,
|
||||
playlistControlBinding: PlaylistControlBinding,
|
||||
fragment: PlaylistControlViewHolder
|
||||
) {
|
||||
// click listener
|
||||
playlistControlBinding.playlistCtrlPlayAllButton.setOnClickListener {
|
||||
NavigationHelper.playOnMainPlayer(activity, fragment.getPlayQueue())
|
||||
showHoldToAppendToastIfNeeded(activity)
|
||||
}
|
||||
playlistControlBinding.playlistCtrlPlayPopupButton.setOnClickListener {
|
||||
NavigationHelper.playOnPopupPlayer(activity, fragment.getPlayQueue(), false)
|
||||
showHoldToAppendToastIfNeeded(activity)
|
||||
}
|
||||
playlistControlBinding.playlistCtrlPlayBgButton.setOnClickListener {
|
||||
NavigationHelper.playOnBackgroundPlayer(activity, fragment.getPlayQueue(), false)
|
||||
showHoldToAppendToastIfNeeded(activity)
|
||||
}
|
||||
|
||||
// long click listener
|
||||
playlistControlBinding.playlistCtrlPlayAllButton.setOnLongClickListener {
|
||||
NavigationHelper.enqueueOnPlayer(activity, fragment.getPlayQueue(), PlayerType.MAIN)
|
||||
true
|
||||
}
|
||||
playlistControlBinding.playlistCtrlPlayPopupButton.setOnLongClickListener {
|
||||
NavigationHelper.enqueueOnPlayer(activity, fragment.getPlayQueue(), PlayerType.POPUP)
|
||||
true
|
||||
}
|
||||
playlistControlBinding.playlistCtrlPlayBgButton.setOnLongClickListener {
|
||||
NavigationHelper.enqueueOnPlayer(activity, fragment.getPlayQueue(), PlayerType.AUDIO)
|
||||
true
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Show the "hold to append" toast if the corresponding preference is enabled.
|
||||
*
|
||||
* @param context The context to show the toast.
|
||||
*/
|
||||
private fun showHoldToAppendToastIfNeeded(context: Context) {
|
||||
if (shouldShowHoldToAppendTip(context)) {
|
||||
Toast.makeText(context, R.string.hold_to_append, Toast.LENGTH_SHORT).show()
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if the "hold to append" toast should be shown.
|
||||
*
|
||||
*
|
||||
*
|
||||
* The tip is shown if the corresponding preference is enabled.
|
||||
* This is the default behaviour.
|
||||
*
|
||||
*
|
||||
* @param context The context to get the preference.
|
||||
* @return `true` if the tip should be shown, `false` otherwise.
|
||||
*/
|
||||
@JvmStatic
|
||||
fun shouldShowHoldToAppendTip(context: Context): Boolean {
|
||||
return PreferenceManager.getDefaultSharedPreferences(context)
|
||||
.getBoolean(context.getString(R.string.show_hold_to_append_key), true)
|
||||
}
|
||||
}
|
||||
@ -1,213 +0,0 @@
|
||||
package org.schabi.newpipe.util;
|
||||
|
||||
import static org.schabi.newpipe.extractor.ServiceList.SoundCloud;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.SharedPreferences;
|
||||
|
||||
import androidx.annotation.DrawableRes;
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.annotation.StringRes;
|
||||
import androidx.preference.PreferenceManager;
|
||||
|
||||
import com.grack.nanojson.JsonObject;
|
||||
import com.grack.nanojson.JsonParser;
|
||||
import com.grack.nanojson.JsonParserException;
|
||||
|
||||
import org.schabi.newpipe.R;
|
||||
import org.schabi.newpipe.extractor.NewPipe;
|
||||
import org.schabi.newpipe.extractor.ServiceList;
|
||||
import org.schabi.newpipe.extractor.StreamingService;
|
||||
import org.schabi.newpipe.extractor.exceptions.ExtractionException;
|
||||
import org.schabi.newpipe.extractor.services.peertube.PeertubeInstance;
|
||||
|
||||
import java.util.Optional;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
public final class ServiceHelper {
|
||||
private static final StreamingService DEFAULT_FALLBACK_SERVICE = ServiceList.YouTube;
|
||||
|
||||
private ServiceHelper() { }
|
||||
|
||||
@DrawableRes
|
||||
public static int getIcon(final int serviceId) {
|
||||
switch (serviceId) {
|
||||
case 0:
|
||||
return R.drawable.ic_smart_display;
|
||||
case 1:
|
||||
return R.drawable.ic_cloud;
|
||||
case 2:
|
||||
return R.drawable.ic_placeholder_media_ccc;
|
||||
case 3:
|
||||
return R.drawable.ic_placeholder_peertube;
|
||||
case 4:
|
||||
return R.drawable.ic_placeholder_bandcamp;
|
||||
default:
|
||||
return R.drawable.ic_circle;
|
||||
}
|
||||
}
|
||||
|
||||
public static String getTranslatedFilterString(final String filter, final Context c) {
|
||||
switch (filter) {
|
||||
case "all":
|
||||
return c.getString(R.string.all);
|
||||
case "videos":
|
||||
case "sepia_videos":
|
||||
case "music_videos":
|
||||
return c.getString(R.string.videos_string);
|
||||
case "channels":
|
||||
return c.getString(R.string.channels);
|
||||
case "playlists":
|
||||
case "music_playlists":
|
||||
return c.getString(R.string.playlists);
|
||||
case "tracks":
|
||||
return c.getString(R.string.tracks);
|
||||
case "users":
|
||||
return c.getString(R.string.users);
|
||||
case "conferences":
|
||||
return c.getString(R.string.conferences);
|
||||
case "events":
|
||||
return c.getString(R.string.events);
|
||||
case "music_songs":
|
||||
return c.getString(R.string.songs);
|
||||
case "music_albums":
|
||||
return c.getString(R.string.albums);
|
||||
case "music_artists":
|
||||
return c.getString(R.string.artists);
|
||||
default:
|
||||
return filter;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a resource string with instructions for importing subscriptions for each service.
|
||||
*
|
||||
* @param serviceId service to get the instructions for
|
||||
* @return the string resource containing the instructions or -1 if the service don't support it
|
||||
*/
|
||||
@StringRes
|
||||
public static int getImportInstructions(final int serviceId) {
|
||||
switch (serviceId) {
|
||||
case 0:
|
||||
return R.string.import_youtube_instructions;
|
||||
case 1:
|
||||
return R.string.import_soundcloud_instructions;
|
||||
default:
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* For services that support importing from a channel url, return a hint that will
|
||||
* be used in the EditText that the user will type in his channel url.
|
||||
*
|
||||
* @param serviceId service to get the hint for
|
||||
* @return the hint's string resource or -1 if the service don't support it
|
||||
*/
|
||||
@StringRes
|
||||
public static int getImportInstructionsHint(final int serviceId) {
|
||||
switch (serviceId) {
|
||||
case 1:
|
||||
return R.string.import_soundcloud_instructions_hint;
|
||||
default:
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
public static int getSelectedServiceId(final Context context) {
|
||||
return Optional.ofNullable(getSelectedService(context))
|
||||
.orElse(DEFAULT_FALLBACK_SERVICE)
|
||||
.getServiceId();
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public static StreamingService getSelectedService(final Context context) {
|
||||
final String serviceName = PreferenceManager.getDefaultSharedPreferences(context)
|
||||
.getString(context.getString(R.string.current_service_key),
|
||||
context.getString(R.string.default_service_value));
|
||||
|
||||
try {
|
||||
return NewPipe.getService(serviceName);
|
||||
} catch (final ExtractionException e) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
@NonNull
|
||||
public static String getNameOfServiceById(final int serviceId) {
|
||||
return ServiceList.all().stream()
|
||||
.filter(s -> s.getServiceId() == serviceId)
|
||||
.findFirst()
|
||||
.map(StreamingService::getServiceInfo)
|
||||
.map(StreamingService.ServiceInfo::getName)
|
||||
.orElse("<unknown>");
|
||||
}
|
||||
|
||||
/**
|
||||
* @param serviceId the id of the service
|
||||
* @return the service corresponding to the provided id
|
||||
* @throws java.util.NoSuchElementException if there is no service with the provided id
|
||||
*/
|
||||
@NonNull
|
||||
public static StreamingService getServiceById(final int serviceId) {
|
||||
return ServiceList.all().stream()
|
||||
.filter(s -> s.getServiceId() == serviceId)
|
||||
.findFirst()
|
||||
.orElseThrow();
|
||||
}
|
||||
|
||||
public static void setSelectedServiceId(final Context context, final int serviceId) {
|
||||
String serviceName;
|
||||
try {
|
||||
serviceName = NewPipe.getService(serviceId).getServiceInfo().getName();
|
||||
} catch (final ExtractionException e) {
|
||||
serviceName = DEFAULT_FALLBACK_SERVICE.getServiceInfo().getName();
|
||||
}
|
||||
|
||||
setSelectedServicePreferences(context, serviceName);
|
||||
}
|
||||
|
||||
private static void setSelectedServicePreferences(final Context context,
|
||||
final String serviceName) {
|
||||
PreferenceManager.getDefaultSharedPreferences(context).edit().
|
||||
putString(context.getString(R.string.current_service_key), serviceName).apply();
|
||||
}
|
||||
|
||||
public static long getCacheExpirationMillis(final int serviceId) {
|
||||
if (serviceId == SoundCloud.getServiceId()) {
|
||||
return TimeUnit.MILLISECONDS.convert(5, TimeUnit.MINUTES);
|
||||
} else {
|
||||
return TimeUnit.MILLISECONDS.convert(1, TimeUnit.HOURS);
|
||||
}
|
||||
}
|
||||
|
||||
public static void initService(final Context context, final int serviceId) {
|
||||
if (serviceId == ServiceList.PeerTube.getServiceId()) {
|
||||
final SharedPreferences sharedPreferences = PreferenceManager
|
||||
.getDefaultSharedPreferences(context);
|
||||
final String json = sharedPreferences.getString(context.getString(
|
||||
R.string.peertube_selected_instance_key), null);
|
||||
if (null == json) {
|
||||
return;
|
||||
}
|
||||
|
||||
final JsonObject jsonObject;
|
||||
try {
|
||||
jsonObject = JsonParser.object().from(json);
|
||||
} catch (final JsonParserException e) {
|
||||
return;
|
||||
}
|
||||
final String name = jsonObject.getString("name");
|
||||
final String url = jsonObject.getString("url");
|
||||
final PeertubeInstance instance = new PeertubeInstance(url, name);
|
||||
ServiceList.PeerTube.setInstance(instance);
|
||||
}
|
||||
}
|
||||
|
||||
public static void initServices(final Context context) {
|
||||
for (final StreamingService s : ServiceList.all()) {
|
||||
initService(context, s.getServiceId());
|
||||
}
|
||||
}
|
||||
}
|
||||
168
app/src/main/java/org/schabi/newpipe/util/ServiceHelper.kt
Normal file
168
app/src/main/java/org/schabi/newpipe/util/ServiceHelper.kt
Normal file
@ -0,0 +1,168 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2018-2026 NewPipe contributors <https://newpipe.net>
|
||||
* SPDX-License-Identifier: GPL-3.0-or-later
|
||||
*/
|
||||
|
||||
package org.schabi.newpipe.util
|
||||
|
||||
import android.content.Context
|
||||
import androidx.annotation.DrawableRes
|
||||
import androidx.annotation.StringRes
|
||||
import androidx.core.content.edit
|
||||
import androidx.preference.PreferenceManager
|
||||
import com.grack.nanojson.JsonParser
|
||||
import java.util.concurrent.TimeUnit
|
||||
import org.schabi.newpipe.R
|
||||
import org.schabi.newpipe.extractor.NewPipe
|
||||
import org.schabi.newpipe.extractor.ServiceList
|
||||
import org.schabi.newpipe.extractor.StreamingService
|
||||
import org.schabi.newpipe.extractor.services.peertube.PeertubeInstance
|
||||
import org.schabi.newpipe.ktx.getStringSafe
|
||||
|
||||
object ServiceHelper {
|
||||
private val DEFAULT_FALLBACK_SERVICE: StreamingService = ServiceList.YouTube
|
||||
|
||||
@JvmStatic
|
||||
@DrawableRes
|
||||
fun getIcon(serviceId: Int): Int {
|
||||
return when (serviceId) {
|
||||
0 -> R.drawable.ic_smart_display
|
||||
1 -> R.drawable.ic_cloud
|
||||
2 -> R.drawable.ic_placeholder_media_ccc
|
||||
3 -> R.drawable.ic_placeholder_peertube
|
||||
4 -> R.drawable.ic_placeholder_bandcamp
|
||||
else -> R.drawable.ic_circle
|
||||
}
|
||||
}
|
||||
|
||||
@JvmStatic
|
||||
fun getTranslatedFilterString(filter: String, context: Context): String {
|
||||
return when (filter) {
|
||||
"all" -> context.getString(R.string.all)
|
||||
"videos", "sepia_videos", "music_videos" -> context.getString(R.string.videos_string)
|
||||
"channels" -> context.getString(R.string.channels)
|
||||
"playlists", "music_playlists" -> context.getString(R.string.playlists)
|
||||
"tracks" -> context.getString(R.string.tracks)
|
||||
"users" -> context.getString(R.string.users)
|
||||
"conferences" -> context.getString(R.string.conferences)
|
||||
"events" -> context.getString(R.string.events)
|
||||
"music_songs" -> context.getString(R.string.songs)
|
||||
"music_albums" -> context.getString(R.string.albums)
|
||||
"music_artists" -> context.getString(R.string.artists)
|
||||
else -> filter
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a resource string with instructions for importing subscriptions for each service.
|
||||
*
|
||||
* @param serviceId service to get the instructions for
|
||||
* @return the string resource containing the instructions or -1 if the service don't support it
|
||||
*/
|
||||
@JvmStatic
|
||||
@StringRes
|
||||
fun getImportInstructions(serviceId: Int): Int {
|
||||
return when (serviceId) {
|
||||
0 -> R.string.import_youtube_instructions
|
||||
1 -> R.string.import_soundcloud_instructions
|
||||
else -> -1
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* For services that support importing from a channel url, return a hint that will
|
||||
* be used in the EditText that the user will type in his channel url.
|
||||
*
|
||||
* @param serviceId service to get the hint for
|
||||
* @return the hint's string resource or -1 if the service don't support it
|
||||
*/
|
||||
@JvmStatic
|
||||
@StringRes
|
||||
fun getImportInstructionsHint(serviceId: Int): Int {
|
||||
return when (serviceId) {
|
||||
1 -> R.string.import_soundcloud_instructions_hint
|
||||
else -> -1
|
||||
}
|
||||
}
|
||||
|
||||
@JvmStatic
|
||||
fun getSelectedServiceId(context: Context): Int {
|
||||
return (getSelectedService(context) ?: DEFAULT_FALLBACK_SERVICE).serviceId
|
||||
}
|
||||
|
||||
@JvmStatic
|
||||
fun getSelectedService(context: Context): StreamingService? {
|
||||
val serviceName: String = PreferenceManager.getDefaultSharedPreferences(context)
|
||||
.getStringSafe(
|
||||
context.getString(R.string.current_service_key),
|
||||
context.getString(R.string.default_service_value)
|
||||
)
|
||||
|
||||
return runCatching { NewPipe.getService(serviceName) }.getOrNull()
|
||||
}
|
||||
|
||||
@JvmStatic
|
||||
fun getNameOfServiceById(serviceId: Int): String {
|
||||
return ServiceList.all().stream()
|
||||
.filter { it.serviceId == serviceId }
|
||||
.findFirst()
|
||||
.map(StreamingService::getServiceInfo)
|
||||
.map(StreamingService.ServiceInfo::getName)
|
||||
.orElse("<unknown>")
|
||||
}
|
||||
|
||||
/**
|
||||
* @param serviceId the id of the service
|
||||
* @return the service corresponding to the provided id
|
||||
* @throws java.util.NoSuchElementException if there is no service with the provided id
|
||||
*/
|
||||
@JvmStatic
|
||||
fun getServiceById(serviceId: Int): StreamingService {
|
||||
return ServiceList.all().firstNotNullOf { it.takeIf { it.serviceId == serviceId } }
|
||||
}
|
||||
|
||||
@JvmStatic
|
||||
fun setSelectedServiceId(context: Context, serviceId: Int) {
|
||||
val serviceName = runCatching { NewPipe.getService(serviceId).serviceInfo.name }
|
||||
.getOrDefault(DEFAULT_FALLBACK_SERVICE.serviceInfo.name)
|
||||
|
||||
setSelectedServicePreferences(context, serviceName)
|
||||
}
|
||||
|
||||
private fun setSelectedServicePreferences(context: Context, serviceName: String?) {
|
||||
val sharedPreferences = PreferenceManager.getDefaultSharedPreferences(context)
|
||||
sharedPreferences.edit { putString(context.getString(R.string.current_service_key), serviceName) }
|
||||
}
|
||||
|
||||
@JvmStatic
|
||||
fun getCacheExpirationMillis(serviceId: Int): Long {
|
||||
return if (serviceId == ServiceList.SoundCloud.serviceId) {
|
||||
TimeUnit.MILLISECONDS.convert(5, TimeUnit.MINUTES)
|
||||
} else {
|
||||
TimeUnit.MILLISECONDS.convert(1, TimeUnit.HOURS)
|
||||
}
|
||||
}
|
||||
|
||||
fun initService(context: Context, serviceId: Int) {
|
||||
if (serviceId == ServiceList.PeerTube.serviceId) {
|
||||
val sharedPreferences = PreferenceManager.getDefaultSharedPreferences(context)
|
||||
val json = sharedPreferences.getString(
|
||||
context.getString(R.string.peertube_selected_instance_key),
|
||||
null
|
||||
) ?: return
|
||||
|
||||
val jsonObject = runCatching { JsonParser.`object`().from(json) }
|
||||
.getOrElse { return@initService }
|
||||
|
||||
ServiceList.PeerTube.instance = PeertubeInstance(
|
||||
jsonObject.getString("url"),
|
||||
jsonObject.getString("name")
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@JvmStatic
|
||||
fun initServices(context: Context) {
|
||||
ServiceList.all().forEach { initService(context, it.serviceId) }
|
||||
}
|
||||
}
|
||||
@ -1,50 +0,0 @@
|
||||
package org.schabi.newpipe.util;
|
||||
|
||||
import org.schabi.newpipe.extractor.stream.StreamType;
|
||||
|
||||
/**
|
||||
* Utility class for {@link StreamType}.
|
||||
*/
|
||||
public final class StreamTypeUtil {
|
||||
private StreamTypeUtil() {
|
||||
// No impl pls
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if the {@link StreamType} of a stream is a livestream.
|
||||
*
|
||||
* @param streamType the stream type of the stream
|
||||
* @return whether the stream type is {@link StreamType#AUDIO_STREAM},
|
||||
* {@link StreamType#AUDIO_LIVE_STREAM} or {@link StreamType#POST_LIVE_AUDIO_STREAM}
|
||||
*/
|
||||
public static boolean isAudio(final StreamType streamType) {
|
||||
return streamType == StreamType.AUDIO_STREAM
|
||||
|| streamType == StreamType.AUDIO_LIVE_STREAM
|
||||
|| streamType == StreamType.POST_LIVE_AUDIO_STREAM;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if the {@link StreamType} of a stream is a livestream.
|
||||
*
|
||||
* @param streamType the stream type of the stream
|
||||
* @return whether the stream type is {@link StreamType#VIDEO_STREAM},
|
||||
* {@link StreamType#LIVE_STREAM} or {@link StreamType#POST_LIVE_STREAM}
|
||||
*/
|
||||
public static boolean isVideo(final StreamType streamType) {
|
||||
return streamType == StreamType.VIDEO_STREAM
|
||||
|| streamType == StreamType.LIVE_STREAM
|
||||
|| streamType == StreamType.POST_LIVE_STREAM;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if the {@link StreamType} of a stream is a livestream.
|
||||
*
|
||||
* @param streamType the stream type of the stream
|
||||
* @return whether the stream type is {@link StreamType#LIVE_STREAM} or
|
||||
* {@link StreamType#AUDIO_LIVE_STREAM}
|
||||
*/
|
||||
public static boolean isLiveStream(final StreamType streamType) {
|
||||
return streamType == StreamType.LIVE_STREAM
|
||||
|| streamType == StreamType.AUDIO_LIVE_STREAM;
|
||||
}
|
||||
}
|
||||
54
app/src/main/java/org/schabi/newpipe/util/StreamTypeUtil.kt
Normal file
54
app/src/main/java/org/schabi/newpipe/util/StreamTypeUtil.kt
Normal file
@ -0,0 +1,54 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2021-2026 NewPipe contributors <https://newpipe.net>
|
||||
* SPDX-License-Identifier: GPL-3.0-or-later
|
||||
*/
|
||||
|
||||
package org.schabi.newpipe.util
|
||||
|
||||
import org.schabi.newpipe.extractor.stream.StreamType
|
||||
|
||||
/**
|
||||
* Utility class for [StreamType].
|
||||
*/
|
||||
object StreamTypeUtil {
|
||||
/**
|
||||
* Check if the [StreamType] of a stream is a livestream.
|
||||
*
|
||||
* @param streamType the stream type of the stream
|
||||
* @return whether the stream type is [StreamType.AUDIO_STREAM],
|
||||
* [StreamType.AUDIO_LIVE_STREAM] or [StreamType.POST_LIVE_AUDIO_STREAM]
|
||||
*/
|
||||
@JvmStatic
|
||||
fun isAudio(streamType: StreamType): Boolean {
|
||||
return streamType == StreamType.AUDIO_STREAM ||
|
||||
streamType == StreamType.AUDIO_LIVE_STREAM ||
|
||||
streamType == StreamType.POST_LIVE_AUDIO_STREAM
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if the [StreamType] of a stream is a livestream.
|
||||
*
|
||||
* @param streamType the stream type of the stream
|
||||
* @return whether the stream type is [StreamType.VIDEO_STREAM],
|
||||
* [StreamType.LIVE_STREAM] or [StreamType.POST_LIVE_STREAM]
|
||||
*/
|
||||
@JvmStatic
|
||||
fun isVideo(streamType: StreamType): Boolean {
|
||||
return streamType == StreamType.VIDEO_STREAM ||
|
||||
streamType == StreamType.LIVE_STREAM ||
|
||||
streamType == StreamType.POST_LIVE_STREAM
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if the [StreamType] of a stream is a livestream.
|
||||
*
|
||||
* @param streamType the stream type of the stream
|
||||
* @return whether the stream type is [StreamType.LIVE_STREAM] or
|
||||
* [StreamType.AUDIO_LIVE_STREAM]
|
||||
*/
|
||||
@JvmStatic
|
||||
fun isLiveStream(streamType: StreamType): Boolean {
|
||||
return streamType == StreamType.LIVE_STREAM ||
|
||||
streamType == StreamType.AUDIO_LIVE_STREAM
|
||||
}
|
||||
}
|
||||
Loading…
x
Reference in New Issue
Block a user