1
mirror of https://github.com/TeamNewPipe/NewPipe synced 2025-09-20 23:00:50 +02:00

Compare commits

...

582 Commits

Author SHA1 Message Date
Stypox
abfde872f1 Merge pull request #12623 from Isira-Seneviratne/Merge-dev-to-refactor 2025-09-10 09:17:40 +02:00
Isira Seneviratne
c98f56bf7b Merge branch 'dev' into Merge-dev-to-refactor
# Conflicts:
#	app/src/main/java/org/schabi/newpipe/fragments/detail/VideoDetailFragment.java
#	app/src/main/java/org/schabi/newpipe/player/Player.java
#	app/src/main/java/org/schabi/newpipe/player/PlayerService.java
#	app/src/main/java/org/schabi/newpipe/player/playqueue/PlayQueue.java
#	app/src/main/java/org/schabi/newpipe/player/playqueue/PlayQueueItem.java
2025-09-10 08:37:57 +05:30
Profpatsch
45c22c0db8 Merge pull request #12615 from Isira-Seneviratne/Player-intent-refactor
Refactor player intent logic
2025-09-09 10:24:42 +02:00
Isira Seneviratne
89c4eb5237 Refactor player intent logic 2025-09-08 07:56:13 +05:30
Stypox
759342fa62 Merge pull request #12612 from Profpatsch/rename-fullscreen-buttons 2025-09-07 18:00:47 +02:00
Profpatsch
0382cfd2ae MainPlayerUi: separate enter/exit fullscreen methods
Most usages of `toggleFullscreen` are clear about whether they want to
enter or exit fullscreen, so let’s split the setup into two functions
for easier debugging.

The two remaining uses of `toggleFullscreen` *should* really toggle,
but I’m not 100% sure.

Also rename `onScreenRotationButtonClicked` to
`onFullscreenToggleButtonClicked`, since we renamed the button id
earlier.
2025-09-07 13:23:15 +02:00
Profpatsch
753a3e68d5 player.xml: Rename fullscreen buttons
Their names must have come from a very old version of the app, they
both toggle the fullscreen mode and rotate the screen depending on
circumstances.

So
`fullscreenButton` -> `fullscreenToggleButtonSecondaryMenu` because it
is only visible in the secondary video menu on some configurations.
and
`screenRotationButton` -> `fullscreenToggleButton` because it is the main
fullscreen button next to the video progress bar.
2025-09-07 12:25:56 +02:00
Stypox
b6bd87a4dc Merge pull request #12609 from Stypox/image-vector-app-icon 2025-09-06 18:01:10 +02:00
Stypox
b36201442d Use ImageVector to render NewPipe squircle app icon 2025-09-06 17:59:42 +02:00
Stypox
803aba4935 Merge pull request #12254 from TeamNewPipe/timestamp-keep-current-player 2025-09-06 17:51:36 +02:00
Profpatsch
1723bf0e8a Player/handleIntent: keep current player when clicking timestamp
This was always a bit weird, that clicking a timestamp would
unconditionally switch to the popup player.

With the new enum, it’s trivial to change it to always stay at the
selected player now ;)
2025-09-06 17:40:18 +02:00
Stypox
9d3775f132 Rewrite logo SVGs to make them line-only
Also optimize them with svgo
2025-09-06 17:23:31 +02:00
Stypox
b2d89a41fb Merge pull request #12604 from Isira-Seneviratne/Refactor-EmptyState 2025-09-06 15:33:49 +02:00
Profpatsch
eb277fe14b Player/handleIntent: call handleIntentPost unconditionally
We always need to handleIntentPost otherwise the VideoDetailFragment
is not setup correctly.
2025-09-06 15:31:14 +02:00
Profpatsch
d77771a60c Player/handleIntent: fix enqueue if player not running
In 063dcd41e5 I falsely claimed that the
fallthrough case is always degenerate, but it kinda somehow still
worked because if you long-click on e.g. the popup button, it would
call enqueue, but if nothing was running yet it would fallthrough to
the very last case and start the player with the video.

So let’s return to that and add a TODO for further refactoring in the
future.
2025-09-06 15:09:11 +02:00
Profpatsch
01f9a3de33 Fix Checkstyle & remove unused fields 2025-09-06 15:09:11 +02:00
Profpatsch
150649aea9 Player/handleIntent: Don’t delete queue when clicking on timestamp
Fixes https://github.com/TeamNewPipe/NewPipe/issues/11013

We finally are at the point where we can have good logic around
clicking on timestamps.

This is pretty straightforward:

1) if we are already playing the stream (usual case), we skip to the
   correct second directly
2) If we don’t have a queue yet, create a trivial one with the stream
3) If we have a queue, we insert the video as next item and start
  playing it.

The skipping logic in 1) is similar to the one further down in the old
optimization block, but will always correctly fire for timestamps now.
I copied it because it’s not quite the same code, and moving into a
separate method at this stage would complicate the code too much.
2025-09-06 15:09:11 +02:00
Profpatsch
3803d49489 Player/handleIntent: separate out the timestamp request into enum
Instead of implicitely reconstructing whether the intent was
intended (lol) to be a timestamp change, we create a new kind of
intent that *only* sets the data we need to switch to a new timestamp.

This means that the logic of what to do (opening a popup player) gets
moved from `InternalUrlsHandler.playOnPopup` to the
`Player.handleIntent` method, we only pass that we want to jump to a
new timestamp. Thus, the stream is now loaded *after* sending the
intent instead of before sending.

This is somewhat messy right now and still does not fix the issue of
queue deletion, but from now on the queue logic should get more
straightforward to implement.

In the end, everything should be a giant switch. Thus we don’t
fall-through anymore, but run the post-setup code manually by calling
`handeIntentPost` and then returning.
2025-09-06 15:06:53 +02:00
Profpatsch
25a4a9a253 Player/handleIntent: move prefs parameters into initPlayback
They are just read from the player preferences and don’t influence the
branching, no need to read them in the intent parsing logic.
2025-09-06 15:04:06 +02:00
Profpatsch
d534946550 Player: inline repeat mode cycling 2025-09-06 15:04:06 +02:00
Profpatsch
8fb3e90fe1 Player: remove unused REPEAT_MODE intent key 2025-09-06 15:04:06 +02:00
Profpatsch
5750ef6aa8 Player/handleIntent: start converting intent data to enum
The goal here is to convert all player intents to use a single enum
with extra data for each case. The queue ones are pretty easy, they
don’t carry any extra data. We fall through for everything else for
now.
2025-09-06 15:04:06 +02:00
Profpatsch
ab7d1377e5 Player/handleIntent: always early return on ENQUEUE an ENQUEUE_NEXT
We can do this, because:

1. if `playQueue` is not null, we return early
2. if `playQueue` is null and we need to enqueue:
  - the only “proper” case that could be triggered is
    the `RESUME_PLAYBACK` case, which is never `true` for the queuing
    intents, see the comment in `NavigationHelper.enqueueOnPlayer`
  - the generic `else` case is degenerate, because it would crash on
  `playQueue` being `null`.

This makes some sense, because there is no way to trigger the
enqueueing logic via the UI currently if there is no video playing
yet, in which case `playQueue` is not `null`.

So we need to transform this whole if desaster into a big switch.
2025-09-06 15:04:06 +02:00
Profpatsch
fd24c08529 Player/handleIntent: de morgan samePlayQueue
Okay, so this is the … only? branch in this if-chain that will
conditionally fire if `playQueue` *is* `null`, sometimes.

This is why the unconditional `initPlayback` in `else` is not passed a
`null` in many cases … because `RESUME_PLAYBACK` is `true` and
`playQueue` is `null`.

It’s gonna be hard to figure out which parts of that are intentional,
I say.
2025-09-06 15:04:06 +02:00
Profpatsch
e14ec3a4f9 NavigationHelper: inline trivial getPlayerIntent use 2025-09-06 15:04:06 +02:00
Profpatsch
b592403a66 NavigationHelper: push out resumePlayback one layer 2025-09-06 15:04:06 +02:00
Profpatsch
90e1ac56ef NavigationHelper: inline getPlayerEnqueueIntent
Funnily enough, I’m pretty sure that whole comment will be not
necessary, because we never check `resumePlayback` on handling the
intent anyway.
2025-09-06 15:04:06 +02:00
Profpatsch
32eb3afe16 Player/handleIntent: a few comments 2025-09-06 15:04:06 +02:00
Profpatsch
35c7f2f5d1 Player: Remove unused IS_MUTED intent key
The only use of the key was removed in commit
2a2c82e73b
but the handling logic stayed around. So let’s get rid of it.
2025-09-05 16:57:27 +02:00
Isira Seneviratne
01a8c4e584 Clean up EmptyStateComposable code 2025-09-05 18:22:19 +05:30
Stypox
2ee7cc4344 Merge branch 'dev' into refactor 2025-09-05 13:34:53 +02:00
Stypox
8afb00d2f0 Merge pull request #12603 from Stypox/better-error-panel 2025-09-05 13:31:39 +02:00
Stypox
f27ec53c08 Even more centralized error handling in ErrorInfo 2025-09-05 12:39:16 +02:00
Stypox
2cb465c89d Merge branch 'dev' into refactor 2025-09-04 15:25:45 +02:00
Stypox
a3ddd616f9 Merge pull request #12578 from Stypox/better-error-messages 2025-09-04 13:18:40 +02:00
Stypox
79980e2078 Address PR reviews 2025-09-04 13:17:45 +02:00
Isira Seneviratne
ccca89dc8a Merge pull request #12585 from Isira-Seneviratne/Merge-dev-to-refactor
Merge dev to refactor
2025-09-01 05:37:29 +05:30
Isira Seneviratne
9bf23abcd1 Merge branch 'dev' into Merge-dev-to-refactor
# Conflicts:
#	app/src/main/AndroidManifest.xml
2025-09-01 05:22:51 +05:30
Isira Seneviratne
b204fad9d5 Merge pull request #12471 from Isira-Seneviratne/Fix-notifications
Fix foreground service issues
2025-09-01 05:05:47 +05:30
Isira Seneviratne
08f51abefb Added comments 2025-08-31 22:25:12 +05:30
Stypox
204df4c45a Fix test 2025-08-30 14:58:08 +02:00
Stypox
989c0cfd28 Fix REPORT in snackbar not opening ErrorActivity if MainActivity not shown
Bug caused by https://github.com/TeamNewPipe/NewPipe/pull/11789
2025-08-30 14:39:23 +02:00
Stypox
a369deeef4 Allow ErrorInfo messages with formatArgs
- ErrorInfo.getMessage() now returns an ErrorMessage instance that can be formatted into a string using a context (this allows the construction of an ErrorInfo to remain independent of a Context)
- now the service ID is used in ErrorInfo.getMessage() to customize some messages based on the currently selected service
- player HTTP invalid statuses are now included in the message
- building a custom error message for AccountTerminatedException was moved from ErrorPanelHelper to ErrorInfo
2025-08-30 14:36:27 +02:00
Stypox
1bde2dcd9f Fix ordering of error messages conditions 2025-08-28 17:06:10 +02:00
Stypox
29a3ca83b5 Show better information about player errors 2025-08-28 17:06:09 +02:00
Stypox
38064be702 Add more specific error messages and deduplicate their handling 2025-08-28 17:05:52 +02:00
Tobi
d17eae9bad Merge pull request #12253 from Profpatsch/popup-overlay-alert-dialog
Overlay Permission: display explanatory dialog for Android > R
2025-08-27 02:50:45 -07:00
TobiGr
74562db965 Use androidx compat alert dialog 2025-08-27 11:45:31 +02:00
Profpatsch
386d5197d8 Permission: display explanatory dialog for Android > R
On Android > R, ACTION_MANAGE_OVERLAY_PERMISSION always brings the
user to the app selection screen.

https://developer.android.com/about/versions/11/privacy/permissions#manage_overlay

This is highly confusing behaviour from the system, so let’s add an
instruction before navigating to the settings menu.
2025-08-27 11:38:25 +02:00
Tobi
ccd76dea1f Merge pull request #12544 from Stypox/download-options
Add option to delete a download without also deleting file
2025-08-27 02:31:14 -07:00
Tobi
10c5a5d02c Merge pull request #12569 from Isira-Seneviratne/Fix-import
Fix database import
2025-08-27 01:55:55 -07:00
Isira Seneviratne
cf4b5e17c5 Fix database import 2025-08-25 14:32:19 +05:30
Stypox
deb5425871 Merge branch 'dev' into refactor 2025-08-17 12:48:30 +02:00
Stypox
7644066c5a Add option to delete a download without also deleting file 2025-08-16 16:50:01 +02:00
Stypox
9bc8139b8c Merge pull request #12483 from TeamNewPipe/ignore-picasso-update 2025-08-11 17:48:30 +02:00
Tobi
ff3526b28d Merge pull request #12460 from Isira-Seneviratne/Short-count-refactor
Fix short count formatting for Android versions below 7.0
2025-08-01 10:56:41 -07:00
TobiGr
d6c0dc32d1 Correctly ignore new version check for picasso 2025-08-01 10:50:54 +02:00
Stypox
124ab56c5f Merge branch 'master' into dev 2025-07-31 23:52:01 +02:00
Stypox
95a0e0ca39 Merge pull request #12435 from TeamNewPipe/release-0.28.0 2025-07-31 23:51:10 +02:00
Stypox
4d97a7653d Merge pull request #12450 from TeamNewPipe/yt-trending-migration 2025-07-31 23:48:53 +02:00
Hosted Weblate
5aefa4aff2 Translated using Weblate (Tigrinya)
Currently translated at 12.7% (95 of 748 strings)

Co-authored-by: fool <thing-sauna-cussed@duck.com>
2025-07-31 23:43:24 +02:00
Stypox
b846746119 Update NewPipeExtractor to v0.24.8 2025-07-31 23:43:19 +02:00
Stypox
b7b836e941 Update the names of YT kiosks 2025-07-31 23:43:19 +02:00
Stypox
d96c0aebb1 Show tabs above kiosks in drawer 2025-07-31 23:43:19 +02:00
Stypox
8400a9ae8e Remove DEBUG statements and don't replace yt trending with live
You can use this command to test instead:

adb shell run-as org.schabi.newpipe.debug.pr12450 'sed -i '"'"'s#<int name="last_used_preferences_version" value="8" />#<int name="last_used_preferences_version" value="6" />#'"'"' shared_prefs/org.schabi.newpipe.debug.pr12450_preferences.xml' && adb shell run-as org.schabi.newpipe.debug.pr12450 'sed -i '"'"'s#\]}</string>#,{\&quot;tab_id\&quot;:5,\&quot;service_id\&quot;:0,\&quot;kiosk_id\&quot;:\&quot;Trending\&quot;},{\&quot;tab_id\&quot;:5,\&quot;service_id\&quot;:1,\&quot;kiosk_id\&quot;:\&quot;Top 50\&quot;}]}</string>#'"'"' shared_prefs/org.schabi.newpipe.debug.pr12450_preferences.xml'
2025-07-31 23:43:19 +02:00
Stypox
7cecd11f72 [YouTube] Add icons and strings for new trending pages 2025-07-31 23:43:19 +02:00
TobiGr
ed93603815 WIP: Add SettingsMigration to change YouTube trending kiosk tab 2025-07-31 23:43:19 +02:00
Stypox
56f79fac13 Merge branch 'release-0.28.0' into dev 2025-07-30 11:42:06 +02:00
Stypox
86efde5996 Merge pull request #12476 from TeamNewPipe/weblate 2025-07-29 20:23:08 +02:00
Stypox
ca9fc14c2a Fix name of nepali language (there was a leftover N) 2025-07-29 20:19:31 +02:00
tobigr
7130adb4ec Clean strings 2025-07-29 20:19:31 +02:00
tobigr
e08d2d8726 Add new locals to the in-app language chooser 2025-07-29 20:19:31 +02:00
Isira Seneviratne
ef29c318b0 Remove NewApi suppression 2025-07-29 06:18:27 +05:30
Hosted Weblate
6516fb96fd Translated using Weblate (Romanian)
Currently translated at 100.0% (748 of 748 strings)

Translated using Weblate (Arabic)

Currently translated at 100.0% (86 of 86 strings)

Translated using Weblate (Russian)

Currently translated at 100.0% (86 of 86 strings)

Translated using Weblate (Arabic)

Currently translated at 100.0% (748 of 748 strings)

Translated using Weblate (Arabic)

Currently translated at 100.0% (748 of 748 strings)

Translated using Weblate (Russian)

Currently translated at 100.0% (748 of 748 strings)

Translated using Weblate (Turkish)

Currently translated at 100.0% (748 of 748 strings)

Translated using Weblate (Indonesian)

Currently translated at 100.0% (748 of 748 strings)

Translated using Weblate (French)

Currently translated at 100.0% (748 of 748 strings)

Translated using Weblate (Icelandic)

Currently translated at 99.4% (745 of 749 strings)

Translated using Weblate (Estonian)

Currently translated at 18.6% (16 of 86 strings)

Translated using Weblate (Slovak)

Currently translated at 100.0% (86 of 86 strings)

Translated using Weblate (Portuguese (Portugal))

Currently translated at 99.5% (746 of 749 strings)

Translated using Weblate (Belarusian)

Currently translated at 99.7% (747 of 749 strings)

Translated using Weblate (Estonian)

Currently translated at 100.0% (749 of 749 strings)

Translated using Weblate (Bulgarian)

Currently translated at 100.0% (749 of 749 strings)

Translated using Weblate (Hebrew)

Currently translated at 99.7% (747 of 749 strings)

Translated using Weblate (Chinese (Traditional Han script))

Currently translated at 100.0% (749 of 749 strings)

Translated using Weblate (Chinese (Simplified Han script))

Currently translated at 100.0% (749 of 749 strings)

Translated using Weblate (Portuguese (Brazil))

Currently translated at 100.0% (749 of 749 strings)

Translated using Weblate (Polish)

Currently translated at 100.0% (749 of 749 strings)

Translated using Weblate (Ukrainian)

Currently translated at 100.0% (749 of 749 strings)

Translated using Weblate (Czech)

Currently translated at 100.0% (749 of 749 strings)

Translated using Weblate (Slovak)

Currently translated at 99.7% (747 of 749 strings)

Translated using Weblate (Greek)

Currently translated at 100.0% (749 of 749 strings)

Translated using Weblate (Portuguese)

Currently translated at 99.5% (746 of 749 strings)

Translated using Weblate (Italian)

Currently translated at 100.0% (749 of 749 strings)

Translated using Weblate (Hungarian)

Currently translated at 100.0% (749 of 749 strings)

Translated using Weblate (German)

Currently translated at 100.0% (749 of 749 strings)

Translated using Weblate (German)

Currently translated at 100.0% (749 of 749 strings)

Translated using Weblate (Tamazight (Central Atlas))

Currently translated at 19.2% (144 of 749 strings)

Translated using Weblate (Macedonian)

Currently translated at 79.3% (594 of 749 strings)

Translated using Weblate (Slovenian)

Currently translated at 54.6% (409 of 749 strings)

Translated using Weblate (Tigrinya)

Currently translated at 12.7% (95 of 747 strings)

Translated using Weblate (Tigrinya)

Currently translated at 3.4% (3 of 86 strings)

Translated using Weblate (Icelandic)

Currently translated at 99.4% (743 of 747 strings)

Translated using Weblate (Chinese (Simplified Han script))

Currently translated at 90.6% (78 of 86 strings)

Translated using Weblate (Slovak)

Currently translated at 100.0% (86 of 86 strings)

Translated using Weblate (French)

Currently translated at 100.0% (86 of 86 strings)

Translated using Weblate (Italian)

Currently translated at 100.0% (86 of 86 strings)

Translated using Weblate (Italian)

Currently translated at 100.0% (86 of 86 strings)

Translated using Weblate (Polish)

Currently translated at 58.1% (50 of 86 strings)

Translated using Weblate (Hindi)

Currently translated at 100.0% (86 of 86 strings)

Translated using Weblate (Hungarian)

Currently translated at 100.0% (86 of 86 strings)

Translated using Weblate (Punjabi)

Currently translated at 100.0% (86 of 86 strings)

Translated using Weblate (Czech)

Currently translated at 100.0% (86 of 86 strings)

Translated using Weblate (Ukrainian)

Currently translated at 100.0% (86 of 86 strings)

Translated using Weblate (German)

Currently translated at 100.0% (86 of 86 strings)

Translated using Weblate (Belarusian)

Currently translated at 100.0% (747 of 747 strings)

Translated using Weblate (Punjabi)

Currently translated at 100.0% (747 of 747 strings)

Translated using Weblate (Hindi)

Currently translated at 100.0% (747 of 747 strings)

Translated using Weblate (Czech)

Currently translated at 100.0% (747 of 747 strings)

Translated using Weblate (Slovak)

Currently translated at 100.0% (747 of 747 strings)

Translated using Weblate (Slovak)

Currently translated at 100.0% (747 of 747 strings)

Translated using Weblate (German)

Currently translated at 100.0% (747 of 747 strings)

Co-authored-by: 439JBYL80IGQTF25UXNR0X1BG <439JBYL80IGQTF25UXNR0X1BG@users.noreply.hosted.weblate.org>
Co-authored-by: Agnieszka C <aga_04@o2.pl>
Co-authored-by: Drugi Sapog <dindrugi@users.noreply.hosted.weblate.org>
Co-authored-by: Dual Natan <dvapatinatan@gmail.com>
Co-authored-by: Emin Tufan Çetin <etcetin@gmail.com>
Co-authored-by: Fjuro <fjuro@alius.cz>
Co-authored-by: Ghost of Sparta <makesocialfoss32@keemail.me>
Co-authored-by: Hakim Oubouali <hakim.oubouali.skr@gmail.com>
Co-authored-by: Hosted Weblate <hosted@weblate.org>
Co-authored-by: Igor Rückert <igorruckert@yahoo.com.br>
Co-authored-by: Igor Sorocean <sorocean.igor@gmail.com>
Co-authored-by: Jeff Huang <s8321414@gmail.com>
Co-authored-by: Marian Hanzel <marulinko@gmail.com>
Co-authored-by: Matej U <mateju@src.gnome.org>
Co-authored-by: Michael Moroni <michaelmoroni@disroot.org>
Co-authored-by: Mickaël Binos <mickaelbinos@outlook.com>
Co-authored-by: Milan <mobrcian@hotmail.com>
Co-authored-by: NTFSynergy <ntfsynergy@gmail.com>
Co-authored-by: Priit Jõerüüt <jrthwlate@users.noreply.hosted.weblate.org>
Co-authored-by: Random <random-r@users.noreply.hosted.weblate.org>
Co-authored-by: Rex_sa <rex.sa@pm.me>
Co-authored-by: Stypox <stypox@pm.me>
Co-authored-by: Sveinn í Felli <sv1@fellsnet.is>
Co-authored-by: Trunars <trunars@abv.bg>
Co-authored-by: Vasilis K <skyhirules@gmail.com>
Co-authored-by: VfBFan <drop0815@posteo.de>
Co-authored-by: Yaron Shahrabani <sh.yaron@gmail.com>
Co-authored-by: Yassin Amir <y6b5@proton.me>
Co-authored-by: erti <erti@users.noreply.hosted.weblate.org>
Co-authored-by: ikanakova <ikanakova@users.noreply.hosted.weblate.org>
Co-authored-by: nautilusx <translate@disroot.org>
Co-authored-by: ssantos <ssantos@web.de>
Co-authored-by: whistlingwoods <72640314+whistlingwoods@users.noreply.github.com>
Co-authored-by: zmni <zmni@outlook.com>
Co-authored-by: Максим Горпиніч <gorpinicmaksim5@gmail.com>
Co-authored-by: 大王叫我来巡山 <hamburger2048@users.noreply.hosted.weblate.org>
Co-authored-by: 赖诚俊 <cosmic.universe.glitch@gmail.com>
Translate-URL: https://hosted.weblate.org/projects/newpipe/metadata/ar/
Translate-URL: https://hosted.weblate.org/projects/newpipe/metadata/cs/
Translate-URL: https://hosted.weblate.org/projects/newpipe/metadata/de/
Translate-URL: https://hosted.weblate.org/projects/newpipe/metadata/et/
Translate-URL: https://hosted.weblate.org/projects/newpipe/metadata/fr/
Translate-URL: https://hosted.weblate.org/projects/newpipe/metadata/hi/
Translate-URL: https://hosted.weblate.org/projects/newpipe/metadata/hu/
Translate-URL: https://hosted.weblate.org/projects/newpipe/metadata/it/
Translate-URL: https://hosted.weblate.org/projects/newpipe/metadata/pa/
Translate-URL: https://hosted.weblate.org/projects/newpipe/metadata/pl/
Translate-URL: https://hosted.weblate.org/projects/newpipe/metadata/ru/
Translate-URL: https://hosted.weblate.org/projects/newpipe/metadata/sk/
Translate-URL: https://hosted.weblate.org/projects/newpipe/metadata/ti/
Translate-URL: https://hosted.weblate.org/projects/newpipe/metadata/uk/
Translate-URL: https://hosted.weblate.org/projects/newpipe/metadata/zh_Hans/
Translation: NewPipe/Metadata
2025-07-28 23:05:05 +02:00
Stypox
e9922fe162 Merge pull request #12470 from litetex/cleanup-PlayerHelper-localization 2025-07-28 15:30:07 +02:00
Stypox
eea2b7417e Fix player formatters resetting too early on language change
formatters() is called again by the player before the user has a chance to click on the language in the language chooser.

So the correct solution would probably be to attach to https://developer.android.com/reference/android/content/Intent#ACTION_LOCALE_CHANGED, but let's keep it simple. I added `PlayerHelper.resetFormat();` in `ContentSettingsFragment.onDestroy()` and it works. It will mean the player formatters will be reset every time the user exits content settings, but whatever.
2025-07-28 15:29:06 +02:00
litetex
893a1cb699 Encapsulate Formatters in PlayerHelper
and reset them when the language is changed/changing.
This way they will be re-initialized on the next call.

Also Remove a bunch of outdated/non-thread safe code (STRING_FORMATTER)
2025-07-28 15:11:27 +02:00
litetex
ebd5e1a318 Remove unused method 2025-07-28 15:11:27 +02:00
litetex
70841db92f Cleanup `Localization` formatting 2025-07-28 15:11:27 +02:00
litetex
859555e129 Use regions 2025-07-28 15:11:27 +02:00
Stypox
c1cef19b33 Merge pull request #12455 from TobiGr/nextPage-nullable 2025-07-28 14:52:08 +02:00
Stypox
9ba30887f9 Improve null checking further in SearchFragment.handleNextItems 2025-07-28 14:43:46 +02:00
Stypox
0ef38e3a4d Merge pull request #12472 from TeamNewPipe/user-agent-140 2025-07-28 14:03:42 +02:00
Isira Seneviratne
9f11db8e06 Improve scale display 2025-07-28 09:02:52 +05:30
Isira Seneviratne
fece0741e5 Suppress NewApi 2025-07-27 15:47:06 +05:30
TobiGr
a9ce2e9605 Update USER_AGENT to Firefox 140 ESR 2025-07-27 09:39:53 +02:00
Isira Seneviratne
b9b47fc520 Update manifest, startForeground call 2025-07-27 11:58:01 +05:30
Isira Seneviratne
59db955493 Fix new streams notification issue 2025-07-27 11:31:23 +05:30
Isira Seneviratne
2915ab6aef Merge pull request #12462 from Isira-Seneviratne/Merge-dev-to-refactor
Merge dev to refactor
2025-07-25 06:23:19 +05:30
Isira Seneviratne
be662a9f1a Merge branch 'dev' into Merge-dev-to-refactor
# Conflicts:
#	app/build.gradle
#	app/src/main/AndroidManifest.xml
#	app/src/main/java/org/schabi/newpipe/fragments/detail/VideoDetailFragment.java
#	app/src/main/java/org/schabi/newpipe/player/mediabrowser/PackageValidator.kt
2025-07-24 19:28:41 +05:30
Isira Seneviratne
22a709d53b Merge pull request #12388 from mikooomich/sdk35
Target SDK 35
2025-07-24 08:18:32 +05:30
Michael Zh
329d76c857 Bump emulator target 33 -> 35 2025-07-23 22:30:34 -04:00
Isira Seneviratne
9f526e8e8f Fix short count formatting for Android versions below 7.0 2025-07-24 07:56:44 +05:30
Michael Zh
50caba6606 Fix compile
Co-Authored-By: Isira Seneviratne <31027858+Isira-Seneviratne@users.noreply.github.com>
2025-07-23 18:49:28 -04:00
Michael Zh
26443f9f14 WIP: Fix compile 2025-07-23 18:45:30 -04:00
Michael Zh
366129eee2 Fix error toast crash 2025-07-23 18:45:30 -04:00
Michael Zh
4c8d44b6ba Bump compileSdk to 36 and targetSdk to 35
* Sdk 36 requires edge to edge, so use 35 so we can opt out for now
2025-07-23 18:45:30 -04:00
Michael Zh
14cd562ebd Update manifest for sdk34 FGS changes 2025-07-23 18:45:30 -04:00
Michael Zh
04ef608f7a Specify RECEIVER_EXPORTED/RECEIVER_NOT_EXPORTED for sdk34 2025-07-23 18:45:30 -04:00
Stypox
71fcc5ebce Release v0.28.0 (1005) 2025-07-23 14:22:07 +02:00
TobiGr
30e33d59e8 Use correct fix for nextPage being null while creating error report in SearchFragment.handleNextItems() 2025-07-22 16:12:02 +02:00
Kouki Badr
a4bd82be8a fix: handle nullable nextPage behavior when searching albums #12401 (#12408)
* fix: handle nullable nextPage behavior when searching albums #12401

