diff --git a/README.ja.md b/README.ja.md index c101f3851..c45158656 100644 --- a/README.ja.md +++ b/README.ja.md @@ -84,6 +84,7 @@ NewPipe は複数のサービスに対応しています。[ドキュメント]( * SoundCloud \[ベータ\] * media.ccc.de \[ベータ\] * PeerTube インスタンス \[ベータ\] +* Bandcamp \[ベータ\] diff --git a/README.ko.md b/README.ko.md index af5b209be..34b117bb6 100644 --- a/README.ko.md +++ b/README.ko.md @@ -79,6 +79,7 @@ NewPipe는 여러가지 서비스를 지원합니다. 우리의 [문서](https:/ * SoundCloud \[beta\] * media.ccc.de \[beta\] * PeerTube instances \[beta\] +* Bandcamp \[beta\] ## Updates NewPipe 코드의 변경이 있을 때(기능 추가 또는 버그 수정으로 인해), 결국 릴리즈가 발생할 것입니다. 이것들의 형식은 x.xx.x 입니다. diff --git a/README.md b/README.md index f1791de4c..4dc889910 100644 --- a/README.md +++ b/README.md @@ -81,6 +81,7 @@ NewPipe supports multiple services. Our [docs](https://teamnewpipe.github.io/doc * SoundCloud \[beta\] * media.ccc.de \[beta\] * PeerTube instances \[beta\] +* Bandcamp \[beta\] diff --git a/README.pt_BR.md b/README.pt_BR.md index dedb64a7c..28e565c99 100644 --- a/README.pt_BR.md +++ b/README.pt_BR.md @@ -79,6 +79,7 @@ O NewPipe suporta vários serviços. Nosso [documentação](https://teamnewpipe. * SoundCloud \[beta\] * media.ccc.de \[beta\] * PeerTube instances \[beta\] +* Bandcamp \[beta\] ## Atualizações Quando uma alteração no código NewPipe (devido à adição de recursos ou fixação de bugs), eventualmente ocorrerá uma versão. Estes estão no formato x.xx.x . A fim de obter esta nova versão, você pode: diff --git a/README.ro.md b/README.ro.md index 75e3bd5b0..df8869499 100644 --- a/README.ro.md +++ b/README.ro.md @@ -81,6 +81,7 @@ NewPipe suportă servicii multiple. [Documentele](https://teamnewpipe.github.io/ * SoundCloud \[beta\] * media.ccc.de \[beta\] * Instanţe PeerTube \[beta\] +* Bandcamp \[beta\] diff --git a/README.so.md b/README.so.md index f8bc51e59..19f995363 100644 --- a/README.so.md +++ b/README.so.md @@ -79,6 +79,7 @@ NewPipe wuxuu taageeraa adeegyo badan. [warqadan](https://teamnewpipe.github.io/ * SoundCloud \[tijaabo\] * media.ccc.de \[tijaabo\] * PeerTube instances \[tijaabo\] +* Bandcamp \[tijaabo\] ## Kushubida iyo cusboonaysiinta Marka koodhka NewPipe isbadal ku dhaco (wax cusub oo lagusoo kordhiyay ama cilad bixin), ugu dambayn waxaa lasii daayaa mid cusub (Siidayn). Siidaynta qaabkeedu waa x.xx.x . Si aad midka cusub u hesho, waxaad samayn kartaa: diff --git a/app/build.gradle b/app/build.gradle index 7c504e968..0b8de4d41 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -180,7 +180,7 @@ dependencies { // NewPipe dependencies // You can use a local version by uncommenting a few lines in settings.gradle - implementation "com.github.TeamNewPipe:NewPipeExtractor:7e6f464407fc1a2c8fb0886d294093526a6ef0f1" + implementation 'com.github.TeamNewPipe:NewPipeExtractor:def745b801b2ef35c1a0fee1be950331ca6a0cd2' implementation "com.github.TeamNewPipe:nanojson:1d9e1aea9049fc9f85e68b43ba39fe7be1c1f751" implementation "org.jsoup:jsoup:1.13.1" diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index e7fa95759..23128117a 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -317,6 +317,22 @@ + + + + + + + + + + + + + + + + + * This is necessary when the thumbnail's height is larger than the device's height + * and thus is enlarging the player's height + * causing the bottom playback controls to be out of the visible screen. + *

+ */ + public void updateEndScreenThumbnail() { + if (currentThumbnail == null) { + return; + } + + final float endScreenHeight = calculateMaxEndScreenThumbnailHeight(); + + final Bitmap endScreenBitmap = Bitmap.createScaledBitmap( + currentThumbnail, + (int) (currentThumbnail.getWidth() + / (currentThumbnail.getHeight() / endScreenHeight)), + (int) endScreenHeight, + true); + + if (DEBUG) { + Log.d(TAG, "Thumbnail - updateEndScreenThumbnail() called with: " + + "currentThumbnail = [" + currentThumbnail + "], " + + currentThumbnail.getWidth() + "x" + currentThumbnail.getHeight() + + ", scaled end screen height = " + endScreenHeight + + ", scaled end screen width = " + endScreenBitmap.getWidth()); + } + + binding.endScreen.setImageBitmap(endScreenBitmap); + } + + /** + * Calculate the maximum allowed height for the {@link R.id.endScreen} + * to prevent it from enlarging the player. + *

+ * The calculating follows these rules: + *

    + *
  • + * Show at least stream title and content creator on TVs and tablets + * when in landscape (always the case for TVs) and not in fullscreen mode. + * This requires to have at least 85dp free space for {@link R.id.detail_root} + * and additional space for the stream title text size + * ({@link R.id.detail_title_root_layout}). + * The text size is 15sp on tablets and 16sp on TVs, + * see {@link R.id.titleTextView}. + *
  • + *
  • + * Otherwise, the max thumbnail height is the screen height. + *
  • + *
+ * + * @return the maximum height for the end screen thumbnail + */ + private float calculateMaxEndScreenThumbnailHeight() { + // ensure that screenHeight is initialized and thus not 0 + updateScreenSize(); + + if (DeviceUtils.isTv(context) && !isFullscreen) { + final int videoInfoHeight = + DeviceUtils.dpToPx(85, context) + DeviceUtils.spToPx(16, context); + return Math.min(currentThumbnail.getHeight(), screenHeight - videoInfoHeight); + } else if (DeviceUtils.isTablet(context) && service.isLandscape() && !isFullscreen) { + final int videoInfoHeight = + DeviceUtils.dpToPx(85, context) + DeviceUtils.spToPx(15, context); + return Math.min(currentThumbnail.getHeight(), screenHeight - videoInfoHeight); + } else { // fullscreen player: max height is the device height + return Math.min(currentThumbnail.getHeight(), screenHeight); + } + } + @Override public void onLoadingStarted(final String imageUri, final View view) { if (DEBUG) { @@ -1207,23 +1285,29 @@ public final class Player implements @Override public void onLoadingComplete(final String imageUri, final View view, final Bitmap loadedImage) { - final float width = Math.min( + // scale down the notification thumbnail for performance + final float notificationThumbnailWidth = Math.min( context.getResources().getDimension(R.dimen.player_notification_thumbnail_width), loadedImage.getWidth()); + currentThumbnail = Bitmap.createScaledBitmap( + loadedImage, + (int) notificationThumbnailWidth, + (int) (loadedImage.getHeight() + / (loadedImage.getWidth() / notificationThumbnailWidth)), + true); if (DEBUG) { Log.d(TAG, "Thumbnail - onLoadingComplete() called with: " + "imageUri = [" + imageUri + "], view = [" + view + "], " + "loadedImage = [" + loadedImage + "], " + loadedImage.getWidth() + "x" + loadedImage.getHeight() - + ", scaled width = " + width); + + ", scaled notification width = " + notificationThumbnailWidth); } - currentThumbnail = Bitmap.createScaledBitmap(loadedImage, - (int) width, - (int) (loadedImage.getHeight() / (loadedImage.getWidth() / width)), true); - binding.endScreen.setImageBitmap(loadedImage); NotificationUtil.getInstance().createNotificationIfNeededAndUpdate(this, false); + + // there is a new thumbnail, thus the end screen thumbnail needs to be changed, too. + updateEndScreenThumbnail(); } @Override diff --git a/app/src/main/java/org/schabi/newpipe/util/DeviceUtils.java b/app/src/main/java/org/schabi/newpipe/util/DeviceUtils.java index 1afedcaef..52069fd0e 100644 --- a/app/src/main/java/org/schabi/newpipe/util/DeviceUtils.java +++ b/app/src/main/java/org/schabi/newpipe/util/DeviceUtils.java @@ -6,8 +6,10 @@ import android.content.pm.PackageManager; import android.content.res.Configuration; import android.os.BatteryManager; import android.os.Build; +import android.util.TypedValue; import android.view.KeyEvent; +import androidx.annotation.Dimension; import androidx.annotation.NonNull; import androidx.core.content.ContextCompat; @@ -70,4 +72,20 @@ public final class DeviceUtils { return false; } } + + public static int dpToPx(@Dimension(unit = Dimension.DP) final int dp, + @NonNull final Context context) { + return (int) TypedValue.applyDimension( + TypedValue.COMPLEX_UNIT_DIP, + dp, + context.getResources().getDisplayMetrics()); + } + + public static int spToPx(@Dimension(unit = Dimension.SP) final int sp, + @NonNull final Context context) { + return (int) TypedValue.applyDimension( + TypedValue.COMPLEX_UNIT_SP, + sp, + context.getResources().getDisplayMetrics()); + } } diff --git a/app/src/main/java/org/schabi/newpipe/util/KioskTranslator.java b/app/src/main/java/org/schabi/newpipe/util/KioskTranslator.java index d2daaf6cc..2f0b3e132 100644 --- a/app/src/main/java/org/schabi/newpipe/util/KioskTranslator.java +++ b/app/src/main/java/org/schabi/newpipe/util/KioskTranslator.java @@ -48,6 +48,10 @@ public final class KioskTranslator { return c.getString(R.string.recent); case "live": return c.getString(R.string.duration_live); + case "Featured": + return c.getString(R.string.featured); + case "Radio": + return c.getString(R.string.radio); default: return kioskId; } @@ -69,6 +73,10 @@ public final class KioskTranslator { return ThemeHelper.resolveResourceIdFromAttr(c, R.attr.ic_thumb_up); case "live": return ThemeHelper.resolveResourceIdFromAttr(c, R.attr.ic_live_tv); + case "Featured": + return ThemeHelper.resolveResourceIdFromAttr(c, R.attr.ic_stars); + case "Radio": + return ThemeHelper.resolveResourceIdFromAttr(c, R.attr.ic_radio); default: return 0; } diff --git a/app/src/main/java/org/schabi/newpipe/util/ServiceHelper.java b/app/src/main/java/org/schabi/newpipe/util/ServiceHelper.java index b38edfeb4..d41493a7f 100644 --- a/app/src/main/java/org/schabi/newpipe/util/ServiceHelper.java +++ b/app/src/main/java/org/schabi/newpipe/util/ServiceHelper.java @@ -38,6 +38,8 @@ public final class ServiceHelper { return R.drawable.place_holder_gadse; case 3: return R.drawable.place_holder_peertube; + case 4: + return R.drawable.place_holder_bandcamp; default: return R.drawable.place_holder_circle; } diff --git a/app/src/main/res/drawable-nodpi/place_holder_bandcamp.png b/app/src/main/res/drawable-nodpi/place_holder_bandcamp.png new file mode 100644 index 000000000..848e109c2 Binary files /dev/null and b/app/src/main/res/drawable-nodpi/place_holder_bandcamp.png differ diff --git a/app/src/main/res/values/colors_services.xml b/app/src/main/res/values/colors_services.xml index 2ff59e8dd..45a816924 100644 --- a/app/src/main/res/values/colors_services.xml +++ b/app/src/main/res/values/colors_services.xml @@ -44,4 +44,13 @@ #FFFFFF #9e9e9e + + #17a0c4 + #000000 + #17a0c4 + + #17a0c4 + #FFFFFF + #17a0c4 + \ No newline at end of file diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 25e7f6210..9fb15e463 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -707,4 +707,6 @@ This content is private, so it cannot be streamed or downloaded by NewPipe. This video is available only to YouTube Music Premium members, so it cannot be streamed or downloaded by NewPipe. This content is only available to users who have paid, so it cannot be streamed or downloaded by NewPipe. + Featured + Radio diff --git a/app/src/main/res/values/styles_services.xml b/app/src/main/res/values/styles_services.xml index ad8b35899..89d04e49f 100644 --- a/app/src/main/res/values/styles_services.xml +++ b/app/src/main/res/values/styles_services.xml @@ -70,4 +70,23 @@ @color/dark_media_ccc_accent_color + + + + + + +