Merge branch 'dev' into feature/notifications

This commit is contained in:
TobiGr 2022-02-19 12:34:44 +01:00
commit c75babedb8
248 changed files with 5894 additions and 1665 deletions

View file

@ -0,0 +1,43 @@
package org.schabi.newpipe.util;
import android.app.Activity;
import android.view.inputmethod.InputMethodManager;
import android.widget.EditText;
import androidx.core.content.ContextCompat;
/**
* Utility class for the Android keyboard.
* <p>
* See also <a href="https://stackoverflow.com/q/1109022">https://stackoverflow.com/q/1109022</a>
* </p>
*/
public final class KeyboardUtil {
private KeyboardUtil() {
}
public static void showKeyboard(final Activity activity, final EditText editText) {
if (activity == null || editText == null) {
return;
}
if (editText.requestFocus()) {
final InputMethodManager imm = ContextCompat.getSystemService(activity,
InputMethodManager.class);
imm.showSoftInput(editText, InputMethodManager.SHOW_FORCED);
}
}
public static void hideKeyboard(final Activity activity, final EditText editText) {
if (activity == null || editText == null) {
return;
}
final InputMethodManager imm = ContextCompat.getSystemService(activity,
InputMethodManager.class);
imm.hideSoftInputFromWindow(editText.getWindowToken(),
InputMethodManager.RESULT_UNCHANGED_SHOWN);
editText.clearFocus();
}
}

View file

@ -0,0 +1,94 @@
package org.schabi.newpipe.util;
import static org.schabi.newpipe.extractor.utils.Utils.isNullOrEmpty;
import android.content.Context;
import android.widget.Toast;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.fragment.app.Fragment;
import org.schabi.newpipe.NewPipeDatabase;
import org.schabi.newpipe.R;
import org.schabi.newpipe.error.ErrorInfo;
import org.schabi.newpipe.error.ErrorUtil;
import org.schabi.newpipe.error.UserAction;
import org.schabi.newpipe.extractor.stream.StreamInfoItem;
import org.schabi.newpipe.player.playqueue.PlayQueueItem;
import io.reactivex.rxjava3.android.schedulers.AndroidSchedulers;
import io.reactivex.rxjava3.schedulers.Schedulers;
/**
* Utility class for putting the uploader url into the database - when required.
*/
public final class SaveUploaderUrlHelper {
private SaveUploaderUrlHelper() {
}
// Public functions which call the function that does
// the actual work with the correct parameters
public static void saveUploaderUrlIfNeeded(@NonNull final Fragment fragment,
@NonNull final StreamInfoItem infoItem,
@NonNull final SaveUploaderUrlCallback callback) {
saveUploaderUrlIfNeeded(fragment.requireContext(),
infoItem.getServiceId(),
infoItem.getUrl(),
infoItem.getUploaderUrl(),
callback);
}
public static void saveUploaderUrlIfNeeded(@NonNull final Context context,
@NonNull final PlayQueueItem queueItem,
@NonNull final SaveUploaderUrlCallback callback) {
saveUploaderUrlIfNeeded(context,
queueItem.getServiceId(),
queueItem.getUrl(),
queueItem.getUploaderUrl(),
callback);
}
/**
* Fetches and saves the uploaderUrl if it is empty (meaning that it does
* not exist in the video item). The callback is called with either the
* fetched uploaderUrl, or the already saved uploaderUrl, but it is always
* called with a valid uploaderUrl that can be used to show channel details.
*
* @param context Context
* @param serviceId The serviceId of the item
* @param url The item url
* @param uploaderUrl The uploaderUrl of the item, if null or empty, it
* will be fetched using the item url.
* @param callback The callback that returns the fetched or existing
* uploaderUrl
*/
private static void saveUploaderUrlIfNeeded(@NonNull final Context context,
final int serviceId,
@NonNull final String url,
// Only used if not null or empty
@Nullable final String uploaderUrl,
@NonNull final SaveUploaderUrlCallback callback) {
if (isNullOrEmpty(uploaderUrl)) {
Toast.makeText(context, R.string.loading_channel_details,
Toast.LENGTH_SHORT).show();
ExtractorHelper.getStreamInfo(serviceId, url, false)
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(result -> {
NewPipeDatabase.getInstance(context).streamDAO()
.setUploaderUrl(serviceId, url, result.getUploaderUrl())
.subscribeOn(Schedulers.io()).subscribe();
callback.onCallback(result.getUploaderUrl());
}, throwable -> ErrorUtil.createNotification(context,
new ErrorInfo(throwable, UserAction.REQUESTED_CHANNEL,
"Could not load channel details")
));
} else {
callback.onCallback(uploaderUrl);
}
}
public interface SaveUploaderUrlCallback {
void onCallback(@NonNull String uploaderUrl);
}
}

View file

@ -3,12 +3,10 @@ package org.schabi.newpipe.util;
import android.content.Context;
import android.net.Uri;
import android.util.Log;
import android.widget.Toast;
import androidx.fragment.app.Fragment;
import androidx.preference.PreferenceManager;
import org.schabi.newpipe.NewPipeDatabase;
import org.schabi.newpipe.R;
import org.schabi.newpipe.database.stream.model.StreamEntity;
import org.schabi.newpipe.extractor.stream.StreamInfoItem;
@ -27,36 +25,14 @@ import java.util.function.Consumer;
import io.reactivex.rxjava3.android.schedulers.AndroidSchedulers;
import io.reactivex.rxjava3.schedulers.Schedulers;
import static org.schabi.newpipe.extractor.utils.Utils.isNullOrEmpty;
public enum StreamDialogEntry {
//////////////////////////////////////
// enum values with DEFAULT actions //
//////////////////////////////////////
show_channel_details(R.string.show_channel_details, (fragment, item) -> {
if (isNullOrEmpty(item.getUploaderUrl())) {
final int serviceId = item.getServiceId();
final String url = item.getUrl();
Toast.makeText(fragment.getContext(), R.string.loading_channel_details,
Toast.LENGTH_SHORT).show();
ExtractorHelper.getStreamInfo(serviceId, url, false)
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(result -> {
NewPipeDatabase.getInstance(fragment.requireContext()).streamDAO()
.setUploaderUrl(serviceId, url, result.getUploaderUrl())
.subscribeOn(Schedulers.io()).subscribe();
openChannelFragment(fragment, item, result.getUploaderUrl());
}, throwable -> Toast.makeText(
// TODO: Open the Error Activity
fragment.getContext(),
R.string.error_show_channel_details,
Toast.LENGTH_SHORT
).show());
} else {
openChannelFragment(fragment, item, item.getUploaderUrl());
}
SaveUploaderUrlHelper.saveUploaderUrlIfNeeded(fragment, item,
uploaderUrl -> openChannelFragment(fragment, item, uploaderUrl));
}),
/**