* feat: add nullable annotation to newPage attribute in SearchFragment

* Updated more usages of InfoItemsPage#getNextPage. Nullability is already handled in these areas so no other changes needed

---------

Co-authored-by: Siddhesh Naik <siddheshnaik20@protonmail.com>
2025-07-22 08:58:56 +05:30
Isira Seneviratne
1534c880ef Fix compilation errors 2025-07-21 09:11:24 +05:30
Isira Seneviratne
ded7205588 Merge branch 'dev' into Merge-dev-to-refactor
# Conflicts:
#	app/build.gradle
#	app/src/main/java/org/schabi/newpipe/App.java
#	app/src/main/java/org/schabi/newpipe/about/AboutActivity.kt
#	app/src/main/java/org/schabi/newpipe/about/LicenseFragment.kt
#	app/src/main/java/org/schabi/newpipe/local/subscription/ImportConfirmationDialog.java
#	app/src/main/java/org/schabi/newpipe/player/Player.java
#	app/src/main/java/org/schabi/newpipe/player/PlayerService.java
#	app/src/main/java/org/schabi/newpipe/settings/ContentSettingsFragment.java
2025-07-21 09:05:32 +05:30
litetex
45589dbf26 Merge pull request #12444 from Isira-Seneviratne/Per-app-language
Enable per-app language preferences for Android < 13
2025-07-20 22:20:12 +02:00
litetex
99ae3fdd4e Removed no longer needed translation key 2025-07-20 22:05:05 +02:00
litetex
f48e73eb2a Cleaned up some code related to app language
* Use build constants when possible
* Inline variables
* Don't use var for normal-sized types (that way it's easier to review)
* Split code into methods
2025-07-20 21:52:07 +02:00
Isira Seneviratne
99003bab07 Clean up imports 2025-07-20 16:43:37 +05:30
Isira Seneviratne
9e14f93186 Properly handle when system language is selected 2025-07-20 16:27:07 +05:30
Isira Seneviratne
1f2e5799f7 Merge branch 'dev' into Merge-dev-to-refactor
# Conflicts:
#	app/build.gradle
#	app/src/main/java/org/schabi/newpipe/settings/SettingMigrations.java
#	app/src/main/res/values/strings.xml
2025-07-20 05:57:27 +05:30
Isira Seneviratne
abd9aade87 Update AppCompat 2025-07-20 05:24:56 +05:30
Isira Seneviratne
b8f9c125cd Add link for future reference 2025-07-20 05:03:20 +05:30
Isira Seneviratne
893a227ab1 Enable per-app language preferences for Android < 13 2025-07-20 04:50:49 +05:30
Stypox
0db859e225 Merge pull request #12438 from TeamNewPipe/soundcloud/top_50 2025-07-19 20:53:44 +02:00
Stypox
e61f98bd47 Merge pull request #12434 from TeamNewPipe/fix-new-badge-links-on-readme 2025-07-19 20:44:03 +02:00
Stypox
991d9ea3df Fix state not saved 2025-07-19 20:39:55 +02:00
Stypox
f94892166d Improve comment 2025-07-19 20:34:09 +02:00
Stypox
9697112db6 Show error panel in EmptyFragment 2025-07-19 19:41:13 +02:00
litetex
f64dba0107 Fix new badge links on Readme being rendered incorrectly
For all non default Readmes
2025-07-19 22:45:32 +05:30
litetex
9bf01e1241 Fix new badge links on Readme being rendered incorrectly 2025-07-19 22:45:32 +05:30
Stypox
474efbebc1 Merge pull request #12437 from TeamNewPipe/localization-main-page-content 2025-07-19 19:04:34 +02:00
tobigr
fe58ec85ed Fix error detection when loading main page tabs
Do not crash if something unexpected happens.
2025-07-19 13:37:54 +02:00
tobigr
941f85781b Display dialog informing the user about the removal of the Top 50 kiosk 2025-07-19 13:37:54 +02:00
tobigr
7e0ee4eb7a Update Extractor and add migration to remove SoundCloud Top 50 kiosk 2025-07-18 18:59:28 +02:00
Isira Seneviratne
f93806293a Merge branch 'dev' into Merge-dev-to-refactor
# Conflicts:
#	app/build.gradle
#	app/src/main/java/org/schabi/newpipe/player/PlayerService.java
#	app/src/main/res/values-ca/strings.xml
2025-07-18 19:14:58 +05:30
tobigr
4a41214df4 Do not capitalize "page" for main page content options 2025-07-18 10:28:59 +02:00
Stypox
938265d127 Update NewPipeExtractor 2025-07-17 23:57:03 +02:00
Stypox
ba4e7a3c7f Add changelog for v0.28.0 (1005) 2025-07-17 10:18:10 +02:00
Hosted Weblate
58b5ccb66f Translated using Weblate (Czech)
Currently translated at 100.0% (85 of 85 strings)

Translated using Weblate (Estonian)

Currently translated at 100.0% (747 of 747 strings)

Translated using Weblate (Bulgarian)

Currently translated at 100.0% (747 of 747 strings)

Translated using Weblate (Hebrew)

Currently translated at 100.0% (747 of 747 strings)

Translated using Weblate (Hebrew)

Currently translated at 100.0% (747 of 747 strings)

Translated using Weblate (Chinese (Traditional Han script))

Currently translated at 100.0% (745 of 745 strings)

Translated using Weblate (Chinese (Simplified Han script))

Currently translated at 100.0% (745 of 745 strings)

Translated using Weblate (Polish)

Currently translated at 100.0% (747 of 747 strings)

Translated using Weblate (Polish)

Currently translated at 100.0% (747 of 747 strings)

Translated using Weblate (Turkish)

Currently translated at 100.0% (745 of 745 strings)

Translated using Weblate (Ukrainian)

Currently translated at 100.0% (745 of 745 strings)

Translated using Weblate (Czech)

Currently translated at 100.0% (747 of 747 strings)

Translated using Weblate (Slovak)

Currently translated at 100.0% (747 of 747 strings)

Translated using Weblate (Italian)

Currently translated at 100.0% (747 of 747 strings)

Translated using Weblate (Italian)

Currently translated at 100.0% (747 of 747 strings)

Translated using Weblate (Serbian)

Currently translated at 99.7% (745 of 747 strings)

Translated using Weblate (Hungarian)

Currently translated at 100.0% (747 of 747 strings)

Translated using Weblate (French)

Currently translated at 100.0% (747 of 747 strings)

Translated using Weblate (Tigrinya)

Currently translated at 12.6% (94 of 744 strings)

Translated using Weblate (Tigrinya)

Currently translated at 12.6% (94 of 744 strings)

Translated using Weblate (Tigrinya)

Currently translated at 12.6% (94 of 744 strings)

Translated using Weblate (Tigrinya)

Currently translated at 12.6% (94 of 744 strings)

Translated using Weblate (Tigrinya)

Currently translated at 12.6% (94 of 744 strings)

Translated using Weblate (Tigrinya)

Currently translated at 12.6% (94 of 744 strings)

Translated using Weblate (Tigrinya)

Currently translated at 12.6% (94 of 744 strings)

Translated using Weblate (Tigrinya)

Currently translated at 12.6% (94 of 744 strings)

Translated using Weblate (Tigrinya)

Currently translated at 12.6% (94 of 744 strings)

Translated using Weblate (Tigrinya)

Currently translated at 12.6% (94 of 744 strings)

Translated using Weblate (Tigrinya)

Currently translated at 12.6% (94 of 744 strings)

Translated using Weblate (Tigrinya)

Currently translated at 12.6% (94 of 744 strings)

Translated using Weblate (Tigrinya)

Currently translated at 12.6% (94 of 744 strings)

Translated using Weblate (Tigrinya)

Currently translated at 12.6% (94 of 744 strings)

Translated using Weblate (Tigrinya)

Currently translated at 12.6% (94 of 744 strings)

Translated using Weblate (Tigrinya)

Currently translated at 12.6% (94 of 744 strings)

Translated using Weblate (English (United Kingdom))

Currently translated at 8.2% (7 of 85 strings)

Translated using Weblate (Serbian)

Currently translated at 16.4% (14 of 85 strings)

Translated using Weblate (Portuguese (Portugal))

Currently translated at 100.0% (744 of 744 strings)

Translated using Weblate (Portuguese)

Currently translated at 100.0% (744 of 744 strings)

Translated using Weblate (Serbian)

Currently translated at 100.0% (744 of 744 strings)

Translated using Weblate (Azerbaijani (Southern))

Currently translated at 1.1% (1 of 85 strings)

Added translation using Weblate (Azerbaijani (Southern))

Translated using Weblate (Azerbaijani)

Currently translated at 100.0% (744 of 744 strings)

Translated using Weblate (Slovak)

Currently translated at 100.0% (744 of 744 strings)

Translated using Weblate (Hungarian)

Currently translated at 100.0% (744 of 744 strings)

Translated using Weblate (Serbian)

Currently translated at 16.4% (14 of 85 strings)

Translated using Weblate (Greek)

Currently translated at 100.0% (744 of 744 strings)

Translated using Weblate (Tamil)

Currently translated at 100.0% (85 of 85 strings)

Translated using Weblate (Danish)

Currently translated at 100.0% (744 of 744 strings)

Translated using Weblate (Tamil)

Currently translated at 100.0% (744 of 744 strings)

Translated using Weblate (Arabic)

Currently translated at 100.0% (85 of 85 strings)

Translated using Weblate (Romanian)

Currently translated at 99.7% (742 of 744 strings)

Translated using Weblate (Serbian)

Currently translated at 100.0% (744 of 744 strings)

Translated using Weblate (Spanish)

Currently translated at 100.0% (744 of 744 strings)

Translated using Weblate (Catalan)

Currently translated at 100.0% (744 of 744 strings)

Translated using Weblate (Russian)

Currently translated at 100.0% (85 of 85 strings)

Translated using Weblate (Belarusian)

Currently translated at 100.0% (744 of 744 strings)

Translated using Weblate (Arabic)

Currently translated at 100.0% (744 of 744 strings)

Translated using Weblate (Russian)

Currently translated at 100.0% (744 of 744 strings)

Translated using Weblate (Bulgarian)

Currently translated at 100.0% (744 of 744 strings)

Translated using Weblate (Swedish)

Currently translated at 100.0% (744 of 744 strings)

Translated using Weblate (Hebrew)

Currently translated at 100.0% (744 of 744 strings)

Translated using Weblate (Chinese (Traditional Han script))

Currently translated at 100.0% (744 of 744 strings)

Translated using Weblate (Chinese (Simplified Han script))

Currently translated at 100.0% (744 of 744 strings)

Translated using Weblate (Portuguese (Brazil))

Currently translated at 100.0% (744 of 744 strings)

Translated using Weblate (Turkish)

Currently translated at 100.0% (744 of 744 strings)

Translated using Weblate (Ukrainian)

Currently translated at 100.0% (744 of 744 strings)

Translated using Weblate (Indonesian)

Currently translated at 100.0% (744 of 744 strings)

Translated using Weblate (Italian)

Currently translated at 100.0% (744 of 744 strings)

Translated using Weblate (Dutch)

Currently translated at 100.0% (744 of 744 strings)

Translated using Weblate (Hungarian)

Currently translated at 100.0% (744 of 744 strings)

Translated using Weblate (French)

Currently translated at 100.0% (744 of 744 strings)

Translated using Weblate (Estonian)

Currently translated at 100.0% (744 of 744 strings)

Translated using Weblate (Polish)

Currently translated at 100.0% (744 of 744 strings)

Translated using Weblate (Ukrainian)

Currently translated at 100.0% (744 of 744 strings)

Translated using Weblate (Czech)

Currently translated at 100.0% (744 of 744 strings)

Translated using Weblate (German)

Currently translated at 100.0% (744 of 744 strings)

Translated using Weblate (Persian)

Currently translated at 100.0% (741 of 741 strings)

Translated using Weblate (Arabic)

Currently translated at 100.0% (741 of 741 strings)

Translated using Weblate (Portuguese (Portugal))

Currently translated at 97.6% (83 of 85 strings)

Translated using Weblate (Hebrew)

Currently translated at 100.0% (741 of 741 strings)

Translated using Weblate (Hebrew)

Currently translated at 100.0% (741 of 741 strings)

Translated using Weblate (Hebrew)

Currently translated at 100.0% (741 of 741 strings)

Translated using Weblate (Hebrew)

Currently translated at 100.0% (741 of 741 strings)

Translated using Weblate (Hebrew)

Currently translated at 100.0% (741 of 741 strings)

Translated using Weblate (Hebrew)

Currently translated at 100.0% (741 of 741 strings)

Translated using Weblate (Hebrew)

Currently translated at 100.0% (741 of 741 strings)

Translated using Weblate (Hungarian)

Currently translated at 100.0% (85 of 85 strings)

Translated using Weblate (Kabyle)

Currently translated at 29.0% (215 of 741 strings)

Translated using Weblate (Portuguese (Brazil))

Currently translated at 100.0% (741 of 741 strings)

Added translation using Weblate (Luri (Bakhtiari))

Translated using Weblate (Portuguese (Brazil))

Currently translated at 100.0% (741 of 741 strings)

Translated using Weblate (Portuguese (Brazil))

Currently translated at 100.0% (741 of 741 strings)

Translated using Weblate (Persian)

Currently translated at 94.3% (699 of 741 strings)

Translated using Weblate (Estonian)

Currently translated at 100.0% (741 of 741 strings)

Translated using Weblate (Serbian)

Currently translated at 100.0% (741 of 741 strings)

Translated using Weblate (Persian)

Currently translated at 94.1% (698 of 741 strings)

Translated using Weblate (Belarusian)

Currently translated at 100.0% (741 of 741 strings)

Translated using Weblate (Punjabi)

Currently translated at 100.0% (741 of 741 strings)

Translated using Weblate (Belarusian)

Currently translated at 100.0% (741 of 741 strings)

Translated using Weblate (Finnish)

Currently translated at 98.5% (730 of 741 strings)

Translated using Weblate (French)

Currently translated at 100.0% (741 of 741 strings)

Translated using Weblate (Swedish)

Currently translated at 100.0% (85 of 85 strings)

Translated using Weblate (French)

Currently translated at 100.0% (85 of 85 strings)

Translated using Weblate (German)

Currently translated at 100.0% (85 of 85 strings)

Translated using Weblate (Sardinian)

Currently translated at 100.0% (741 of 741 strings)

Translated using Weblate (German)

Currently translated at 100.0% (741 of 741 strings)

Translated using Weblate (Portuguese (Brazil))

Currently translated at 69.4% (59 of 85 strings)

Translated using Weblate (Spanish)

Currently translated at 100.0% (741 of 741 strings)

Translated using Weblate (Spanish)

Currently translated at 100.0% (741 of 741 strings)

Translated using Weblate (Latvian)

Currently translated at 21.4% (18 of 84 strings)

Translated using Weblate (Latvian)

Currently translated at 99.7% (739 of 741 strings)

Translated using Weblate (Latvian)

Currently translated at 20.2% (17 of 84 strings)

Translated using Weblate (Latvian)

Currently translated at 16.6% (14 of 84 strings)

Translated using Weblate (Greek)

Currently translated at 100.0% (741 of 741 strings)

Translated using Weblate (French)

Currently translated at 100.0% (741 of 741 strings)

Translated using Weblate (Greek)

Currently translated at 32.1% (27 of 84 strings)

Translated using Weblate (Greek)

Currently translated at 100.0% (741 of 741 strings)

Translated using Weblate (Portuguese (Portugal))

Currently translated at 100.0% (741 of 741 strings)

Translated using Weblate (Portuguese)

Currently translated at 100.0% (741 of 741 strings)

Translated using Weblate (Dutch)

Currently translated at 100.0% (741 of 741 strings)

Translated using Weblate (Romanian)

Currently translated at 100.0% (741 of 741 strings)

Translated using Weblate (Urdu)

Currently translated at 69.2% (513 of 741 strings)

Translated using Weblate (Hungarian)

Currently translated at 100.0% (741 of 741 strings)

Translated using Weblate (Hungarian)

Currently translated at 100.0% (741 of 741 strings)

Translated using Weblate (Catalan)

Currently translated at 100.0% (741 of 741 strings)

Translated using Weblate (Catalan)

Currently translated at 90.2% (669 of 741 strings)

Translated using Weblate (Estonian)

Currently translated at 17.8% (15 of 84 strings)

Translated using Weblate (Spanish)

Currently translated at 100.0% (741 of 741 strings)

Translated using Weblate (Russian)

Currently translated at 100.0% (741 of 741 strings)

Translated using Weblate (Dutch (Belgium))

Currently translated at 76.7% (569 of 741 strings)

Translated using Weblate (Dutch (Belgium))

Currently translated at 76.2% (565 of 741 strings)

Translated using Weblate (Lithuanian)

Currently translated at 100.0% (741 of 741 strings)

Translated using Weblate (Hebrew)

Currently translated at 100.0% (741 of 741 strings)

Translated using Weblate (Hebrew)

Currently translated at 100.0% (741 of 741 strings)

Translated using Weblate (Danish)

Currently translated at 100.0% (741 of 741 strings)

Translated using Weblate (Czech)

Currently translated at 100.0% (741 of 741 strings)

Translated using Weblate (Kabyle)

Currently translated at 28.8% (214 of 741 strings)

Translated using Weblate (Indonesian)

Currently translated at 100.0% (741 of 741 strings)

Translated using Weblate (Hungarian)

Currently translated at 100.0% (84 of 84 strings)

Translated using Weblate (Arabic)

Currently translated at 100.0% (741 of 741 strings)

Translated using Weblate (Italian)

Currently translated at 100.0% (741 of 741 strings)

Translated using Weblate (Serbian)

Currently translated at 100.0% (741 of 741 strings)

Translated using Weblate (Dutch)

Currently translated at 100.0% (741 of 741 strings)

Translated using Weblate (Spanish)

Currently translated at 99.8% (740 of 741 strings)

Translated using Weblate (Chinese (Traditional Han script))

Currently translated at 67.8% (57 of 84 strings)

Translated using Weblate (Chinese (Traditional Han script))

Currently translated at 100.0% (741 of 741 strings)

Translated using Weblate (Slovak)

Currently translated at 100.0% (741 of 741 strings)

Translated using Weblate (Icelandic)

Currently translated at 99.4% (737 of 741 strings)

Translated using Weblate (Swedish)

Currently translated at 100.0% (741 of 741 strings)

Translated using Weblate (Turkish)

Currently translated at 100.0% (741 of 741 strings)

Translated using Weblate (French)

Currently translated at 100.0% (741 of 741 strings)

Translated using Weblate (Azerbaijani)

Currently translated at 100.0% (741 of 741 strings)

Translated using Weblate (German)

Currently translated at 100.0% (741 of 741 strings)

Translated using Weblate (Estonian)

Currently translated at 100.0% (741 of 741 strings)

Translated using Weblate (Portuguese (Brazil))

Currently translated at 100.0% (741 of 741 strings)

Translated using Weblate (Polish)

Currently translated at 100.0% (741 of 741 strings)

Translated using Weblate (Belarusian)

Currently translated at 100.0% (741 of 741 strings)

Translated using Weblate (Breton)

Currently translated at 13.6% (101 of 741 strings)

Translated using Weblate (Bulgarian)

Currently translated at 100.0% (741 of 741 strings)

Translated using Weblate (Chinese (Simplified Han script))

Currently translated at 100.0% (741 of 741 strings)

Translated using Weblate (Czech)

Currently translated at 100.0% (741 of 741 strings)

Translated using Weblate (Hungarian)

Currently translated at 100.0% (741 of 741 strings)

Translated using Weblate (Breton)

Currently translated at 12.1% (90 of 741 strings)

Translated using Weblate (Breton)

Currently translated at 7.6% (57 of 741 strings)

Translated using Weblate (Breton)

Currently translated at 7.4% (55 of 741 strings)

Translated using Weblate (Breton)

Currently translated at 7.4% (55 of 741 strings)

Translated using Weblate (Breton)

Currently translated at 7.4% (55 of 741 strings)

Translated using Weblate (Belarusian)

Currently translated at 99.8% (740 of 741 strings)

Translated using Weblate (Ukrainian)

Currently translated at 100.0% (741 of 741 strings)

Added translation using Weblate (Breton)

Translated using Weblate (Romanian)

Currently translated at 100.0% (740 of 740 strings)

Translated using Weblate (Chinese (Traditional Han script))

Currently translated at 100.0% (740 of 740 strings)

Translated using Weblate (Portuguese (Portugal))

Currently translated at 100.0% (740 of 740 strings)

Translated using Weblate (Portuguese)

Currently translated at 100.0% (740 of 740 strings)

Translated using Weblate (Arabic)

Currently translated at 100.0% (740 of 740 strings)

Translated using Weblate (Swedish)

Currently translated at 100.0% (740 of 740 strings)

Translated using Weblate (Japanese)

Currently translated at 100.0% (740 of 740 strings)

Translated using Weblate (Ukrainian)

Currently translated at 100.0% (740 of 740 strings)

Translated using Weblate (Serbian)

Currently translated at 100.0% (740 of 740 strings)

Translated using Weblate (Danish)

Currently translated at 100.0% (740 of 740 strings)

Translated using Weblate (Estonian)

Currently translated at 100.0% (740 of 740 strings)

Translated using Weblate (Finnish)

Currently translated at 98.5% (729 of 740 strings)

Translated using Weblate (Italian)

Currently translated at 100.0% (740 of 740 strings)

Translated using Weblate (French)

Currently translated at 100.0% (740 of 740 strings)

Translated using Weblate (Icelandic)

Currently translated at 99.4% (736 of 740 strings)

Translated using Weblate (Bulgarian)

Currently translated at 100.0% (740 of 740 strings)

Translated using Weblate (Chinese (Simplified Han script))

Currently translated at 100.0% (740 of 740 strings)

Translated using Weblate (Indonesian)

Currently translated at 100.0% (740 of 740 strings)

Translated using Weblate (Slovak)

Currently translated at 100.0% (740 of 740 strings)

Translated using Weblate (German)

Currently translated at 100.0% (740 of 740 strings)

Translated using Weblate (Polish)

Currently translated at 100.0% (740 of 740 strings)

Translated using Weblate (Polish)

Currently translated at 100.0% (740 of 740 strings)

Translated using Weblate (Azerbaijani)

Currently translated at 100.0% (740 of 740 strings)

Translated using Weblate (Ukrainian)

Currently translated at 100.0% (740 of 740 strings)

Translated using Weblate (Czech)

Currently translated at 100.0% (740 of 740 strings)

Translated using Weblate (Hungarian)

Currently translated at 100.0% (740 of 740 strings)

