Merge remote-tracking branch 'origin/dev' into dev

This commit is contained in:
Weblate 2018-04-07 13:37:23 +02:00
commit 8ae1768f71
6 changed files with 79 additions and 80 deletions

View File

@ -54,7 +54,7 @@ dependencies {
exclude module: 'support-annotations' exclude module: 'support-annotations'
} }
implementation 'com.github.TeamNewPipe:NewPipeExtractor:a6b6235644474' implementation 'com.github.TeamNewPipe:NewPipeExtractor:77a74b8'
testImplementation 'junit:junit:4.12' testImplementation 'junit:junit:4.12'

View File

@ -1,6 +1,7 @@
package org.schabi.newpipe; package org.schabi.newpipe;
import android.app.IntentService; import android.app.IntentService;
import android.content.Context;
import android.content.DialogInterface; import android.content.DialogInterface;
import android.content.Intent; import android.content.Intent;
import android.content.SharedPreferences; import android.content.SharedPreferences;
@ -24,7 +25,6 @@ import android.widget.Toast;
import org.schabi.newpipe.extractor.Info; import org.schabi.newpipe.extractor.Info;
import org.schabi.newpipe.extractor.NewPipe; import org.schabi.newpipe.extractor.NewPipe;
import org.schabi.newpipe.extractor.ServiceList;
import org.schabi.newpipe.extractor.StreamingService; import org.schabi.newpipe.extractor.StreamingService;
import org.schabi.newpipe.extractor.StreamingService.LinkType; import org.schabi.newpipe.extractor.StreamingService.LinkType;
import org.schabi.newpipe.extractor.channel.ChannelInfo; import org.schabi.newpipe.extractor.channel.ChannelInfo;
@ -43,9 +43,11 @@ import org.schabi.newpipe.util.PermissionHelper;
import org.schabi.newpipe.util.ThemeHelper; import org.schabi.newpipe.util.ThemeHelper;
import java.io.Serializable; import java.io.Serializable;
import java.util.ArrayList;
import java.util.Arrays; import java.util.Arrays;
import java.util.Collection; import java.util.Collection;
import java.util.HashSet; import java.util.HashSet;
import java.util.List;
import icepick.Icepick; import icepick.Icepick;
import icepick.State; import icepick.State;
@ -57,6 +59,7 @@ import io.reactivex.disposables.Disposable;
import io.reactivex.functions.Consumer; import io.reactivex.functions.Consumer;
import io.reactivex.schedulers.Schedulers; import io.reactivex.schedulers.Schedulers;
import static org.schabi.newpipe.extractor.StreamingService.ServiceInfo.MediaCapability.*;
import static org.schabi.newpipe.util.ThemeHelper.resolveResourceIdFromAttr; import static org.schabi.newpipe.util.ThemeHelper.resolveResourceIdFromAttr;
/** /**
@ -122,7 +125,7 @@ public class RouterActivity extends AppCompatActivity {
currentService = NewPipe.getServiceByUrl(url); currentService = NewPipe.getServiceByUrl(url);
currentServiceId = currentService.getServiceId(); currentServiceId = currentService.getServiceId();
currentLinkType = currentService.getLinkTypeByUrl(url); currentLinkType = currentService.getLinkTypeByUrl(url);
currentUrl = NavigationHelper.getCleanUrl(currentService, url, currentLinkType); currentUrl = url;
} else { } else {
currentService = NewPipe.getService(currentServiceId); currentService = NewPipe.getService(currentServiceId);
} }
@ -168,18 +171,23 @@ public class RouterActivity extends AppCompatActivity {
return; return;
} }
// TODO: Add some sort of "capabilities" field to services (audio only, video and audio, etc.) final String playerChoiceKey = preferences.getString(getString(R.string.preferred_open_action_key), getString(R.string.preferred_open_action_default));
if (currentService == ServiceList.SoundCloud) {
handleChoice(getString(R.string.background_player_key));
return;
}
final String playerChoiceKey = preferences.getString( final String videoPlayerKey = getString(R.string.video_player_key);
getString(R.string.preferred_open_action_key), final String backgroundPlayerKey = getString(R.string.background_player_key);
getString(R.string.preferred_open_action_default)); final String popupPlayerKey = getString(R.string.popup_player_key);
final String alwaysAskKey = getString(R.string.always_ask_open_action_key); final String alwaysAskKey = getString(R.string.always_ask_open_action_key);
if (playerChoiceKey.equals(alwaysAskKey)) { final List<StreamingService.ServiceInfo.MediaCapability> capabilities = currentService.getServiceInfo().getMediaCapabilities();
boolean serviceSupportsPlayer = false;
if (playerChoiceKey.equals(videoPlayerKey) || playerChoiceKey.equals(popupPlayerKey)) {
serviceSupportsPlayer = capabilities.contains(VIDEO);
} else if (playerChoiceKey.equals(backgroundPlayerKey)) {
serviceSupportsPlayer = capabilities.contains(AUDIO);
}
if (playerChoiceKey.equals(alwaysAskKey) || !serviceSupportsPlayer) {
showDialog(); showDialog();
} else { } else {
handleChoice(playerChoiceKey); handleChoice(playerChoiceKey);
@ -187,29 +195,20 @@ public class RouterActivity extends AppCompatActivity {
} }
private void showDialog() { private void showDialog() {
SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(this); final SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(this);
final ContextThemeWrapper themeWrapper = new ContextThemeWrapper(this, final ContextThemeWrapper themeWrapperContext = new ContextThemeWrapper(this,
ThemeHelper.isLightThemeSelected(this) ? R.style.LightTheme : R.style.DarkTheme); ThemeHelper.isLightThemeSelected(this) ? R.style.LightTheme : R.style.DarkTheme);
LayoutInflater inflater = LayoutInflater.from(themeWrapper); final LayoutInflater inflater = LayoutInflater.from(themeWrapperContext);
final LinearLayout rootLayout = (LinearLayout) inflater.inflate(R.layout.preferred_player_dialog_view, null, false); final LinearLayout rootLayout = (LinearLayout) inflater.inflate(R.layout.preferred_player_dialog_view, null, false);
final RadioGroup radioGroup = rootLayout.findViewById(android.R.id.list); final RadioGroup radioGroup = rootLayout.findViewById(android.R.id.list);
final AdapterChoiceItem[] choices = { final List<AdapterChoiceItem> choices = getChoicesForService(themeWrapperContext, currentService);
new AdapterChoiceItem(getString(R.string.show_info_key), getString(R.string.show_info),
resolveResourceIdFromAttr(themeWrapper, R.attr.info)),
new AdapterChoiceItem(getString(R.string.video_player_key), getString(R.string.video_player),
resolveResourceIdFromAttr(themeWrapper, R.attr.play)),
new AdapterChoiceItem(getString(R.string.background_player_key), getString(R.string.background_player),
resolveResourceIdFromAttr(themeWrapper, R.attr.audio)),
new AdapterChoiceItem(getString(R.string.popup_player_key), getString(R.string.popup_player),
resolveResourceIdFromAttr(themeWrapper, R.attr.popup))
};
final DialogInterface.OnClickListener dialogButtonsClickListener = (dialog, which) -> { final DialogInterface.OnClickListener dialogButtonsClickListener = (dialog, which) -> {
final int indexOfChild = radioGroup.indexOfChild( final int indexOfChild = radioGroup.indexOfChild(
radioGroup.findViewById(radioGroup.getCheckedRadioButtonId())); radioGroup.findViewById(radioGroup.getCheckedRadioButtonId()));
final AdapterChoiceItem choice = choices[indexOfChild]; final AdapterChoiceItem choice = choices.get(indexOfChild);
handleChoice(choice.key); handleChoice(choice.key);
@ -218,7 +217,7 @@ public class RouterActivity extends AppCompatActivity {
} }
}; };
final AlertDialog alertDialog = new AlertDialog.Builder(themeWrapper) final AlertDialog alertDialog = new AlertDialog.Builder(themeWrapperContext)
.setTitle(R.string.preferred_player_share_menu_title) .setTitle(R.string.preferred_player_share_menu_title)
.setView(radioGroup) .setView(radioGroup)
.setCancelable(true) .setCancelable(true)
@ -227,6 +226,7 @@ public class RouterActivity extends AppCompatActivity {
.setOnDismissListener((dialog) -> finish()) .setOnDismissListener((dialog) -> finish())
.create(); .create();
//noinspection CodeBlock2Expr
alertDialog.setOnShowListener(dialog -> { alertDialog.setOnShowListener(dialog -> {
setDialogButtonsState(alertDialog, radioGroup.getCheckedRadioButtonId() != -1); setDialogButtonsState(alertDialog, radioGroup.getCheckedRadioButtonId() != -1);
}); });
@ -240,7 +240,7 @@ public class RouterActivity extends AppCompatActivity {
selectedRadioPosition = indexOfChild; selectedRadioPosition = indexOfChild;
if (selectedPreviously == selectedRadioPosition) { if (selectedPreviously == selectedRadioPosition) {
handleChoice(choices[selectedRadioPosition].key); handleChoice(choices.get(selectedRadioPosition).key);
} }
}; };
@ -259,8 +259,8 @@ public class RouterActivity extends AppCompatActivity {
if (selectedRadioPosition == -1) { if (selectedRadioPosition == -1) {
final String lastSelectedPlayer = preferences.getString(getString(R.string.preferred_open_action_last_selected_key), null); final String lastSelectedPlayer = preferences.getString(getString(R.string.preferred_open_action_last_selected_key), null);
if (!TextUtils.isEmpty(lastSelectedPlayer)) { if (!TextUtils.isEmpty(lastSelectedPlayer)) {
for (int i = 0; i < choices.length; i++) { for (int i = 0; i < choices.size(); i++) {
AdapterChoiceItem c = choices[i]; AdapterChoiceItem c = choices.get(i);
if (lastSelectedPlayer.equals(c.key)) { if (lastSelectedPlayer.equals(c.key)) {
selectedRadioPosition = i; selectedRadioPosition = i;
break; break;
@ -269,7 +269,7 @@ public class RouterActivity extends AppCompatActivity {
} }
} }
selectedRadioPosition = Math.min(Math.max(-1, selectedRadioPosition), choices.length - 1); selectedRadioPosition = Math.min(Math.max(-1, selectedRadioPosition), choices.size() - 1);
if (selectedRadioPosition != -1) { if (selectedRadioPosition != -1) {
((RadioButton) radioGroup.getChildAt(selectedRadioPosition)).setChecked(true); ((RadioButton) radioGroup.getChildAt(selectedRadioPosition)).setChecked(true);
} }
@ -278,6 +278,28 @@ public class RouterActivity extends AppCompatActivity {
alertDialog.show(); alertDialog.show();
} }
private List<AdapterChoiceItem> getChoicesForService(Context context, StreamingService service) {
final List<AdapterChoiceItem> returnList = new ArrayList<>();
final List<StreamingService.ServiceInfo.MediaCapability> capabilities = service.getServiceInfo().getMediaCapabilities();
returnList.add(new AdapterChoiceItem(getString(R.string.show_info_key), getString(R.string.show_info),
resolveResourceIdFromAttr(context, R.attr.info)));
if (capabilities.contains(VIDEO)) {
returnList.add(new AdapterChoiceItem(getString(R.string.video_player_key), getString(R.string.video_player),
resolveResourceIdFromAttr(context, R.attr.play)));
returnList.add(new AdapterChoiceItem(getString(R.string.popup_player_key), getString(R.string.popup_player),
resolveResourceIdFromAttr(context, R.attr.popup)));
}
if (capabilities.contains(AUDIO)) {
returnList.add(new AdapterChoiceItem(getString(R.string.background_player_key), getString(R.string.background_player),
resolveResourceIdFromAttr(context, R.attr.audio)));
}
return returnList;
}
private void setDialogButtonsState(AlertDialog dialog, boolean state) { private void setDialogButtonsState(AlertDialog dialog, boolean state) {
final Button negativeButton = dialog.getButton(DialogInterface.BUTTON_NEGATIVE); final Button negativeButton = dialog.getButton(DialogInterface.BUTTON_NEGATIVE);
final Button positiveButton = dialog.getButton(DialogInterface.BUTTON_POSITIVE); final Button positiveButton = dialog.getButton(DialogInterface.BUTTON_POSITIVE);
@ -288,16 +310,14 @@ public class RouterActivity extends AppCompatActivity {
} }
private void handleChoice(final String playerChoiceKey) { private void handleChoice(final String playerChoiceKey) {
if (Arrays.asList(getResources() final List<String> validChoicesList = Arrays.asList(getResources().getStringArray(R.array.preferred_open_action_values_list));
.getStringArray(R.array.preferred_open_action_values_list)) if (validChoicesList.contains(playerChoiceKey)) {
.contains(playerChoiceKey)) {
PreferenceManager.getDefaultSharedPreferences(this).edit() PreferenceManager.getDefaultSharedPreferences(this).edit()
.putString(getString(R.string.preferred_open_action_last_selected_key), .putString(getString(R.string.preferred_open_action_last_selected_key), playerChoiceKey)
playerChoiceKey).apply(); .apply();
} }
if (playerChoiceKey.equals(getString(R.string.popup_player_key)) if (playerChoiceKey.equals(getString(R.string.popup_player_key)) && !PermissionHelper.isPopupEnabled(this)) {
&& !PermissionHelper.isPopupEnabled(this)) {
PermissionHelper.showPopupEnablementToast(this); PermissionHelper.showPopupEnablementToast(this);
finish(); finish();
return; return;
@ -322,11 +342,8 @@ public class RouterActivity extends AppCompatActivity {
} }
final Intent intent = new Intent(this, FetcherService.class); final Intent intent = new Intent(this, FetcherService.class);
intent.putExtra(FetcherService.KEY_CHOICE, final Choice choice = new Choice(currentService.getServiceId(), currentLinkType, currentUrl, playerChoiceKey);
new Choice(currentService.getServiceId(), intent.putExtra(FetcherService.KEY_CHOICE, choice);
currentLinkType,
currentUrl,
playerChoiceKey));
startService(intent); startService(intent);
finish(); finish();
@ -334,8 +351,7 @@ public class RouterActivity extends AppCompatActivity {
private static class AdapterChoiceItem { private static class AdapterChoiceItem {
final String description, key; final String description, key;
@DrawableRes @DrawableRes final int icon;
final int icon;
AdapterChoiceItem(String key, String description, int icon) { AdapterChoiceItem(String key, String description, int icon) {
this.description = description; this.description = description;

View File

@ -70,7 +70,6 @@ import org.schabi.newpipe.player.helper.PlayerHelper;
import org.schabi.newpipe.player.old.PlayVideoActivity; import org.schabi.newpipe.player.old.PlayVideoActivity;
import org.schabi.newpipe.playlist.PlayQueue; import org.schabi.newpipe.playlist.PlayQueue;
import org.schabi.newpipe.playlist.SinglePlayQueue; import org.schabi.newpipe.playlist.SinglePlayQueue;
import org.schabi.newpipe.report.ErrorActivity;
import org.schabi.newpipe.report.UserAction; import org.schabi.newpipe.report.UserAction;
import org.schabi.newpipe.util.Constants; import org.schabi.newpipe.util.Constants;
import org.schabi.newpipe.util.ExtractorHelper; import org.schabi.newpipe.util.ExtractorHelper;
@ -205,7 +204,7 @@ public class VideoDetailFragment
} }
@Override @Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { public View onCreateView(@NonNull LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
return inflater.inflate(R.layout.fragment_video_detail, container, false); return inflater.inflate(R.layout.fragment_video_detail, container, false);
} }
@ -682,14 +681,14 @@ public class VideoDetailFragment
switch (id) { switch (id) {
case R.id.menu_item_share: { case R.id.menu_item_share: {
if (currentInfo != null) { if (currentInfo != null) {
shareUrl(currentInfo.getName(), url); shareUrl(currentInfo.getName(), currentInfo.getUrl());
} else {
shareUrl(url, url);
} }
return true; return true;
} }
case R.id.menu_item_openInBrowser: { case R.id.menu_item_openInBrowser: {
openUrlInBrowser(url); if (currentInfo != null) {
openUrlInBrowser(currentInfo.getUrl());
}
return true; return true;
} }
case R.id.action_play_with_kodi: case R.id.action_play_with_kodi:
@ -818,7 +817,7 @@ public class VideoDetailFragment
public void prepareAndHandleInfo(final StreamInfo info, boolean scrollToTop) { public void prepareAndHandleInfo(final StreamInfo info, boolean scrollToTop) {
if (DEBUG) Log.d(TAG, "prepareAndHandleInfo() called with: info = [" + info + "], scrollToTop = [" + scrollToTop + "]"); if (DEBUG) Log.d(TAG, "prepareAndHandleInfo() called with: info = [" + info + "], scrollToTop = [" + scrollToTop + "]");
setInitialData(info.getServiceId(), info.getUrl(), info.getName()); setInitialData(info.getServiceId(), info.getOriginalUrl(), info.getName());
pushToStack(serviceId, url, name); pushToStack(serviceId, url, name);
showLoading(); showLoading();
@ -1112,7 +1111,7 @@ public class VideoDetailFragment
public void handleResult(@NonNull StreamInfo info) { public void handleResult(@NonNull StreamInfo info) {
super.handleResult(info); super.handleResult(info);
setInitialData(info.getServiceId(), info.getUrl(), info.getName()); setInitialData(info.getServiceId(), info.getOriginalUrl(), info.getName());
pushToStack(serviceId, url, name); pushToStack(serviceId, url, name);
animateView(thumbnailPlayButton, true, 200); animateView(thumbnailPlayButton, true, 200);
@ -1192,7 +1191,9 @@ public class VideoDetailFragment
toggleExpandRelatedVideos(currentInfo); toggleExpandRelatedVideos(currentInfo);
wasRelatedStreamsExpanded = false; wasRelatedStreamsExpanded = false;
} }
setTitleToUrl(info.getServiceId(), info.getUrl(), info.getName()); setTitleToUrl(info.getServiceId(), info.getUrl(), info.getName());
setTitleToUrl(info.getServiceId(), info.getOriginalUrl(), info.getName());
if (!info.getErrors().isEmpty()) { if (!info.getErrors().isEmpty()) {
showSnackBarError(info.getErrors(), showSnackBarError(info.getErrors(),

View File

@ -28,12 +28,12 @@ public class PlayQueueItem implements Serializable {
private long recoveryPosition; private long recoveryPosition;
private Throwable error; private Throwable error;
private transient Single<StreamInfo> stream;
PlayQueueItem(@NonNull final StreamInfo info) { PlayQueueItem(@NonNull final StreamInfo info) {
this(info.getName(), info.getUrl(), info.getServiceId(), info.getDuration(), this(info.getName(), info.getUrl(), info.getServiceId(), info.getDuration(),
info.getThumbnailUrl(), info.getUploaderName(), info.getStreamType()); info.getThumbnailUrl(), info.getUploaderName(), info.getStreamType());
this.stream = Single.just(info);
if (info.getStartPosition() > 0)
setRecoveryPosition(info.getStartPosition() * 1000);
} }
PlayQueueItem(@NonNull final StreamInfoItem item) { PlayQueueItem(@NonNull final StreamInfoItem item) {
@ -100,11 +100,6 @@ public class PlayQueueItem implements Serializable {
@NonNull @NonNull
public Single<StreamInfo> getStream() { public Single<StreamInfo> getStream() {
return stream == null ? stream = getInfo() : stream;
}
@NonNull
private Single<StreamInfo> getInfo() {
return ExtractorHelper.getStreamInfo(this.serviceId, this.url, false) return ExtractorHelper.getStreamInfo(this.serviceId, this.url, false)
.subscribeOn(Schedulers.io()) .subscribeOn(Schedulers.io())
.doOnError(throwable -> error = throwable); .doOnError(throwable -> error = throwable);

View File

@ -475,7 +475,6 @@ public class NavigationHelper {
throw new ExtractionException("Url not known to service. service=" + service + " url=" + url); throw new ExtractionException("Url not known to service. service=" + service + " url=" + url);
} }
url = getCleanUrl(service, url, linkType);
Intent rIntent = getOpenIntent(context, url, service.getServiceId(), linkType); Intent rIntent = getOpenIntent(context, url, service.getServiceId(), linkType);
switch (linkType) { switch (linkType) {
@ -488,20 +487,6 @@ public class NavigationHelper {
return rIntent; return rIntent;
} }
public static String getCleanUrl(StreamingService service, String dirtyUrl, StreamingService.LinkType linkType) throws ExtractionException {
switch (linkType) {
case STREAM:
return service.getStreamUrlIdHandler().cleanUrl(dirtyUrl);
case CHANNEL:
return service.getChannelUrlIdHandler().cleanUrl(dirtyUrl);
case PLAYLIST:
return service.getPlaylistUrlIdHandler().cleanUrl(dirtyUrl);
case NONE:
break;
}
return null;
}
private static Uri openMarketUrl(String packageName) { private static Uri openMarketUrl(String packageName) {
return Uri.parse("market://details") return Uri.parse("market://details")
.buildUpon() .buildUpon()

View File

@ -3,4 +3,6 @@ distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists distributionPath=wrapper/dists
zipStoreBase=GRADLE_USER_HOME zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists zipStorePath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-4.4-all.zip distributionUrl=https\://services.gradle.org/distributions/gradle-4.6-all.zip
distributionSha256Sum=9af7345c199f1731c187c96d3fe3d31f5405192a42046bafa71d846c3d9adacb
#distributionSha256Sum must be updated along with the version of gradle in distributionUrl