Co-authored-by: 439JBYL80IGQTF25UXNR0X1BG <439JBYL80IGQTF25UXNR0X1BG@users.noreply.hosted.weblate.org>
Co-authored-by: AP <kubanto@users.noreply.hosted.weblate.org>
Co-authored-by: Abu Sarim Hindi <sarfaraz.ahmed78@gmail.com>
Co-authored-by: Agnieszka C <aga_04@o2.pl>
Co-authored-by: Ajeje Brazorf <lmelonimamo@yahoo.it>
Co-authored-by: Alex25820 <alexs25820@gmail.com>
Co-authored-by: Balázs Meskó <meskobalazs@mailbox.org>
Co-authored-by: Bastian <basti.anderl774@gmail.com>
Co-authored-by: ButterflyOfFire <boffire@users.noreply.hosted.weblate.org>
Co-authored-by: Danial Behzadi <dani.behzi@ubuntu.com>
Co-authored-by: Darth23G (DarthGamer23) <fref2329@gmail.com>
Co-authored-by: Deleted User <noreply+48943@weblate.org>
Co-authored-by: Dream X <nodem49316@daupload.com>
Co-authored-by: Drugi Sapog <dindrugi@users.noreply.hosted.weblate.org>
Co-authored-by: Emin Tufan Çetin <etcetin@gmail.com>
Co-authored-by: Fareedar Islami <fareedar.islami@gmail.com>
Co-authored-by: Femini <nizamismidov4@gmail.com>
Co-authored-by: Fjuro <fjuro@alius.cz>
Co-authored-by: Fjuro <fjuro@users.noreply.hosted.weblate.org>
Co-authored-by: Fjuro <git@alius.cz>
Co-authored-by: Ghost of Sparta <makesocialfoss32@keemail.me>
Co-authored-by: GiannosOB <giannos2105@gmail.com>
Co-authored-by: Hosted Weblate <hosted@weblate.org>
Co-authored-by: Igor Rückert <igorruckert@yahoo.com.br>
Co-authored-by: Igor Sorocean <sorocean.igor@gmail.com>
Co-authored-by: Ihor Hordiichuk <igor_ck@outlook.com>
Co-authored-by: J. Lavoie <j.lavoie@net-c.ca>
Co-authored-by: Jay Tromp <jaytromp@pm.me>
Co-authored-by: Jeff Huang <s8321414@gmail.com>
Co-authored-by: Jordi Cambrells <cambrells@users.noreply.hosted.weblate.org>
Co-authored-by: Jordi Cambrells <hanta.hrabal@gmail.com>
Co-authored-by: Juzé <dedakir923@exoular.com>
Co-authored-by: KaGaster <mohamed.kooli@medtech.tn>
Co-authored-by: Languages add-on <noreply-addon-languages@weblate.org>
Co-authored-by: Linerly <linerly@proton.me>
Co-authored-by: MS-PC <MSPCtranslator@gmail.com>
Co-authored-by: Mandeep <mandeeps708@gmail.com>
Co-authored-by: Massimo Pissarello <mapi68@gmail.com>
Co-authored-by: Michael Moroni <michaelmoroni@disroot.org>
Co-authored-by: Mickaël Binos <mickaelbinos@outlook.com>
Co-authored-by: Milan <mobrcian@hotmail.com>
Co-authored-by: Mohammed al-Qubati <mhraqeeb@gmail.com>
Co-authored-by: Mücteba <muctebanesiri@gmail.com>
Co-authored-by: NEXI <nexiphotographer@gmail.com>
Co-authored-by: Nick Wick <NickWick@users.noreply.hosted.weblate.org>
Co-authored-by: Philip Goto <philip.goto@gmail.com>
Co-authored-by: Priit Jõerüüt <hwlate@joeruut.com>
Co-authored-by: Priit Jõerüüt <jrthwlate@users.noreply.hosted.weblate.org>
Co-authored-by: Q. Boii <sf1hks@marketmail.info>
Co-authored-by: Random <random-r@users.noreply.hosted.weblate.org>
Co-authored-by: Rex_sa <rex.sa@pm.me>
Co-authored-by: Sveinn í Felli <sv1@fellsnet.is>
Co-authored-by: THANOS SIOURDAKIS <siourdakisthanos@gmail.com>
Co-authored-by: Trunars <trunars@abv.bg>
Co-authored-by: Vasilis K <skyhirules@gmail.com>
Co-authored-by: VfBFan <drop0815@posteo.de>
Co-authored-by: Yaron Shahrabani <sh.yaron@gmail.com>
Co-authored-by: Yasser Althuwaini <ymth2000@outlook.com>
Co-authored-by: Yauhen <bugomol@users.noreply.hosted.weblate.org>
Co-authored-by: ab_09 <ab_09@users.noreply.hosted.weblate.org>
Co-authored-by: cat <catsnote@proton.me>
Co-authored-by: dekiw39846 <dekiw39846@bariswc.com>
Co-authored-by: elid <shopisrael12@gmail.com>
Co-authored-by: gfbdrgn <erfvvgtyhbnjhyuu@wireconnected.com>
Co-authored-by: late <late@users.noreply.hosted.weblate.org>
Co-authored-by: moton03 <moton.cat@outlook.com>
Co-authored-by: rehork <cooky@e.email>
Co-authored-by: rimasx <riks_12@hot.ee>
Co-authored-by: ssantos <ssantos@web.de>
Co-authored-by: trunars <trunars@gmail.com>
Co-authored-by: Максим Горпиніч <gorpinicmaksim5@gmail.com>
Co-authored-by: Максим Горпиніч <maksimgorpinic2005a@gmail.com>
Co-authored-by: Максим Горпиніч <maksimgorpinic4@gmail.com>
Co-authored-by: Саша Петровић <salepetronije@gmail.com>
Co-authored-by: தமிழ்நேரம் <anishprabu.t@gmail.com>
Co-authored-by: ℂ𝕠𝕠𝕠𝕝 (𝕘𝕚𝕥𝕙𝕦𝕓.𝕔𝕠𝕞/ℂ𝕠𝕠𝕠𝕝) <coool@mail.lv>
Co-authored-by: 大王叫我来巡山 <hamburger2048@users.noreply.hosted.weblate.org>
Co-authored-by: 李恩霆 <timothylee0802@outlook.com>
Translate-URL: https://hosted.weblate.org/projects/newpipe/metadata/ar/
Translate-URL: https://hosted.weblate.org/projects/newpipe/metadata/azb/
Translate-URL: https://hosted.weblate.org/projects/newpipe/metadata/cs/
Translate-URL: https://hosted.weblate.org/projects/newpipe/metadata/de/
Translate-URL: https://hosted.weblate.org/projects/newpipe/metadata/el/
Translate-URL: https://hosted.weblate.org/projects/newpipe/metadata/en_GB/
Translate-URL: https://hosted.weblate.org/projects/newpipe/metadata/et/
Translate-URL: https://hosted.weblate.org/projects/newpipe/metadata/fr/
Translate-URL: https://hosted.weblate.org/projects/newpipe/metadata/hu/
Translate-URL: https://hosted.weblate.org/projects/newpipe/metadata/lv/
Translate-URL: https://hosted.weblate.org/projects/newpipe/metadata/pt_BR/
Translate-URL: https://hosted.weblate.org/projects/newpipe/metadata/pt_PT/
Translate-URL: https://hosted.weblate.org/projects/newpipe/metadata/ru/
Translate-URL: https://hosted.weblate.org/projects/newpipe/metadata/sr/
Translate-URL: https://hosted.weblate.org/projects/newpipe/metadata/sv/
Translate-URL: https://hosted.weblate.org/projects/newpipe/metadata/ta/
Translate-URL: https://hosted.weblate.org/projects/newpipe/metadata/zh_Hant/
Translation: NewPipe/Metadata
2025-07-17 09:16:38 +02:00
Stypox
da36b8a140 Merge pull request #12337 from Profpatsch/video-detail-fragment-kotlin-conversion 2025-07-16 15:56:39 +02:00
Stypox
046ea7301b Apply Kotlin suggestion by @Isira-Seneviratne 2025-07-16 15:53:05 +02:00
Stypox
3998982002 Smaller style fixes 2025-07-16 15:53:05 +02:00
Stypox
a4182b474b More improve Kotlin converted from java in various places 2025-07-16 15:53:05 +02:00
Stypox
317db719db Fix comments in PlayerUiList 2025-07-16 15:47:00 +02:00
Stypox
3f62ec7e53 Improve Kotlin converted from java in various places 2025-07-16 15:46:59 +02:00
Profpatsch
7330541499 PlayerUIList: remove remaining uses of getOpt
mediaSession is now `@NonNull`, so the getter is as well.
2025-07-16 15:42:59 +02:00
Profpatsch
ed0051a3f6 Player: small class comment 2025-07-16 15:42:59 +02:00
Profpatsch
91aed1e240 VideoDetailFragment: replace every getOpt() with get() 2025-07-16 15:42:59 +02:00
Profpatsch
38ed1da79e PlayerHolder: use object class to implement singleton pattern 2025-07-16 15:42:59 +02:00
Profpatsch
cc3ecd4169 VideoDetailFragment: convert to kotlin (mechanical, fixup)
Mostly 1:1, I had to fix a few places where the automatic conversion
did not infer the right kotlin types, and places where it tried to
convert to `double` instead of using `float` like the original.

Everything else is the result of automatic conversion.
2025-07-16 15:42:58 +02:00
Profpatsch
bf72fd1fa5 VideoDetailFragment: convert to kotlin (mechanical, failing)
Just the conversion, errors still there for easier rebasing later.
2025-07-16 15:42:12 +02:00
Profpatsch
86b27cf77d PlayerHolder: kotlinify optional calls 2025-07-16 15:15:28 +02:00
Profpatsch
4fd3ddf392 PlayerHolder: kotlinify setListener 2025-07-16 15:14:50 +02:00
Profpatsch
fc7daa96e9 PlayerHolder: kotlinify getters 2025-07-16 15:14:50 +02:00
Profpatsch
9b22773070 PlayerHolder: convert to kotlin (mechanical) 2025-07-16 15:14:49 +02:00
Profpatsch
86063fda6a PlayQueueActivity: inline getServiceConnection() and bind()
Both are only used once, and it’s easier to see what’s going on if
they are just inlined in `onCreate`.
2025-07-16 15:07:43 +02:00
Profpatsch
c9be4066f2 PlayerService: inline init block & make non-optional 2025-07-16 15:07:43 +02:00
Profpatsch
462f0ad5c0 PlayerUIList: inline init block 2025-07-16 15:07:43 +02:00
Stypox
4e94b2602d Merge pull request #12258 from Profpatsch/show-service-name-in-search 2025-07-16 15:02:43 +02:00
Stypox
4ddc0648ef Merge pull request #12412 from Stypox/fix-ghost-notifications 2025-07-14 21:56:22 +02:00
Tobi
4c920a4406 Merge pull request #12367 from watermelon42/3783_Import_Soundcloud_likes
Support Soundcloud likes in channel and feed
2025-07-14 01:01:02 -07:00
watermelon42
1c0eabf75c Updated extractor version to latest commit 2025-07-13 16:21:42 +02:00
Isira Seneviratne
183cc580fc Merge pull request #12415 from Isira-Seneviratne/Zip-migrate-Path
Migrate zip import/export to use Path
2025-07-12 06:04:31 +05:30
watermelon42
f119a368d8 Added support for importing Soundcloud likes as a new tab before About in a user's channel.
The likes are also retrieved in the feed if the user is subscribed to.
2025-07-11 09:50:33 +02:00
Isira Seneviratne
52ff052d6a Merge pull request #12347 from Isira-Seneviratne/PlayQueueItem-equals
Add PlayQueueItem equals and hashCode
2025-07-10 02:18:43 +05:30
Isira Seneviratne
31f8dd05a7 Convert play queue classes to Kotlin 2025-07-09 07:48:08 +05:30
Isira Seneviratne
c2b6c71947 Rename .java to .kt 2025-07-09 07:48:07 +05:30
Isira Seneviratne
bb7873d157 Fix Sonar warning 2025-07-09 07:48:07 +05:30
Isira Seneviratne
e2a02a1f86 Fix some issues 2025-07-09 07:48:07 +05:30
Isira Seneviratne
690af88db9 Add PlayQueueItem equals and hashCode 2025-07-09 07:48:07 +05:30
Isira Seneviratne
4ffadc2057 Inline variable 2025-07-09 07:47:25 +05:30
Isira Seneviratne
225cb91105 Use InputStream#transferTo() 2025-07-09 07:47:25 +05:30
Isira Seneviratne
3e106b5e4f Fix DB import/export issue 2025-07-09 07:47:25 +05:30
Isira Seneviratne
72b67ab5d4 Refactor zip import/export using Path 2025-07-09 07:47:25 +05:30
Isira Seneviratne
840084d2c9 Merge pull request #12419 from Isira-Seneviratne/Merge-dev-to-refactor
Merge dev to refactor
2025-07-09 07:46:11 +05:30
Isira Seneviratne
2acfefd0bc Merge branch 'dev' into Merge-dev-to-refactor
# Conflicts:
#	app/src/main/java/org/schabi/newpipe/player/helper/PlayerHolder.java
2025-07-09 07:10:18 +05:30
Stypox
f3c20d43be Merge pull request #12410 from Stypox/fix-android-auto-thumbnails 2025-07-08 11:42:20 +02:00
Tobi
c9559fa801 Merge pull request #12416 from Stypox/fix-fullscreen-clear-queue-prompt
Fix fullscreen eliciting "clear queue" prompt
2025-07-07 11:47:27 -07:00
Stypox
8ab79488e9 Merge pull request #12409 from Stypox/readme-badge-size-fix 2025-07-07 16:26:20 +02:00
Stypox
f0b26e208b Update notice about rewrite in the README 2025-07-07 16:25:38 +02:00
Stypox
79084568f2 Fix fullscreen eliciting "clear queue" prompt 2025-07-07 15:07:46 +02:00
Stypox
705b5e5580 Fix ghost notifications on Android 10
Fixes #12400, see there for explanation. Citing from there:

So apparently the problem is onGetRoot always returning a BrowserRoot instance. Making it return null solved the issue (but again, breaks Android Auto compatibility). It turns out (see https://stackoverflow.com/q/63818988/) that onGetRoot is also used for media resumption https://developer.android.com/media/implement/surfaces/mobile#mediabrowserservice_implementation, which causes a new notification to pop up (in this case a useless notification because our onGetRoot does not return something that can be used for resumption). So what needs to be done is to check if rootHints?.getBoolean(EXTRA_RECENT) == true and if that's the case not return anything (as EXTRA_RECENT is used by the system for resumption).

The PackageValidator file is taken from 329a21b63c/common/src/main/java/com/example/android/uamp/media/PackageValidator.kt .
2025-07-07 01:06:59 +02:00
Stypox
a4d457b2b2 Use Kotlin's .toUri() instead of Uri.parse() 2025-07-06 15:05:30 +02:00
Stypox
834c93f22a Fix thumbnails appearing on Android Auto even if disabled 2025-07-06 14:49:09 +02:00
Stypox
a0adeb0099 Fix "Get it on F-Droid" appearing giant in README 2025-07-06 13:51:59 +02:00
Isira Seneviratne
2dd11f70a3 Merge pull request #12356 from dev-victoria/fix-json-importing-oldandroid
check if the JSON MimeType is supported
2025-07-04 07:06:34 +05:30
Stypox
d048bca8b4 Temporarily disable sonarcloud CI step 2025-06-28 15:17:18 +02:00
Diana Victoria Furrer
0c9f5ddcaf change according to Isira-Seneviratne suggestion 2025-06-17 15:42:01 +02:00
Diana Victoria Furrer
aa75a1449f use MimeTypeMap from android webkit to check if the json MimeType is unsupported 2025-06-15 02:19:56 +02:00
Stypox
d81b571d05 Merge pull request #12348 from Isira-Seneviratne/Merge-dev-to-refactor 2025-06-11 10:13:36 +02:00
Isira Seneviratne
6efb92a38f Merge branch 'dev' into Merge-dev-to-refactor
# Conflicts:
#	app/src/main/java/org/schabi/newpipe/MainActivity.java
2025-06-11 08:20:00 +05:30
Stypox
f16becc872 Merge pull request #12217 from SttApollo/Update-EmptyStateComposable 2025-06-06 15:49:13 +02:00
Stypox
60ea317e61 NoComments -> NoVideos in related items screen 2025-06-06 15:36:07 +02:00
Su TT
e53f0ff94a Update EmptyStateComposable usages to include modifiers 2025-06-05 12:33:21 -04:00
Profpatsch
16e32dfc96 SearchFragment: show filter in brackets behind service name
This is still not perfect, but it will show the selected search filter
in addition to the service name, like: “Search YouTube (Playlists)”.

It will not distinguish between a YouTube Music and Youtube filter, so
it will display the same thing. Could be improved, but then the text
gets too long! :(
2025-06-05 14:30:04 +02:00
Profpatsch
006b4c9ae1 Merge pull request #11965 from Profpatsch/player-classes-kotlin-conversion
Some simple refactors & beginning of kotlin conversions of the player classes
2025-06-05 14:13:33 +02:00
Profpatsch
73fef268fc PlayerService/PlayerUIList: some small improvements 2025-06-05 13:52:04 +02:00
Profpatsch
cf8fe95abf PlayerService: runtime-assert that we get passed a service
We directly call the `getService` function after receiving the
argument, so resolving the WeakPointer should never return `null` in
our case.
Of course there could be a race condition in theory, but I feel like
if that happens we have bigger problems?
2025-06-05 13:52:04 +02:00
Profpatsch
36115c3164 PlayerService: remove !! where possible
It’s a bit unwieldy in places, but should improve the safety of the
code in the face of possible race conditions.
2025-06-05 13:52:04 +02:00
Profpatsch
be373dca8d PlayerUIList: make UI list private 2025-06-05 13:52:04 +02:00
Profpatsch
f5a4af2d67 Player: destroy -> saveAndShutdown 2025-06-05 13:52:04 +02:00
Profpatsch
06cf511188 PlayerHolder: improve interface docstrings 2025-06-05 13:52:04 +02:00
Profpatsch
26050d808e VideoPlayerUi: suppress warnings
The `R.id` link from the comment cannot be resolved, so let’s not link
it for now.

We are using some exoplayer2 resources, let’s silence the warning.
2025-06-05 13:52:04 +02:00
Profpatsch
0b32738d42 VideoDetailFragment: remove duplicate code in startLoading 2025-06-05 13:52:04 +02:00
Profpatsch
c37db85b97 VideoDetailFragment: apply more IDE suggestions 2025-06-05 13:52:04 +02:00
Profpatsch
4d6e1a4ecf VideoDetailFragment: apply visibility suggestions
Because the class is final, protected does not make sense (Android
Studio auto-suggestions)
2025-06-05 13:52:04 +02:00
Profpatsch
b5dd49ecd3 PlayerService: simplify nullable calls, getters 2025-06-05 13:52:04 +02:00
Profpatsch
945fbd884b PlayerService: Convert to kotlin (mechanical) 2025-06-05 13:52:04 +02:00
Profpatsch
545c4f078f PlayerUIList: restrict superclasses a little 2025-06-05 13:52:04 +02:00
Stypox
8c4a789f78 Merge pull request #12302 from davidasunmo/update-readmes 2025-06-04 11:59:56 +02:00
Stypox
769e98acd0 Show search filter in search bar hint 2025-06-04 11:54:31 +02:00
Stypox
8e036b5e69 Merge pull request #12325 from dev-victoria/FeedGroupTab 2025-06-04 11:24:32 +02:00
Stypox
571b7bc74b Improve layout of select_feed_group_item 2025-06-04 11:18:04 +02:00
Stt_lens
d4cd54fd7b Update app/src/main/java/org/schabi/newpipe/ui/emptystate/EmptyStateComposable.kt
Co-authored-by: Stypox <stypox@pm.me>
2025-05-31 12:27:16 -04:00
Stt_lens
15ab3df511 Update app/src/main/java/org/schabi/newpipe/ui/emptystate/EmptyStateComposable.kt
Co-authored-by: Stypox <stypox@pm.me>
2025-05-31 12:07:37 -04:00
Audric V.
033cc08c26 Merge pull request #12322 from dev-victoria/tiny-code-fixes
Fix equality comparison in Tab class
2025-05-31 16:56:37 +02:00
Diana Victoria Furrer
205d18f4c4 Use GroupName for the Settings Text.
The Tabname displays the default Feed title.
2025-05-31 14:11:26 +02:00
Diana Victoria Furrer
712724211c added FeedGroup to Tab Settings UnitTest 2025-05-31 01:41:06 +02:00
Diana Victoria Furrer
fd09e6147f # Fixed Feed Group Titlebar
- use default fragment_feed_title for TabName
- only clear FeedFragment bar subtitle when it matches the groupName to clear.
2025-05-31 01:30:49 +02:00
Diana Victoria Furrer
279caac915 # Change
Layout select_feed_group_item (FeedGroup Picker in the Settings)
Remove rounded style from the icons
2025-05-30 21:00:37 +02:00
Diana Victoria Furrer
f8ed8e575e # Change
Added FEEDGROUP Tab Code to
 - ChooseTabsFragment
 - Tab

Added strings:
- feed_group_page_summary
2025-05-30 20:47:37 +02:00
Diana Victoria Furrer
436626fa83 # Change
Adjusted select_feed_group_fragment Layout
 - reference select_feed_group_item layout
 - use new Strings

Added strings:
- select_a_feed_group
- no_feed_group_created_yet
2025-05-30 17:54:49 +02:00
Diana Victoria Furrer
7c3989ff93 # Change
Adjusted the new Class SelectFeedGroupFragment for its Role
- Renamed Variables
- adjusted Imports
- adjusted Interface with FeedGroupEntity Values
2025-05-30 17:45:51 +02:00
Diana Victoria Furrer
e6c4690e7d # Copied Layouts
Copied select_channel_fragment to select_feed_group_fragment

Copied select_channel_item to select_feed_group_item

# Change
Replaced the Layout references in the new Class SelectFeedGroupFragment
2025-05-30 17:07:19 +02:00
Diana Victoria Furrer
86869f0a14 Copied SelectFeedGroupFragment from SelectChannelFragment 2025-05-30 16:55:07 +02:00
Diana Victoria Furrer
aa0b45c05f ChannelTab.equals fix comparison 2025-05-30 13:21:45 +02:00
David Asunmo
55bf74b4a7 Fix CI status badge 2025-05-24 02:15:45 +01:00
David Asunmo
de3d11568d Add nightly builds to all readmes
Add matrix to .ru
2025-05-22 03:29:12 +01:00
David Asunmo
16077dee80 Add matrix chat link to all READMEs 2025-05-22 03:29:12 +01:00
Stypox
c9155f7834 Merge pull request #12298 from davidasunmo/add-dev-refactor-nightly-badges
Add dev and refactor nightly build badges
2025-05-20 11:13:38 +02:00
David
7dd1abdf9c Add dev and refactor nightly build badges
bottom text
2025-05-20 02:22:47 +01:00
Isira Seneviratne
f41b34c090 Merge pull request #11759 from Isira-Seneviratne/Import-export-worker
Rewrite import and export subscriptions functionality using coroutines
2025-05-16 01:16:34 +05:30
Stypox
d1954baf29 Merge pull request #11829 from Profpatsch/PlayerUIList-to-kotlin
Player UI list to kotlin
2025-05-13 23:36:16 +02:00
Profpatsch
a8da9946d1 PlayerUiList: guard list actions with mutex
The new implementation would throw `ConcurrentModificationExceptions`
when destroying the UIs. So let’s play it safe and put the list behind
a mutex.

Adds a helper class `GuardedByMutex` that can be wrapped around a
property to force all use-sites to acquire the lock before doing
anything with the data.
2025-05-11 15:23:03 +02:00
Profpatsch
3d069cdf5b PlayerUIList: rename get to getOpt and make get nullable
In Kotlin, dealing with nulls works better so we don’t need optional.
2025-05-11 15:12:37 +02:00
Profpatsch
eccedc0ab0 PlayerUIList: transform to kotlin
And simplify the code a little
2025-05-11 15:06:52 +02:00
Profpatsch
f3858e70a3 Merge pull request #11789 from Thompson3142/fix_background_crash_focus
Fix background crash focus
2025-05-09 23:41:38 +02:00
Thompson3142
76202e6b4b Remove no longer needed dependency 2025-05-09 22:29:05 +02:00
Thompson3142
90e2f234e7 Initial commit for better handling of background crashes
Fix crashing behaviour with entry in SharedPreferences

A few minor improvements

Added docs for isInBackground

Some more minor changes

Overwrite methods in MainActivity instead of creating a new class
2025-05-09 22:29:00 +02:00
Profpatsch
42a52b7118 Merge pull request #12259 from Profpatsch/put-@-on-right-side-of-rtl-usernames
Comments: Put @ on the right side of right-to-left usernames
2025-05-08 21:46:00 +02:00
Stypox
7cecda5713 Merge branch 'dev' into refactor
Had to make some adjustments to make https://github.com/TeamNewPipe/NewPipe/pull/12188 work
2025-05-08 15:34:00 +02:00
Stypox
d9dccfa8af Merge branch 'master' into dev 2025-05-08 15:04:06 +02:00
Profpatsch
e554c77f2e Comments: Put @ on the right side of right-to-left usernames
From the discussion in
https://github.com/TeamNewPipe/NewPipe/pull/12188 it reads more
natural for RTL readers.
2025-05-07 14:20:44 +02:00
Stypox
81b4e3f970 Hotfix release v0.27.7 (1004) 2025-05-07 12:52:43 +02:00
TobiGr
ef068e1eca Update NewPipe Extractor and add new proguard rules
New rules are required since Rhino and Rhino Engine 1.8.0
2025-05-07 12:50:37 +02:00
Stypox
8407b5aefd Add translated changelogs for v0.27.7
Copied from 985.txt
2025-05-07 12:49:31 +02:00
Stypox
b6aa07545a Add changelog for v0.26.7 (1004) 2025-05-07 12:48:59 +02:00
Stypox
1dcb1953ba Update NewPipeExtractor to v0.24.6
For some reason
com.github.TeamNewPipe.NewPipeExtractor:v0.24.6
didn't work, but
com.github.TeamNewPipe.NewPipeExtractor:NewPipeExtractor:v0.24.6
as suggested on https://jitpack.io/#TeamNewPipe/NewPipeExtractor/v0.24.6 worked...
2025-05-07 12:36:08 +02:00
Profpatsch
862a8e8f26 Merge pull request #12188 from VougJo23/commentsfix
fix: support RTL usernames in comment header
2025-05-07 12:20:23 +02:00
Profpatsch
88395fa852 Merge pull request #12202 from AndrianaBilali/fix/timestamp-clicks-in-replies
Fix timestamps not working in comment replies
2025-05-07 12:07:03 +02:00
VougJo23
8d679626f0 fix: support RTL usernames in comment header
The `@` gets added by the youtube API and thus is a fixed member of
the username, so we do some simple detection logic to handle that
case (otherwise the `@` will be at the right side of a RTL username,
which is different of how Youtube displays these usernames in the
browser).

Fixes https://github.com/TeamNewPipe/NewPipe/issues/12141
2025-05-07 12:05:09 +02:00
Profpatsch
d2dc20c551 SearchFragment: show service name in search hint
The only hint (haha) which service one is searching in is currently
the color of the background. This is super confusing, yesterday a
friend tried to search for a video on youtube and the app was set to
Bandcamp, and they were super confused why nothing turned up.

So let’s put the name of the service in the hint!

The `updateService()` thing is a little confused, but I didn’t want
to refactor to improve the logic. It’s not doing anything
computationally intensive anyway.

For PeerTube, the sidebar calls it FramaTube but the service name is
PeerTube, I’m not sure why that is the case. Looks like the string
depends on the name of the instance? Hm, can be improved later I
think.
2025-05-07 10:12:41 +02:00
Andriana
e7f3750f5e Fix timestamps not working in comment replies
Use LinkMovementMethodCompat for comment links

Co-authored-by: Isira Seneviratne <31027858+Isira-Seneviratne@users.noreply.github.com>

Update import

Use LongPressLinkMovementMethod
2025-05-06 17:12:17 +02:00
j-haldane
48e826e912 Fix header crash in History List view (#12214)
* Adapt header handling changes from other recyclerview adapters to fix issue #4475 in StatisticsPlaylistFragment

* Remove unneeded LayoutInflater

* Revert "Remove unneeded LayoutInflater"

This reverts commit ab73dc1e72.

* Revert "Adapt header handling changes from other recyclerview adapters to fix issue #4475 in StatisticsPlaylistFragment"

This reverts commit 2abe71cc98.

* Remove header animation causing view recycling issue
2025-05-06 17:07:45 +02:00
Profpatsch
088cb8353e Merge pull request #12256 from Profpatsch/improve-jitpack-workaraund-docs
build.gradle: Improve jitpack workaround doc & fix hash
2025-05-06 12:56:38 +02:00
Profpatsch
5ca544bc42 build.gradle: Improve jitpack workaround doc & fix hash 2025-05-06 10:48:20 +02:00
Isira Seneviratne
b6144d01f3 Merge branch 'refactor' into Import-export-worker 2025-04-29 10:18:13 +05:30
Su TT
df11e53a74 Refactor EmptyStateComposable to remove modifier from EmptyStateSpec and fix modifier usage ... 2025-04-28 17:24:11 -04:00
Stypox
aa1b7f8584 Merge pull request #12215 from naveensingh/fix-image-minimizer
Fix image minimizer pattern
2025-04-28 07:34:06 +02:00
Naveen Singh
ce16c6df5f Fix image minimizer pattern
Added non-capturing group that matches either:

 - `user-attachments/assets`
 - `owner/repo/assets/digits`
2025-04-27 19:35:31 -04:00
Isira Seneviratne
1d94fd1582 Merge pull request #12195 from Isira-Seneviratne/Merge-dev-to-refactor
Merge dev to refactor
2025-04-27 08:01:33 +05:30
Isira Seneviratne
c9542ad6fd Update extractor 2025-04-27 07:43:52 +05:30
Isira Seneviratne
cbe598182a Merge branch 'refactor' into Import-export-worker 2025-04-20 07:10:07 +05:30
Isira Seneviratne
7615f79aca Merge branch 'dev' into Merge-dev-to-refactor
# Conflicts:
#	app/src/main/java/org/schabi/newpipe/settings/ContentSettingsFragment.java
2025-04-14 07:29:30 +05:30
Stypox
276bf390b2 Merge pull request #12117 from malania02/dev
Show download date of downloaded videos
2025-04-11 20:17:27 +02:00
malania02
f39eda086f Fix for overlapping 2025-04-09 23:40:14 +02:00
Stypox
756327da39 Merge pull request #12093 from mileskrell/mileskrell/support-per-app-language-preferences
Support per-app language preferences
2025-04-08 23:13:07 +02:00
Stypox
5840d3a437 Merge pull request #12150 from FineFindus/fix/potoken-index
[YouTube] Access first element if array size is one
2025-04-08 23:06:04 +02:00
Stypox
47299c9184 Merge pull request #12164 from Isira-Seneviratne/Merge-dev-to-refactor
Merge dev to refactor
2025-04-08 10:55:28 +02:00
Isira Seneviratne
6486f2de56 Merge branch 'dev' into Merge-dev-to-refactor
# Conflicts:
#	app/build.gradle
#	app/src/main/java/org/schabi/newpipe/fragments/detail/VideoDetailFragment.java
#	app/src/main/java/org/schabi/newpipe/local/feed/notifications/NotificationHelper.kt
#	app/src/main/java/org/schabi/newpipe/player/PlayQueueActivity.java
#	app/src/main/java/org/schabi/newpipe/player/PlayerService.java
#	app/src/main/java/org/schabi/newpipe/player/event/PlayerServiceExtendedEventListener.java
#	app/src/main/java/org/schabi/newpipe/player/helper/PlayerHolder.java
#	app/src/main/res/values-is/strings.xml
2025-04-08 05:42:31 +05:30
FineFindus
e1dedd45ed [YouTube] Access first element if array size is one
Fixes a regression, where if the challenge data array size was one, the second element
would be accessed, leading to a crash.
This was introduced when porting the challenge parsing from JS to
Kotlin.

Ref: 53b599b042
2025-04-02 22:14:01 +02:00
malania02
912f07a1dd Missing lines added 2025-03-30 14:50:05 +02:00
Miles Krell
205466c56a Move call to setApplicationLocales 2025-03-27 19:14:41 -04:00
Miles Krell
7f10312d0a Move migration to NewPipeSettings 2025-03-23 17:39:21 -04:00
malania02
63be3220e7 Show download date 2025-03-22 16:19:26 +01:00
malania02
536b78f2e6 textview for download date added 2025-03-22 16:13:45 +01:00
malania02
6d6b73ef73 textview for download date added 2025-03-22 16:09:58 +01:00
Stypox
196c27792b Merge pull request #12044 from TeamNewPipe/android-auto
Add support for Android Auto *(season 2)*
2025-03-21 11:21:58 +01:00
Stypox
b3789315ad Merge pull request #12104 from TeamNewPipe/update-npe
Update NewPipe Extractor and add new proguard rules
2025-03-21 10:52:37 +01:00
Miles Krell
c7bf498c04 Don't show toast because of changing content language or country 2025-03-16 20:27:05 -04:00
Miles Krell
35abb99dac Only show toast on Android <13 2025-03-16 20:15:38 -04:00
Miles Krell
70416e73f3 Move app language setting migration to SettingMigrations 2025-03-16 19:24:04 -04:00
TobiGr
a0b76c3385 Update NewPipe Extractor and add new proguard rules
New rules are required since Rhino and Rhino Engine 1.8.0
2025-03-16 22:08:10 +01:00
Tobi
c232193a46 Merge pull request #12083 from har-123/bugfix/11894_fix_duplicate_menu_options
Fix duplicate menu options in ChannelFragment
2025-03-16 10:34:52 +01:00
Siddhesh Naik
f289bea6b3 Fix sonar warning 2025-03-16 12:44:05 +05:30
Harshita
48b200868a BF-11894 : Fix the menu disappearing on performing backGesture 2025-03-16 12:44:05 +05:30
Harshita
54bf7f0ced BF-11894 : Fix the Duplicate menu options in ChannelFragment 2025-03-16 12:44:05 +05:30
Miles Krell
980a35a708 Move migration to separate method 2025-03-15 23:00:31 -04:00
Miles Krell
da106e2361 Don't try to migrate "system" app language 2025-03-15 22:54:17 -04:00
Miles Krell
3532ac96b4 Migrate from pre-Android 13 app language pref 2025-03-15 22:13:01 -04:00
Miles Krell
87693a2ad1 Redirect to per-app language settings on Android 13+ 2025-03-15 21:56:02 -04:00
Hosted Weblate
d321e57620 Translated using Weblate (Czech)
Currently translated at 100.0% (740 of 740 strings)

Translated using Weblate (Swedish)

Currently translated at 100.0% (740 of 740 strings)

Translated using Weblate (Catalan)

Currently translated at 88.2% (653 of 740 strings)

Translated using Weblate (Chinese (Simplified Han script))

Currently translated at 90.4% (76 of 84 strings)

Translated using Weblate (Belarusian)

Currently translated at 100.0% (740 of 740 strings)

Translated using Weblate (Hindi)

Currently translated at 100.0% (84 of 84 strings)

Translated using Weblate (Punjabi)

Currently translated at 100.0% (84 of 84 strings)

Translated using Weblate (Belarusian)

Currently translated at 100.0% (740 of 740 strings)

Translated using Weblate (Punjabi)

Currently translated at 100.0% (740 of 740 strings)

Translated using Weblate (Hindi)

Currently translated at 100.0% (740 of 740 strings)

Translated using Weblate (Portuguese)

Currently translated at 100.0% (740 of 740 strings)

Translated using Weblate (Bulgarian)

Currently translated at 100.0% (740 of 740 strings)

Translated using Weblate (German)

Currently translated at 100.0% (740 of 740 strings)

Translated using Weblate (German)

Currently translated at 100.0% (740 of 740 strings)

Translated using Weblate (Bulgarian)

Currently translated at 100.0% (740 of 740 strings)

Translated using Weblate (Croatian)

Currently translated at 99.7% (738 of 740 strings)

Translated using Weblate (Russian)

Currently translated at 100.0% (740 of 740 strings)

Translated using Weblate (Indonesian)

Currently translated at 100.0% (740 of 740 strings)

Translated using Weblate (Belarusian)

Currently translated at 100.0% (740 of 740 strings)

Translated using Weblate (Belarusian)

Currently translated at 100.0% (740 of 740 strings)

Translated using Weblate (Belarusian)

Currently translated at 100.0% (740 of 740 strings)

Translated using Weblate (Italian)

Currently translated at 100.0% (84 of 84 strings)

Translated using Weblate (Czech)

Currently translated at 100.0% (84 of 84 strings)

Translated using Weblate (Portuguese)

Currently translated at 99.8% (739 of 740 strings)

Translated using Weblate (Ukrainian)

Currently translated at 100.0% (740 of 740 strings)

Translated using Weblate (Czech)

Currently translated at 100.0% (740 of 740 strings)

Translated using Weblate (Russian)

Currently translated at 100.0% (740 of 740 strings)

Translated using Weblate (Hungarian)

Currently translated at 100.0% (740 of 740 strings)

Translated using Weblate (French)

Currently translated at 100.0% (84 of 84 strings)

Translated using Weblate (Arabic)

Currently translated at 100.0% (84 of 84 strings)

Translated using Weblate (Arabic)

Currently translated at 100.0% (740 of 740 strings)

Translated using Weblate (Belarusian)

Currently translated at 99.5% (737 of 740 strings)

Translated using Weblate (Turkish)

Currently translated at 100.0% (740 of 740 strings)

Translated using Weblate (Hebrew)

Currently translated at 100.0% (740 of 740 strings)

Translated using Weblate (Icelandic)

Currently translated at 99.4% (736 of 740 strings)

Translated using Weblate (Portuguese (Brazil))

Currently translated at 100.0% (740 of 740 strings)

Translated using Weblate (Ukrainian)

Currently translated at 100.0% (740 of 740 strings)

Translated using Weblate (Greek)

Currently translated at 25.0% (21 of 84 strings)

Translated using Weblate (Greek)

Currently translated at 23.8% (20 of 84 strings)

Translated using Weblate (Estonian)

Currently translated at 100.0% (740 of 740 strings)

Translated using Weblate (Bulgarian)

Currently translated at 100.0% (740 of 740 strings)

Translated using Weblate (French)

Currently translated at 99.5% (737 of 740 strings)

Co-authored-by: 439JBYL80IGQTF25UXNR0X1BG <439JBYL80IGQTF25UXNR0X1BG@users.noreply.hosted.weblate.org>
Co-authored-by: Andrey F <firsan777@mail.ru>
Co-authored-by: Anonymous <noreply@weblate.org>
Co-authored-by: Antonin Del Fabbro <message@antonin.one>
Co-authored-by: Christian Eichert <c@zp1.net>
Co-authored-by: Drugi Sapog <dindrugi@users.noreply.hosted.weblate.org>
Co-authored-by: Eduardo Calixto <eduardogubertcalixto@gmail.com>
Co-authored-by: Emin Tufan Çetin <etcetin@gmail.com>
Co-authored-by: Fjuro <fjuro@users.noreply.hosted.weblate.org>
Co-authored-by: Ghost of Sparta <makesocialfoss32@keemail.me>
Co-authored-by: Hosted Weblate <hosted@weblate.org>
Co-authored-by: Igor Rückert <igorruckert@yahoo.com.br>
Co-authored-by: Ihor Hordiichuk <igor_ck@outlook.com>
Co-authored-by: Jan Layola <gilajan@protonmail.com>
Co-authored-by: Kevin Wang <wmk153024@gmail.com>
Co-authored-by: Linerly <linerly@proton.me>
Co-authored-by: Massimo Pissarello <mapi68@gmail.com>
Co-authored-by: Milo Ivir <mail@milotype.de>
Co-authored-by: Petr Kadlec <mormegil@centrum.cz>
Co-authored-by: Priit Jõerüüt <hwlate@joeruut.com>
Co-authored-by: Rex_sa <rex.sa@pm.me>
Co-authored-by: Sergio Marques <so.boston.android@gmail.com>
Co-authored-by: Sveinn í Felli <sv1@fellsnet.is>
Co-authored-by: XxVictoriaxX <evakonoob@gmail.com>
Co-authored-by: Yaron Shahrabani <sh.yaron@gmail.com>
Co-authored-by: bittin1ddc447d824349b2 <bittin@reimu.nl>
Co-authored-by: trunars <trunars@gmail.com>
Co-authored-by: whistlingwoods <72640314+whistlingwoods@users.noreply.github.com>
Co-authored-by: Максим Горпиніч <maksimgorpinic2005a@gmail.com>
Translate-URL: https://hosted.weblate.org/projects/newpipe/metadata/ar/
Translate-URL: https://hosted.weblate.org/projects/newpipe/metadata/cs/
Translate-URL: https://hosted.weblate.org/projects/newpipe/metadata/el/
Translate-URL: https://hosted.weblate.org/projects/newpipe/metadata/fr/
Translate-URL: https://hosted.weblate.org/projects/newpipe/metadata/hi/
Translate-URL: https://hosted.weblate.org/projects/newpipe/metadata/it/
Translate-URL: https://hosted.weblate.org/projects/newpipe/metadata/pa/
Translate-URL: https://hosted.weblate.org/projects/newpipe/metadata/zh_Hans/
Translation: NewPipe/Metadata
2025-03-15 17:43:36 +01:00
Tobi
fb4a65a14a Merge pull request #12043 from TeamNewPipe/hide-view-logs
Disable logs about view animations by default
2025-03-15 17:17:59 +01:00
Stypox
3047704e1c Merge pull request #12089 from mileskrell/mileskrell/fix-audio-track-labels
Disambiguate audio track labels
2025-03-15 12:45:20 +01:00
Stypox
3dcfdaf510 Merge pull request #12065 from tfga/YouTubeTemporaryPlaylist
Share as YouTube temporary playlist
2025-03-15 10:11:59 +01:00
Thiago F. G. Albuquerque
2ceb70236e sharePlaylist(): converting javadoc from Markdown back to "classic javadoc"
(request from @Stypox)
2025-03-14 21:56:42 -03:00
Thiago F. G. Albuquerque
be097f26c8 Deleting the "explanatory text" bellow the title
<string name="share_playlist_with_titles_message">Share playlist with details such as playlist name and video titles or as a simple list of video URLs</string>
    Share playlist with details such as playlist name and video titles or as a simple list of video URLs</string>

(Discussion: https://github.com/TeamNewPipe/NewPipe/pull/12065#discussion_r1994349485)
2025-03-13 19:10:26 -03:00
Thiago F. G. Albuquerque
098f60d593 Don't add the title when sharing as YouTube temp playlist 2025-03-13 18:16:09 -03:00
Thiago F. G. Albuquerque
eb0568044a R.string.share_playlist_as_youtube_temporary_playlist: pt-BR
+ Minor fixes to related translations
2025-03-12 19:09:31 -03:00
Thiago F. G. Albuquerque
f3b3d5c3e7 R.string.share_playlist_as_youtube_temporary_playlist 2025-03-12 19:08:09 -03:00
Miles Krell
b888dc72cf Support per-app language preferences 2025-03-11 23:29:23 -04:00
Thiago F. G. Albuquerque
599d86151a Making ktLint happy 2025-03-11 21:26:58 -03:00
tfga
587df093ea YouTube video IDs are 11 characters long
Co-authored-by: Stypox <stypox@pm.me>
2025-03-11 20:35:41 -03:00
tfga
8830e87242 YouTube video IDs are 11 characters long
Co-authored-by: Stypox <stypox@pm.me>
2025-03-11 20:35:18 -03:00
Thiago F. G. Albuquerque
f96b8f7b2a Comment: maximum length of 50 items
(PR review from @Stypox)
2025-03-11 20:19:54 -03:00
Thiago F. G. Albuquerque
c28478ae53 getYouTubeId(): Changing implementation to use YoutubeStreamLinkHandler
(PR review from @Stypox)
2025-03-11 20:12:25 -03:00
Miles Krell
10110397fd Use display name instead of only the language 2025-03-10 22:01:09 -04:00
tfga
d81244e77c YT temp playlist URL: http => https
Co-authored-by: Stypox <stypox@pm.me>
2025-03-10 19:11:20 -03:00
Isira Seneviratne
d805679a5e Use workDataOf 2025-03-08 09:18:30 +05:30
Stypox
ea20ca9e72 Merge pull request #12067 from Isira-Seneviratne/Fix-notification-grouping
Fix stream notification grouping
2025-02-28 11:51:11 +01:00
Isira Seneviratne
f0c89494dd Fix stream notification grouping 2025-02-27 09:15:40 +05:30
Thiago F. G. Albuquerque
0fd2d4fed6 [#11930] Removing Apache Commons Collections
It's no longer needed after the conversion to Kotlin.
2025-02-26 21:29:48 -03:00
Stypox
c1bdffd917 Merge pull request #11978 from Profpatsch/fix-back-button-on-remaining-stack
MainActivity: Fix onBackPressed handling for open player
2025-02-26 16:56:04 +01:00
Thiago F. G. Albuquerque
3c7b026d7d [#11930] Updating javadoc 2025-02-25 20:23:07 -03:00
Thiago F. G. Albuquerque
998d84de6c [#11930] Converting to Kotlin 2025-02-25 18:56:12 -03:00
Thiago F. G. Albuquerque
76a02d5858 [#11930] Extracting to a separate file 2025-02-24 20:16:40 -03:00
Thiago F. G. Albuquerque
24bb71a23f [#11930] Making it more efficient: Reverse iteration + limit(50) + reverse 2025-02-24 19:22:36 -03:00
Stypox
49b71942ad Fix style and add comment about null player 2025-02-24 14:21:05 +01:00
Isira Seneviratne
abaf16e12b Merge branch 'refactor' into Import-export-worker
# Conflicts:
#	gradle/libs.versions.toml
2025-02-23 05:10:34 +05:30
Thompson3142
c9ec257a5e Ugly fix for broken text colors in dark mode (#12035)
* Ugly fix for broken text colors in dark mode

* Add comment for clarification

* Added error prevention

* Update app/src/main/java/org/schabi/newpipe/MainActivity.java

---------

Co-authored-by: Stypox <stypox@pm.me>
2025-02-21 09:38:58 +00:00
Thiago F. G. Albuquerque
b1f995a78c [#11930] Playlist with more than 50 items 2025-02-20 16:26:03 -03:00
Thiago F. G. Albuquerque
acac50a1d1 [#11930] Non-Youtube URLs should be ignored 2025-02-19 16:29:34 -03:00
Thiago F. G. Albuquerque
c6b87cd316 [#11930] Making CheckStyle happy 2025-02-18 20:59:13 -03:00
Thiago F. G. Albuquerque
94d4c21cc7 [#11930] @Test export_justUrls() 2025-02-18 17:47:22 -03:00
Stypox
a7a7dc5363 Handle player and player service separately
This is, again, a consequence of the commit "Drop some assumptions on how PlayerService is started and reused".
This commit notified VideoDetailFragment of player starting and stopping independently of the player.
Read the comments in the code changes for more information.
2025-02-18 19:27:46 +01:00
Stypox
126f4b0e30 Fix crash when closing video detail fragment
This bug started appearing because the way to close the player is now unified in PlayerHolder.stopService(), which causes the player to reach back to the video detail fragment with a notification of the shutdown (i.e. onServiceStopped() is called). This is fixed by adding a nullability check on the binding.
2025-02-18 18:03:10 +01:00
Stypox
6558794d26 Try to bind to PlayerService when MainActivity starts
Fixes mini-player not appearing on app start if the player service is already playing something.

The PlayerService (and the player) may be started from an external intent that does not involve the MainActivity (e.g. RouterActivity or Android Auto's media browser interface).
This PR tries to bind to the PlayerService as soon as the MainActivity starts, but only does so in a passive way, i.e. if the service is not already running it is not started.
Once the connection between PlayerHolder and PlayerService is setup, the ACTION_PLAYER_STARTED broadcast is sent to MainActivity so that it can setup the bottom mini-player.
Another important thing this commit does is to check whether the player is open before actually adding the mini-player view, since the PlayerService could be bound even without a running player (e.g. Android Auto's media browser is being used). This is a consequence of commit "Drop some assumptions on how PlayerService is started and reused".
2025-02-18 17:49:38 +01:00
Stypox
1d12874937 Merge pull request #12046 from TobiGr/weblate
Update translations
2025-02-16 22:01:41 +01:00
Stypox
1d98518bfa Fix loading remote playlists in media browser 2025-02-16 21:44:50 +01:00
Stypox
e5458bcb14 Properly handle item errors during media browser loading
Non-item errors, i.e. critical parsing errors of the page, are still handled properly.
2025-02-16 21:44:50 +01:00
Stypox
dc62d211f5 Properly stop PlayerService
This commit is a consequence of the commit "Drop some assumptions on how PlayerService is started and reused". Since the assumptions on how the PlayerService is started and reused have changed, we also need to adapt the way it is stopped. This means allowing the service to remain alive even after the player is destroyed, in case the system is still accessing PlayerService e.g. through the media browser interface. The foreground service needs to be stopped and the notification removed in any case.
2025-02-16 21:44:49 +01:00
Stypox
ec6612dd71 Call exoPlayer.prepare() on PlaybackPreparer.onPrepare()
If a playbackPreparer is set, then instead of calling `player.prepare()`, the MediaSessionConnector will call `playbackPreparer.onPrepare(true)` instead, as seen below.
This commit makes it so that playbackPreparer.onPrepare(true) restores the original behavior of just calling player.prepare().

From MediaSessionConnector -> MediaSessionCompat.Callback implementation:
```java
    @Override
    public void onPlay() {
      if (canDispatchPlaybackAction(PlaybackStateCompat.ACTION_PLAY)) {
        if (player.getPlaybackState() == Player.STATE_IDLE) {
          if (playbackPreparer != null) {
            playbackPreparer.onPrepare(/* playWhenReady= */ true);
          } else {
            player.prepare();
          }
        } else if (player.getPlaybackState() == Player.STATE_ENDED) {
          seekTo(player, player.getCurrentMediaItemIndex(), C.TIME_UNSET);
        }
        Assertions.checkNotNull(player).play();
      }
    }
```
2025-02-16 21:44:49 +01:00
Stypox
064e1d39c7 Use the media browser implementation in PlayerService
Now the media browser queries are replied to by MediaBrowserImpl

Co-authored-by: Haggai Eran <haggai.eran@gmail.com>
2025-02-16 21:44:05 +01:00
Stypox
4c88a193bd Add MediaBrowserImpl
This class implements the media browser service interface as a standalone class for clearer separation of concerns (otherwise everything would need to go in PlayerService, since PlayerService overrides MediaBrowserServiceCompat)

Co-authored-by: Haggai Eran <haggai.eran@gmail.com>
Co-authored-by: Profpatsch <mail@profpatsch.de>
2025-02-16 21:43:46 +01:00
Stypox
3fcac10e7f Add MediaBrowserPlaybackPreparer
This class will receive the media URLs generated by [MediaBrowserImpl] and will start playback of the corresponding streams or playlists.

Co-authored-by: Haggai Eran <haggai.eran@gmail.com>
Co-authored-by: Profpatsch <mail@profpatsch.de>
2025-02-16 21:43:35 +01:00
Stypox
6cedd117fe Add StreamHistoryEntry.toStreamInfoItem()
Co-authored-by: Haggai Eran <haggai.eran@gmail.com>
2025-02-16 21:40:55 +01:00
Stypox
5eabcb52b5 Add getThumbnailUrl() to PlaylistLocalItem interface
Co-authored-by: Haggai Eran <haggai.eran@gmail.com>
2025-02-16 21:40:48 +01:00
Stypox
690b40d0c4 Allow creating PlayQueue from ListInfo and index 2025-02-16 21:40:47 +01:00
Stypox
9bb2c0b484 Add getPlaylist(id) to RemotePlaylistManager
Co-authored-by: Haggai Eran <haggai.eran@gmail.com>
2025-02-16 21:40:36 +01:00
Stypox
1e08cc8c8f Add MediaBrowserCommon with info item's and pages' IDs
Co-authored-by: Haggai Eran <haggai.eran@gmail.com>
2025-02-16 21:40:29 +01:00
Stypox
7d17468266 Instantiate media session and connector in PlayerService
This changes significantly how the MediaSessionCompat and MediaSessionConnector objects are used:
- now they are tied to the service and not to the player, and so they might be reused with multiple players (which should be allowed)
- now they can exist even if there is no player (which is fundamental to be able to answer media browser queries)
2025-02-16 21:40:13 +01:00
Stypox
5819546ea9 Have PlayerService implement MediaBrowserServiceCompat
Co-authored-by: Haggai Eran <haggai.eran@gmail.com>
2025-02-16 21:36:59 +01:00
Stypox
cfb6e114d6 Disable logs about view animations by default 2025-02-16 10:31:42 +01:00
Stypox
b764ad33c4 Drop some assumptions on how PlayerService is started and reused
Read the comments in the lines changed to understand more
2025-02-15 17:48:19 +01:00
Hosted Weblate
430b4eb916 Translated using Weblate (Persian)
Currently translated at 92.7% (686 of 740 strings)

Translated using Weblate (Swedish)

Currently translated at 100.0% (84 of 84 strings)

Translated using Weblate (Turkish)

Currently translated at 100.0% (740 of 740 strings)

Translated using Weblate (Georgian)

Currently translated at 83.3% (70 of 84 strings)

Translated using Weblate (Estonian)

Currently translated at 16.6% (14 of 84 strings)

Translated using Weblate (Estonian)

Currently translated at 100.0% (740 of 740 strings)

Translated using Weblate (Mainfränkisch)

Currently translated at 1.0% (8 of 740 strings)

Translated using Weblate (Bavarian)

Currently translated at 3.9% (29 of 740 strings)

Translated using Weblate (German)

Currently translated at 100.0% (84 of 84 strings)

Added translation using Weblate (Mainfränkisch)

Translated using Weblate (Thai)

Currently translated at 36.6% (271 of 740 strings)

Translated using Weblate (Armenian)

Currently translated at 28.2% (209 of 740 strings)

Translated using Weblate (Georgian)

Currently translated at 85.7% (72 of 84 strings)

Translated using Weblate (Thai)

Currently translated at 34.3% (254 of 740 strings)

Translated using Weblate (Gujarati)

Currently translated at 11.3% (84 of 740 strings)

Translated using Weblate (Hungarian)

Currently translated at 100.0% (84 of 84 strings)

Translated using Weblate (Slovak)

Currently translated at 100.0% (84 of 84 strings)

Translated using Weblate (Nepali)

Currently translated at 1.1% (1 of 84 strings)

Translated using Weblate (Slovak)

Currently translated at 100.0% (84 of 84 strings)

Translated using Weblate (French)

Currently translated at 100.0% (84 of 84 strings)

Translated using Weblate (Portuguese)

Currently translated at 100.0% (740 of 740 strings)

Translated using Weblate (Gujarati)

Currently translated at 11.0% (82 of 740 strings)

Translated using Weblate (Arabic)

Currently translated at 100.0% (740 of 740 strings)

Co-authored-by: Alex25820 <alexs25820@gmail.com>
Co-authored-by: Bruno Fragoso <darth_signa@hotmail.com>
Co-authored-by: Davit Mayilyan <davit.mayilyan@protonmail.ch>
Co-authored-by: Emin Tufan Çetin <etcetin@gmail.com>
Co-authored-by: Garfield2150 <knd.garfield@gmail.com>
Co-authored-by: Ghost of Sparta <makesocialfoss32@keemail.me>
Co-authored-by: Goudarz Jafari <goudarz.jafari@gmail.com>
Co-authored-by: Hosted Weblate <hosted@weblate.org>
Co-authored-by: Kchenik Poudel <Kakapoudel7@gmail.com>
Co-authored-by: Kuko <kuko7@protonmail.ch>
Co-authored-by: Paul Sibila <p.aul@mail.de>
Co-authored-by: Priit Jõerüüt <hwlate@joeruut.com>
Co-authored-by: Rex_sa <rex.sa@pm.me>
Co-authored-by: Temuri Doghonadze <temuri.doghonadze@gmail.com>
Co-authored-by: freddyLovesUs <compteperso@outlook.com>
Co-authored-by: રાજ ભાતેલીઆ <rajbhatelia@gmail.com>
Translate-URL: https://hosted.weblate.org/projects/newpipe/metadata/de/
Translate-URL: https://hosted.weblate.org/projects/newpipe/metadata/et/
Translate-URL: https://hosted.weblate.org/projects/newpipe/metadata/fr/
Translate-URL: https://hosted.weblate.org/projects/newpipe/metadata/hu/
Translate-URL: https://hosted.weblate.org/projects/newpipe/metadata/ka/
Translate-URL: https://hosted.weblate.org/projects/newpipe/metadata/ne/
Translate-URL: https://hosted.weblate.org/projects/newpipe/metadata/sk/
Translate-URL: https://hosted.weblate.org/projects/newpipe/metadata/sv/
Translation: NewPipe/Metadata
2025-02-15 13:08:00 +01:00
Thiago F. G. Albuquerque
2339f51ad4 [#11930] Share as YouTube temporary playlist
Initial commit.
2025-02-14 21:14:42 -03:00
Stypox
99aae7eb28 Merge branch 'dev' into refactor 2025-02-05 15:15:41 +01:00
Stypox
c6e1721884 Add translated changelogs for v0.27.6 (1003)
Copied from 1002.txt
2025-02-05 11:30:37 +01:00
Stypox
94684fe380 Merge branch 'weblate-dev' into dev 2025-02-05 11:29:14 +01:00
Hosted Weblate
398a2f55ce Merge branch 'origin/dev' into Weblate. 2025-02-05 11:28:09 +01:00
Stypox
1f7b3b5b06 Add changelog for v0.27.6 (1003) 2025-02-05 11:25:58 +01:00
Stypox
909ed616c4 Hotfix release v0.27.6 (1003) 2025-02-05 11:14:17 +01:00
Stypox
dd223af28d Merge pull request #11955 from Stypox/po-token
[YouTube] Add support for poTokens
2025-02-05 10:52:16 +01:00
Stypox
dbee8d8128 Update NewPipeExtractor to v0.24.5
Using commit 9f83b385a since JitPack is buggy...
2025-02-05 10:24:34 +01:00
Stypox
b62a09b5b3 Use WebSettingsCompat.setSafeBrowsingEnabled 2025-02-04 21:50:10 +01:00
Stypox
87317c6faf Reorder functions in PoTokenWebView 2025-02-04 21:38:01 +01:00
Stypox
53b599b042 Make JavaScript code compatible with older WebViews 2025-02-04 21:38:01 +01:00
Stypox
21df24abfd Detect when WebView is broken and return null poToken
Some old Android devices have a broken WebView implementation, that can't execute the poToken code. This is now detected and the getWebClientPoToken return null instead of throwing an error in such a case, to allow the extractor to try to extract the video data even without a poToken.
2025-02-04 11:22:50 +01:00
Hosted Weblate
ca4592a935 Translated using Weblate (Russian)
Currently translated at 100.0% (740 of 740 strings)

Translated using Weblate (Estonian)

Currently translated at 13.2% (11 of 83 strings)

Translated using Weblate (Latin)

Currently translated at 8.6% (64 of 740 strings)

Translated using Weblate (Portuguese (Brazil))

Currently translated at 100.0% (740 of 740 strings)

Translated using Weblate (Azerbaijani)

Currently translated at 100.0% (740 of 740 strings)

Translated using Weblate (Hungarian)

Currently translated at 100.0% (83 of 83 strings)

Translated using Weblate (Turkish)

Currently translated at 48.1% (40 of 83 strings)

Translated using Weblate (Icelandic)

Currently translated at 99.4% (736 of 740 strings)

Translated using Weblate (Portuguese (Portugal))

Currently translated at 96.3% (80 of 83 strings)

Translated using Weblate (Swedish)

Currently translated at 100.0% (83 of 83 strings)

Translated using Weblate (Swedish)

Currently translated at 100.0% (740 of 740 strings)

Translated using Weblate (Vietnamese)

Currently translated at 78.3% (65 of 83 strings)

Translated using Weblate (Slovak)

Currently translated at 100.0% (740 of 740 strings)

Translated using Weblate (Bulgarian)

Currently translated at 100.0% (740 of 740 strings)

Translated using Weblate (German)

Currently translated at 100.0% (740 of 740 strings)

Translated using Weblate (German)

Currently translated at 100.0% (740 of 740 strings)

Translated using Weblate (Belarusian)

Currently translated at 100.0% (740 of 740 strings)

Translated using Weblate (Belarusian)

Currently translated at 100.0% (740 of 740 strings)

Translated using Weblate (German)

Currently translated at 100.0% (83 of 83 strings)

Translated using Weblate (German)

Currently translated at 100.0% (83 of 83 strings)

Translated using Weblate (German)

Currently translated at 100.0% (740 of 740 strings)

Translated using Weblate (Azerbaijani)

Currently translated at 100.0% (740 of 740 strings)

Translated using Weblate (Portuguese)

Currently translated at 100.0% (83 of 83 strings)

Translated using Weblate (Greek)

Currently translated at 100.0% (740 of 740 strings)

Translated using Weblate (Polish)

Currently translated at 100.0% (740 of 740 strings)

Translated using Weblate (Ukrainian)

Currently translated at 100.0% (740 of 740 strings)

Translated using Weblate (Indonesian)

Currently translated at 100.0% (740 of 740 strings)

Translated using Weblate (German)

Currently translated at 100.0% (740 of 740 strings)

Translated using Weblate (Icelandic)

Currently translated at 99.4% (736 of 740 strings)

Translated using Weblate (Arabic)

Currently translated at 100.0% (83 of 83 strings)

Translated using Weblate (Estonian)

Currently translated at 100.0% (740 of 740 strings)

Translated using Weblate (Arabic)

Currently translated at 100.0% (740 of 740 strings)

Translated using Weblate (Ukrainian)

Currently translated at 99.8% (739 of 740 strings)

Translated using Weblate (Chinese (Simplified Han script))

Currently translated at 100.0% (740 of 740 strings)

Translated using Weblate (Hungarian)

Currently translated at 100.0% (740 of 740 strings)

Translated using Weblate (ryu (generated) (ryu))

Currently translated at 99.4% (736 of 740 strings)

Translated using Weblate (N’Ko)

Currently translated at 89.4% (662 of 740 strings)

Translated using Weblate (Norwegian Nynorsk)

Currently translated at 19.8% (147 of 740 strings)

Translated using Weblate (Georgian)

Currently translated at 89.1% (660 of 740 strings)

Translated using Weblate (Icelandic)

Currently translated at 99.0% (733 of 740 strings)

Translated using Weblate (Kurdish (Northern))

Currently translated at 65.4% (484 of 740 strings)

Translated using Weblate (Somali)

Currently translated at 75.1% (556 of 740 strings)

Translated using Weblate (Uzbek (Latin script))

Currently translated at 62.0% (459 of 740 strings)

Translated using Weblate (English (United Kingdom))

Currently translated at 7.4% (55 of 740 strings)

Translated using Weblate (Odia)

Currently translated at 99.4% (736 of 740 strings)

Translated using Weblate (Santali)

Currently translated at 14.5% (108 of 740 strings)

Translated using Weblate (Bengali)

Currently translated at 76.7% (568 of 740 strings)

Translated using Weblate (Sardinian)

Currently translated at 99.5% (737 of 740 strings)

Translated using Weblate (Bengali (India))

Currently translated at 40.1% (297 of 740 strings)

Translated using Weblate (Kurdish (Central))

Currently translated at 84.0% (622 of 740 strings)

Translated using Weblate (Arabic (Libya))

Currently translated at 97.7% (723 of 740 strings)

Translated using Weblate (Malayalam)

Currently translated at 76.4% (566 of 740 strings)

Translated using Weblate (Interlingua)

Currently translated at 32.2% (239 of 740 strings)

Translated using Weblate (Filipino)

Currently translated at 31.3% (232 of 740 strings)

Translated using Weblate (Thai)

Currently translated at 30.0% (222 of 740 strings)

Translated using Weblate (Nepali)

Currently translated at 59.0% (437 of 740 strings)

Translated using Weblate (Danish)

Currently translated at 99.8% (739 of 740 strings)

Translated using Weblate (Galician)

Currently translated at 99.5% (737 of 740 strings)

Translated using Weblate (Malay)

Currently translated at 57.9% (429 of 740 strings)

Translated using Weblate (Belarusian)

Currently translated at 99.5% (737 of 740 strings)

Translated using Weblate (Norwegian Bokmål)

Currently translated at 94.0% (696 of 740 strings)

Translated using Weblate (Estonian)

Currently translated at 99.7% (738 of 740 strings)

Translated using Weblate (Punjabi)

Currently translated at 99.5% (737 of 740 strings)

Translated using Weblate (Albanian)

Currently translated at 79.8% (591 of 740 strings)

Translated using Weblate (Dutch (Belgium))

Currently translated at 75.1% (556 of 740 strings)

Translated using Weblate (Urdu)

Currently translated at 68.2% (505 of 740 strings)

Translated using Weblate (Azerbaijani)

Currently translated at 99.5% (737 of 740 strings)

Translated using Weblate (Catalan)

Currently translated at 87.0% (644 of 740 strings)

Translated using Weblate (Kurdish)

Currently translated at 63.7% (472 of 740 strings)

Translated using Weblate (Bulgarian)

Currently translated at 99.7% (738 of 740 strings)

Translated using Weblate (Telugu)

Currently translated at 58.1% (430 of 740 strings)

Translated using Weblate (Hindi)

Currently translated at 99.5% (737 of 740 strings)

Translated using Weblate (Finnish)

Currently translated at 97.9% (725 of 740 strings)

Translated using Weblate (Croatian)

Currently translated at 98.9% (732 of 740 strings)

Translated using Weblate (Vietnamese)

Currently translated at 99.5% (737 of 740 strings)

Translated using Weblate (Lithuanian)

Currently translated at 99.4% (736 of 740 strings)

Translated using Weblate (Swedish)

Currently translated at 99.8% (739 of 740 strings)

Translated using Weblate (Hebrew)

Currently translated at 99.4% (736 of 740 strings)

Translated using Weblate (Bengali (Bangladesh))

Currently translated at 54.3% (402 of 740 strings)

Translated using Weblate (Chinese (Traditional Han script))

Currently translated at 99.5% (737 of 740 strings)

Translated using Weblate (Chinese (Simplified Han script))

Currently translated at 99.7% (738 of 740 strings)

Translated using Weblate (Portuguese (Brazil))

Currently translated at 99.7% (738 of 740 strings)

Translated using Weblate (Asturian)

Currently translated at 63.3% (469 of 740 strings)

Translated using Weblate (Persian)

Currently translated at 92.4% (684 of 740 strings)

Translated using Weblate (Polish)

Currently translated at 99.5% (737 of 740 strings)

Translated using Weblate (Turkish)

Currently translated at 99.5% (737 of 740 strings)

Translated using Weblate (Ukrainian)

Currently translated at 99.5% (737 of 740 strings)

Translated using Weblate (Indonesian)

Currently translated at 99.7% (738 of 740 strings)

Translated using Weblate (Arabic)

Currently translated at 99.7% (738 of 740 strings)

Translated using Weblate (Czech)

Currently translated at 99.5% (737 of 740 strings)

Translated using Weblate (Esperanto)

Currently translated at 71.4% (529 of 740 strings)

Translated using Weblate (Slovak)

Currently translated at 99.8% (739 of 740 strings)

Translated using Weblate (Romanian)

Currently translated at 99.8% (739 of 740 strings)

Translated using Weblate (Chinese (Traditional Han script, Hong Kong))

Currently translated at 99.3% (735 of 740 strings)

Translated using Weblate (Basque)

Currently translated at 99.8% (739 of 740 strings)

Translated using Weblate (Italian)

Currently translated at 99.7% (738 of 740 strings)

Translated using Weblate (Korean)

Currently translated at 99.4% (736 of 740 strings)

Translated using Weblate (Japanese)

Currently translated at 99.4% (736 of 740 strings)

Translated using Weblate (Russian)

Currently translated at 99.5% (737 of 740 strings)

Translated using Weblate (Serbian)

Currently translated at 99.5% (737 of 740 strings)

Translated using Weblate (Dutch)

Currently translated at 99.5% (737 of 740 strings)

Translated using Weblate (Hungarian)

Currently translated at 99.5% (737 of 740 strings)

Translated using Weblate (Spanish)

Currently translated at 99.7% (738 of 740 strings)

Translated using Weblate (German)

Currently translated at 99.5% (737 of 740 strings)

Translated using Weblate (Spanish)

Currently translated at 100.0% (82 of 82 strings)

Translated using Weblate (Greek)

Currently translated at 100.0% (740 of 740 strings)

Translated using Weblate (Portuguese (Portugal))

Currently translated at 100.0% (740 of 740 strings)

Translated using Weblate (Portuguese)

Currently translated at 100.0% (740 of 740 strings)

Translated using Weblate (Tamil)

Currently translated at 100.0% (740 of 740 strings)

Translated using Weblate (Tamil)

Currently translated at 100.0% (82 of 82 strings)

Translated using Weblate (Tamil)

Currently translated at 100.0% (740 of 740 strings)

Translated using Weblate (French)

Currently translated at 100.0% (82 of 82 strings)

Translated using Weblate (Belarusian)

Currently translated at 100.0% (740 of 740 strings)

Translated using Weblate (Turkish)

Currently translated at 100.0% (740 of 740 strings)

Translated using Weblate (German)

Currently translated at 100.0% (740 of 740 strings)

Translated using Weblate (Macedonian)

Currently translated at 6.0% (5 of 82 strings)

Translated using Weblate (Macedonian)

Currently translated at 80.6% (597 of 740 strings)

Translated using Weblate (French)

Currently translated at 100.0% (82 of 82 strings)

Translated using Weblate (French)

Currently translated at 100.0% (740 of 740 strings)

Translated using Weblate (Belarusian)

Currently translated at 100.0% (740 of 740 strings)

Translated using Weblate (Swedish)

Currently translated at 100.0% (82 of 82 strings)

Translated using Weblate (Belarusian)

Currently translated at 100.0% (740 of 740 strings)

Translated using Weblate (Swedish)

Currently translated at 100.0% (740 of 740 strings)

Translated using Weblate (Romanian)

Currently translated at 100.0% (740 of 740 strings)

Translated using Weblate (French)

Currently translated at 100.0% (82 of 82 strings)

Translated using Weblate (Hungarian)

Currently translated at 100.0% (82 of 82 strings)

Translated using Weblate (Belarusian)

Currently translated at 100.0% (740 of 740 strings)

Translated using Weblate (Esperanto)

Currently translated at 71.7% (531 of 740 strings)

Translated using Weblate (Spanish)

Currently translated at 100.0% (740 of 740 strings)

Translated using Weblate (Kabyle)

Currently translated at 28.7% (213 of 740 strings)

Translated using Weblate (Estonian)

Currently translated at 12.1% (10 of 82 strings)

Translated using Weblate (Estonian)

Currently translated at 100.0% (740 of 740 strings)

Translated using Weblate (Gujarati)

Currently translated at 11.0% (82 of 740 strings)

Translated using Weblate (Azerbaijani)

Currently translated at 100.0% (740 of 740 strings)

Translated using Weblate (Estonian)

Currently translated at 10.9% (9 of 82 strings)

Translated using Weblate (Danish)

Currently translated at 100.0% (740 of 740 strings)

Translated using Weblate (Serbian)

Currently translated at 100.0% (740 of 740 strings)

Translated using Weblate (Arabic)

Currently translated at 100.0% (82 of 82 strings)

Translated using Weblate (Arabic)

Currently translated at 100.0% (740 of 740 strings)

Translated using Weblate (French)

Currently translated at 98.7% (81 of 82 strings)

Translated using Weblate (Estonian)

Currently translated at 100.0% (740 of 740 strings)

Translated using Weblate (French)

Currently translated at 100.0% (740 of 740 strings)

Translated using Weblate (Undetermined)

Currently translated at 2.4% (2 of 82 strings)

Translated using Weblate (Hungarian)

Currently translated at 100.0% (82 of 82 strings)

Translated using Weblate (Chinese (Traditional Han script, Hong Kong))

Currently translated at 28.0% (23 of 82 strings)

Translated using Weblate (Slovak)

Currently translated at 100.0% (82 of 82 strings)

Translated using Weblate (Dutch)

Currently translated at 100.0% (740 of 740 strings)

Translated using Weblate (Gujarati)

Currently translated at 9.4% (70 of 740 strings)

Translated using Weblate (Estonian)

Currently translated at 9.7% (8 of 82 strings)

Translated using Weblate (Spanish)

Currently translated at 100.0% (82 of 82 strings)

Translated using Weblate (Indonesian)

Currently translated at 100.0% (82 of 82 strings)

Translated using Weblate (Italian)

Currently translated at 100.0% (82 of 82 strings)

Translated using Weblate (Hungarian)

Currently translated at 74.3% (61 of 82 strings)

Translated using Weblate (Russian)

Currently translated at 98.7% (81 of 82 strings)

Translated using Weblate (Estonian)

Currently translated at 100.0% (740 of 740 strings)

Translated using Weblate (Italian)

Currently translated at 100.0% (740 of 740 strings)

Translated using Weblate (Italian)

Currently translated at 100.0% (740 of 740 strings)

Translated using Weblate (Russian)

Currently translated at 100.0% (740 of 740 strings)

Translated using Weblate (Hungarian)

Currently translated at 64.6% (53 of 82 strings)

Translated using Weblate (Czech)

Currently translated at 100.0% (82 of 82 strings)

Translated using Weblate (Ukrainian)

Currently translated at 100.0% (82 of 82 strings)

Translated using Weblate (Russian)

Currently translated at 97.5% (80 of 82 strings)

Translated using Weblate (German)

Currently translated at 100.0% (82 of 82 strings)

Translated using Weblate (Bulgarian)

Currently translated at 100.0% (740 of 740 strings)

Co-authored-by: Agnieszka C <aga_04@o2.pl>
Co-authored-by: Alex25820 <alexs25820@gmail.com>
Co-authored-by: Andrey F <firsan777@mail.ru>
Co-authored-by: Anonymous <noreply@weblate.org>
Co-authored-by: Anthony Romero <dagazcii@gmail.com>
Co-authored-by: ButterflyOfFire <boffire@users.noreply.hosted.weblate.org>
Co-authored-by: Bảo Nam (Namm) <namb20994@gmail.com>
Co-authored-by: C. Rüdinger <Mail-an-CR@web.de>
Co-authored-by: Ding User <dengus@users.noreply.hosted.weblate.org>
Co-authored-by: Emin Tufan Çetin <etcetin@gmail.com>
Co-authored-by: Femini <nizamismidov4@gmail.com>
Co-authored-by: Fjuro <fjuro@alius.cz>
Co-authored-by: GeoCup <geokapaniaris@gmail.com>
Co-authored-by: Ghost of Sparta <makesocialfoss32@keemail.me>
Co-authored-by: H Tamás <hovanszki@gmail.com>
Co-authored-by: Hosted Weblate <hosted@weblate.org>
Co-authored-by: Igor Sorocean <sorocean.igor@gmail.com>
Co-authored-by: Ihor Hordiichuk <igor_ck@outlook.com>
Co-authored-by: Jaidyn Ann <jadedctrl@posteo.net>
Co-authored-by: Linerly <linerly@proton.me>
Co-authored-by: Massimo Pissarello <mapi68@gmail.com>
Co-authored-by: MatthieuPh <matthieu.philippe@protonmail.com>
Co-authored-by: Mickaël Binos <mickaelbinos@outlook.com>
Co-authored-by: Miguel <mp0187595@tutamail.com>
Co-authored-by: Milan <mobrcian@hotmail.com>
Co-authored-by: NEXI <nexiphotographer@gmail.com>
Co-authored-by: Nicolas SALMIERI <1salmieri.nicolas@gmail.com>
Co-authored-by: NormalRandomPeople <normal.scribe833@silomails.com>
Co-authored-by: Philip Goto <philip.goto@gmail.com>
Co-authored-by: Priit Jõerüüt <hwlate@joeruut.com>
Co-authored-by: Random <random-r@users.noreply.hosted.weblate.org>
Co-authored-by: Rex_sa <rex.sa@pm.me>
Co-authored-by: Rijolo <rijolo4790@gholar.com>
Co-authored-by: Sveinn í Felli <sv1@fellsnet.is>
Co-authored-by: Szia Tomi <sziatomi01@gmail.com>
Co-authored-by: TobiGr <TobiGr@users.noreply.github.com>
Co-authored-by: VfBFan <VfBFan@users.noreply.hosted.weblate.org>
Co-authored-by: VfBFan <drop0815@posteo.de>
Co-authored-by: VisionR1 <25982450+VisionR1@users.noreply.github.com>
Co-authored-by: Vtrytobe <vtrytobe@gmail.com>
Co-authored-by: cat <catsnote@proton.me>
Co-authored-by: gallegonovato <fran-carro@hotmail.es>
Co-authored-by: gfbdrgng <hnaofegnp@hldrive.com>
Co-authored-by: hajayad577 <hajayad577@numerobo.com>
Co-authored-by: jpkaster 77 <jpkaster81@gmail.com>
Co-authored-by: polarwood <wreckfitzgerald@proton.me>
Co-authored-by: ssantos <ssantos@web.de>
Co-authored-by: trunars <trunars@gmail.com>
Co-authored-by: yummysheepouo <jerry88182821@gmail.com>
Co-authored-by: zmni <zmni@outlook.com>
Co-authored-by: Валентин Барсуков <valikbars04@gmail.com>
Co-authored-by: Максим Горпиніч <maksimgorpinic2005a@gmail.com>
Co-authored-by: Максим Горпиніч <mgorpinic2005@gmail.com>
Co-authored-by: મેબીરાજ <rajbhatelia@gmail.com>
Co-authored-by: રાજ ભાતેલીઆ <rajbhatelia@gmail.com>
Co-authored-by: தமிழ்நேரம் <anishprabu.t@gmail.com>
Co-authored-by: 大王叫我来巡山 <hamburger2048@users.noreply.hosted.weblate.org>
Translate-URL: https://hosted.weblate.org/projects/newpipe/metadata/ar/
Translate-URL: https://hosted.weblate.org/projects/newpipe/metadata/cs/
Translate-URL: https://hosted.weblate.org/projects/newpipe/metadata/de/
Translate-URL: https://hosted.weblate.org/projects/newpipe/metadata/es/
Translate-URL: https://hosted.weblate.org/projects/newpipe/metadata/et/
Translate-URL: https://hosted.weblate.org/projects/newpipe/metadata/fr/
Translate-URL: https://hosted.weblate.org/projects/newpipe/metadata/hu/
Translate-URL: https://hosted.weblate.org/projects/newpipe/metadata/id/
Translate-URL: https://hosted.weblate.org/projects/newpipe/metadata/it/
Translate-URL: https://hosted.weblate.org/projects/newpipe/metadata/mk/
Translate-URL: https://hosted.weblate.org/projects/newpipe/metadata/pt/
Translate-URL: https://hosted.weblate.org/projects/newpipe/metadata/pt_PT/
Translate-URL: https://hosted.weblate.org/projects/newpipe/metadata/ru/
Translate-URL: https://hosted.weblate.org/projects/newpipe/metadata/sk/
Translate-URL: https://hosted.weblate.org/projects/newpipe/metadata/sv/
Translate-URL: https://hosted.weblate.org/projects/newpipe/metadata/ta/
Translate-URL: https://hosted.weblate.org/projects/newpipe/metadata/tr/
Translate-URL: https://hosted.weblate.org/projects/newpipe/metadata/uk/
Translate-URL: https://hosted.weblate.org/projects/newpipe/metadata/und/
Translate-URL: https://hosted.weblate.org/projects/newpipe/metadata/vi/
Translate-URL: https://hosted.weblate.org/projects/newpipe/metadata/zh_Hant_HK/
Translation: NewPipe/Metadata
2025-02-04 10:59:39 +01:00
Stypox
3fc487310b Use Runnable instead of () -> Unit if converted to Runnable anyway 2025-02-04 10:23:45 +01:00
Stypox
056809cb0d Use "this" instead of "globalThis" as global scope
globalThis was introduced only on newer versions of JS
2025-02-04 10:22:10 +01:00
AudricV
a60bb3e7af [YouTube] Change BotGuard endpoint to youtube.com's one
This prevents non-abilities to fetch BotGuard challenge and send its
result with the jnn-pa.googleapis.com domain (domain block like done
on Pi-hole lists or DNS servers).

That's what the official website uses to send the challenge execution
result, however it uses InnerTube to fetch the challenge. Embeds
still use the jnn-pa.googleapis.com domain.

Also rename the makeJnnPaGoogleapisRequest method appropriately.
2025-02-03 13:05:39 +01:00
AudricV
ecd3f6c2ee [YouTube] Clarify BotGuard API key's origin and disable related Sonar warning 2025-02-01 15:40:16 +01:00
AudricV
70ff47b810 [YouTube] Get visitorData from the service to get valid responses 2025-02-01 15:39:07 +01:00
AudricV
b8e050f6c4 Adapt YoutubeHttpDataSource to extractor changes and improve requests
Always use POST requests and the same body that official HTML5 clients
use for a while.
2025-01-31 22:50:10 +01:00
AudricV
46d0bc1004 Update NewPipeExtractor 2025-01-31 22:28:08 +01:00
Stypox
e7fe84f2c7 Make sure downloadAndRunBotguard() is called after <script> loaded 2025-01-31 21:47:46 +01:00
Stypox
2b183a0576 Wrap logs in BuildConfig.DEBUG 2025-01-31 21:47:46 +01:00
Stypox
f856bd9306 Recreate poToken generator if current is broken
This will be tried only once, and afterwards an error will be thrown
2025-01-31 21:47:45 +01:00
Stypox
0066b322e1 Unify running on main thread 2025-01-31 21:47:45 +01:00
Stypox
3bdae81c0a Fix checkstyle 2025-01-31 21:47:45 +01:00
Stypox
6010c4ea7f Connect poToken generation to extractor 2025-01-31 21:47:45 +01:00
Stypox
690b3410e9 Interfaces for poTokens + WebView implementation 2025-01-31 21:47:44 +01:00
Profpatsch
ba86ce137b Merge pull request #11969 from neosis91/dev
DownloaderImpl: Auto-close resources and simplify header setting
2025-01-31 15:56:39 +01:00
Bertrand Jaunet
410c01547c DownloaderImpl: Auto-close resources and simplify header setting
The headers should be overwritten in the same way, based on how
`.header` is the same as `.removeHeader().addHeader()`.

We weren’t closing the request resources after using them, potentially
leaking file handles. This will add autoclosing for both the request
and the body objects.
2025-01-31 12:36:27 +01:00
Profpatsch
fd99c5e461 MainActivity: Fix onBackPressed handling for open player
The change
b9dd7078ad
accidentally moved the `return` into the `{}`, so the logic would fall
through to

```
if (fragmentManager.getBackStackEntryCount() == 1) {`
```

and close the app even though there are still items on the
`VideoFragmentDetail` stack.

To reproduce:
Start video, enqueue another video, then start a third video (which
adds one entry to the stack), and press `back` on the expanded video.

This should keep the player open and go back to the first 2-video
queue, but it actually closes the app before this fix.
2025-01-30 19:40:44 +01:00
Stypox
407d2d768d Merge pull request #11539 from Isira-Seneviratne/Compose-theme-improvements
Compose theme improvements
2025-01-28 14:02:50 +01:00
Stypox
47263f5254 Merge pull request #11959 from Stypox/fix-loading-stream-twice
Fix loading StreamInfo twice on first VideoDetailFragment opening
2025-01-27 14:56:51 +01:00
Stypox
01bf855015 Fix naming in VideoDetailFragment: video->stream, videoUrl->url 2025-01-27 14:52:35 +01:00
Profpatsch
ebf3008729 Merge pull request #11870 from TeamNewPipe/sidebar_donations
Add link to donation page on app drawer
2025-01-27 13:59:29 +01:00
Christian Schabesberger
33ecfb757e Sidebar: Add donation link to app drawer
This creates a donation link that leads to our donation page on the
NewPipe website.
2025-01-27 13:43:34 +01:00
Profpatsch
b109e4d3cc Merge pull request #11867 from Profpatsch/player-holder-refactor
PlayerHolder refactor
2025-01-27 13:29:53 +01:00
Profpatsch
137ade24ff Adjust javadoc format 2025-01-27 12:45:30 +01:00
Stypox
ffe26d882b Fix loading StreamInfo twice on first VideoDetailFragment opening 2025-01-26 12:39:07 +01:00
Stypox
83f8141fe7 Merge pull request #11806 from Thompson3142/fix_subtitle_size
Fix caption sizes not being changed
2025-01-25 18:10:56 +01:00
Isira Seneviratne
48d682016e Rm ViewPager version 2025-01-25 11:21:58 +05:30
Isira Seneviratne
b78e0b2da8 Merge branch 'refactor' into Compose-theme-improvements 2025-01-25 09:41:29 +05:30
Isira Seneviratne
32a88ab890 Truncate existing file in export 2025-01-25 07:57:01 +05:30
Isira Seneviratne
af3ed992e5 Add error handling for import 2025-01-25 05:40:00 +05:30
Isira Seneviratne
a79516dfff Use fragment arguments 2025-01-25 05:30:14 +05:30
Profpatsch
9253640fae Merge pull request #11887 from Nikunj-Aggarwal/bg-iso-timestamp
Convert error report timestamps to ISO format
2025-01-23 19:51:18 +01:00
Profpatsch
dbd11a6a8d SubscriptionImportWorker: inputs as sealed class 2025-01-22 15:34:04 +01:00
Isira Seneviratne
21973b362a Use Kotlin Pair 2025-01-22 13:03:57 +01:00
Isira Seneviratne
60586c90d6 Improve subscription upsert methods 2025-01-22 13:03:57 +01:00
Isira Seneviratne
095155d35f Only get subscription extractor when needed 2025-01-22 13:03:57 +01:00
Isira Seneviratne
af8e5646a6 Remove LocalBroadcastManager 2025-01-22 13:03:57 +01:00
Isira Seneviratne
c9d155a335 Combine notification and ForegroundInfo creation methods 2025-01-22 13:03:57 +01:00
Isira Seneviratne
4e31ccebf8 Moved Kotlinx Serialization to library catalog 2025-01-22 13:03:57 +01:00
Isira Seneviratne
c0965a42a1 Added success toasts 2025-01-22 13:03:57 +01:00
Isira Seneviratne
fc7f1b0af0 Convert subscription import service to a worker 2025-01-22 13:03:57 +01:00
Isira Seneviratne
dfb035dfa5 Improve import/export tests 2025-01-22 13:03:57 +01:00
Isira Seneviratne
8e9503cfe4 Convert subscription export service to a worker 2025-01-22 13:03:55 +01:00
Isira Seneviratne
82516dd75c Rename .java to .kt 2025-01-22 13:02:36 +01:00
Stypox
3e6e980362 Merge branch 'dev' into refactor 2025-01-22 11:12:51 +01:00
Stypox
8b5aa5cd9b Merge branch 'master' into dev 2025-01-22 11:10:22 +01:00
Stypox
58393ad4ef Release v0.27.5 (1002) 2025-01-21 23:34:42 +01:00
Stypox
977f7e28b5 Add changelogs for hotfix release v0.27.5 (1002) 2025-01-21 23:34:12 +01:00
Stypox
99e77249de Update NewPipeExtractor to v0.24.4 2025-01-21 23:19:49 +01:00
Profpatsch
1890fbb19a Merge pull request #11809 from Isira-Seneviratne/Merge-dev
Merge dev to refactor
2025-01-21 17:56:00 +01:00
Profpatsch
a955408053 Merge pull request #11928 from LeMeuble/bug-checksum-deleted-file
Fix the issue of getting the checksum of a removed file
2025-01-21 17:40:50 +01:00
Thompson3142
86203d6800 MainPlayer/PopupPlayer: Use system settings for subtitle size
This will use the exact subtitle sizes the user requested, both for
the main and the popup player. They will always be the same fraction
of the video, even if the popup player is resized.
2025-01-21 17:23:08 +01:00
Profpatsch
edd19641ac ErrorActivity: add Timestamp and Package/Service to markdown export
These were displayed in the UI, but not added into the markdown export
string.
2025-01-21 16:25:54 +01:00
Nikunj-Aggarwal
65749cbac0 ErrorActivity: Use a proper zoned ISO timestamp
Will have a timezone offset and be parsable as valid ISO8601
timestamp.

Also change the label in the UI to just say “Timestamp”
2025-01-21 16:24:07 +01:00
LeMeuble
658ddfc921 Fix issue of checksum for removed file 2025-01-16 10:46:25 +01:00
Isira Seneviratne
efb3aa530d Merge branch 'dev' into Merge-dev 2025-01-11 18:45:51 +05:30
Stypox
f7d0fd545d Merge pull request #11879 from tom93/pr/fix-image-minimizer-multiple-images
Fix image-minimizer on lines containing multiple images
2025-01-04 09:34:07 +01:00
Tom Levy
27e6be792f Fix image-minimizer on lines containing multiple images 2025-01-04 08:15:44 +00:00
Profpatsch
ce919215fb PlayerHolder: Separate holder and service event interface
Should make it easier to seperate the two further later, both of them
are only implemented by VideoDetailFragment anyway, which is kind of a
code smell!
2024-12-26 01:31:17 +01:00
Profpatsch
6a4aaba431 PlayerHolder: add some more docstrings 2024-12-26 01:02:59 +01:00
Profpatsch
83d93e16e7 PlayerHolder: move unbind right next to stopService 2024-12-26 00:36:49 +01:00
Profpatsch
8d15a141b1 PlayerHolder: invert isBound 2024-12-26 00:26:59 +01:00
Profpatsch
a78bed700a PlayerHolder: inline bind
Only used once. Now the code looks weird … why is the service started
twice??
2024-12-26 00:26:22 +01:00
Profpatsch
ef3c76645f PlayerHolder/PlayerService: inline & remove duplicate player passing
The player in playerHolder is exactly the player inside the
`PlayerService`, which in turn is exactly passed through the IBinder
interface. Thus we don’t have to pass both.

Instead add `PlayerService.getPlayer()`.

Also inline a few methods of `PlayerHolder` and simplify.
2024-12-25 22:14:22 +01:00
Isira Seneviratne
d4ed18bf08 Merge branch 'dev' into Merge-dev
# Conflicts:
#	app/build.gradle
#	app/src/main/java/org/schabi/newpipe/App.java
#	app/src/main/java/org/schabi/newpipe/about/AboutActivity.kt
#	app/src/main/java/org/schabi/newpipe/fragments/detail/VideoDetailFragment.java
#	app/src/main/java/org/schabi/newpipe/fragments/list/channel/ChannelFragment.java
#	app/src/main/java/org/schabi/newpipe/fragments/list/comments/CommentRepliesFragment.java
#	app/src/main/java/org/schabi/newpipe/fragments/list/videos/RelatedItemsFragment.java
#	app/src/main/java/org/schabi/newpipe/local/bookmark/BookmarkFragment.java
#	app/src/main/res/values-bg/strings.xml
#	app/src/main/res/values-da/strings.xml
#	app/src/main/res/values-is/strings.xml
#	app/src/main/res/values-lv/strings.xml
#	app/src/main/res/values-zh-rTW/strings.xml
#	build.gradle
2024-12-21 07:45:20 +05:30
Stypox
3fc0147f47 Merge pull request #11784 from Rishi2003Das/typo_change
Correct a Typo in Contributing.md
2024-12-17 10:42:34 +01:00
Isira Seneviratne
fbafdeb2ca Merge pull request #11767 from tsiflimagas/remove_viewpager2
Remove ViewPager2 dependency
2024-12-17 08:49:01 +05:30
Rishi Das
c6b05c6094 Update CONTRIBUTING.md 2024-12-08 02:00:41 +05:30
Rishi Das
240a2fe36b Update CONTRIBUTING.md 2024-12-08 02:00:04 +05:30
Rishi Das
de46e3abb3 Update CONTRIBUTING.md 2024-12-08 01:59:14 +05:30
Stypox
70748fa0bc Use JDK 21 in build-release-apk.yml
See https://github.com/TeamNewPipe/NewPipe/issues/11754
2024-12-02 13:49:30 +01:00
Kostas Giapis
781040efaa Remove ViewPager2 dependency 2024-12-01 22:24:39 +02:00
Isira Seneviratne
1547b50b4e Merge branch 'refactor' into Compose-theme-improvements 2024-11-28 06:12:33 +05:30
Stypox
3f7ef49979 NewPipe license is GPLv3-or-later, not -only, in AboutScreen 2024-11-27 22:15:23 +01:00
Stypox
dab0148a78 Merge pull request #11750 from Isira-Seneviratne/Fix-image-loading
Fix image loading
2024-11-27 16:50:38 +01:00
Stypox
c0c08a4f63 Merge pull request #11282 from Isira-Seneviratne/About-Compose
Migrate about activity to Jetpack Compose
2024-11-27 16:42:35 +01:00
Stypox
aaf337421d Merge branch 'refactor' into pr11282 2024-11-27 16:20:49 +01:00
Stypox
79a0edacd7 Merge pull request #11752 from JL0000/sort-dependencies
Sort dependencies in `libs.versions.toml`
2024-11-27 16:10:31 +01:00
Stypox
d56eef6ece Use content padding instead of padding on container 2024-11-27 15:59:20 +01:00
Stypox
72f054a4fa Library should not be clickable if spdx is blank 2024-11-27 15:46:39 +01:00
Jie Li
172c3c92ac gradle script to enforce dependencies order 2024-11-26 18:32:44 +00:00
Isira Seneviratne
137ef3fee4 Fix image loading 2024-11-26 10:08:27 +05:30
Stypox
e49156fb11 Merge pull request #11684 from JL0000/version-catalogs
Migrate build to version catalogs
2024-11-25 19:05:52 +01:00
Jie Li
de5d45849f migrated to version catalogs 2024-11-25 23:12:29 +05:30
Stypox
a25034b898 Fix toolbar colors in light theme 2024-11-25 04:43:43 +01:00
Stypox
ae9e82b2c1 Implement showing libraries and licenses 2024-11-25 04:43:43 +01:00
Stypox
a70b38a8e5 Minor updates to some libraries 2024-11-25 03:56:13 +01:00
Isira Seneviratne
08f3dba42c Merge branch 'refactor' into Compose-theme-improvements
# Conflicts:
#	app/src/main/java/org/schabi/newpipe/ui/components/common/NoItemsMessage.kt
#	app/src/main/java/org/schabi/newpipe/ui/components/video/comment/CommentRepliesDialog.kt
2024-11-25 07:22:03 +05:30
Stypox
0cff3a6ecd Improve AboutTab spacing 2024-11-24 16:06:21 +01:00
Profpatsch
9b78e49e45 Merge pull request #11725 from Profpatsch/lwj.compose_migrate_empty_state_view
Migrate empty_state_view xml/view to Jetpack Compose
2024-11-22 11:49:22 +01:00
Isira Seneviratne
e6eea8f851 Merge branch 'refactor' into Compose-theme-improvements 2024-11-21 21:26:03 +05:30
Isira Seneviratne
4e55f1bee6 Merge branch 'refactor' into About-Compose 2024-11-21 21:11:52 +05:30
Stypox
cff3834fde Fix setEmptyStateComposable dark theme 2024-11-21 13:17:33 +01:00
Stypox
c8b01a06b0 Use empty state view in compose 2024-11-21 13:14:39 +01:00
Stypox
414b1a8344 Remove unused methods in EmptyStateUtil 2024-11-21 13:14:19 +01:00
Stypox
404d9f3fac Use empty state view in a few more places 2024-11-21 12:42:58 +01:00
Stypox
55e4014036 Use custom EmptyStateSpec for bookmark fragment 2024-11-21 12:24:11 +01:00
Stypox
1cd5563b27 All empty states now have the same style 2024-11-21 12:14:40 +01:00
Stypox
1abced992b Use normal colors for empty state view 2024-11-21 12:07:03 +01:00
Stypox
46b9243661 Remove unneeded empty state changes in ChannelFragment 2024-11-21 11:53:48 +01:00
toliuweijing
ad72b2cb31 boost error hint color 2024-11-21 11:52:42 +01:00
toliuweijing
8b79d0ee29 Migrate empty_state_view to Jetpack Compose 2024-11-21 11:52:42 +01:00
Stypox
295f719b77 Merge pull request #11723 from Isira-Seneviratne/Coil-3
Migrate to Coil 3
2024-11-21 10:56:07 +01:00
Stypox
b584353f4d Small fixes to code style 2024-11-21 10:52:15 +01:00
Isira Seneviratne
d73314b4dd Make App instance variable immutable outside class 2024-11-21 08:09:57 +05:30
Isira Seneviratne
9f4a33c7a8 Fix lint 2024-11-21 06:56:10 +05:30
Isira Seneviratne
3a9540b042 Update app/src/main/java/org/schabi/newpipe/App.kt
Co-authored-by: Tobi <TobiGr@users.noreply.github.com>
2024-11-20 16:04:39 +05:30
Isira Seneviratne
ca855cbca0 Migrate to Coil 3 2024-11-20 09:28:20 +05:30
Isira Seneviratne
6a98b1dac7 Rename .java to .kt 2024-11-20 08:44:16 +05:30
Isira Seneviratne
7d4a2836fc Use existing scrollbar theme method 2024-11-16 16:45:35 +05:30
Isira Seneviratne
6ea715a18d Clean up unnecessary manual color specification in Compose code 2024-11-16 16:09:10 +05:30
Isira Seneviratne
a56debfce6 Merge branch 'refs/heads/refactor' into Compose-theme-improvements
# Conflicts:
#	app/src/main/java/org/schabi/newpipe/fragments/list/videos/RelatedItemsFragment.kt
#	app/src/main/java/org/schabi/newpipe/ui/components/items/ItemList.kt
2024-11-16 15:50:48 +05:30
Isira Seneviratne
226b6de34f Merge branch 'refs/heads/refactor' into About-Compose
# Conflicts:
#	app/src/main/java/org/schabi/newpipe/about/AboutActivity.kt
#	build.gradle
2024-11-16 15:41:50 +05:30
Stypox
13585ca0be Avoid drawing surface background twice for comments fragment 2024-11-11 16:15:36 +01:00
Stypox
62ab9bd740 Merge pull request #11060 from Isira-Seneviratne/Comments-Compose
Migrate comment fragments to Jetpack Compose
2024-11-11 16:12:53 +01:00
Stypox
fdf36cbad6 Deduplicate and improve Scrollbar theme 2024-11-11 15:20:38 +01:00
Stypox
aea2b7c7f3 Show correct reply count in dialog 2024-11-11 14:58:54 +01:00
Stypox
37d1c784fa Create utilities to copy to clipboard in Compose code 2024-11-11 14:58:54 +01:00
Stypox
cea149f852 Add .kotlin/ to gitignore 2024-11-11 14:26:01 +01:00
Stypox
a92a28517e Use Icons.Default.* instead of vector assets 2024-11-11 14:25:28 +01:00
Stypox
800961c3d7 Unexpand bottom sheet dialog when clicking on a channel 2024-11-11 13:51:24 +01:00
Stypox
9d8a79b0bd Slightly improve comment replies header spacing 2024-11-11 13:34:18 +01:00
Stypox
ef56dea817 Fix content color in comment replies fragment 2024-11-11 00:29:29 +01:00
Stypox
23b3835af0 Fix PagingSource for comments
The previous implementation was skipping the first page of comments
2024-11-11 00:16:32 +01:00
Stypox
412e1d602a Better handle unknown values for comment & like count 2024-11-10 23:45:10 +01:00
Stypox
802a094154 Improve comment replies dialog layout 2024-11-10 23:28:59 +01:00
Stypox
e6b1341246 Improve Comment layout 2024-11-10 23:09:29 +01:00
Stypox
36ede243e3 Update compose bom and fix navigation compose without version 2024-11-10 20:53:49 +01:00
Stypox
bac9f7eebf Merge branch 'refactor' into pr11060 2024-11-10 16:50:46 +01:00
litetex
8ada566bf1 Replaced `Icepick with Bridge and Android-State`
* IcePick fails on Java 21 (default in Android Studio 2024.2)
* Bridge is the most modern alternative that is currently available. It is backed by ``Android-State`` and can be configured with various frameworks
* In the long term this should be replaced with something better
2024-11-10 16:42:42 +01:00
litetex
5bd4ed77df Fix Android Gradle plugin warning 2024-11-10 16:42:42 +01:00
litetex
97652ac015 Update Gradle to latest version 2024-11-10 16:42:41 +01:00
litetex
6dd24033a4 Replace symlink with original
Co-Authored-By: Thompson3142 <115718208+thompson3142@users.noreply.github.com>
2024-11-10 16:42:41 +01:00
litetex
4de3ef20be Delete symlink 2024-11-10 16:42:41 +01:00
litetex
702f74291d Use working Extractor version
The tag can't be resolved by Jitpack so use the commit-hash instead
2024-11-10 16:42:41 +01:00
litetex
d8759993a9 CI: Use Java 21 2024-11-10 16:42:41 +01:00
litetex
7787eafd3a Fix build failing locally due to outdated kotlin version 2024-11-10 16:42:41 +01:00
Isira Seneviratne
4f4136c6e9 Merge branch 'refs/heads/refactor' into About-Compose
# Conflicts:
#	app/build.gradle
#	build.gradle
2024-10-22 20:15:07 +05:30
Siddhesh Naik
b399030e19 Settings redesign debug page (#10876)
Initial Work for Settings Page with Jetpack Compose

- Implemented a new settings page using Jetpack Compose.
- Added a new settings option to enable the redesigned settings page.
- This option allows for gradual integration and testing of the new
  settings page, minimizing disruptions to current functionality.

Plan for Settings Items:
- Jetpack Compose does not have a direct equivalent to the
  Preference/settings library.
- We could consider using third-party libraries that offer preference
  items as composables.
- However, these libraries may be incomplete or lack active development.
- Given our specific needs for only a subset of preference types,
  creating custom composables would be beneficial.
- This approach allows for fine-tuning the components to our specific
  use case.
2024-10-22 00:47:26 +05:30
Isira Seneviratne
0991461d04 Merge branch 'refs/heads/refactor' into About-Compose 2024-09-26 07:01:03 +05:30
Stypox
49bcf2c41b Merge branch 'dev' into refactor 2024-09-24 14:45:59 +02:00
Isira Seneviratne
c00c6c460c Add scaffold preview, use container color in about screen and scaffold 2024-09-17 04:26:36 +05:30
Isira Seneviratne
4c4fe3f511 Add scrollbar color scheme 2024-09-16 16:28:49 +05:30
Isira Seneviratne
db485c3d77 Remove unnecessary annotation 2024-09-16 16:15:37 +05:30
Isira Seneviratne
c0388d948b Add colors for Compose scrollbars 2024-09-16 15:33:41 +05:30
Isira Seneviratne
43bbddcc26 Add theme generated from the Material Theme Builder 2024-09-16 15:27:21 +05:30
Isira Seneviratne
6471b64ab6 Update dependencies 2024-09-16 12:53:16 +05:30
Isira Seneviratne
b9fcf0dff8 Enable edge-to-edge display 2024-09-16 12:45:03 +05:30
Isira Seneviratne
3177ca6e8a Avoid issues if context is a ContextWrapper 2024-09-11 21:57:51 +05:30
Isira Seneviratne
5017f4f05a Update dependencies 2024-09-05 09:23:00 +05:30
Isira Seneviratne
823d4a041f Improve loading indicator positioning 2024-08-30 16:59:15 +05:30
Isira Seneviratne
62d4044d6c Make lazy column scrollbars red 2024-08-30 09:02:56 +05:30
Isira Seneviratne
3785404618 Display number of comments 2024-08-30 08:46:02 +05:30
Isira Seneviratne
c98ad62163 Implement black theme in Compose 2024-08-29 08:06:56 +05:30
Isira Seneviratne
4cac111b66 Reduce preview count 2024-08-29 07:46:37 +05:30
Isira Seneviratne
941b8eb194 Implement copy on long click 2024-08-29 07:24:03 +05:30
Isira Seneviratne
b1add13bfd Address code review comments 2024-08-28 18:15:11 +05:30
Isira Seneviratne
5fffee2c7d Fix text color in bottom sheet 2024-08-28 17:59:38 +05:30
Isira Seneviratne
f9340ae604 Improve compose function organisation 2024-08-27 08:19:37 +05:30
Isira Seneviratne
d3a6991fd4 Use Fragment.content extension, improve comment composables 2024-08-26 19:29:46 +05:30
Isira Seneviratne
b0bfd4a807 Merge branch 'refs/heads/refactor' into About-Compose
# Conflicts:
#	app/build.gradle
#	app/src/main/java/org/schabi/newpipe/ktx/Bundle.kt
#	build.gradle
2024-08-23 20:16:19 +05:30
Isira Seneviratne
3641698379 Merge branch 'refs/heads/refactor' into Comments-Compose
# Conflicts:
#	app/build.gradle
2024-08-23 20:13:03 +05:30
Isira Seneviratne
2836191fb3 Migrate related items fragment to Jetpack Compose (#11383)
* Rename .java to .kt

* Migrate related items fragment to Jetpack Compose

* Specify mode parameter explicitly

* Rm unused class

* Fix list item size

* Added stream progress bar, separate stream and playlist thumbnails

* Display message if no related streams are available

* Dispose of related items when closing the video player

* Add modifiers for no items message function

* Implement remaining stream menu items

* Improved stream composables

* Use view model lifecycle scope

* Make live color solid red

* Use nested scroll modifier

* Simplify determineItemViewMode()
2024-08-23 19:51:32 +05:30
Isira Seneviratne
0df6c7fc2c Remove unused assets 2024-08-23 14:48:41 +05:30
Isira Seneviratne
b1ebd3ecd9 Update Compose BOM 2024-08-23 14:22:45 +05:30
Isira Seneviratne
4758244cf5 Use AboutLibraries to display library information 2024-08-23 14:05:50 +05:30
Isira Seneviratne
294b9cf347 Rm unused declaration 2024-08-17 08:25:39 +05:30
Isira Seneviratne
6d05af484e Use int array 2024-08-11 09:31:09 +05:30
Isira Seneviratne
e082bca5e0 Use nested scroll modifier 2024-08-11 08:23:13 +05:30
Isira Seneviratne
f9dae9078e Always show comment thumbnails, even if placeholders 2024-08-11 08:23:13 +05:30
Isira Seneviratne
e955beeef1 Update Kotlin to 2.0, update dependencies and fix issues 2024-08-11 08:23:10 +05:30
Isira Seneviratne
eaac7f3f85 Improved component organisation 2024-08-11 08:21:53 +05:30
Isira Seneviratne
ea414f57d4 Added DescriptionText composable 2024-08-11 08:21:53 +05:30
Isira Seneviratne
f984b26626 Fix some modifiers 2024-08-11 08:21:53 +05:30
Isira Seneviratne
edab9a6a1f Fix alignment of comment message 2024-08-11 08:21:53 +05:30
Isira Seneviratne
4740e3be86 Make parsed links clickable, visible 2024-08-11 08:21:53 +05:30
Isira Seneviratne
e639b02fed Animate comment expand/collapse 2024-08-11 08:21:53 +05:30
Isira Seneviratne
ac1ca1412d Improve comment loading smoothness 2024-08-11 08:21:52 +05:30
Isira Seneviratne
d131d3399a Rm unused method 2024-08-11 08:21:52 +05:30
Isira Seneviratne
1009dc4d4e Added loading indicator 2024-08-11 08:21:52 +05:30
Isira Seneviratne
42cb914616 Replace padding modifier with verticalArrangement in comment header 2024-08-11 08:21:52 +05:30
Isira Seneviratne
e72da94eb1 Rm extra padding in header 2024-08-11 08:21:52 +05:30
Isira Seneviratne
c5d94a5b60 Add comment view model 2024-08-11 08:21:52 +05:30
Isira Seneviratne
02c5f2607a Cache paging data using the cachedIn() extension 2024-08-11 08:21:52 +05:30
Isira Seneviratne
369a46f8fe Improve code organization 2024-08-11 08:21:52 +05:30
Isira Seneviratne
909d214002 Rm redundant Surface 2024-08-11 08:21:52 +05:30
Isira Seneviratne
5e7e14ee4d Handle no comments and comments disabled scenarios 2024-08-11 08:21:52 +05:30
Isira Seneviratne
b092fe2c76 Replace Spacers with the horizontalArrangement parameter 2024-08-11 08:21:52 +05:30
Isira Seneviratne
b9dd7078ad Replace CommentRepliesFragment with bottom sheet composable, improve previews 2024-08-11 08:21:52 +05:30
Isira Seneviratne
93310955f2 Added scrollbar to comment section 2024-08-11 08:21:52 +05:30
Isira Seneviratne
9c52e039ee Migrate comments fragment to Jetpack Compose 2024-08-11 08:21:52 +05:30
Isira Seneviratne
be037e0756 Rename .java to .kt 2024-08-11 08:21:52 +05:30
Isira Seneviratne
5bfb0449cf Fixed fragment title 2024-08-11 08:21:52 +05:30
Isira Seneviratne
0ec81c9e52 Fixed like count display 2024-08-11 08:21:52 +05:30
Isira Seneviratne
5841eaa6d7 Set view strategy 2024-08-11 08:21:52 +05:30
Isira Seneviratne
e92ba8f5d1 Add replies button 2024-08-11 08:21:52 +05:30
Isira Seneviratne
1908e18dc4 Use AnnotatedString to handle HTML parsing 2024-08-11 08:21:52 +05:30
Isira Seneviratne
e30d5e4305 Fixed some comment issues 2024-08-11 08:21:52 +05:30
Isira Seneviratne
11bb2495ba Improve previews, display date of comment 2024-08-11 08:21:52 +05:30
Isira Seneviratne
341cc37ce7 Update replies fragment to use the comment composable as well 2024-08-11 08:21:52 +05:30
Isira Seneviratne
1620668966 Add comment ellipsis 2024-08-11 08:21:51 +05:30
Isira Seneviratne
56c80ce6dd Added missing comment features, fixed theming 2024-08-11 08:21:51 +05:30
Isira Seneviratne
8ce9a7e43c Added like count 2024-08-11 08:21:51 +05:30
Isira Seneviratne
e05d97732e Use reply header composable in fragment 2024-08-11 08:21:51 +05:30
Isira Seneviratne
644a345b55 Rename .java to .kt 2024-08-11 08:21:51 +05:30
Isira Seneviratne
bda961a04c Convert comment replies views to Jetpack Compose 2024-08-11 08:21:51 +05:30
Isira Seneviratne
ba2efded76 Replace Picasso with Coil in about 2024-08-11 08:13:21 +05:30
Isira Seneviratne
b05b98ca61 Improved component organisation 2024-08-11 08:13:21 +05:30
Isira Seneviratne
7a7f81ac7f Fix tab text color 2024-08-11 08:13:21 +05:30
Isira Seneviratne
6e6c171dd7 Added new icon 2024-08-11 08:13:21 +05:30
Isira Seneviratne
8a41c8cf66 Added buttons to alert dialog 2024-08-11 08:13:21 +05:30
Isira Seneviratne
05271d95a9 Migrate about activity to Jetpack Compose 2024-08-11 08:13:21 +05:30
Isira Seneviratne
9d04a73c85 Merge dev to refactor (#11427)
* add NP icon for Android Studio's NewUI

* Fix NPE in MediaSessionPlayerUi while destroying player

* Update NewPipeExtractor to v0.24.1

* Add changelogs for hotfix release v0.27.1 (998)

* Hotfix release v0.27.1 (998)

* Update README.pt_BR.md (#11275)

* Update Matrix room link, and prioritise it (#11350)

* Update Matrix room link, and prioritise it

* Update Matrix room link in CONTRIBUTING.md

* Prioritise Matrix in contribution doc too

* Update NewPipeExtractor to v0.24.2

* Hotfix release v0.27.2 (999)

* Add changelogs for hotfix release v0.27.2 (999)

* Don't warn about rhino class in proguard

Likely related to 01a7b20655 but I am not completely sure.
I tested the app and it works well, so I think that org.mozilla.javascript.JavaToJSONConverters is not used really.

This is the full list of errors:
Missing class java.beans.BeanDescriptor (referenced from: java.lang.Object org.mozilla.javascript.JavaToJSONConverters.lambda$static$4(java.lang.Object))
Missing class java.beans.BeanInfo (referenced from: java.lang.Object org.mozilla.javascript.JavaToJSONConverters.lambda$static$4(java.lang.Object))
Missing class java.beans.IntrospectionException (referenced from: java.lang.Object org.mozilla.javascript.JavaToJSONConverters.lambda$static$4(java.lang.Object))
Missing class java.beans.Introspector (referenced from: java.lang.Object org.mozilla.javascript.JavaToJSONConverters.lambda$static$4(java.lang.Object))
Missing class java.beans.PropertyDescriptor (referenced from: java.lang.Object org.mozilla.javascript.JavaToJSONConverters.lambda$static$4(java.lang.Object))

* Remove code committed accidentally

---------

Co-authored-by: Christian Schabesberger <chris.schabesberger@mailbox.org>
Co-authored-by: Tobi <TobiGr@users.noreply.github.com>
Co-authored-by: Stypox <stypox@pm.me>
Co-authored-by: #27 <68751594+tag27@users.noreply.github.com>
Co-authored-by: opusforlife2 <53176348+opusforlife2@users.noreply.github.com>
2024-08-11 08:11:50 +05:30
Stypox
d336f4cef2 Merge pull request #11238 from Isira-Seneviratne/Coil
Migrate image loading from Picasso to Coil
2024-08-07 18:45:16 +02:00
Isira Seneviratne
4ec7532126 Addressed code review comments 2024-07-23 05:25:55 +05:30
Isira Seneviratne
da83646303 Update Coil 2024-07-22 08:12:37 +05:30
Isira Seneviratne
5062d38b65 Merge pull request #11237 from TeamNewPipe/revert-11201-Coil
Revert "Migrate image loading from Picasso to Coil"
2024-07-05 08:40:34 +05:30
Isira Seneviratne
82b492c050 Revert "Migrate image loading from Picasso to Coil (#11201)"
This reverts commit 73e3a69aaf.
2024-07-05 08:29:21 +05:30
Isira Seneviratne
73e3a69aaf Migrate image loading from Picasso to Coil (#11201)
* Load notification icons using Coil

* Migrate to Coil from Picasso

* Clean up Picasso leftovers

* Enable RGB-565 for low-end devices

* Added Coil helper method

* Add annotation

* Simplify newImageLoader implementation

* Use Coil's default disk and memory cache config

* Enable crossfade animation

* Correct method name

* Fix thumbnail not being displayed in media notification
2024-07-03 18:53:04 +05:30
Isira Seneviratne
348a79f91d Fix thumbnail not being displayed in media notification 2024-07-03 14:41:47 +05:30
Isira Seneviratne
c4ada7ff6e Correct method name 2024-07-03 09:30:47 +05:30
Isira Seneviratne
39d0691c7e Enable crossfade animation 2024-07-03 09:10:57 +05:30
Isira Seneviratne
71361de8ee Use Coil's default disk and memory cache config 2024-07-03 09:10:54 +05:30
Isira Seneviratne
8aa2590fd3 Simplify newImageLoader implementation 2024-07-03 09:10:52 +05:30
Isira Seneviratne
e3b7bf467e Add annotation 2024-07-03 09:10:49 +05:30
Isira Seneviratne
f74402bc94 Added Coil helper method 2024-07-03 09:10:46 +05:30
Isira Seneviratne
4d3b4a7b20 Enable RGB-565 for low-end devices 2024-07-03 09:10:44 +05:30
Isira Seneviratne
e6302cc868 Clean up Picasso leftovers 2024-07-03 09:10:40 +05:30
Isira Seneviratne
844b4edf48 Migrate to Coil from Picasso 2024-07-03 09:10:37 +05:30
Isira Seneviratne
92a7f22d3c Load notification icons using Coil 2024-07-03 09:10:34 +05:30
Isira Seneviratne
03167a1e9c Merge pull request #11234 from TeamNewPipe/dev
Merge dev to refactor
2024-07-03 09:05:32 +05:30
Stypox
d479f29e9b Merge pull request #10875 from snaik20/intro-jetpack-compose
Introducing Jetpack Compose in NewPipe
2024-05-13 21:17:11 +02:00
Siddhesh Naik
1af798b04b Introducing Jetpack Compose in NewPipe
This pull request integrates Jetpack Compose into NewPipe by:
- Adding the necessary dependencies and setup.
- This is part of the NewPipe rewrite and fulfils the requirement for
  the planned settings page redesign.
- Introducing a Toolbar composable with theming that aligns with
  NewPipe's design.

Note:
- Theme colors are generated using the Material Theme builder (https://m3.material.io/styles/color/overview).
2024-05-13 03:53:35 +05:30
723 changed files with 18763 additions and 11027 deletions

View File

@@ -6,7 +6,7 @@ NewPipe contribution guidelines
## Crash reporting
Report crashes through the **automated crash report system** of NewPipe.
This way all the data needed for debugging is included in your bugreport for GitHub.
This way all the data needed for debugging is included in your bug report for GitHub.
You'll see *exactly* what is sent, be able to add **your comments**, and then send it.
## Issue reporting/feature requests

View File

@@ -14,7 +14,7 @@ jobs:
- uses: actions/setup-java@v4
with:
distribution: 'temurin'
java-version: '17'
java-version: '21'
cache: 'gradle'
- name: "Build release APK"

View File

@@ -72,8 +72,8 @@ jobs:
- api-level: 21
target: default
arch: x86
- api-level: 33
target: google_apis # emulator API 33 only exists with Google APIs
- api-level: 35
target: default
arch: x86_64
permissions:
@@ -111,6 +111,7 @@ jobs:
path: app/build/reports/androidTests/connected/**
sonar:
if: ${{ false }} # the key has expired and needs to be regenerated by the sonar admins
runs-on: ubuntu-latest
permissions:

View File

@@ -32,12 +32,12 @@ module.exports = async ({github, context}) => {
}
// Regex for finding images (simple variant) ![ALT_TEXT](https://*.githubusercontent.com/<number>/<variousHexStringsAnd->.<fileExtension>)
const REGEX_USER_CONTENT_IMAGE_LOOKUP = /\!\[(.*)\]\((https:\/\/[-a-z0-9]+\.githubusercontent\.com\/\d+\/[-0-9a-f]{32,512}\.(jpg|gif|png))\)/gm;
const REGEX_ASSETS_IMAGE_LOCKUP = /\!\[(.*)\]\((https:\/\/github\.com\/[-\w\d]+\/[-\w\d]+\/assets\/\d+\/[\-0-9a-f]{32,512})\)/gm;
const REGEX_USER_CONTENT_IMAGE_LOOKUP = /\!\[([^\]]*)\]\((https:\/\/[-a-z0-9]+\.githubusercontent\.com\/\d+\/[-0-9a-f]{32,512}\.(jpg|gif|png))\)/gm;
const REGEX_ASSETS_IMAGE_LOOKUP = /\!\[([^\]]*)\]\((https:\/\/github\.com\/(?:user-attachments\/assets|[-\w\d]+\/[-\w\d]+\/assets\/\d+)\/[\-0-9a-f]{32,512})\)/gm;
// Check if we found something
let foundSimpleImages = REGEX_USER_CONTENT_IMAGE_LOOKUP.test(initialBody)
|| REGEX_ASSETS_IMAGE_LOCKUP.test(initialBody);
|| REGEX_ASSETS_IMAGE_LOOKUP.test(initialBody);
if (!foundSimpleImages) {
console.log('Found no simple images to process');
return;
@@ -52,7 +52,7 @@ module.exports = async ({github, context}) => {
// Try to find and replace the images with minimized ones
let newBody = await replaceAsync(initialBody, REGEX_USER_CONTENT_IMAGE_LOOKUP, minimizeAsync);
newBody = await replaceAsync(newBody, REGEX_ASSETS_IMAGE_LOCKUP, minimizeAsync);
newBody = await replaceAsync(newBody, REGEX_ASSETS_IMAGE_LOOKUP, minimizeAsync);
if (!wasMatchModified) {
console.log('Nothing was modified. Skipping update');

1
.gitignore vendored
View File

@@ -10,6 +10,7 @@ captures/
*.class
app/debug/
app/release/
.kotlin/
# vscode / eclipse files
*.classpath

View File

@@ -1,20 +1,26 @@
<h3 align="center">We are planning to <i>rewrite</i> large chunks of the codebase, to bring about <a href="https://github.com/TeamNewPipe/NewPipe/discussions/10118">a new, modern and stable NewPipe</a>!</h3>
<h4 align="center">Please do <b>not</b> open pull requests for <i>new features</i> now, only bugfix PRs will be accepted.</h4>
<h3 align="center">We are <i>rewriting</i> large chunks of the codebase, to bring about <a href="https://newpipe.net/blog/pinned/announcement/newpipe-0.27.6-rewrite-team-states/#the-refactor">a modern and stable NewPipe</a>! You can download nightly builds <a href="https://github.com/TeamNewPipe/NewPipe-refactor-nightly/releases">here</a>.</h3>
<h4 align="center">Please work on the <code>refactor</code> branch if you want to contribute <i>new features</i>. The current codebase is in maintenance mode and will only receive <i>bugfixes</i>.</h4>
<p align="center"><a href="https://newpipe.net"><img src="assets/new_pipe_icon_5.png" width="150"></a></p>
<h2 align="center"><b>NewPipe</b></h2>
<h4 align="center">A libre lightweight streaming front-end for Android.</h4>
<p align="center"><a href="https://f-droid.org/packages/org.schabi.newpipe/"><img src="https://fdroid.gitlab.io/artwork/badge/get-it-on-en.svg" alt="Get it on F-Droid" height=80/></a></p>
<p align="center"><a href="https://f-droid.org/packages/org.schabi.newpipe/"><img src="https://fdroid.gitlab.io/artwork/badge/get-it-on-en.svg" alt="Get it on F-Droid" width=206/></a></p>
<p align="center">
<a href="https://github.com/TeamNewPipe/NewPipe/releases" alt="GitHub release"><img src="https://img.shields.io/github/release/TeamNewPipe/NewPipe.svg" ></a>
<a href="https://github.com/TeamNewPipe/NewPipe/releases" alt="GitHub NewPipe releases"><img src="https://img.shields.io/github/release/TeamNewPipe/NewPipe.svg" ></a>
<a href="https://github.com/TeamNewPipe/NewPipe-nightly/releases" alt="GitHub NewPipe nightly releases"><img src="https://img.shields.io/github/release/TeamNewPipe/NewPipe-nightly.svg?labelColor=purple&label=dev%20nightly"></a>
<a href="https://github.com/TeamNewPipe/NewPipe-refactor-nightly/releases" alt="GitHub NewPipe refactor nightly releases"><img src="https://img.shields.io/github/release/TeamNewPipe/NewPipe-refactor-nightly.svg?labelColor=purple&label=refactor%20nightly"></a>
<a href="https://www.gnu.org/licenses/gpl-3.0" alt="License: GPLv3"><img src="https://img.shields.io/badge/License-GPL%20v3-blue.svg"></a>
<a href="https://github.com/TeamNewPipe/NewPipe/actions" alt="Build Status"><img src="https://github.com/TeamNewPipe/NewPipe/workflows/CI/badge.svg?branch=dev&event=push"></a>
<a href="https://github.com/TeamNewPipe/NewPipe/actions" alt="Build Status"><img src="https://github.com/TeamNewPipe/NewPipe/actions/workflows/ci.yml/badge.svg?branch=dev&event=push"></a>
<a href="https://hosted.weblate.org/engage/newpipe/" alt="Translation Status"><img src="https://hosted.weblate.org/widgets/newpipe/-/svg-badge.svg"></a>
</p>
<p align="center">
<a href="https://web.libera.chat/#newpipe" alt="IRC channel: #newpipe"><img src="https://img.shields.io/badge/IRC%20chat-%23newpipe-brightgreen.svg"></a>
<a href="https://matrix.to/#/#newpipe:matrix.newpipe-ev.de" alt="Matrix channel: #newpipe"><img src="https://img.shields.io/badge/Matrix%20chat-%23newpipe-blue"></a>
</p>
<hr>
<p align="center"><a href="#screenshots">Screenshots</a> &bull; <a href="#supported-services">Supported Services</a> &bull; <a href="#description">Description</a> &bull; <a href="#features">Features</a> &bull; <a href="#installation-and-updates">Installation and updates</a> &bull; <a href="#contribution">Contribution</a> &bull; <a href="#donate">Donate</a> &bull; <a href="#license">License</a></p>
<p align="center"><a href="https://newpipe.net">Website</a> &bull; <a href="https://newpipe.net/blog/">Blog</a> &bull; <a href="https://newpipe.net/FAQ/">FAQ</a> &bull; <a href="https://newpipe.net/press/">Press</a></p>

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,48 @@
tasks.register('checkDependenciesOrder') {
group = 'verification'
description = 'Checks that each section in libs.versions.toml is sorted alphabetically'
def tomlFile = file('../gradle/libs.versions.toml')
doLast {
if (!tomlFile.exists()) {
throw new GradleException('TOML file not found')
}
def lines = tomlFile.readLines()
def nonSortedBlocks = []
def currentBlock = []
def prevLine = ''
def prevIndex = 0
lines.eachWithIndex { line, lineIndex ->
if (line.trim() && !line.startsWith('#')) {
if (line.startsWith('[')) {
prevLine = ''
} else {
def currIndex = lineIndex + 1
if (prevLine > line) {
if (currentBlock && currentBlock[-1] == "${prevIndex}: ${prevLine}") {
currentBlock.add("${currIndex}: ${line}")
} else {
if (!currentBlock.isEmpty()) {
nonSortedBlocks.add(currentBlock)
currentBlock = []
}
currentBlock.add("${prevIndex}: ${prevLine}")
currentBlock.add("${currIndex}: ${line}")
}
}
prevLine = line
prevIndex = lineIndex + 1
}
}
}
if (!currentBlock.isEmpty()) {
nonSortedBlocks.add(currentBlock)
throw new GradleException("The following lines were not sorted:\n" +
nonSortedBlocks.collect { it.join("\n") }.join("\n\n"))
}
}
}

View File

@@ -5,10 +5,17 @@
## Rules for NewPipeExtractor
-keep class org.schabi.newpipe.extractor.timeago.patterns.** { *; }
## Rules for Rhino and Rhino Engine
-keep class org.mozilla.javascript.* { *; }
-keep class org.mozilla.javascript.** { *; }
-keep class org.mozilla.javascript.engine.** { *; }
-keep class org.mozilla.classfile.ClassFileWriter
-dontwarn org.mozilla.javascript.JavaToJSONConverters
-dontwarn org.mozilla.javascript.tools.**
-keep class javax.script.** { *; }
-dontwarn javax.script.**
-keep class jdk.dynalink.** { *; }
-dontwarn jdk.dynalink.**
## Rules for ExoPlayer
-keep class com.google.android.exoplayer2.** { *; }
@@ -27,3 +34,18 @@
## For some reason NotificationModeConfigFragment wasn't kept (only referenced in a preference xml)
-keep class org.schabi.newpipe.settings.notifications.** { *; }
## Keep Kotlinx Serialization classes
-keepclassmembers class kotlinx.serialization.json.** {
*** Companion;
}
-keepclasseswithmembers class kotlinx.serialization.json.** {
kotlinx.serialization.KSerializer serializer(...);
}
-keep,includedescriptorclasses class org.schabi.newpipe.**$$serializer { *; }
-keepclassmembers class org.schabi.newpipe.** {
*** Companion;
}
-keepclasseswithmembers class org.schabi.newpipe.** {
kotlinx.serialization.KSerializer serializer(...);
}

View File

@@ -12,6 +12,7 @@ import org.schabi.newpipe.extractor.ServiceList;
import org.schabi.newpipe.extractor.exceptions.ParsingException;
import java.util.Arrays;
import java.util.Objects;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;
@@ -23,8 +24,23 @@ import static org.junit.Assert.assertTrue;
@LargeTest
public class ErrorInfoTest {
/**
* @param errorInfo the error info to access
* @return the private field errorInfo.message.stringRes using reflection
*/
private int getMessageFromErrorInfo(final ErrorInfo errorInfo)
throws NoSuchFieldException, IllegalAccessException {
final var message = ErrorInfo.class.getDeclaredField("message");
message.setAccessible(true);
final var messageValue = (ErrorInfo.Companion.ErrorMessage) message.get(errorInfo);
final var stringRes = ErrorInfo.Companion.ErrorMessage.class.getDeclaredField("stringRes");
stringRes.setAccessible(true);
return (int) Objects.requireNonNull(stringRes.get(messageValue));
}
@Test
public void errorInfoTestParcelable() {
public void errorInfoTestParcelable() throws NoSuchFieldException, IllegalAccessException {
final ErrorInfo info = new ErrorInfo(new ParsingException("Hello"),
UserAction.USER_REPORT, "request", ServiceList.YouTube.getServiceId());
// Obtain a Parcel object and write the parcelable object to it:
@@ -39,7 +55,7 @@ public class ErrorInfoTest {
assertEquals(ServiceList.YouTube.getServiceInfo().getName(),
infoFromParcel.getServiceName());
assertEquals("request", infoFromParcel.getRequest());
assertEquals(R.string.parsing_error, infoFromParcel.getMessageStringId());
assertEquals(R.string.parsing_error, getMessageFromErrorInfo(infoFromParcel));
parcel.recycle();
}

View File

@@ -9,6 +9,8 @@
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW" />
<uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
<uses-permission android:name="android.permission.FOREGROUND_SERVICE_DATA_SYNC" />
<uses-permission android:name="android.permission.FOREGROUND_SERVICE_MEDIA_PLAYBACK" />
<uses-permission android:name="android.permission.POST_NOTIFICATIONS"/>
<!-- We need to be able to open links in the browser on API 30+ -->
@@ -57,6 +59,15 @@
</intent-filter>
</receiver>
<service
android:name="androidx.appcompat.app.AppLocalesMetadataHolderService"
android:enabled="false"
android:exported="false">
<meta-data
android:name="autoStoreLocales"
android:value="true" />
</service>
<service
android:name=".player.PlayerService"
android:exported="true"
@@ -64,6 +75,9 @@
<intent-filter>
<action android:name="android.intent.action.MEDIA_BUTTON" />
</intent-filter>
<intent-filter>
<action android:name="android.media.browse.MediaBrowserService"/>
</intent-filter>
</service>
<activity
@@ -77,14 +91,24 @@
android:exported="false"
android:label="@string/settings" />
<activity
android:name=".settings.SettingsV2Activity"
android:exported="true"
android:label="@string/settings" />
<activity
android:name=".about.AboutActivity"
android:exported="false"
android:label="@string/title_activity_about" />
<service android:name=".local.subscription.services.SubscriptionsImportService" />
<service android:name=".local.subscription.services.SubscriptionsExportService" />
<service android:name=".local.feed.service.FeedLoadService" />
<service
android:name="androidx.work.impl.foreground.SystemForegroundService"
android:foregroundServiceType="dataSync"
tools:node="merge" />
<service
android:name=".local.feed.service.FeedLoadService"
android:foregroundServiceType="dataSync" />
<activity
android:name=".PanicResponderActivity"
@@ -116,7 +140,9 @@
android:label="@string/app_name"
android:launchMode="singleTask" />
<service android:name="us.shandian.giga.service.DownloadManagerService" />
<service
android:name="us.shandian.giga.service.DownloadManagerService"
android:foregroundServiceType="dataSync" />
<activity
android:name=".util.FilePickerActivityHelper"
@@ -409,6 +435,7 @@
</activity>
<service
android:name=".RouterActivity$FetcherService"
android:foregroundServiceType="dataSync"
android:exported="false" />
<!-- opting out of sending metrics to Google in Android System WebView -->
@@ -424,5 +451,10 @@
<meta-data
android:name="com.samsung.android.multidisplay.keep_process_alive"
android:value="true" />
<!-- Android Auto -->
<meta-data android:name="com.google.android.gms.car.application"
android:resource="@xml/automotive_app_desc" />
<meta-data android:name="com.google.android.gms.car.notification.SmallIcon"
android:resource="@mipmap/ic_launcher" />
</application>
</manifest>

View File

@@ -0,0 +1,127 @@
<!DOCTYPE html>
<html lang="en"><head><title></title><script>
/**
* Factory method to create and load a BotGuardClient instance.
* @param options - Configuration options for the BotGuardClient.
* @returns A promise that resolves to a loaded BotGuardClient instance.
*/
function loadBotGuard(challengeData) {
this.vm = this[challengeData.globalName];
this.program = challengeData.program;
this.vmFunctions = {};
this.syncSnapshotFunction = null;
if (!this.vm)
throw new Error('[BotGuardClient]: VM not found in the global object');
if (!this.vm.a)
throw new Error('[BotGuardClient]: Could not load program');
const vmFunctionsCallback = function (
asyncSnapshotFunction,
shutdownFunction,
passEventFunction,
checkCameraFunction
) {
this.vmFunctions = {
asyncSnapshotFunction: asyncSnapshotFunction,
shutdownFunction: shutdownFunction,
passEventFunction: passEventFunction,
checkCameraFunction: checkCameraFunction
};
};
this.syncSnapshotFunction = this.vm.a(this.program, vmFunctionsCallback, true, this.userInteractionElement, function () {/** no-op */ }, [ [], [] ])[0]
// an asynchronous function runs in the background and it will eventually call
// `vmFunctionsCallback`, however we need to manually tell JavaScript to pass
// control to the things running in the background by interrupting this async
// function in any way, e.g. with a delay of 1ms. The loop is most probably not
// needed but is there just because.
return new Promise(function (resolve, reject) {
i = 0
refreshIntervalId = setInterval(function () {
if (!!this.vmFunctions.asyncSnapshotFunction) {
resolve(this)
clearInterval(refreshIntervalId);
}
if (i >= 10000) {
reject("asyncSnapshotFunction is null even after 10 seconds")
clearInterval(refreshIntervalId);
}
i += 1;
}, 1);
})
}
/**
* Takes a snapshot asynchronously.
* @returns The snapshot result.
* @example
* ```ts
* const result = await botguard.snapshot({
* contentBinding: {
* c: "a=6&a2=10&b=SZWDwKVIuixOp7Y4euGTgwckbJA&c=1729143849&d=1&t=7200&c1a=1&c6a=1&c6b=1&hh=HrMb5mRWTyxGJphDr0nW2Oxonh0_wl2BDqWuLHyeKLo",
* e: "ENGAGEMENT_TYPE_VIDEO_LIKE",
* encryptedVideoId: "P-vC09ZJcnM"
* }
* });
*
* console.log(result);
* ```
*/
function snapshot(args) {
return new Promise(function (resolve, reject) {
if (!this.vmFunctions.asyncSnapshotFunction)
return reject(new Error('[BotGuardClient]: Async snapshot function not found'));
this.vmFunctions.asyncSnapshotFunction(function (response) { resolve(response) }, [
args.contentBinding,
args.signedTimestamp,
args.webPoSignalOutput,
args.skipPrivacyBuffer
]);
});
}
function runBotGuard(challengeData) {
const interpreterJavascript = challengeData.interpreterJavascript.privateDoNotAccessOrElseSafeScriptWrappedValue;
if (interpreterJavascript) {
new Function(interpreterJavascript)();
} else throw new Error('Could not load VM');
const webPoSignalOutput = [];
return loadBotGuard({
globalName: challengeData.globalName,
globalObj: this,
program: challengeData.program
}).then(function (botguard) {
return botguard.snapshot({ webPoSignalOutput: webPoSignalOutput })
}).then(function (botguardResponse) {
return { webPoSignalOutput: webPoSignalOutput, botguardResponse: botguardResponse }
})
}
function obtainPoToken(webPoSignalOutput, integrityToken, identifier) {
const getMinter = webPoSignalOutput[0];
if (!getMinter)
throw new Error('PMD:Undefined');
const mintCallback = getMinter(integrityToken);
if (!(mintCallback instanceof Function))
throw new Error('APF:Failed');
const result = mintCallback(identifier);
if (!result)
throw new Error('YNJ:Undefined');
if (!(result instanceof Uint8Array))
throw new Error('ODM:Invalid');
return result;
}
</script></head><body></body></html>

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,22 @@
package org.schabi.newpipe
import android.content.Context
import android.content.SharedPreferences
import androidx.preference.PreferenceManager
import dagger.Module
import dagger.Provides
import dagger.hilt.InstallIn
import dagger.hilt.android.qualifiers.ApplicationContext
import dagger.hilt.components.SingletonComponent
import javax.inject.Singleton
@Module
@InstallIn(SingletonComponent::class)
class AppModule {
@Provides
@Singleton
fun providesSharedPreference(@ApplicationContext context: Context): SharedPreferences {
return PreferenceManager.getDefaultSharedPreferences(context)
}
}

View File

@@ -29,7 +29,7 @@ import okhttp3.ResponseBody;
public final class DownloaderImpl extends Downloader {
public static final String USER_AGENT =
"Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:128.0) Gecko/20100101 Firefox/128.0";
"Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:140.0) Gecko/20100101 Firefox/140.0";
public static final String YOUTUBE_RESTRICTED_MODE_COOKIE_KEY =
"youtube_restricted_mode_key";
public static final String YOUTUBE_RESTRICTED_MODE_COOKIE = "PREF=f2=8000000";
@@ -48,6 +48,11 @@ public final class DownloaderImpl extends Downloader {
this.mCookies = new HashMap<>();
}
@NonNull
public OkHttpClient getClient() {
return client;
}
/**
* It's recommended to call exactly once in the entire lifetime of the application.
*
@@ -137,7 +142,8 @@ public final class DownloaderImpl extends Downloader {
}
final okhttp3.Request.Builder requestBuilder = new okhttp3.Request.Builder()
.method(httpMethod, requestBody).url(url)
.method(httpMethod, requestBody)
.url(url)
.addHeader("User-Agent", USER_AGENT);
final String cookies = getCookies(url);
@@ -145,38 +151,33 @@ public final class DownloaderImpl extends Downloader {
requestBuilder.addHeader("Cookie", cookies);
}
for (final Map.Entry<String, List<String>> pair : headers.entrySet()) {
final String headerName = pair.getKey();
final List<String> headerValueList = pair.getValue();
headers.forEach((headerName, headerValueList) -> {
requestBuilder.removeHeader(headerName);
headerValueList.forEach(headerValue ->
requestBuilder.addHeader(headerName, headerValue));
});
if (headerValueList.size() > 1) {
requestBuilder.removeHeader(headerName);
for (final String headerValue : headerValueList) {
requestBuilder.addHeader(headerName, headerValue);
}
} else if (headerValueList.size() == 1) {
requestBuilder.header(headerName, headerValueList.get(0));
try (
okhttp3.Response response = client.newCall(requestBuilder.build()).execute()
) {
if (response.code() == 429) {
throw new ReCaptchaException("reCaptcha Challenge requested", url);
}
String responseBodyToReturn = null;
try (ResponseBody body = response.body()) {
if (body != null) {
responseBodyToReturn = body.string();
}
}
final String latestUrl = response.request().url().toString();
return new Response(
response.code(),
response.message(),
response.headers().toMultimap(),
responseBodyToReturn,
latestUrl);
}
final okhttp3.Response response = client.newCall(requestBuilder.build()).execute();
if (response.code() == 429) {
response.close();
throw new ReCaptchaException("reCaptcha Challenge requested", url);
}
final ResponseBody body = response.body();
String responseBodyToReturn = null;
if (body != null) {
responseBodyToReturn = body.string();
}
final String latestUrl = response.request().url().toString();
return new Response(response.code(), response.message(), response.headers().toMultimap(),
responseBodyToReturn, latestUrl);
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -58,20 +58,10 @@ import org.schabi.newpipe.extractor.NewPipe;
import org.schabi.newpipe.extractor.StreamingService;
import org.schabi.newpipe.extractor.StreamingService.LinkType;
import org.schabi.newpipe.extractor.channel.ChannelInfo;
import org.schabi.newpipe.extractor.exceptions.AgeRestrictedContentException;
import org.schabi.newpipe.extractor.exceptions.ContentNotAvailableException;
import org.schabi.newpipe.extractor.exceptions.ContentNotSupportedException;
import org.schabi.newpipe.extractor.exceptions.ExtractionException;
import org.schabi.newpipe.extractor.exceptions.GeographicRestrictionException;
import org.schabi.newpipe.extractor.exceptions.PaidContentException;
import org.schabi.newpipe.extractor.exceptions.PrivateContentException;
import org.schabi.newpipe.extractor.exceptions.ReCaptchaException;
import org.schabi.newpipe.extractor.exceptions.SoundCloudGoPlusContentException;
import org.schabi.newpipe.extractor.exceptions.YoutubeMusicPremiumContentException;
import org.schabi.newpipe.extractor.linkhandler.ListLinkHandler;
import org.schabi.newpipe.extractor.playlist.PlaylistInfo;
import org.schabi.newpipe.extractor.stream.StreamInfo;
import org.schabi.newpipe.ktx.ExceptionUtils;
import org.schabi.newpipe.local.dialog.PlaylistDialog;
import org.schabi.newpipe.player.PlayerType;
import org.schabi.newpipe.player.helper.PlayerHelper;
@@ -84,7 +74,6 @@ import org.schabi.newpipe.util.ChannelTabHelper;
import org.schabi.newpipe.util.Constants;
import org.schabi.newpipe.util.DeviceUtils;
import org.schabi.newpipe.util.ExtractorHelper;
import org.schabi.newpipe.util.Localization;
import org.schabi.newpipe.util.NavigationHelper;
import org.schabi.newpipe.util.PermissionHelper;
import org.schabi.newpipe.util.ThemeHelper;
@@ -132,7 +121,6 @@ public class RouterActivity extends AppCompatActivity {
ThemeHelper.setDayNightMode(this);
setTheme(ThemeHelper.isLightThemeSelected(this)
? R.style.RouterActivityThemeLight : R.style.RouterActivityThemeDark);
Localization.assureCorrectAppLanguage(this);
// Pass-through touch events to background activities
// so that our transparent window won't lock UI in the mean time
@@ -262,7 +250,8 @@ public class RouterActivity extends AppCompatActivity {
showUnsupportedUrlDialog(url);
}
}, throwable -> handleError(this, new ErrorInfo(throwable,
UserAction.SHARE_TO_NEWPIPE, "Getting service from url: " + url))));
UserAction.SHARE_TO_NEWPIPE, "Getting service from url: " + url,
null, url))));
}
/**
@@ -271,40 +260,19 @@ public class RouterActivity extends AppCompatActivity {
* @param errorInfo the error information
*/
private static void handleError(final Context context, final ErrorInfo errorInfo) {
if (errorInfo.getThrowable() != null) {
errorInfo.getThrowable().printStackTrace();
}
if (errorInfo.getThrowable() instanceof ReCaptchaException) {
if (errorInfo.getRecaptchaUrl() != null) {
Toast.makeText(context, R.string.recaptcha_request_toast, Toast.LENGTH_LONG).show();
// Starting ReCaptcha Challenge Activity
final Intent intent = new Intent(context, ReCaptchaActivity.class);
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
intent.putExtra(ReCaptchaActivity.RECAPTCHA_URL_EXTRA, errorInfo.getRecaptchaUrl());
context.startActivity(intent);
} else if (errorInfo.getThrowable() != null
&& ExceptionUtils.isNetworkRelated(errorInfo.getThrowable())) {
Toast.makeText(context, R.string.network_error, Toast.LENGTH_LONG).show();
} else if (errorInfo.getThrowable() instanceof AgeRestrictedContentException) {
Toast.makeText(context, R.string.restricted_video_no_stream,
Toast.LENGTH_LONG).show();
} else if (errorInfo.getThrowable() instanceof GeographicRestrictionException) {
Toast.makeText(context, R.string.georestricted_content, Toast.LENGTH_LONG).show();
} else if (errorInfo.getThrowable() instanceof PaidContentException) {
Toast.makeText(context, R.string.paid_content, Toast.LENGTH_LONG).show();
} else if (errorInfo.getThrowable() instanceof PrivateContentException) {
Toast.makeText(context, R.string.private_content, Toast.LENGTH_LONG).show();
} else if (errorInfo.getThrowable() instanceof SoundCloudGoPlusContentException) {
Toast.makeText(context, R.string.soundcloud_go_plus_content,
Toast.LENGTH_LONG).show();
} else if (errorInfo.getThrowable() instanceof YoutubeMusicPremiumContentException) {
Toast.makeText(context, R.string.youtube_music_premium_content,
Toast.LENGTH_LONG).show();
} else if (errorInfo.getThrowable() instanceof ContentNotAvailableException) {
Toast.makeText(context, R.string.content_not_available, Toast.LENGTH_LONG).show();
} else if (errorInfo.getThrowable() instanceof ContentNotSupportedException) {
Toast.makeText(context, R.string.content_not_supported, Toast.LENGTH_LONG).show();
} else {
} else if (errorInfo.isReportable()) {
ErrorUtil.createNotification(context, errorInfo);
} else {
// this exception does not usually indicate a problem that should be reported,
// so just show a toast instead of the notification
Toast.makeText(context, errorInfo.getMessage(context), Toast.LENGTH_LONG).show();
}
if (context instanceof RouterActivity) {
@@ -667,7 +635,8 @@ public class RouterActivity extends AppCompatActivity {
startActivity(intent);
finish();
}, throwable -> handleError(this, new ErrorInfo(throwable,
UserAction.SHARE_TO_NEWPIPE, "Starting info activity: " + currentUrl)))
UserAction.SHARE_TO_NEWPIPE, "Starting info activity: " + currentUrl,
null, currentUrl)))
);
return;
}
@@ -701,7 +670,7 @@ public class RouterActivity extends AppCompatActivity {
}
// ...the player is not running or in normal Video-mode/type
final PlayerType playerType = PlayerHolder.getInstance().getType();
final PlayerType playerType = PlayerHolder.INSTANCE.getType();
return playerType == null || playerType == PlayerType.MAIN;
}
@@ -854,10 +823,10 @@ public class RouterActivity extends AppCompatActivity {
})
)),
throwable -> runOnVisible(ctx -> handleError(ctx, new ErrorInfo(
throwable,
UserAction.REQUESTED_STREAM,
throwable, UserAction.REQUESTED_STREAM,
"Tried to add " + currentUrl + " to a playlist",
((RouterActivity) ctx).currentService.getServiceId())
((RouterActivity) ctx).currentService.getServiceId(),
currentUrl)
))
)
);
@@ -997,7 +966,7 @@ public class RouterActivity extends AppCompatActivity {
}
}, throwable -> handleError(this, new ErrorInfo(throwable, finalUserAction,
choice.url + " opened with " + choice.playerChoice,
choice.serviceId)));
choice.serviceId, choice.url)));
}
}

View File

@@ -1,203 +1,29 @@
package org.schabi.newpipe.about
import android.os.Bundle
import android.view.LayoutInflater
import android.view.MenuItem
import android.view.View
import android.view.ViewGroup
import android.widget.Button
import androidx.annotation.StringRes
import androidx.activity.compose.setContent
import androidx.activity.enableEdgeToEdge
import androidx.appcompat.app.AppCompatActivity
import androidx.fragment.app.Fragment
import androidx.fragment.app.FragmentActivity
import androidx.viewpager2.adapter.FragmentStateAdapter
import com.google.android.material.tabs.TabLayoutMediator
import org.schabi.newpipe.BuildConfig
import androidx.compose.ui.res.stringResource
import org.schabi.newpipe.R
import org.schabi.newpipe.databinding.ActivityAboutBinding
import org.schabi.newpipe.databinding.FragmentAboutBinding
import org.schabi.newpipe.util.Localization
import org.schabi.newpipe.util.ThemeHelper
import org.schabi.newpipe.util.external_communication.ShareUtils
import org.schabi.newpipe.ui.components.common.ScaffoldWithToolbar
import org.schabi.newpipe.ui.screens.AboutScreen
import org.schabi.newpipe.ui.theme.AppTheme
class AboutActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
Localization.assureCorrectAppLanguage(this)
enableEdgeToEdge()
super.onCreate(savedInstanceState)
ThemeHelper.setTheme(this)
title = getString(R.string.title_activity_about)
val aboutBinding = ActivityAboutBinding.inflate(layoutInflater)
setContentView(aboutBinding.root)
setSupportActionBar(aboutBinding.aboutToolbar)
supportActionBar?.setDisplayHomeAsUpEnabled(true)
// Create the adapter that will return a fragment for each of the three
// primary sections of the activity.
val mAboutStateAdapter = AboutStateAdapter(this)
// Set up the ViewPager with the sections adapter.
aboutBinding.aboutViewPager2.adapter = mAboutStateAdapter
TabLayoutMediator(
aboutBinding.aboutTabLayout,
aboutBinding.aboutViewPager2
) { tab, position ->
tab.setText(mAboutStateAdapter.getPageTitle(position))
}.attach()
}
override fun onOptionsItemSelected(item: MenuItem): Boolean {
if (item.itemId == android.R.id.home) {
finish()
return true
}
return super.onOptionsItemSelected(item)
}
/**
* A placeholder fragment containing a simple view.
*/
class AboutFragment : Fragment() {
private fun Button.openLink(@StringRes url: Int) {
setOnClickListener {
ShareUtils.openUrlInApp(context, requireContext().getString(url))
setContent {
AppTheme {
ScaffoldWithToolbar(
title = stringResource(R.string.title_activity_about),
onBackClick = { onBackPressedDispatcher.onBackPressed() }
) { padding ->
AboutScreen(padding)
}
}
}
override fun onCreateView(
inflater: LayoutInflater,
container: ViewGroup?,
savedInstanceState: Bundle?
): View {
FragmentAboutBinding.inflate(inflater, container, false).apply {
aboutAppVersion.text = BuildConfig.VERSION_NAME
aboutGithubLink.openLink(R.string.github_url)
aboutDonationLink.openLink(R.string.donation_url)
aboutWebsiteLink.openLink(R.string.website_url)
aboutPrivacyPolicyLink.openLink(R.string.privacy_policy_url)
faqLink.openLink(R.string.faq_url)
return root
}
}
}
/**
* A [FragmentStateAdapter] that returns a fragment corresponding to
* one of the sections/tabs/pages.
*/
private class AboutStateAdapter(fa: FragmentActivity) : FragmentStateAdapter(fa) {
private val posAbout = 0
private val posLicense = 1
private val totalCount = 2
override fun createFragment(position: Int): Fragment {
return when (position) {
posAbout -> AboutFragment()
posLicense -> LicenseFragment.newInstance(SOFTWARE_COMPONENTS)
else -> throw IllegalArgumentException("Unknown position for ViewPager2")
}
}
override fun getItemCount(): Int {
// Show 2 total pages.
return totalCount
}
fun getPageTitle(position: Int): Int {
return when (position) {
posAbout -> R.string.tab_about
posLicense -> R.string.tab_licenses
else -> throw IllegalArgumentException("Unknown position for ViewPager2")
}
}
}
companion object {
/**
* List of all software components.
*/
private val SOFTWARE_COMPONENTS = arrayListOf(
SoftwareComponent(
"ACRA", "2013", "Kevin Gaudin",
"https://github.com/ACRA/acra", StandardLicenses.APACHE2
),
SoftwareComponent(
"AndroidX", "2005 - 2011", "The Android Open Source Project",
"https://developer.android.com/jetpack", StandardLicenses.APACHE2
),
SoftwareComponent(
"ExoPlayer", "2014 - 2020", "Google, Inc.",
"https://github.com/google/ExoPlayer", StandardLicenses.APACHE2
),
SoftwareComponent(
"GigaGet", "2014 - 2015", "Peter Cai",
"https://github.com/PaperAirplane-Dev-Team/GigaGet", StandardLicenses.GPL3
),
SoftwareComponent(
"Groupie", "2016", "Lisa Wray",
"https://github.com/lisawray/groupie", StandardLicenses.MIT
),
SoftwareComponent(
"Android-State", "2018", "Evernote",
"https://github.com/Evernote/android-state", StandardLicenses.EPL1
),
SoftwareComponent(
"Bridge", "2021", "Livefront",
"https://github.com/livefront/bridge", StandardLicenses.APACHE2
),
SoftwareComponent(
"Jsoup", "2009 - 2020", "Jonathan Hedley",
"https://github.com/jhy/jsoup", StandardLicenses.MIT
),
SoftwareComponent(
"Markwon", "2019", "Dimitry Ivanov",
"https://github.com/noties/Markwon", StandardLicenses.APACHE2
),
SoftwareComponent(
"Material Components for Android", "2016 - 2020", "Google, Inc.",
"https://github.com/material-components/material-components-android",
StandardLicenses.APACHE2
),
SoftwareComponent(
"NewPipe Extractor", "2017 - 2020", "Christian Schabesberger",
"https://github.com/TeamNewPipe/NewPipeExtractor", StandardLicenses.GPL3
),
SoftwareComponent(
"NoNonsense-FilePicker", "2016", "Jonas Kalderstam",
"https://github.com/spacecowboy/NoNonsense-FilePicker", StandardLicenses.MPL2
),
SoftwareComponent(
"OkHttp", "2019", "Square, Inc.",
"https://square.github.io/okhttp/", StandardLicenses.APACHE2
),
SoftwareComponent(
"Picasso", "2013", "Square, Inc.",
"https://square.github.io/picasso/", StandardLicenses.APACHE2
),
SoftwareComponent(
"PrettyTime", "2012 - 2020", "Lincoln Baxter, III",
"https://github.com/ocpsoft/prettytime", StandardLicenses.APACHE2
),
SoftwareComponent(
"ProcessPhoenix", "2015", "Jake Wharton",
"https://github.com/JakeWharton/ProcessPhoenix", StandardLicenses.APACHE2
),
SoftwareComponent(
"RxAndroid", "2015", "The RxAndroid authors",
"https://github.com/ReactiveX/RxAndroid", StandardLicenses.APACHE2
),
SoftwareComponent(
"RxBinding", "2015", "Jake Wharton",
"https://github.com/JakeWharton/RxBinding", StandardLicenses.APACHE2
),
SoftwareComponent(
"RxJava", "2016 - 2020", "RxJava Contributors",
"https://github.com/ReactiveX/RxJava", StandardLicenses.APACHE2
),
SoftwareComponent(
"SearchPreference", "2018", "ByteHamster",
"https://github.com/ByteHamster/SearchPreference", StandardLicenses.MIT
),
)
}
}

View File

@@ -1,11 +0,0 @@
package org.schabi.newpipe.about
import android.os.Parcelable
import kotlinx.parcelize.Parcelize
import java.io.Serializable
/**
* Class for storing information about a software license.
*/
@Parcelize
class License(val name: String, val abbreviation: String, val filename: String) : Parcelable, Serializable

View File

@@ -1,140 +0,0 @@
package org.schabi.newpipe.about
import android.os.Bundle
import android.util.Base64
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.webkit.WebView
import androidx.appcompat.app.AlertDialog
import androidx.core.os.bundleOf
import androidx.fragment.app.Fragment
import io.reactivex.rxjava3.android.schedulers.AndroidSchedulers
import io.reactivex.rxjava3.core.Observable
import io.reactivex.rxjava3.disposables.CompositeDisposable
import io.reactivex.rxjava3.disposables.Disposable
import io.reactivex.rxjava3.schedulers.Schedulers
import org.schabi.newpipe.BuildConfig
import org.schabi.newpipe.R
import org.schabi.newpipe.databinding.FragmentLicensesBinding
import org.schabi.newpipe.databinding.ItemSoftwareComponentBinding
import org.schabi.newpipe.ktx.parcelableArrayList
import org.schabi.newpipe.util.Localization
import org.schabi.newpipe.util.external_communication.ShareUtils
/**
* Fragment containing the software licenses.
*/
class LicenseFragment : Fragment() {
private lateinit var softwareComponents: List<SoftwareComponent>
private var activeSoftwareComponent: SoftwareComponent? = null
private val compositeDisposable = CompositeDisposable()
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
softwareComponents = arguments?.parcelableArrayList<SoftwareComponent>(ARG_COMPONENTS)!!
.sortedBy { it.name } // Sort components by name
activeSoftwareComponent = savedInstanceState?.getSerializable(SOFTWARE_COMPONENT_KEY) as? SoftwareComponent
}
override fun onDestroy() {
compositeDisposable.dispose()
super.onDestroy()
}
override fun onCreateView(
inflater: LayoutInflater,
container: ViewGroup?,
savedInstanceState: Bundle?
): View {
val binding = FragmentLicensesBinding.inflate(inflater, container, false)
binding.licensesAppReadLicense.setOnClickListener {
compositeDisposable.add(
showLicense(NEWPIPE_SOFTWARE_COMPONENT)
)
}
for (component in softwareComponents) {
val componentBinding = ItemSoftwareComponentBinding
.inflate(inflater, container, false)
componentBinding.name.text = component.name
componentBinding.copyright.text = getString(
R.string.copyright,
component.years,
component.copyrightOwner,
component.license.abbreviation
)
val root: View = componentBinding.root
root.tag = component
root.setOnClickListener {
compositeDisposable.add(
showLicense(component)
)
}
binding.licensesSoftwareComponents.addView(root)
registerForContextMenu(root)
}
activeSoftwareComponent?.let { compositeDisposable.add(showLicense(it)) }
return binding.root
}
override fun onSaveInstanceState(savedInstanceState: Bundle) {
super.onSaveInstanceState(savedInstanceState)
activeSoftwareComponent?.let { savedInstanceState.putSerializable(SOFTWARE_COMPONENT_KEY, it) }
}
private fun showLicense(
softwareComponent: SoftwareComponent
): Disposable {
return if (context == null) {
Disposable.empty()
} else {
val context = requireContext()
activeSoftwareComponent = softwareComponent
Observable.fromCallable { getFormattedLicense(context, softwareComponent.license) }
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe { formattedLicense ->
val webViewData = Base64.encodeToString(
formattedLicense.toByteArray(), Base64.NO_PADDING
)
val webView = WebView(context)
webView.loadData(webViewData, "text/html; charset=UTF-8", "base64")
Localization.assureCorrectAppLanguage(context)
val builder = AlertDialog.Builder(requireContext())
.setTitle(softwareComponent.name)
.setView(webView)
.setOnCancelListener { activeSoftwareComponent = null }
.setOnDismissListener { activeSoftwareComponent = null }
.setPositiveButton(R.string.done) { dialog, _ -> dialog.dismiss() }
if (softwareComponent != NEWPIPE_SOFTWARE_COMPONENT) {
builder.setNeutralButton(R.string.open_website_license) { _, _ ->
ShareUtils.openUrlInApp(requireContext(), softwareComponent.link)
}
}
builder.show()
}
}
}
companion object {
private const val ARG_COMPONENTS = "components"
private const val SOFTWARE_COMPONENT_KEY = "ACTIVE_SOFTWARE_COMPONENT"
private val NEWPIPE_SOFTWARE_COMPONENT = SoftwareComponent(
"NewPipe",
"2014-2023",
"Team NewPipe",
"https://newpipe.net/",
StandardLicenses.GPL3,
BuildConfig.VERSION_NAME
)
fun newInstance(softwareComponents: ArrayList<SoftwareComponent>): LicenseFragment {
val fragment = LicenseFragment()
fragment.arguments = bundleOf(ARG_COMPONENTS to softwareComponents)
return fragment
}
}
}

View File

@@ -1,52 +0,0 @@
package org.schabi.newpipe.about
import android.content.Context
import org.schabi.newpipe.R
import org.schabi.newpipe.util.ThemeHelper
import java.io.IOException
/**
* @param context the context to use
* @param license the license
* @return String which contains a HTML formatted license page
* styled according to the context's theme
*/
fun getFormattedLicense(context: Context, license: License): String {
try {
return context.assets.open(license.filename).bufferedReader().use { it.readText() }
// split the HTML file and insert the stylesheet into the HEAD of the file
.replace("</head>", "<style>${getLicenseStylesheet(context)}</style></head>")
} catch (e: IOException) {
throw IllegalArgumentException("Could not get license file: ${license.filename}", e)
}
}
/**
* @param context the Android context
* @return String which is a CSS stylesheet according to the context's theme
*/
fun getLicenseStylesheet(context: Context): String {
val isLightTheme = ThemeHelper.isLightThemeSelected(context)
val licenseBackgroundColor = getHexRGBColor(
context, if (isLightTheme) R.color.light_license_background_color else R.color.dark_license_background_color
)
val licenseTextColor = getHexRGBColor(
context, if (isLightTheme) R.color.light_license_text_color else R.color.dark_license_text_color
)
val youtubePrimaryColor = getHexRGBColor(
context, if (isLightTheme) R.color.light_youtube_primary_color else R.color.dark_youtube_primary_color
)
return "body{padding:12px 15px;margin:0;background:#$licenseBackgroundColor;color:#$licenseTextColor}" +
"a[href]{color:#$youtubePrimaryColor}pre{white-space:pre-wrap}"
}
/**
* Cast R.color to a hexadecimal color value.
*
* @param context the context to use
* @param color the color number from R.color
* @return a six characters long String with hexadecimal RGB values
*/
fun getHexRGBColor(context: Context, color: Int): String {
return context.getString(color).substring(3)
}

View File

@@ -1,17 +0,0 @@
package org.schabi.newpipe.about
import android.os.Parcelable
import kotlinx.parcelize.Parcelize
import java.io.Serializable
@Parcelize
class SoftwareComponent
@JvmOverloads
constructor(
val name: String,
val years: String,
val copyrightOwner: String,
val link: String,
val license: License,
val version: String? = null
) : Parcelable, Serializable

View File

@@ -1,21 +0,0 @@
package org.schabi.newpipe.about
/**
* Class containing information about standard software licenses.
*/
object StandardLicenses {
@JvmField
val GPL3 = License("GNU General Public License, Version 3.0", "GPLv3", "gpl_3.html")
@JvmField
val APACHE2 = License("Apache License, Version 2.0", "ALv2", "apache2.html")
@JvmField
val MPL2 = License("Mozilla Public License, Version 2.0", "MPL 2.0", "mpl2.html")
@JvmField
val MIT = License("MIT License", "MIT", "mit.html")
@JvmField
val EPL1 = License("Eclipse Public License, Version 1.0", "EPL 1.0", "epl1.html")
}

View File

@@ -3,6 +3,8 @@ package org.schabi.newpipe.database.history.model
import androidx.room.ColumnInfo
import androidx.room.Embedded
import org.schabi.newpipe.database.stream.model.StreamEntity
import org.schabi.newpipe.extractor.stream.StreamInfoItem
import org.schabi.newpipe.util.image.ImageStrategy
import java.time.OffsetDateTime
data class StreamHistoryEntry(
@@ -27,4 +29,17 @@ data class StreamHistoryEntry(
return this.streamEntity.uid == other.streamEntity.uid && streamId == other.streamId &&
accessDate.isEqual(other.accessDate)
}
fun toStreamInfoItem(): StreamInfoItem =
StreamInfoItem(
streamEntity.serviceId,
streamEntity.url,
streamEntity.title,
streamEntity.streamType,
).apply {
duration = streamEntity.duration
uploaderName = streamEntity.uploader
uploaderUrl = streamEntity.uploaderUrl
thumbnails = ImageStrategy.dbUrlToImageList(streamEntity.thumbnailUrl)
}
}

View File

@@ -1,5 +1,7 @@
package org.schabi.newpipe.database.playlist;
import androidx.annotation.Nullable;
import org.schabi.newpipe.database.LocalItem;
public interface PlaylistLocalItem extends LocalItem {
@@ -10,4 +12,7 @@ public interface PlaylistLocalItem extends LocalItem {
long getUid();
void setDisplayIndex(long displayIndex);
@Nullable
String getThumbnailUrl();
}

View File

@@ -9,6 +9,8 @@ import static org.schabi.newpipe.database.playlist.model.PlaylistEntity.PLAYLIST
import static org.schabi.newpipe.database.playlist.model.PlaylistEntity.PLAYLIST_THUMBNAIL_STREAM_ID;
import static org.schabi.newpipe.database.playlist.model.PlaylistEntity.PLAYLIST_THUMBNAIL_URL;
import androidx.annotation.Nullable;
public class PlaylistMetadataEntry implements PlaylistLocalItem {
public static final String PLAYLIST_STREAM_COUNT = "streamCount";
@@ -71,4 +73,10 @@ public class PlaylistMetadataEntry implements PlaylistLocalItem {
public void setDisplayIndex(final long displayIndex) {
this.displayIndex = displayIndex;
}
@Nullable
@Override
public String getThumbnailUrl() {
return thumbnailUrl;
}
}

View File

@@ -34,7 +34,7 @@ public interface PlaylistRemoteDAO extends BasicDAO<PlaylistRemoteEntity> {
@Query("SELECT * FROM " + REMOTE_PLAYLIST_TABLE + " WHERE "
+ REMOTE_PLAYLIST_ID + " = :playlistId")
Flowable<List<PlaylistRemoteEntity>> getPlaylist(long playlistId);
Flowable<PlaylistRemoteEntity> getPlaylist(long playlistId);
@Query("SELECT * FROM " + REMOTE_PLAYLIST_TABLE + " WHERE "
+ REMOTE_PLAYLIST_URL + " = :url AND " + REMOTE_PLAYLIST_SERVICE_ID + " = :serviceId")

View File

@@ -2,6 +2,7 @@ package org.schabi.newpipe.database.playlist.model;
import android.text.TextUtils;
import androidx.annotation.Nullable;
import androidx.room.ColumnInfo;
import androidx.room.Entity;
import androidx.room.Ignore;
@@ -134,6 +135,8 @@ public class PlaylistRemoteEntity implements PlaylistLocalItem {
this.name = name;
}
@Nullable
@Override
public String getThumbnailUrl() {
return thumbnailUrl;
}

View File

@@ -8,6 +8,7 @@ import androidx.room.Query
import androidx.room.Transaction
import io.reactivex.rxjava3.core.Completable
import io.reactivex.rxjava3.core.Flowable
import io.reactivex.rxjava3.core.Maybe
import org.schabi.newpipe.database.BasicDAO
import org.schabi.newpipe.database.stream.model.StreamEntity
import org.schabi.newpipe.database.stream.model.StreamEntity.Companion.STREAM_ID
@@ -27,7 +28,7 @@ abstract class StreamDAO : BasicDAO<StreamEntity> {
abstract override fun listByService(serviceId: Int): Flowable<List<StreamEntity>>
@Query("SELECT * FROM streams WHERE url = :url AND service_id = :serviceId")
abstract fun getStream(serviceId: Long, url: String): Flowable<List<StreamEntity>>
abstract fun getStream(serviceId: Long, url: String): Maybe<StreamEntity>
@Query("UPDATE streams SET uploader_url = :uploaderUrl WHERE url = :url AND service_id = :serviceId")
abstract fun setUploaderUrl(serviceId: Long, url: String, uploaderUrl: String): Completable

View File

@@ -1,5 +1,8 @@
package org.schabi.newpipe.database.stream.dao;
import static org.schabi.newpipe.database.stream.model.StreamStateEntity.JOIN_STREAM_ID;
import static org.schabi.newpipe.database.stream.model.StreamStateEntity.STREAM_STATE_TABLE;
import androidx.room.Dao;
import androidx.room.Insert;
import androidx.room.OnConflictStrategy;
@@ -12,9 +15,7 @@ import org.schabi.newpipe.database.stream.model.StreamStateEntity;
import java.util.List;
import io.reactivex.rxjava3.core.Flowable;
import static org.schabi.newpipe.database.stream.model.StreamStateEntity.JOIN_STREAM_ID;
import static org.schabi.newpipe.database.stream.model.StreamStateEntity.STREAM_STATE_TABLE;
import io.reactivex.rxjava3.core.Maybe;
@Dao
public interface StreamStateDAO extends BasicDAO<StreamStateEntity> {
@@ -32,7 +33,7 @@ public interface StreamStateDAO extends BasicDAO<StreamStateEntity> {
}
@Query("SELECT * FROM " + STREAM_STATE_TABLE + " WHERE " + JOIN_STREAM_ID + " = :streamId")
Flowable<List<StreamStateEntity>> getState(long streamId);
Maybe<StreamStateEntity> getState(long streamId);
@Query("DELETE FROM " + STREAM_STATE_TABLE + " WHERE " + JOIN_STREAM_ID + " = :streamId")
int deleteState(long streamId);

View File

@@ -90,7 +90,7 @@ abstract class SubscriptionDAO : BasicDAO<SubscriptionEntity> {
internal abstract fun silentInsertAllInternal(entities: List<SubscriptionEntity>): List<Long>
@Transaction
open fun upsertAll(entities: List<SubscriptionEntity>): List<SubscriptionEntity> {
open fun upsertAll(entities: List<SubscriptionEntity>) {
val insertUidList = silentInsertAllInternal(entities)
insertUidList.forEachIndexed { index: Int, uidFromInsert: Long ->
@@ -106,7 +106,5 @@ abstract class SubscriptionDAO : BasicDAO<SubscriptionEntity> {
update(entity)
}
}
return entities
}
}

Some files were not shown because too many files have changed in this diff Show More