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

Compare commits

...

197 Commits

Author SHA1 Message Date
Stypox
9828586762 Fix indentation for ktlint 2024-04-23 20:16:04 +02:00
Hosted Weblate
8caaa6d297 Merge branch 'origin/dev' into Weblate. 2024-04-23 19:27:20 +02:00
Stypox
83ca6b9468 Update NewPipeExtractor to v0.24.0 2024-04-23 19:25:13 +02:00
Stypox
24e65ef018 Merge branch 'dev' 2024-04-23 19:23:20 +02:00
Stypox
a69bbab732 Merge pull request from GHSA-wxrm-jhpf-vp6v
Fix preferences import vulnerability
2024-04-23 19:22:17 +02:00
Stypox
a557ac3c7b Merge pull request #10929 from TeamNewPipe/release-0.27.0
Release v0.27.0 (997)
2024-04-23 19:21:12 +02:00
Stypox
d61b4b89ea Merge pull request #10992 from Stypox/fix-download-nnfp
Fix free storage space check for all APIs
2024-04-23 18:42:57 +02:00
Stypox
b8daf16b92 Update app/src/main/java/org/schabi/newpipe/streams/io/StoredDirectoryHelper.java
Co-authored-by: Tobi <TobiGr@users.noreply.github.com>
2024-04-23 18:39:56 +02:00
Stypox
caa3812e13 Ignore all errors when getting free storage space
It's not a critical check that needs to be perfomed, so in case something does not work on some device/version, let's just ignore the error.
2024-04-23 18:05:31 +02:00
Hosted Weblate
23a087c498 Translated using Weblate (Romanian)
Currently translated at 100.0% (738 of 738 strings)

Translated using Weblate (Croatian)

Currently translated at 99.5% (735 of 738 strings)

Translated using Weblate (Dutch)

Currently translated at 100.0% (738 of 738 strings)

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

Currently translated at 100.0% (738 of 738 strings)

Translated using Weblate (Spanish)

Currently translated at 100.0% (78 of 78 strings)

Translated using Weblate (Ukrainian)

Currently translated at 100.0% (78 of 78 strings)

Translated using Weblate (Spanish)

Currently translated at 100.0% (738 of 738 strings)

Translated using Weblate (Portuguese (Brazil))

Currently translated at 100.0% (738 of 738 strings)

Translated using Weblate (French (Louisiana))

Currently translated at 0.2% (2 of 738 strings)

Translated using Weblate (Portuguese (Portugal))

Currently translated at 100.0% (78 of 78 strings)

Translated using Weblate (Portuguese)

Currently translated at 100.0% (78 of 78 strings)

Translated using Weblate (Portuguese (Portugal))

Currently translated at 100.0% (738 of 738 strings)

Translated using Weblate (Portuguese)

Currently translated at 100.0% (738 of 738 strings)

Added translation using Weblate (French (Louisiana))

Translated using Weblate (Vietnamese)

Currently translated at 100.0% (738 of 738 strings)

Translated using Weblate (French)

Currently translated at 99.7% (736 of 738 strings)

Added translation using Weblate (Arabic (Tunisian))

Translated using Weblate (Vietnamese)

Currently translated at 100.0% (738 of 738 strings)

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

Currently translated at 100.0% (738 of 738 strings)

Translated using Weblate (Japanese)

Currently translated at 100.0% (738 of 738 strings)

Translated using Weblate (Kannada)

Currently translated at 5.8% (43 of 738 strings)

Translated using Weblate (Kannada)

Currently translated at 5.1% (4 of 78 strings)

Translated using Weblate (Italian)

Currently translated at 100.0% (78 of 78 strings)

Translated using Weblate (Vietnamese)

Currently translated at 100.0% (738 of 738 strings)

Translated using Weblate (Vietnamese)

Currently translated at 100.0% (738 of 738 strings)

Translated using Weblate (Vietnamese)

Currently translated at 100.0% (738 of 738 strings)

Translated using Weblate (Vietnamese)

Currently translated at 100.0% (738 of 738 strings)

Translated using Weblate (Ukrainian)

Currently translated at 100.0% (738 of 738 strings)

Translated using Weblate (Russian)

Currently translated at 99.8% (737 of 738 strings)

Translated using Weblate (German)

Currently translated at 100.0% (78 of 78 strings)

Translated using Weblate (German)

Currently translated at 100.0% (738 of 738 strings)

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

Currently translated at 99.0% (731 of 738 strings)

Translated using Weblate (Portuguese)

Currently translated at 99.7% (736 of 738 strings)

Translated using Weblate (Japanese)

Currently translated at 100.0% (738 of 738 strings)

Translated using Weblate (Russian)

Currently translated at 99.7% (736 of 738 strings)

Translated using Weblate (Dutch)

Currently translated at 100.0% (738 of 738 strings)

Translated using Weblate (Vietnamese)

Currently translated at 50.0% (39 of 78 strings)

Translated using Weblate (Sardinian)

Currently translated at 100.0% (738 of 738 strings)

Translated using Weblate (Vietnamese)

Currently translated at 100.0% (738 of 738 strings)

Translated using Weblate (Portuguese (Brazil))

Currently translated at 100.0% (738 of 738 strings)

Translated using Weblate (Portuguese (Brazil))

Currently translated at 100.0% (738 of 738 strings)

Translated using Weblate (Portuguese (Brazil))

Currently translated at 100.0% (738 of 738 strings)

Translated using Weblate (Portuguese (Brazil))

Currently translated at 100.0% (738 of 738 strings)

Translated using Weblate (Swedish)

Currently translated at 100.0% (78 of 78 strings)

Translated using Weblate (Greek)

Currently translated at 100.0% (738 of 738 strings)

Translated using Weblate (Japanese)

Currently translated at 99.4% (734 of 738 strings)

Translated using Weblate (Swedish)

Currently translated at 100.0% (738 of 738 strings)

Translated using Weblate (Italian)

Currently translated at 100.0% (738 of 738 strings)

Translated using Weblate (Indonesian)

Currently translated at 100.0% (78 of 78 strings)

Translated using Weblate (Hindi)

Currently translated at 100.0% (78 of 78 strings)

Translated using Weblate (Punjabi)

Currently translated at 100.0% (78 of 78 strings)

Translated using Weblate (Punjabi)

Currently translated at 100.0% (738 of 738 strings)

Translated using Weblate (Hindi)

Currently translated at 100.0% (738 of 738 strings)

Translated using Weblate (Serbian)

Currently translated at 100.0% (738 of 738 strings)

Translated using Weblate (Slovak)

Currently translated at 21.7% (17 of 78 strings)

Translated using Weblate (Czech)

Currently translated at 100.0% (78 of 78 strings)

Translated using Weblate (Chinese (Traditional))

Currently translated at 62.8% (49 of 78 strings)

Translated using Weblate (Spanish)

Currently translated at 100.0% (78 of 78 strings)

Translated using Weblate (Arabic)

Currently translated at 100.0% (78 of 78 strings)

Translated using Weblate (Polish)

Currently translated at 61.5% (48 of 78 strings)

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

Currently translated at 23.0% (18 of 78 strings)

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: AudricV <AudricV@users.noreply.hosted.weblate.org>
Co-authored-by: Fjuro <fjuro@alius.cz>
Co-authored-by: Flavian <3zorro.1@gmail.com>
Co-authored-by: Hosted Weblate <hosted@weblate.org>
Co-authored-by: Ihor Hordiichuk <igor_ck@outlook.com>
Co-authored-by: Jonatan Nyberg <jonatan@autistici.org>
Co-authored-by: Jose Delvani <delvani.eletricista@gmail.com>
Co-authored-by: Linerly <linerly@proton.me>
Co-authored-by: MS-PC <MSPCtranslator@gmail.com>
Co-authored-by: Milan <mobrcian@hotmail.com>
Co-authored-by: Milo Ivir <mail@milotype.de>
Co-authored-by: NEXI <nexiphotographer@gmail.com>
Co-authored-by: Philip Goto <philip.goto@gmail.com>
Co-authored-by: Random <random-r@users.noreply.hosted.weblate.org>
Co-authored-by: Ray <ray@users.noreply.hosted.weblate.org>
Co-authored-by: Rex_sa <rex.sa@pm.me>
Co-authored-by: Sergio Marques <so.boston.android@gmail.com>
Co-authored-by: ShareASmile <ShareASmile@users.noreply.hosted.weblate.org>
Co-authored-by: Tấn Lực Trương <september122022ios16@gmail.com>
Co-authored-by: Vasilis K <skyhirules@gmail.com>
Co-authored-by: VfBFan <VfBFan@users.noreply.hosted.weblate.org>
Co-authored-by: abhijithkjg <abhijithkj2001@gmail.com>
Co-authored-by: gallegonovato <fran-carro@hotmail.es>
Co-authored-by: kaajjo <claymanoff@gmail.com>
Co-authored-by: kuragehime <kuragehime641@gmail.com>
Co-authored-by: ngocanhtve <ngocanh.tve@gmail.com>
Co-authored-by: ssantos <ssantos@web.de>
Co-authored-by: yosrinajar <yosron3@gmail.com>
Co-authored-by: zeineb-b <zeinebbouhejba21@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/es/
Translate-URL: https://hosted.weblate.org/projects/newpipe/metadata/hi/
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/kn/
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/pt/
Translate-URL: https://hosted.weblate.org/projects/newpipe/metadata/pt_PT/
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/uk/
Translate-URL: https://hosted.weblate.org/projects/newpipe/metadata/vi/
Translate-URL: https://hosted.weblate.org/projects/newpipe/metadata/zh_Hant/
Translate-URL: https://hosted.weblate.org/projects/newpipe/metadata/zh_Hant_HK/
Translation: NewPipe/Metadata
2024-04-23 18:00:52 +02:00
Stypox
c3c39a7b24 Fix free storage space check for all APIs
See https://stackoverflow.com/q/31171838
See https://pubs.opengroup.org/onlinepubs/9699919799/functions/fstatvfs.html
2024-04-23 12:16:06 +02:00
Stypox
00770fc634 Update NewPipeExtractor 2024-04-20 13:11:08 +02:00
Stypox
5bf77160f7 Merge pull request #10952 from bg172/release-0.27.0
Add an intuitive prefix for the duration of lists in the UI
2024-04-11 09:27:54 +02:00
Stypox
d9da84c412 Merge pull request #10957 from Stypox/fix-feed-npe
Fix NPE if avatarUrl is null when reloading feed
2024-04-11 09:26:11 +02:00
Audric V
b3a6318672 Merge pull request #10959 from Stypox/fix-comment-replies-state
Fix not saving comment replies state on config change
2024-04-10 16:24:31 +02:00
Stypox
67b41b970d Fix not saving comment replies state on config change 2024-04-10 10:52:47 +02:00
Stypox
3738e30949 Fix NPE when avatarUrl is empty 2024-04-09 20:18:21 +02:00
Stypox
0ba73b11c1 Update NewPipeExtractor 2024-04-08 00:03:37 +02:00
bg1722
13baaa31cd add an intuitive prefix for the duration of lists on UI, and avoid using the new prefix for single videos 2024-04-06 07:58:05 +02:00
TobiGr
f0db2aa43c Improve documentation 2024-04-04 15:49:12 +02:00
Stypox
f704721b59 Release v0.27.0 (997) 2024-04-01 14:23:48 +02:00
Stypox
7abf0f4886 Update NewPipeExtractor to YT comments fix PR
https://github.com/TeamNewPipe/NewPipeExtractor/pull/1163
2024-04-01 14:23:04 +02:00
Stypox
c915b6e68b Add changelog for v0.27.0 (997) 2024-04-01 14:16:51 +02:00
Hosted Weblate
0b28c688c6 Translated using Weblate (Estonian)
Currently translated at 100.0% (738 of 738 strings)

Translated using Weblate (Chinese (Traditional))

Currently translated at 100.0% (738 of 738 strings)

Translated using Weblate (Dutch)

Currently translated at 100.0% (738 of 738 strings)

Translated using Weblate (Hungarian)

Currently translated at 100.0% (738 of 738 strings)

Translated using Weblate (Arabic)

Currently translated at 100.0% (738 of 738 strings)

Translated using Weblate (Spanish)

Currently translated at 100.0% (738 of 738 strings)

Translated using Weblate (Odia)

Currently translated at 100.0% (738 of 738 strings)

Translated using Weblate (Vietnamese)

Currently translated at 46.7% (36 of 77 strings)

Translated using Weblate (Vietnamese)

Currently translated at 100.0% (738 of 738 strings)

Translated using Weblate (Chinese (Simplified))

Currently translated at 100.0% (738 of 738 strings)

Translated using Weblate (Czech)

Currently translated at 100.0% (738 of 738 strings)

Translated using Weblate (Slovak)

Currently translated at 100.0% (738 of 738 strings)

Translated using Weblate (Spanish)

Currently translated at 99.7% (736 of 738 strings)

Translated using Weblate (Indonesian)

Currently translated at 100.0% (738 of 738 strings)

Translated using Weblate (Polish)

Currently translated at 100.0% (738 of 738 strings)

Translated using Weblate (Turkish)

Currently translated at 100.0% (738 of 738 strings)

Translated using Weblate (German)

Currently translated at 99.7% (736 of 738 strings)

Translated using Weblate (Korean)

Currently translated at 31.1% (24 of 77 strings)

Translated using Weblate (Turkish)

Currently translated at 100.0% (734 of 734 strings)

Translated using Weblate (Korean)

Currently translated at 98.9% (726 of 734 strings)

Translated using Weblate (Serbian)

Currently translated at 100.0% (734 of 734 strings)

Translated using Weblate (Chinese (Simplified))

Currently translated at 100.0% (734 of 734 strings)

Translated using Weblate (Polish)

Currently translated at 100.0% (734 of 734 strings)

Translated using Weblate (Arabic)

Currently translated at 100.0% (734 of 734 strings)

Translated using Weblate (Czech)

Currently translated at 100.0% (734 of 734 strings)

Translated using Weblate (Slovak)

Currently translated at 100.0% (734 of 734 strings)

Translated using Weblate (Italian)

Currently translated at 100.0% (734 of 734 strings)

Translated using Weblate (Vietnamese)

Currently translated at 100.0% (734 of 734 strings)

Translated using Weblate (Chinese (Traditional))

Currently translated at 100.0% (734 of 734 strings)

Translated using Weblate (Polish)

Currently translated at 100.0% (734 of 734 strings)

Translated using Weblate (Spanish)

Currently translated at 100.0% (734 of 734 strings)

Translated using Weblate (German)

Currently translated at 99.7% (732 of 734 strings)

Translated using Weblate (Ukrainian)

Currently translated at 100.0% (730 of 730 strings)

Translated using Weblate (Belarusian)

Currently translated at 100.0% (730 of 730 strings)

Translated using Weblate (Vietnamese)

Currently translated at 100.0% (730 of 730 strings)

Translated using Weblate (Swedish)

Currently translated at 100.0% (730 of 730 strings)

Translated using Weblate (Ukrainian)

Currently translated at 100.0% (730 of 730 strings)

Translated using Weblate (Romanian)

Currently translated at 100.0% (730 of 730 strings)

Translated using Weblate (Russian)

Currently translated at 100.0% (730 of 730 strings)

Translated using Weblate (Japanese)

Currently translated at 100.0% (730 of 730 strings)

Translated using Weblate (Slovak)

Currently translated at 100.0% (730 of 730 strings)

Translated using Weblate (German)

Currently translated at 100.0% (730 of 730 strings)

Translated using Weblate (Hungarian)

Currently translated at 16.8% (13 of 77 strings)

Translated using Weblate (Vietnamese)

Currently translated at 100.0% (730 of 730 strings)

Translated using Weblate (Chinese (Traditional))

Currently translated at 100.0% (730 of 730 strings)

Translated using Weblate (Chinese (Simplified))

Currently translated at 100.0% (730 of 730 strings)

Translated using Weblate (Polish)

Currently translated at 100.0% (730 of 730 strings)

Translated using Weblate (Turkish)

Currently translated at 100.0% (730 of 730 strings)

Translated using Weblate (Indonesian)

Currently translated at 100.0% (730 of 730 strings)

Translated using Weblate (Arabic)

Currently translated at 100.0% (730 of 730 strings)

Translated using Weblate (Czech)

Currently translated at 100.0% (730 of 730 strings)

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

Currently translated at 100.0% (730 of 730 strings)

Translated using Weblate (Italian)

Currently translated at 100.0% (730 of 730 strings)

Translated using Weblate (Hungarian)

Currently translated at 100.0% (730 of 730 strings)

Translated using Weblate (Spanish)

Currently translated at 100.0% (730 of 730 strings)

Co-authored-by: Agnieszka C <aga_04@o2.pl>
Co-authored-by: Alex25820 <alexs25820@gmail.com>
Co-authored-by: Apious <apious@kakao.com>
Co-authored-by: Eduardo Malaspina <vaio0@swismail.com>
Co-authored-by: Fjuro <fjuro@alius.cz>
Co-authored-by: GET100PERCENT <eraofphysics@yahoo.com>
Co-authored-by: Ghost of Sparta <makesocialfoss32@keemail.me>
Co-authored-by: Hosted Weblate <hosted@weblate.org>
Co-authored-by: Ihor Hordiichuk <igor_ck@outlook.com>
Co-authored-by: Jeff Huang <s8321414@gmail.com>
Co-authored-by: Linerly <linerly@proton.me>
Co-authored-by: Michael Moroni <michaelmoroni@disroot.org>
Co-authored-by: Milan <mobrcian@hotmail.com>
Co-authored-by: NEXI <nexiphotographer@gmail.com>
Co-authored-by: Oğuz Ersen <oguz@ersen.moe>
Co-authored-by: Philip Goto <philip.goto@gmail.com>
Co-authored-by: Pi-Cla <pirateclip@protonmail.com>
Co-authored-by: Priit Jõerüüt <hwlate@joeruut.com>
Co-authored-by: Rex_sa <rex.sa@pm.me>
Co-authored-by: Tim Trek <T.Trek@byom.de>
Co-authored-by: TobiGr <TobiGr@users.noreply.github.com>
Co-authored-by: Tấn Lực Trương <september122022ios16@gmail.com>
Co-authored-by: gallegonovato <fran-carro@hotmail.es>
Co-authored-by: kuragehime <kuragehime641@gmail.com>
Co-authored-by: rehork <cooky@e.email>
Co-authored-by: Макар Разин <makarrazin14@gmail.com>
Co-authored-by: 大王叫我来巡山 <hamburger2048@users.noreply.hosted.weblate.org>
Translate-URL: https://hosted.weblate.org/projects/newpipe/metadata/hu/
Translate-URL: https://hosted.weblate.org/projects/newpipe/metadata/ko/
Translate-URL: https://hosted.weblate.org/projects/newpipe/metadata/vi/
Translation: NewPipe/Metadata
2024-04-01 13:38:40 +02:00
Stypox
2756ef6d2f Show notification when failing to import settings 2024-03-30 18:53:45 +01:00
Stypox
7da1d30010 Expose all import/export errors to the user 2024-03-30 18:47:20 +01:00
Stypox
8e192acb63 Add test zips and extensive tests for ImportExportManager
Now all possible combinations of files in the zip (present or not) are checked at the same time
2024-03-30 18:42:11 +01:00
Stypox
d8423499dc Use JSON for settings imports/exports 2024-03-30 16:58:12 +01:00
TobiGr
974167fcb8 Add comment that empty constructors are needed for IcePick
See 5e7ad6ffd1 and https://github.com/TeamNewPipe/NewPipe/pull/10781#discussion_r1545351144
2024-03-30 16:19:02 +01:00
Stypox
6afdbd6fd3 Add test: vulnerable settings should fail importing 2024-03-30 16:12:41 +01:00
Stypox
d8668ed226 Show snackbar error when settings import fails 2024-03-30 16:12:41 +01:00
Stypox
d75a6eaa41 Fix vulnerability with whitelist-aware ObjectInputStream
Only a few specific classes are now allowed.
2024-03-30 16:12:35 +01:00
Stypox
235fb92638 Make checkstyle accept javadocs with long links 2024-03-30 15:49:06 +01:00
Stypox
ea18b4ea1f Move import export manager to separate folder 2024-03-30 15:49:05 +01:00
Stypox
58f5ec0181 Merge pull request #9580 from pratyaksh1610/branch-8232
Moved player notification setting to notification section
2024-03-30 15:38:33 +01:00
pratyaksh1610
e42c9abdde moved player notification to notification section 2024-03-30 15:23:46 +01:00
Stypox
5e7ad6ffd1 Fix fragments without empty constructor 2024-03-30 15:15:31 +01:00
Stypox
4c8238874e Merge pull request #8221 from GGAutomaton/feature-7870
Sort bookmarked playlists
2024-03-30 15:02:37 +01:00
Stypox
38d4887901 Undo some unneeded changes to LocalPlaylistManager 2024-03-30 14:46:13 +01:00
Stypox
c9051d33c1 Fix warnings and allow moving only up and down even in grid 2024-03-30 14:39:40 +01:00
Stypox
3cc0205def Fix inconsistencies when removing playlist
Remove checkDisplayIndexModified because it was causing more problems than it solved. Now when adding new playlists they won't necessarily appear at the top, but will get sorted alphabetically along with the other playlists with index -1. This will be the case until any playlist is sorted, at which point all indices are assigned and newly added playlists will appear at the top again.
2024-03-30 14:14:31 +01:00
Stypox
90979e2a81 Fix PlaylistLocalItemTest 2024-03-29 20:58:07 +01:00
Stypox
e66e1b542c Also sort playlist duplicates by display index 2024-03-29 20:55:24 +01:00
Stypox
92e9c3e42e Fix DatabaseMigrationTest
Complete removal of unneeded index, and remove default value for `remote_playlists.display_index`.
2024-03-29 20:43:55 +01:00
Stypox
4591c09637 Apply review 2024-03-29 18:08:37 +01:00
Stypox
e1ce3fef1b Merge branch 'dev' into pr8221 2024-03-29 18:08:31 +01:00
Stypox
3c0a200f7b Merge pull request #6045 from bg172/showOverallDurationInPlaylist
show overall duration of videos in playlist
2024-03-29 14:32:29 +01:00
bg1722
bef5907ec3 show OverallDuration in Playlist
earlier only overall amount of videos was shown. Now overall duration is shown there too - as formatted by existing Localization.concatenateStrings() and Localization.getDurationString().

show all videos OverallDuration in local Playlist too

refactor to make implementation in LocalPlaylistFragment and PlaylistFragment more obviously similar

unfortunately could not refactor upto BaseLocalListFragment

revert the changes for online Playlists

because they are paginated and may be infinite i.e. correct count may come only from the service->extractor chain which unfortunately does not give overall duration yet

next try to improve user-experience with online Playlist

just show that duration is longer (">") than the calculated value in case there is more page(s)

even more improve user-experience for online Playlist

by adding the duration of next items as soon as they are made visible

make showing of playlists duration configurable, disabled by default

adjusted duration to be handled as long because it comes as long from extractor

no idea why I handled it as int earlier

Revert "make showing of playlists duration configurable, disabled by default", refactor

This reverts commit bc1ba17a20d3dd1763210f81d7ca67c5f1734a3d.

Fix rebase

Apply review

Rename video -> stream

Remove unused settings keys
2024-03-29 14:11:27 +01:00
Stypox
f0beb662aa Merge pull request #10790 from TeamNewPipe/update-check-consent
Ask for consent before checking for updates
2024-03-29 11:42:57 +01:00
Stypox
92402685f8 Improve new version checks before running 2024-03-29 11:14:30 +01:00
Stypox
3703fed1a5 update_app_key default value should be false 2024-03-29 11:08:33 +01:00
Tobi
a3bbbf03b4 Ask for consent before starting update checks
NewPipe is contacting its servers without asking for the users' consent. This is categorized as "tracking" by F-Droid (see https://github.com/TeamNewPipe/NewPipe/discussions/10785).

This commit disables checking for udpates by default and adds a dialog asking for the user's consent to automatically check for updates if the app version is eligible for them. After upgrading to a version containing this commit the user is asked directly on the first app start. On fresh installs however, showing it on the first app start contributes to a bad onboarding an welcoming experience. Therefore, the dialog is shown at the second app start.

Co-authored-by: Stypox <stypox@pm.me>
2024-03-28 23:42:00 +01:00
TobiGr
1d3a69a29f Move text from manual_update_title to check_for_updates 2024-03-28 23:08:02 +01:00
Stypox
10c57b15da Merge pull request #10781 from Profpatsch/BaseDescriptionFragment-assert-member-is-initialized
BaseDescriptionFragment: Assert member is initialized
2024-03-28 22:48:00 +01:00
Stypox
b85f7a6747 Some more slight improvements 2024-03-28 22:46:30 +01:00
Stypox
3f94e7b638 Merge pull request #10912 from Stypox/download-fixes
Download fixes
2024-03-28 19:14:20 +01:00
Stypox
2af95cc1d4 Merge pull request #9236 from vincetzr/Option-to-reset-settings
Option to reset settings
2024-03-28 19:00:54 +01:00
Stypox
cefdefdfd2 11111th commit 2024-03-28 18:51:36 +01:00
Stypox
37f7fa7ef4 Merge branch 'dev' into pr9236 2024-03-28 18:43:29 +01:00
Stypox
e687eb5631 Merge pull request #8242 from dtcxzyw/trim-search-string
Trim search string and remove duplicate records from the database
2024-03-28 18:34:59 +01:00
Stypox
88c3af7647 Merge pull request #9975 from Marius1501/landscape_card_mode_improve
Changed the landscape layout of list card item
2024-03-28 15:01:41 +01:00
ge78fug
ddd6c8cbf1 Changed the landscape layout of list card item
Make layout-land/list_stream_card_item a symlink to layout/list_stream_item
2024-03-28 14:46:18 +01:00
Stypox
81220f90d6 Merge pull request #10909 from Stypox/fix-getAudioTrackType-null
Fix not considering nullability when comparing getAudioTrackType
2024-03-28 13:47:12 +01:00
Stypox
e0268a91ad Merge pull request #10717 from Stypox/cache-key-type
Calculate cache key based on info type instead of item type
2024-03-28 13:34:51 +01:00
Stypox
29e4135aaa Try to fix PR labeler
Reference: https://github.com/actions/labeler?tab=readme-ov-file#permissions
2024-03-28 12:03:10 +01:00
Stypox
5d9adce40d Fix NPE, since dismissing a dialog still calls onViewCreated() 2024-03-28 11:35:21 +01:00
Stypox
d3afde8789 Remove unused DownloadDialog.onDismissListener 2024-03-28 11:21:33 +01:00
Stypox
d8a5d5545d Fix choosing audio format to mux with video-only download 2024-03-28 11:09:56 +01:00
Stypox
bed3516687 Fix non-desugared method being used
Search for "Not supported at all minSDK levels" here: https://developer.android.com/studio/write/java8-support-table
2024-03-27 17:30:23 +01:00
Stypox
3a014d8d46 Fix not considering nullability when comparing getAudioTrackType 2024-03-27 16:05:17 +01:00
Stypox
58ae7fbccb Merge pull request #10724 from Roshanjossey/patch-1
use GitHub markdown to emphasise warning in Readme
2024-03-27 10:27:50 +01:00
Stypox
b06a9618d4 use GitHub markdown to emphasise warning in all READMEs 2024-03-27 10:22:52 +01:00
Stypox
434c4a5cbc Merge pull request #10908 from TeamNewPipe/node-20
Update workflows to use Node 20
2024-03-27 09:47:48 +01:00
TobiGr
c34d30dc17 [CI] Update sonar job to use cache@v4
Updates deprecated Node 16 to 20
2024-03-26 22:48:47 +01:00
TobiGr
0d4c1bee3f [CI] Update gradle/wrapper-validation-action to v2
Updates deprecated Node 16 to 20
2024-03-26 22:32:29 +01:00
Tobi
34a25d0be3 Merge pull request #10907 from TeamNewPipe/weblate
Update translations
2024-03-26 21:42:40 +01:00
Mohammed Anas
3134f5e747 Don't add "question" label to question discussions (#10906)
They already have a "Questions" category of their own anyway.
2024-03-26 20:28:28 +00:00
Hosted Weblate
1732584e5e Translated using Weblate (Danish)
Currently translated at 100.0% (729 of 729 strings)

Co-authored-by: cat <158170307+cultcats@users.noreply.github.com>
2024-03-26 21:19:18 +01:00
Tobi
f50cafbac1 Merge pull request #10905 from mhmdanas/fix-question-discussion-form
Fix GitHub question discussion form
2024-03-26 21:04:02 +01:00
Mohammed Anas
bc7c3f48ad Fix GitHub question discussion form
The name and description fields are both invalid here.
2024-03-26 19:53:45 +00:00
Tobi
b760419fd5 Merge pull request #10896 from TeamNewPipe/storage-message
Add separate message when download is rejected due to insufficient storage
2024-03-26 18:56:18 +01:00
Tobi
5cf3c58d0e Merge pull request #10732 from Profpatsch/dont-write-media-format
Don't write defaultFormat setting, use default value
2024-03-25 10:36:35 +01:00
TobiGr
206d1b6db4 Add separate message when download is rejected due to insufficient storage 2024-03-21 11:56:42 +01:00
CloudyRowly
2e318b8b03 Added "free memory" check before downloading [Android N / API 24+] (#10505)
Added "free space" check before downloading eliminating bugs related to out-of-memory on Android N / API 24+
2024-03-21 09:18:55 +01:00
Isira Seneviratne
5bdb6f18d6 Use hexToByteArray() extension 2024-03-20 14:00:13 +01:00
Isira Seneviratne
2e53a99361 Convert isReleaseApk to lazy value 2024-03-20 14:00:13 +01:00
Isira Seneviratne
bec18e13d3 Improve app signature check 2024-03-20 14:00:13 +01:00
Tobi
7edd471ec5 Merge pull request #10890 from TeamNewPipe/weblate
Update translations
2024-03-18 10:58:28 +01:00
Hosted Weblate
e6a4a3fa4f Translated using Weblate (Danish)
Currently translated at 96.4% (703 of 729 strings)

Translated using Weblate (Dutch)

Currently translated at 100.0% (729 of 729 strings)

Translated using Weblate (Danish)

Currently translated at 96.4% (703 of 729 strings)

Translated using Weblate (Ukrainian)

Currently translated at 100.0% (729 of 729 strings)

Translated using Weblate (Danish)

Currently translated at 88.3% (644 of 729 strings)

Translated using Weblate (Danish)

Currently translated at 88.3% (644 of 729 strings)

Translated using Weblate (Belarusian)

Currently translated at 100.0% (729 of 729 strings)

Translated using Weblate (Slovak)

Currently translated at 100.0% (729 of 729 strings)

Translated using Weblate (Russian)

Currently translated at 100.0% (729 of 729 strings)

Translated using Weblate (Georgian)

Currently translated at 92.2% (71 of 77 strings)

Translated using Weblate (Uzbek (latin))

Currently translated at 62.6% (457 of 729 strings)

Translated using Weblate (Santali)

Currently translated at 12.6% (92 of 729 strings)

Translated using Weblate (French)

Currently translated at 89.6% (69 of 77 strings)

Translated using Weblate (Japanese)

Currently translated at 11.6% (9 of 77 strings)

Translated using Weblate (Bulgarian)

Currently translated at 5.1% (4 of 77 strings)

Translated using Weblate (Bengali)

Currently translated at 20.7% (16 of 77 strings)

Translated using Weblate (German)

Currently translated at 100.0% (77 of 77 strings)

Translated using Weblate (Bengali (India))

Currently translated at 40.7% (297 of 729 strings)

Translated using Weblate (Kurdish (Central))

Currently translated at 85.5% (624 of 729 strings)

Translated using Weblate (Tamil)

Currently translated at 46.6% (340 of 729 strings)

Translated using Weblate (Bengali (Bangladesh))

Currently translated at 55.1% (402 of 729 strings)

Translated using Weblate (Turkish)

Currently translated at 100.0% (729 of 729 strings)

Translated using Weblate (Ukrainian)

Currently translated at 100.0% (729 of 729 strings)

Translated using Weblate (Greek)

Currently translated at 100.0% (729 of 729 strings)

Translated using Weblate (German)

Currently translated at 100.0% (729 of 729 strings)

Translated using Weblate (Portuguese (Portugal))

Currently translated at 98.7% (76 of 77 strings)

Translated using Weblate (Hebrew)

Currently translated at 100.0% (729 of 729 strings)

Translated using Weblate (Hebrew)

Currently translated at 99.4% (725 of 729 strings)

Translated using Weblate (Indonesian)

Currently translated at 100.0% (729 of 729 strings)

Translated using Weblate (Croatian)

Currently translated at 99.4% (725 of 729 strings)

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

Currently translated at 100.0% (729 of 729 strings)

Translated using Weblate (Croatian)

Currently translated at 2.5% (2 of 77 strings)

Translated using Weblate (Malay)

Currently translated at 48.6% (355 of 729 strings)

Translated using Weblate (Croatian)

Currently translated at 99.3% (724 of 729 strings)

Translated using Weblate (Romanian)

Currently translated at 100.0% (729 of 729 strings)

Translated using Weblate (Japanese)

Currently translated at 100.0% (729 of 729 strings)

Translated using Weblate (Finnish)

Currently translated at 98.3% (717 of 729 strings)

Translated using Weblate (Hungarian)

Currently translated at 100.0% (729 of 729 strings)

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

Currently translated at 22.0% (17 of 77 strings)

Translated using Weblate (Norwegian Bokmål)

Currently translated at 95.4% (696 of 729 strings)

Translated using Weblate (Portuguese)

Currently translated at 100.0% (729 of 729 strings)

Translated using Weblate (Portuguese)

Currently translated at 100.0% (729 of 729 strings)

Translated using Weblate (Vietnamese)

Currently translated at 42.8% (33 of 77 strings)

Translated using Weblate (Vietnamese)

Currently translated at 100.0% (729 of 729 strings)

Translated using Weblate (Turkish)

Currently translated at 100.0% (729 of 729 strings)

Translated using Weblate (Esperanto)

Currently translated at 70.7% (516 of 729 strings)

Translated using Weblate (Slovak)

Currently translated at 100.0% (729 of 729 strings)

Translated using Weblate (Azerbaijani)

Currently translated at 94.6% (690 of 729 strings)

Translated using Weblate (Hindi)

Currently translated at 100.0% (729 of 729 strings)

Translated using Weblate (Turkish)

Currently translated at 100.0% (729 of 729 strings)

Translated using Weblate (Dutch)

Currently translated at 100.0% (729 of 729 strings)

Translated using Weblate (French)

Currently translated at 100.0% (729 of 729 strings)

Translated using Weblate (Santali)

Currently translated at 10.0% (73 of 729 strings)

Translated using Weblate (Turkish)

Currently translated at 42.8% (33 of 77 strings)

Translated using Weblate (German)

Currently translated at 81.8% (63 of 77 strings)

Translated using Weblate (Portuguese (Portugal))

Currently translated at 100.0% (729 of 729 strings)

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

Currently translated at 100.0% (729 of 729 strings)

Translated using Weblate (Kannada)

Currently translated at 5.4% (40 of 729 strings)

Translated using Weblate (Russian)

Currently translated at 100.0% (77 of 77 strings)

Translated using Weblate (Vietnamese)

Currently translated at 100.0% (729 of 729 strings)

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

Currently translated at 100.0% (729 of 729 strings)

Translated using Weblate (Croatian)

Currently translated at 88.7% (647 of 729 strings)

Translated using Weblate (Slovak)

Currently translated at 100.0% (729 of 729 strings)

Translated using Weblate (Odia)

Currently translated at 100.0% (729 of 729 strings)

Translated using Weblate (Slovak)

Currently translated at 20.7% (16 of 77 strings)

Translated using Weblate (Indonesian)

Currently translated at 100.0% (729 of 729 strings)

Translated using Weblate (Slovak)

Currently translated at 100.0% (729 of 729 strings)

Translated using Weblate (French)

Currently translated at 99.8% (728 of 729 strings)

Translated using Weblate (Indonesian)

Currently translated at 100.0% (77 of 77 strings)

Translated using Weblate (Catalan)

Currently translated at 86.5% (631 of 729 strings)

Translated using Weblate (Telugu)

Currently translated at 58.9% (430 of 729 strings)

Translated using Weblate (Turkish)

Currently translated at 100.0% (729 of 729 strings)

Translated using Weblate (Indonesian)

Currently translated at 100.0% (729 of 729 strings)

Translated using Weblate (Greek)

Currently translated at 100.0% (729 of 729 strings)

Translated using Weblate (Tigrinya)

Currently translated at 8.9% (65 of 729 strings)

Translated using Weblate (Russian)

Currently translated at 98.7% (76 of 77 strings)

Translated using Weblate (Belarusian)

Currently translated at 100.0% (729 of 729 strings)

Translated using Weblate (Swedish)

Currently translated at 100.0% (729 of 729 strings)

Translated using Weblate (Chinese (Traditional))

Currently translated at 100.0% (729 of 729 strings)

Translated using Weblate (Slovak)

Currently translated at 99.7% (727 of 729 strings)

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

Currently translated at 100.0% (729 of 729 strings)

Translated using Weblate (Italian)

Currently translated at 100.0% (729 of 729 strings)

Translated using Weblate (Russian)

Currently translated at 100.0% (729 of 729 strings)

Translated using Weblate (Odia)

Currently translated at 100.0% (729 of 729 strings)

Translated using Weblate (Portuguese)

Currently translated at 100.0% (77 of 77 strings)

Translated using Weblate (Kurdish (Central))

Currently translated at 85.5% (624 of 729 strings)

Translated using Weblate (Estonian)

Currently translated at 100.0% (729 of 729 strings)

Translated using Weblate (Portuguese)

Currently translated at 100.0% (729 of 729 strings)

Translated using Weblate (Japanese)

Currently translated at 99.8% (728 of 729 strings)

Translated using Weblate (Serbian)

Currently translated at 100.0% (729 of 729 strings)

Translated using Weblate (Spanish)

Currently translated at 100.0% (729 of 729 strings)

Translated using Weblate (German)

Currently translated at 100.0% (729 of 729 strings)

Translated using Weblate (Swedish)

Currently translated at 100.0% (77 of 77 strings)

Translated using Weblate (Italian)

Currently translated at 100.0% (77 of 77 strings)

Translated using Weblate (Hindi)

Currently translated at 100.0% (77 of 77 strings)

Translated using Weblate (Punjabi)

Currently translated at 100.0% (77 of 77 strings)

Translated using Weblate (Czech)

Currently translated at 100.0% (77 of 77 strings)

Translated using Weblate (Portuguese (Portugal))

Currently translated at 99.8% (728 of 729 strings)

Translated using Weblate (Punjabi)

Currently translated at 100.0% (729 of 729 strings)

Translated using Weblate (Hindi)

Currently translated at 100.0% (729 of 729 strings)

Translated using Weblate (Swedish)

Currently translated at 99.8% (728 of 729 strings)

Translated using Weblate (Portuguese (Brazil))

Currently translated at 100.0% (729 of 729 strings)

Translated using Weblate (Polish)

Currently translated at 100.0% (729 of 729 strings)

Translated using Weblate (Arabic)

Currently translated at 100.0% (729 of 729 strings)

Translated using Weblate (Czech)

Currently translated at 100.0% (729 of 729 strings)

Translated using Weblate (Portuguese)

Currently translated at 99.8% (728 of 729 strings)

Translated using Weblate (Italian)

Currently translated at 100.0% (729 of 729 strings)

Translated using Weblate (German)

Currently translated at 100.0% (729 of 729 strings)

Translated using Weblate (German)

Currently translated at 100.0% (729 of 729 strings)

Translated using Weblate (Ukrainian)

Currently translated at 100.0% (77 of 77 strings)

Translated using Weblate (Chinese (Simplified))

Currently translated at 100.0% (729 of 729 strings)

Translated using Weblate (Ukrainian)

Currently translated at 100.0% (729 of 729 strings)

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

Currently translated at 100.0% (728 of 728 strings)

Translated using Weblate (Serbian)

Currently translated at 18.1% (14 of 77 strings)

Translated using Weblate (Swedish)

Currently translated at 100.0% (77 of 77 strings)

Translated using Weblate (Spanish)

Currently translated at 100.0% (77 of 77 strings)

Translated using Weblate (Arabic)

Currently translated at 100.0% (77 of 77 strings)

Translated using Weblate (Greek)

Currently translated at 24.6% (19 of 77 strings)

Translated using Weblate (Estonian)

Currently translated at 100.0% (728 of 728 strings)

Translated using Weblate (Swedish)

Currently translated at 100.0% (728 of 728 strings)

Translated using Weblate (Chinese (Simplified))

Currently translated at 100.0% (728 of 728 strings)

Translated using Weblate (Polish)

Currently translated at 100.0% (728 of 728 strings)

Translated using Weblate (Arabic)

Currently translated at 100.0% (728 of 728 strings)

Translated using Weblate (Greek)

Currently translated at 100.0% (728 of 728 strings)

Translated using Weblate (Portuguese)

Currently translated at 100.0% (728 of 728 strings)

Translated using Weblate (Japanese)

Currently translated at 100.0% (728 of 728 strings)

Translated using Weblate (Serbian)

Currently translated at 100.0% (728 of 728 strings)

Translated using Weblate (Dutch)

Currently translated at 100.0% (728 of 728 strings)

Translated using Weblate (Spanish)

Currently translated at 100.0% (728 of 728 strings)

Translated using Weblate (German)

Currently translated at 100.0% (728 of 728 strings)

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

Currently translated at 100.0% (726 of 726 strings)

Translated using Weblate (Kannada)

Currently translated at 5.5% (40 of 726 strings)

Translated using Weblate (Sinhala)

Currently translated at 2.6% (2 of 76 strings)

Translated using Weblate (Sinhala)

Currently translated at 4.1% (30 of 726 strings)

Translated using Weblate (Bulgarian)

Currently translated at 5.2% (4 of 76 strings)

Translated using Weblate (Punjabi)

Currently translated at 100.0% (726 of 726 strings)

Translated using Weblate (Hindi)

Currently translated at 100.0% (726 of 726 strings)

Translated using Weblate (Chinese (Traditional))

Currently translated at 100.0% (726 of 726 strings)

Translated using Weblate (Turkish)

Currently translated at 99.8% (725 of 726 strings)

Translated using Weblate (Slovak)

Currently translated at 98.4% (715 of 726 strings)

Translated using Weblate (Italian)

Currently translated at 100.0% (726 of 726 strings)

Translated using Weblate (Japanese)

Currently translated at 100.0% (726 of 726 strings)

Translated using Weblate (French)

Currently translated at 100.0% (726 of 726 strings)

Translated using Weblate (Chinese (Simplified))

Currently translated at 100.0% (726 of 726 strings)

Translated using Weblate (Polish)

Currently translated at 100.0% (726 of 726 strings)

Translated using Weblate (Arabic)

Currently translated at 100.0% (726 of 726 strings)

Translated using Weblate (Greek)

Currently translated at 100.0% (726 of 726 strings)

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

Currently translated at 100.0% (726 of 726 strings)

Translated using Weblate (Italian)

Currently translated at 99.5% (723 of 726 strings)

Translated using Weblate (Serbian)

Currently translated at 100.0% (726 of 726 strings)

Translated using Weblate (Dutch)

Currently translated at 100.0% (726 of 726 strings)

Translated using Weblate (Czech)

Currently translated at 100.0% (726 of 726 strings)

Translated using Weblate (Spanish)

Currently translated at 100.0% (726 of 726 strings)

Translated using Weblate (German)

Currently translated at 100.0% (726 of 726 strings)

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

Currently translated at 21.0% (16 of 76 strings)

Translated using Weblate (Serbian)

Currently translated at 100.0% (725 of 725 strings)

Translated using Weblate (Portuguese (Brazil))

Currently translated at 100.0% (725 of 725 strings)

Translated using Weblate (Romanian)

Currently translated at 99.8% (724 of 725 strings)

Translated using Weblate (Dutch)

Currently translated at 100.0% (725 of 725 strings)

Translated using Weblate (Spanish)

Currently translated at 100.0% (725 of 725 strings)

Co-authored-by: Agnieszka C <aga_04@o2.pl>
Co-authored-by: Alex25820 <alexs25820@gmail.com>
Co-authored-by: Alexthegib <traducoes@skiff.com>
Co-authored-by: Allan Nordhøy <epost@anotheragency.no>
Co-authored-by: Andrey F <firsan777@mail.ru>
Co-authored-by: Angelk90 <angelo.k90@hotmail.it>
Co-authored-by: Chethan <76928501+ch3thanhs@users.noreply.github.com>
Co-authored-by: Danr <mdp43140@gmail.com>
Co-authored-by: David Svane <davidcygnus@users.noreply.hosted.weblate.org>
Co-authored-by: Deleted User <noreply+77891@weblate.org>
Co-authored-by: DuninduH <mateyh37@gmail.com>
Co-authored-by: Eric <zxmegaxqug@hldrive.com>
Co-authored-by: Fjuro <ifjuro@proton.me>
Co-authored-by: GET100PERCENT <eraofphysics@yahoo.com>
Co-authored-by: Ghost of Sparta <makesocialfoss32@keemail.me>
Co-authored-by: Heidhou chazanouvha <Heidhou@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: Ihfandi <ihfandicahyo@gmail.com>
Co-authored-by: Ihor Hordiichuk <igor_ck@outlook.com>
Co-authored-by: Jan Layola <gilajan@protonmail.com>
Co-authored-by: Jeff Huang <s8321414@gmail.com>
Co-authored-by: Juan Martinez <jjml.nipon@gmail.com>
Co-authored-by: KarmaKat <lloydwestbury@gmail.com>
Co-authored-by: Kuko <kuko7@protonmail.ch>
Co-authored-by: LiJu09 <lisojuraj@gmail.com>
Co-authored-by: Martin Constantino–Bodin <martin.bodin@ens-lyon.org>
Co-authored-by: Mehmet <mehmetyalcin.0103@gmail.com>
Co-authored-by: Michalis <michalisntovas@yahoo.gr>
Co-authored-by: Milan <mobrcian@hotmail.com>
Co-authored-by: Milo Ivir <mail@milotype.de>
Co-authored-by: NEXI <nexiphotographer@gmail.com>
Co-authored-by: Nils Van Zuijlen <nils.van-zuijlen@mailo.com>
Co-authored-by: Nista <42772160+Nista11@users.noreply.github.com>
Co-authored-by: Oğuz Ersen <oguz@ersen.moe>
Co-authored-by: P.O <rasmusson.mikael@protonmail.com>
Co-authored-by: Philip Goto <philip.goto@gmail.com>
Co-authored-by: Pi-Cla <pirateclip@protonmail.com>
Co-authored-by: Prasanta-Hembram <Prasantahembram720@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: Ray <ray@users.noreply.hosted.weblate.org>
Co-authored-by: Rex_sa <rex.sa@pm.me>
Co-authored-by: Scrambled777 <weblate.scrambled777@simplelogin.com>
Co-authored-by: Sergio Marques <so.boston.android@gmail.com>
Co-authored-by: ShareASmile <aapshergill@gmail.com>
Co-authored-by: Subbarayudu <raidu.g6@gmail.com>
Co-authored-by: Subham Jena <subhamjena8465@gmail.com>
Co-authored-by: T1z3n <info@njbraun.de>
Co-authored-by: Terry Louwers <t.louwers@gmail.com>
Co-authored-by: TobiGr <TobiGr@users.noreply.github.com>
Co-authored-by: Vasilis K <skyhirules@gmail.com>
Co-authored-by: VfBFan <VfBFan@users.noreply.hosted.weblate.org>
Co-authored-by: Xəyyam Qocayev <xxmn77@gmail.com>
Co-authored-by: Yaron Shahrabani <sh.yaron@gmail.com>
Co-authored-by: bittin1ddc447d824349b2 <bittin@reimu.nl>
Co-authored-by: cat <158170307+cultcats@users.noreply.github.com>
Co-authored-by: ds-z <drazen.sostaric01@gmail.com>
Co-authored-by: dyare darbani <darbanidyare@gmail.com>
Co-authored-by: fsbat0 <fsbat0@users.noreply.hosted.weblate.org>
Co-authored-by: gallegonovato <fran-carro@hotmail.es>
Co-authored-by: hshbuk <hsh.bukchin@gmail.com>
Co-authored-by: jspast <joao.pastorello@protonmail.com>
Co-authored-by: kuragehime <kuragehime641@gmail.com>
Co-authored-by: ngocanhtve <ngocanh.tve@gmail.com>
Co-authored-by: pjammo <adrianoghr@hotmail.it>
Co-authored-by: ssantos <ssantos@web.de>
Co-authored-by: trunars <trunars@gmail.com>
Co-authored-by: v1s7 <v1s7@users.noreply.hosted.weblate.org>
Co-authored-by: Åzze <laitinen.jere222@gmail.com>
Co-authored-by: Çağla Pickaxe <caglapickaxe@gmail.com>
Co-authored-by: Макар Разин <makarrazin14@gmail.com>
Translate-URL: https://hosted.weblate.org/projects/newpipe/metadata/ar/
Translate-URL: https://hosted.weblate.org/projects/newpipe/metadata/bg/
Translate-URL: https://hosted.weblate.org/projects/newpipe/metadata/bn/
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/es/
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/hr/
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/ja/
Translate-URL: https://hosted.weblate.org/projects/newpipe/metadata/ka/
Translate-URL: https://hosted.weblate.org/projects/newpipe/metadata/pa/
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/si/
Translate-URL: https://hosted.weblate.org/projects/newpipe/metadata/sk/
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/tr/
Translate-URL: https://hosted.weblate.org/projects/newpipe/metadata/uk/
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
2024-03-18 09:59:34 +01:00
Tobi
de2a139340 Merge pull request #10889 from eltociear/patch-1
Fix typo in TextLinkifier.java
2024-03-18 08:38:16 +01:00
Ikko Eltociear Ashimine
9d6ac67c46 Update TextLinkifier.java
minor fix
2024-03-18 14:43:16 +09:00
Audric V
6f7b905983 Merge pull request #10740 from Goooler/gha
Update GitHub action dependencies in workflows
2024-02-05 23:44:45 +01:00
Audric V
bcd4626008 Merge pull request #10817 from Isira-Seneviratne/Jsoup
Update jsoup to 1.17.2
2024-02-05 14:37:43 +01:00
Isira Seneviratne
27730a20d6 Update Jsoup to 1.17.2 2024-02-05 10:52:08 +05:30
Audric V
4aa0190175 Merge pull request #10795 from TeamNewPipe/matrix_room_URL_change
Update Matrix chat URL to new link
2024-01-28 14:14:30 +01:00
opusforlife2
6dd62335e9 Update Matrix room URL to new link 2024-01-27 16:36:13 +00:00
Profpatsch
32d2606a65 BaseDescriptionFragment: Assert member is initialized
`streamInfo` and `channelInfo` have to be initialized, since the only
way to construct the class it to pass them. So we can remove the null
check boilerplate and make some of the accessors `NonNull`.
2024-01-23 14:28:37 +01:00
Zongle Wang
2051334bba Bump GH actions
Old ones are deprecated.
2024-01-08 11:55:57 +08:00
Profpatsch
575e809004 Don't write defaultFormat setting, use default value
Nowhere else does this (write a setting if it’s not set).

It took me a while to see that this code does not do what it intends,
because `defaultFormat` is already the default value in the first
`context.getString`, so calling `getMediaFormatFromKey` again is the
exact same call (“do you know the definition of insanity…”) and will
return `null` again …

So let’s drop the setting write and just rely on the default values.
2024-01-06 17:24:53 +01:00
Roshan Jossy
66e8e2a696 use GitHub markdown to emphasise warning in Readme 2024-01-01 15:07:37 +01:00
Stypox
55373c95d9 Update NewPipeExtractor to include MediaCCC channel fix 2023-12-30 23:49:09 +01:00
Stypox
04bdc1cc0b Base cache key on info type instead of item type
It didn't really made sense to consider two cache keys as equal based on the type of items contained within that list.
2023-12-30 23:46:16 +01:00
Stypox
1d8850d1b2 Merge pull request #10712 from Stypox/notification-actions-api-33-2
[Android 13+] Restore support of custom notification actions
2023-12-30 21:55:44 +01:00
Stypox
f98548698a Android 33 -> Android 13
Co-authored-by: Tobi <TobiGr@users.noreply.github.com>
2023-12-30 21:55:32 +01:00
Stypox
4b1824e8c1 Allow play/pausing from notification when buffering
This change is in line with a recent change in how the play/pause button behaves in the player ui: if the buffering indicator is shown, it's still possible to toggle play/pause, to allow e.g. pausing videos before they even start.
This change was needed because on Android 13+ notification actions can't be null, and thus the buffering hourglass action wasn't shown.
2023-12-29 16:18:26 +01:00
Stypox
17e88f1749 Do not update notification actions if nothing changed
This should avoid costly updates of the media session.
2023-12-29 16:16:45 +01:00
Stypox
5edafca05a Implement notification actions via MediaSessionConnector on Android 13+ 2023-12-29 15:54:15 +01:00
Stypox
2c4c283099 Extract NotificationActionData from NotificationUtil 2023-12-29 15:54:15 +01:00
Stypox
9fb8125655 Allow each notification slot to contain any possible action 2023-12-29 15:54:15 +01:00
Stypox
aab6580195 Extract NotificationSlot from NotificationActionsPreference 2023-12-29 12:31:59 +01:00
Stypox
30f0db1d28 Customize only 2 notification actions on Android 13+ 2023-12-29 12:13:08 +01:00
Stypox
5a4dae2070 Fix settings_notification.xml indentation 2023-12-29 11:37:17 +01:00
Stypox
8345f348f6 Merge pull request #10091 from TeamNewPipe/feat/playlist_description
Add playlist description to playlist fragment
2023-12-29 10:58:13 +01:00
Stypox
9220e32463 Fix FeedDAOTest 2023-12-29 10:54:31 +01:00
Stypox
845e72bf4a Merge branch 'master' into dev 2023-12-29 10:48:37 +01:00
Tobi
49429ff40a Merge pull request #10700 from TeamNewPipe/newpipe_0.26.1
Newpipe 0.26.1
2023-12-26 18:26:48 +01:00
TobiGr
3df21ad25e Bump version to 0.26.1 (996) 2023-12-26 16:59:02 +01:00
TobiGr
d0f4600be4 Add changelog for NewPipe 0.26.1 2023-12-26 16:58:49 +01:00
TobiGr
0fa2e76c3e Fix NPE when ChannelTabLHFactory not implemented for a service
Fixes #10698
2023-12-26 16:55:52 +01:00
Stypox
9ff1b5230f Improve TextEllipsizer class 2023-12-23 18:04:05 +01:00
TobiGr
65eb631711 Ellipsize playlist description if it is longer than 5 lines
The description can be expanded / collapsed via a "show more" / "show less" button.
2023-12-23 12:33:52 +01:00
TobiGr
6c99557553 Add playlist description to PlaylistFragment 2023-12-23 12:13:34 +01:00
Stypox
2b4357fa87 Merge pull request #10530 from TacoTheDank/bumpMiscLibraries
Update miscellaneous libraries
2023-12-23 12:06:42 +01:00
Stypox
cda4b3faaa Update AGP and Gradle 2023-12-23 12:01:50 +01:00
Stypox
5d09a88335 Update more libraries 2023-12-23 11:58:58 +01:00
TacoTheDank
edd4f6b9f3 Update Studio and desugaring versions 2023-12-23 11:47:57 +01:00
TacoTheDank
1e7e2109d2 Exclude RxJava file from META-INF 2023-12-23 11:47:57 +01:00
TacoTheDank
b31d3831e6 Change Converters to class to fix build 2023-12-23 11:47:57 +01:00
TacoTheDank
0f81a0504c Use 'tasks.register' for Gradle tasks 2023-12-23 11:47:57 +01:00
TacoTheDank
4a7fda95ae Update miscellaneous libraries 2023-12-23 11:47:57 +01:00
Stypox
ee3455e1e5 Merge pull request #10086 from TacoTheDank/bumpAndroidX
Update some AndroidX libraries and compileSdk to 34
2023-12-23 11:46:28 +01:00
Isira Seneviratne
f9fc1cd817 Store/retrieve parcelable arrays as lists instead. 2023-12-23 11:38:40 +01:00
TacoTheDank
76f1e588f7 Utilize BundleCompat and IntentCompat methods 2023-12-23 11:38:40 +01:00
Isira Seneviratne
f3b458c803 Bump compileSdk to 34 2023-12-23 11:38:32 +01:00
TacoTheDank
00566ed4d4 Fix AndroidX Work deprecation 2023-12-23 11:36:33 +01:00
TacoTheDank
e4a07411b8 Update some AndroidX libraries 2023-12-23 11:36:32 +01:00
Stypox
2c1bb2706f Merge pull request #10018 from Stypox/comment-replies
Add support for comment replies
2023-12-23 11:01:07 +01:00
Stypox
aa84d6fc8f Add @NonNull annotations 2023-12-22 18:52:42 +01:00
Stypox
d76e9b0bd8 Fix scrolling to correct comment after closing replies 2023-12-22 18:52:42 +01:00
TobiGr
b4016c91c1 scroll last comment into view 2023-12-22 11:57:55 +01:00
TobiGr
5f32d001cc Expand DetailFragment again when exiting the CommentRepliesFragment 2023-12-22 11:57:55 +01:00
Stypox
8c9287d0c8 Revert relying on source ListInfo, use commentsInfoItem.getUrl() instead
This reverts commit bb01da3691ff1d5c3dccd41b7ca1a5deb1b5676f. This commit was not needed
2023-12-22 11:57:55 +01:00
Stypox
3f37e27852 Add some documentation and javadocs
Also further simplify CommentRepliesInfo and RelatedItemsInfo
2023-12-22 11:57:55 +01:00
Stypox
f41ab8b086 Add comment replies fragment header 2023-12-22 11:57:55 +01:00
Stypox
ad68f784ae Extract some utility methods from CommentInfoItemHolder 2023-12-22 11:48:07 +01:00
Stypox
4b6392df54 Set comment replies fragment title 2023-12-22 11:48:07 +01:00
Stypox
94ea329b50 Always show comment replies in list mode 2023-12-22 11:48:07 +01:00
Stypox
591ed2e01f Fix some code smells 2023-12-22 11:48:07 +01:00
Stypox
78cf9aaa7d Save and restore state in CommentRepliesFragment 2023-12-22 11:48:07 +01:00
Stypox
f9494a294f Implement CommentRepliesFragment 2023-12-22 11:48:07 +01:00
Stypox
0dd4553700 Load more items even if initial related items are empty 2023-12-22 11:48:07 +01:00
Stypox
4f7b36cd70 Keep source list info in InfoItemBuilder
Also remove some unused code
2023-12-22 11:48:07 +01:00
Stypox
5d350aec87 Move RelatedItemInfo next to fragment using it 2023-12-22 11:48:07 +01:00
Stypox
059db6fb31 Add replies button to comments 2023-12-22 11:48:05 +01:00
Stypox
4c709b2c4d Use start/end instead of left/right in comment layout 2023-12-22 11:46:03 +01:00
Stypox
8f4cd032b7 Remove mini variant and move upload date to top in comments 2023-12-22 11:46:03 +01:00
TobiGr
df2e0be08d Add summary to reset preference 2023-09-21 16:01:07 +02:00
TobiGr
ff1aca272e Remove strange change 2023-09-21 16:01:07 +02:00
TobiGr
f2e352832a Create new settings category: Backup and restore
Following settings have been move to the new category:
- import database (from ContenttSettings)
- export database (from ContenttSettings)
- reset settings (from DebugSettings)
2023-09-21 16:01:07 +02:00
vincetzr
ad0855ac83 Update app/src/main/res/xml/debug_settings.xml
Ensuring title to be fully displayed on small devices.

Co-authored-by: Tobi <TobiGr@users.noreply.github.com>
2023-09-21 16:01:07 +02:00
Vincent Tanumihardja
d7ef9b1f0c Added strings to strings.xml to allow translation. 2023-09-21 16:01:07 +02:00
Vincent Tanumihardja
40a3e1b18a Revert committed file change of settings key. 2023-09-21 16:01:07 +02:00
Vincent Tanumihardja
25a73090f5 Revert changes made to dev. 2023-09-21 16:01:07 +02:00
Vincent Tanumihardja
a239a26b17 Revert changes made to dev. 2023-09-21 16:01:07 +02:00
Vincent Tanumihardja
06d256294f Revert changes made to dev. 2023-09-21 16:01:07 +02:00
Vincent Tanumihardja
81ad50e82a Added delete xml method inside the yes dialogue. 2023-09-21 16:01:07 +02:00
Zhidong Piao
23de9bf93e clear shared preference xmls 2023-09-21 16:01:07 +02:00
Vincent Tanumihardja
5c46412faa Changed alert dialogue. 2023-09-21 16:01:07 +02:00
Vincent Tanumihardja
076e9eee01 Added alert dialogue and restarts the app when resetting settings. 2023-09-21 16:01:07 +02:00
Vincent Tanumihardja
2103a04092 Cleaned up xml files. 2023-09-21 16:01:07 +02:00
Vincent Tanumihardja
58517d1d27 Added reset button but working as intended for theme. 2023-09-21 16:01:07 +02:00
Vincent Tanumihardja
aa1847189b Added reset button but slightly working as intended. 2023-09-21 16:01:07 +02:00
Vincent Tanumihardja
5d101e7b88 Added reset button but not working as intended. 2023-09-21 16:01:07 +02:00
TobiGr
9118ecd68f Remove unnecessary debug warning and use JDoc instead 2023-08-17 16:51:31 +02:00
TobiGr
15fd47c7f2 Apply review 2023-08-16 22:18:53 +02:00
Yingwei Zheng
ef40ac7bb3 Fix a typo 2023-08-16 22:02:12 +02:00
Yingwei Zheng
881d04ba1e Refactor database migration test and string trimming 2023-08-16 22:02:12 +02:00
TobiGr
4af5b5f6f2 Fix database migration and string trimming
Co-authored-by:  Yingwei Zheng <dtcxzyw@qq.com>
2023-08-16 22:02:12 +02:00
TobiGr
90f0809029 Trim search string and remove duplicate records from the database
Co-authored-by:  Yingwei Zheng <dtcxzyw@qq.com>
2023-08-16 21:26:35 +02:00
GGAutomaton
8ad7bf60d7 Delete saveImmediate warnings & add comments 2022-06-23 23:31:56 +08:00
GGAutomaton
898a936064 Update index modification logic & redo sorting in the merge algorithm 2022-06-23 23:19:59 +08:00
GGAutomaton
4e401bc059 Update playlists in parallel 2022-06-23 20:36:21 +08:00
GGAutomaton
9ecef6f011 Add abstract methods in PlaylistLocalItem & rename setIsModified 2022-06-23 19:20:16 +08:00
GGAutomaton
ba394a7ab4 Update test and Javadoc 2022-05-11 18:08:14 +08:00
GGAutomaton
d32490a4be Create sub-package and default interval for DebounceSaver & sort playlists in db 2022-05-11 16:47:34 +08:00
GGAutomaton
6526ff1612 Add tests 2022-04-17 20:20:20 +08:00
GGAutomaton
bb5390d63a Reuse DebounceSaver 2022-04-17 14:53:02 +08:00
GGAutomaton
bd1aae8d66 Fix sonar warning 2022-04-16 12:44:24 +08:00
GGAutomaton
c24aed054f Fix sonar warning and typo 2022-04-16 12:00:02 +08:00
GGAutomaton
0aa08a5e40 Use new item holder 2022-04-15 23:19:24 +08:00
GGAutomaton
3c48825699 Debounced saver & bugfix & clean code 2022-04-15 20:44:54 +08:00
GGAutomaton
bfb56b4144 UI design and behavior 2022-04-14 16:59:52 +08:00
GGAutomaton
ba8370bcfd Save changes to the database and bugfix 2022-04-14 12:13:42 +08:00
GGAutomaton
813f55152a Merge branch 'TeamNewPipe:dev' into feature-7870 2022-04-13 22:48:26 +08:00
GGAutomaton
270a541a7c Implement algorithm to merge playlists 2022-04-13 22:46:24 +08:00
GGAutomaton
c34549a47d Update database migrations and getter/setter 2022-04-13 21:35:38 +08:00
GGAutomaton
96d6b309ec Migrate database 2022-04-13 19:41:07 +08:00
389 changed files with 10347 additions and 3334 deletions

View File

@@ -1,6 +1,3 @@
name: Question
description: Ask about anything NewPipe-related
labels: [question]
body:
- type: markdown
attributes:

View File

@@ -36,8 +36,8 @@ jobs:
contents: read
steps:
- uses: actions/checkout@v3
- uses: gradle/wrapper-validation-action@v1
- uses: actions/checkout@v4
- uses: gradle/wrapper-validation-action@v2
- name: create and checkout branch
# push events already checked out the branch
@@ -47,7 +47,7 @@ jobs:
run: git checkout -B "$BRANCH"
- name: set up JDK 17
uses: actions/setup-java@v3
uses: actions/setup-java@v4
with:
java-version: 17
distribution: "temurin"
@@ -57,7 +57,7 @@ jobs:
run: ./gradlew assembleDebug lintDebug testDebugUnitTest --stacktrace -DskipFormatKtlint
- name: Upload APK
uses: actions/upload-artifact@v3
uses: actions/upload-artifact@v4
with:
name: app
path: app/build/outputs/apk/debug/*.apk
@@ -80,10 +80,10 @@ jobs:
contents: read
steps:
- uses: actions/checkout@v3
- uses: actions/checkout@v4
- name: set up JDK 17
uses: actions/setup-java@v3
uses: actions/setup-java@v4
with:
java-version: 17
distribution: "temurin"
@@ -98,7 +98,7 @@ jobs:
script: ./gradlew connectedCheck --stacktrace
- name: Upload test report when tests fail # because the printed out stacktrace (console) is too short, see also #7553
uses: actions/upload-artifact@v3
uses: actions/upload-artifact@v4
if: failure()
with:
name: android-test-report-api${{ matrix.api-level }}
@@ -111,19 +111,19 @@ jobs:
contents: read
steps:
- uses: actions/checkout@v3
- uses: actions/checkout@v4
with:
fetch-depth: 0 # Shallow clones should be disabled for a better relevancy of analysis
- name: Set up JDK 17
uses: actions/setup-java@v3
uses: actions/setup-java@v4
with:
java-version: 17
distribution: "temurin"
cache: 'gradle'
- name: Cache SonarCloud packages
uses: actions/cache@v3
uses: actions/cache@v4
with:
path: ~/.sonar/cache
key: ${{ runner.os }}-sonar

View File

@@ -17,9 +17,9 @@ jobs:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- uses: actions/checkout@v4
- uses: actions/setup-node@v3
- uses: actions/setup-node@v4
with:
node-version: 16
@@ -27,7 +27,7 @@ jobs:
run: npm i probe-image-size@7.2.3 --ignore-scripts
- name: Minimize simple images
uses: actions/github-script@v6
uses: actions/github-script@v7
timeout-minutes: 3
with:
script: |

View File

@@ -1,5 +1,5 @@
name: "PR size labeler"
on: [pull_request]
on: [pull_request_target]
permissions:
contents: read
pull-requests: write

File diff suppressed because one or more lines are too long

View File

@@ -12,7 +12,7 @@ plugins {
}
android {
compileSdk 33
compileSdk 34
namespace 'org.schabi.newpipe'
defaultConfig {
@@ -20,8 +20,8 @@ android {
resValue "string", "app_name", "NewPipe"
minSdk 21
targetSdk 33
versionCode 995
versionName "0.26.0"
versionCode 997
versionName "0.27.0"
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
@@ -98,7 +98,9 @@ android {
resources {
// remove two files which belong to jsoup
// no idea how they ended up in the META-INF dir...
excludes += ['META-INF/README.md', 'META-INF/CHANGES']
excludes += ['META-INF/README.md', 'META-INF/CHANGES',
// 'COPYRIGHT' belongs to RxJava...
'META-INF/COPYRIGHT']
}
}
}
@@ -106,9 +108,9 @@ android {
ext {
checkstyleVersion = '10.12.1'
androidxLifecycleVersion = '2.5.1'
androidxRoomVersion = '2.5.2'
androidxWorkVersion = '2.7.1'
androidxLifecycleVersion = '2.6.2'
androidxRoomVersion = '2.6.1'
androidxWorkVersion = '2.8.1'
icepickVersion = '3.2.0'
exoPlayerVersion = '2.18.7'
@@ -118,7 +120,6 @@ ext {
leakCanaryVersion = '2.12'
stethoVersion = '1.6.0'
mockitoVersion = '4.0.0'
}
configurations {
@@ -133,7 +134,7 @@ checkstyle {
toolVersion = checkstyleVersion
}
task runCheckstyle(type: Checkstyle) {
tasks.register('runCheckstyle', Checkstyle) {
source 'src'
include '**/*.java'
exclude '**/gen/**'
@@ -154,7 +155,7 @@ task runCheckstyle(type: Checkstyle) {
def outputDir = "${project.buildDir}/reports/ktlint/"
def inputFiles = project.fileTree(dir: "src", include: "**/*.kt")
task runKtlint(type: JavaExec) {
tasks.register('runKtlint', JavaExec) {
inputs.files(inputFiles)
outputs.dir(outputDir)
getMainClass().set("com.pinterest.ktlint.Main")
@@ -163,7 +164,7 @@ task runKtlint(type: JavaExec) {
jvmArgs("--add-opens", "java.base/java.lang=ALL-UNNAMED")
}
task formatKtlint(type: JavaExec) {
tasks.register('formatKtlint', JavaExec) {
inputs.files(inputFiles)
outputs.dir(outputDir)
getMainClass().set("com.pinterest.ktlint.Main")
@@ -189,7 +190,7 @@ sonar {
dependencies {
/** Desugaring **/
coreLibraryDesugaring 'com.android.tools:desugar_jdk_libs_nio:2.0.3'
coreLibraryDesugaring 'com.android.tools:desugar_jdk_libs_nio:2.0.4'
/** NewPipe libraries **/
// You can use a local version by uncommenting a few lines in settings.gradle
@@ -197,7 +198,7 @@ dependencies {
// name and the commit hash with the commit hash of the (pushed) commit you want to test
// This works thanks to JitPack: https://jitpack.io/
implementation 'com.github.TeamNewPipe:nanojson:1d9e1aea9049fc9f85e68b43ba39fe7be1c1f751'
implementation 'com.github.TeamNewPipe:NewPipeExtractor:v0.23.1'
implementation 'com.github.TeamNewPipe:NewPipeExtractor:v0.24.0'
implementation 'com.github.TeamNewPipe:NoNonsense-FilePicker:5.0.0'
/** Checkstyle **/
@@ -208,28 +209,28 @@ dependencies {
implementation "org.jetbrains.kotlin:kotlin-stdlib:${kotlin_version}"
/** AndroidX **/
implementation 'androidx.appcompat:appcompat:1.5.1'
implementation 'androidx.appcompat:appcompat:1.6.1'
implementation 'androidx.cardview:cardview:1.0.0'
implementation 'androidx.constraintlayout:constraintlayout:2.1.4'
implementation 'androidx.core:core-ktx:1.10.0'
implementation 'androidx.core:core-ktx:1.12.0'
implementation 'androidx.documentfile:documentfile:1.0.1'
implementation 'androidx.fragment:fragment-ktx:1.4.1'
implementation 'androidx.fragment:fragment-ktx:1.6.2'
implementation "androidx.lifecycle:lifecycle-livedata-ktx:${androidxLifecycleVersion}"
implementation "androidx.lifecycle:lifecycle-viewmodel-ktx:${androidxLifecycleVersion}"
implementation 'androidx.localbroadcastmanager:localbroadcastmanager:1.1.0'
implementation 'androidx.media:media:1.6.0'
implementation 'androidx.preference:preference:1.2.0'
implementation 'androidx.recyclerview:recyclerview:1.2.1'
implementation 'androidx.media:media:1.7.0'
implementation 'androidx.preference:preference:1.2.1'
implementation 'androidx.recyclerview:recyclerview:1.3.2'
implementation "androidx.room:room-runtime:${androidxRoomVersion}"
implementation "androidx.room:room-rxjava3:${androidxRoomVersion}"
kapt "androidx.room:room-compiler:${androidxRoomVersion}"
implementation 'androidx.swiperefreshlayout:swiperefreshlayout:1.1.0'
// Newer version specified to prevent accessibility regressions with RecyclerView, see:
// https://developer.android.com/jetpack/androidx/releases/viewpager2#1.1.0-alpha01
implementation 'androidx.viewpager2:viewpager2:1.1.0-beta01'
implementation 'androidx.viewpager2:viewpager2:1.1.0-beta02'
implementation "androidx.work:work-runtime-ktx:${androidxWorkVersion}"
implementation "androidx.work:work-rxjava3:${androidxWorkVersion}"
implementation 'com.google.android.material:material:1.9.0'
implementation 'com.google.android.material:material:1.11.0'
/** Third-party libraries **/
// Instance state boilerplate elimination
@@ -237,13 +238,10 @@ dependencies {
kapt "frankiesardo:icepick-processor:${icepickVersion}"
// HTML parser
implementation "org.jsoup:jsoup:1.16.1"
implementation "org.jsoup:jsoup:1.17.2"
// HTTP client
implementation "com.squareup.okhttp3:okhttp:4.11.0"
// okhttp3:4.11.0 introduces a vulnerability from com.squareup.okio:okio@3.3.0,
// remove com.squareup.okio:okio when updating okhttp
implementation "com.squareup.okio:okio:3.4.0"
implementation "com.squareup.okhttp3:okhttp:4.12.0"
// Media player
implementation "com.google.android.exoplayer:exoplayer-core:${exoPlayerVersion}"
@@ -272,19 +270,19 @@ dependencies {
implementation "io.noties.markwon:linkify:${markwonVersion}"
// Crash reporting
implementation "ch.acra:acra-core:5.10.1"
implementation "ch.acra:acra-core:5.11.3"
// Properly restarting
implementation 'com.jakewharton:process-phoenix:2.1.2'
// Reactive extensions for Java VM
implementation "io.reactivex.rxjava3:rxjava:3.1.6"
implementation "io.reactivex.rxjava3:rxjava:3.1.8"
implementation "io.reactivex.rxjava3:rxandroid:3.0.2"
// RxJava binding APIs for Android UI widgets
implementation "com.jakewharton.rxbinding4:rxbinding:4.0.0"
// Date and time formatting
implementation "org.ocpsoft.prettytime:prettytime:5.0.6.Final"
implementation "org.ocpsoft.prettytime:prettytime:5.0.7.Final"
/** Debugging **/
// Memory leak detection
@@ -297,13 +295,12 @@ dependencies {
/** Testing **/
testImplementation 'junit:junit:4.13.2'
testImplementation "org.mockito:mockito-core:${mockitoVersion}"
testImplementation "org.mockito:mockito-inline:${mockitoVersion}"
testImplementation 'org.mockito:mockito-core:5.6.0'
androidTestImplementation "androidx.test.ext:junit:1.1.5"
androidTestImplementation "androidx.test:runner:1.5.2"
androidTestImplementation "androidx.room:room-testing:${androidxRoomVersion}"
androidTestImplementation "org.assertj:assertj-core:3.23.1"
androidTestImplementation "org.assertj:assertj-core:3.24.2"
}
static String getGitWorkingBranch() {

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -8,10 +8,14 @@ import androidx.test.core.app.ApplicationProvider
import androidx.test.ext.junit.runners.AndroidJUnit4
import androidx.test.platform.app.InstrumentationRegistry
import org.junit.Assert.assertEquals
import org.junit.Assert.assertNotEquals
import org.junit.Assert.assertNull
import org.junit.Rule
import org.junit.Test
import org.junit.runner.RunWith
import org.schabi.newpipe.database.playlist.model.PlaylistEntity
import org.schabi.newpipe.database.playlist.model.PlaylistRemoteEntity
import org.schabi.newpipe.extractor.ServiceList
import org.schabi.newpipe.extractor.stream.StreamType
@RunWith(AndroidJUnit4::class)
@@ -20,13 +24,17 @@ class DatabaseMigrationTest {
private const val DEFAULT_SERVICE_ID = 0
private const val DEFAULT_URL = "https://www.youtube.com/watch?v=cDphUib5iG4"
private const val DEFAULT_TITLE = "Test Title"
private const val DEFAULT_NAME = "Test Name"
private val DEFAULT_TYPE = StreamType.VIDEO_STREAM
private const val DEFAULT_DURATION = 480L
private const val DEFAULT_UPLOADER_NAME = "Uploader Test"
private const val DEFAULT_THUMBNAIL = "https://example.com/example.jpg"
private const val DEFAULT_SECOND_SERVICE_ID = 0
private const val DEFAULT_SECOND_SERVICE_ID = 1
private const val DEFAULT_SECOND_URL = "https://www.youtube.com/watch?v=ncQU6iBn5Fc"
private const val DEFAULT_THIRD_SERVICE_ID = 2
private const val DEFAULT_THIRD_URL = "https://www.youtube.com/watch?v=dQw4w9WgXcQ"
}
@get:Rule
@@ -106,6 +114,20 @@ class DatabaseMigrationTest {
Migrations.MIGRATION_6_7
)
testHelper.runMigrationsAndValidate(
AppDatabase.DATABASE_NAME,
Migrations.DB_VER_8,
true,
Migrations.MIGRATION_7_8
)
testHelper.runMigrationsAndValidate(
AppDatabase.DATABASE_NAME,
Migrations.DB_VER_9,
true,
Migrations.MIGRATION_8_9
)
val migratedDatabaseV3 = getMigratedDatabase()
val listFromDB = migratedDatabaseV3.streamDAO().all.blockingFirst()
@@ -140,6 +162,157 @@ class DatabaseMigrationTest {
assertNull(secondStreamFromMigratedDatabase.isUploadDateApproximation)
}
@Test
fun migrateDatabaseFrom7to8() {
val databaseInV7 = testHelper.createDatabase(AppDatabase.DATABASE_NAME, Migrations.DB_VER_7)
val defaultSearch1 = " abc "
val defaultSearch2 = " abc"
val serviceId = DEFAULT_SERVICE_ID // YouTube
// Use id different to YouTube because two searches with the same query
// but different service are considered not equal.
val otherServiceId = ServiceList.SoundCloud.serviceId
databaseInV7.run {
insert(
"search_history", SQLiteDatabase.CONFLICT_FAIL,
ContentValues().apply {
put("service_id", serviceId)
put("search", defaultSearch1)
}
)
insert(
"search_history", SQLiteDatabase.CONFLICT_FAIL,
ContentValues().apply {
put("service_id", serviceId)
put("search", defaultSearch2)
}
)
insert(
"search_history", SQLiteDatabase.CONFLICT_FAIL,
ContentValues().apply {
put("service_id", otherServiceId)
put("search", defaultSearch1)
}
)
insert(
"search_history", SQLiteDatabase.CONFLICT_FAIL,
ContentValues().apply {
put("service_id", otherServiceId)
put("search", defaultSearch2)
}
)
close()
}
testHelper.runMigrationsAndValidate(
AppDatabase.DATABASE_NAME, Migrations.DB_VER_8,
true, Migrations.MIGRATION_7_8
)
testHelper.runMigrationsAndValidate(
AppDatabase.DATABASE_NAME, Migrations.DB_VER_9,
true, Migrations.MIGRATION_8_9
)
val migratedDatabaseV8 = getMigratedDatabase()
val listFromDB = migratedDatabaseV8.searchHistoryDAO().all.blockingFirst()
assertEquals(2, listFromDB.size)
assertEquals("abc", listFromDB[0].search)
assertEquals("abc", listFromDB[1].search)
assertNotEquals(listFromDB[0].serviceId, listFromDB[1].serviceId)
}
@Test
fun migrateDatabaseFrom8to9() {
val databaseInV8 = testHelper.createDatabase(AppDatabase.DATABASE_NAME, Migrations.DB_VER_8)
val localUid1: Long
val localUid2: Long
val remoteUid1: Long
val remoteUid2: Long
databaseInV8.run {
localUid1 = insert(
"playlists", SQLiteDatabase.CONFLICT_FAIL,
ContentValues().apply {
put("name", DEFAULT_NAME + "1")
put("is_thumbnail_permanent", false)
put("thumbnail_stream_id", -1)
}
)
localUid2 = insert(
"playlists", SQLiteDatabase.CONFLICT_FAIL,
ContentValues().apply {
put("name", DEFAULT_NAME + "2")
put("is_thumbnail_permanent", false)
put("thumbnail_stream_id", -1)
}
)
delete(
"playlists", "uid = ?",
Array(1) { localUid1 }
)
remoteUid1 = insert(
"remote_playlists", SQLiteDatabase.CONFLICT_FAIL,
ContentValues().apply {
put("service_id", DEFAULT_SERVICE_ID)
put("url", DEFAULT_URL)
}
)
remoteUid2 = insert(
"remote_playlists", SQLiteDatabase.CONFLICT_FAIL,
ContentValues().apply {
put("service_id", DEFAULT_SECOND_SERVICE_ID)
put("url", DEFAULT_SECOND_URL)
}
)
delete(
"remote_playlists", "uid = ?",
Array(1) { remoteUid2 }
)
close()
}
testHelper.runMigrationsAndValidate(
AppDatabase.DATABASE_NAME,
Migrations.DB_VER_9,
true,
Migrations.MIGRATION_8_9
)
val migratedDatabaseV9 = getMigratedDatabase()
var localListFromDB = migratedDatabaseV9.playlistDAO().all.blockingFirst()
var remoteListFromDB = migratedDatabaseV9.playlistRemoteDAO().all.blockingFirst()
assertEquals(1, localListFromDB.size)
assertEquals(localUid2, localListFromDB[0].uid)
assertEquals(-1, localListFromDB[0].displayIndex)
assertEquals(1, remoteListFromDB.size)
assertEquals(remoteUid1, remoteListFromDB[0].uid)
assertEquals(-1, remoteListFromDB[0].displayIndex)
val localUid3 = migratedDatabaseV9.playlistDAO().insert(
PlaylistEntity(DEFAULT_NAME + "3", false, -1, -1)
)
val remoteUid3 = migratedDatabaseV9.playlistRemoteDAO().insert(
PlaylistRemoteEntity(
DEFAULT_THIRD_SERVICE_ID, DEFAULT_NAME, DEFAULT_THIRD_URL,
DEFAULT_THUMBNAIL, DEFAULT_UPLOADER_NAME, -1, 10
)
)
localListFromDB = migratedDatabaseV9.playlistDAO().all.blockingFirst()
remoteListFromDB = migratedDatabaseV9.playlistRemoteDAO().all.blockingFirst()
assertEquals(2, localListFromDB.size)
assertEquals(localUid3, localListFromDB[1].uid)
assertEquals(-1, localListFromDB[1].displayIndex)
assertEquals(2, remoteListFromDB.size)
assertEquals(remoteUid3, remoteListFromDB[1].uid)
assertEquals(-1, remoteListFromDB[1].displayIndex)
}
private fun getMigratedDatabase(): AppDatabase {
val database: AppDatabase = Room.databaseBuilder(
ApplicationProvider.getApplicationContext(),

View File

@@ -85,7 +85,13 @@ class FeedDAOTest {
private fun assertEqual(streams: List<StreamWithState>?, allowedStreams: List<StreamEntity>) {
assertNotNull(streams)
assertEquals(allowedStreams, streams!!.stream().map { it.stream }.toList().sortedBy { it.uid })
assertEquals(
allowedStreams,
streams!!
.map { it.stream }
.sortedBy { it.uid }
.toList()
)
}
private fun setupUnlinkDelete(time: String) {

View File

@@ -25,6 +25,7 @@ import android.view.ViewGroup;
import androidx.annotation.IntDef;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.core.os.BundleCompat;
import androidx.lifecycle.Lifecycle;
import androidx.viewpager.widget.PagerAdapter;
@@ -284,7 +285,7 @@ public abstract class FragmentStatePagerAdapterMenuWorkaround extends PagerAdapt
Bundle state = null;
if (!mSavedState.isEmpty()) {
state = new Bundle();
state.putParcelableArray("states", mSavedState.toArray(new Fragment.SavedState[0]));
state.putParcelableArrayList("states", mSavedState);
}
for (int i = 0; i < mFragments.size(); i++) {
final Fragment f = mFragments.get(i);
@@ -311,13 +312,12 @@ public abstract class FragmentStatePagerAdapterMenuWorkaround extends PagerAdapt
if (state != null) {
final Bundle bundle = (Bundle) state;
bundle.setClassLoader(loader);
final Parcelable[] fss = bundle.getParcelableArray("states");
final var states = BundleCompat.getParcelableArrayList(bundle, "states",
Fragment.SavedState.class);
mSavedState.clear();
mFragments.clear();
if (fss != null) {
for (final Parcelable parcelable : fss) {
mSavedState.add((Fragment.SavedState) parcelable);
}
if (states != null) {
mSavedState.addAll(states);
}
final Iterable<String> keys = bundle.keySet();
for (final String key : keys) {

View File

@@ -60,6 +60,8 @@ import io.reactivex.rxjava3.plugins.RxJavaPlugins;
public class App extends Application {
public static final String PACKAGE_NAME = BuildConfig.APPLICATION_ID;
private static final String TAG = App.class.toString();
private boolean isFirstRun = false;
private static App app;
@NonNull
@@ -85,7 +87,13 @@ public class App extends Application {
return;
}
// Initialize settings first because others inits can use its values
// check if the last used preference version is set
// to determine whether this is the first app run
final int lastUsedPrefVersion = PreferenceManager.getDefaultSharedPreferences(this)
.getInt(getString(R.string.last_used_preferences_version), -1);
isFirstRun = lastUsedPrefVersion == -1;
// Initialize settings first because other initializations can use its values
NewPipeSettings.initSettings(this);
NewPipe.init(getDownloader(),
@@ -255,4 +263,7 @@ public class App extends Application {
return false;
}
public boolean isFirstRun() {
return isFirstRun;
}
}

View File

@@ -44,6 +44,7 @@ import android.widget.FrameLayout;
import android.widget.Spinner;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.appcompat.app.ActionBar;
import androidx.appcompat.app.ActionBarDrawerToggle;
import androidx.appcompat.app.AppCompatActivity;
@@ -51,6 +52,7 @@ import androidx.core.app.ActivityCompat;
import androidx.core.view.GravityCompat;
import androidx.drawerlayout.widget.DrawerLayout;
import androidx.fragment.app.Fragment;
import androidx.fragment.app.FragmentContainerView;
import androidx.fragment.app.FragmentManager;
import androidx.preference.PreferenceManager;
@@ -64,17 +66,20 @@ import org.schabi.newpipe.databinding.ToolbarLayoutBinding;
import org.schabi.newpipe.error.ErrorUtil;
import org.schabi.newpipe.extractor.NewPipe;
import org.schabi.newpipe.extractor.StreamingService;
import org.schabi.newpipe.extractor.comments.CommentsInfoItem;
import org.schabi.newpipe.extractor.exceptions.ExtractionException;
import org.schabi.newpipe.extractor.services.peertube.PeertubeInstance;
import org.schabi.newpipe.fragments.BackPressable;
import org.schabi.newpipe.fragments.MainFragment;
import org.schabi.newpipe.fragments.detail.VideoDetailFragment;
import org.schabi.newpipe.fragments.list.comments.CommentRepliesFragment;
import org.schabi.newpipe.fragments.list.search.SearchFragment;
import org.schabi.newpipe.local.feed.notifications.NotificationWorker;
import org.schabi.newpipe.player.Player;
import org.schabi.newpipe.player.event.OnKeyDownListener;
import org.schabi.newpipe.player.helper.PlayerHolder;
import org.schabi.newpipe.player.playqueue.PlayQueue;
import org.schabi.newpipe.settings.UpdateSettingsFragment;
import org.schabi.newpipe.util.Constants;
import org.schabi.newpipe.util.DeviceUtils;
import org.schabi.newpipe.util.KioskTranslator;
@@ -82,6 +87,7 @@ import org.schabi.newpipe.util.Localization;
import org.schabi.newpipe.util.NavigationHelper;
import org.schabi.newpipe.util.PeertubeHelper;
import org.schabi.newpipe.util.PermissionHelper;
import org.schabi.newpipe.util.ReleaseVersionUtil;
import org.schabi.newpipe.util.SerializedCache;
import org.schabi.newpipe.util.ServiceHelper;
import org.schabi.newpipe.util.StateSaver;
@@ -163,6 +169,11 @@ public class MainActivity extends AppCompatActivity {
// if this is enabled by the user.
NotificationWorker.initialize(this);
}
if (!UpdateSettingsFragment.wasUserAskedForConsent(this)
&& !App.getApp().isFirstRun()
&& ReleaseVersionUtil.INSTANCE.isReleaseApk()) {
UpdateSettingsFragment.askForConsentToUpdateChecks(this);
}
}
@Override
@@ -172,7 +183,8 @@ public class MainActivity extends AppCompatActivity {
final App app = App.getApp();
final SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(app);
if (prefs.getBoolean(app.getString(R.string.update_app_key), true)) {
if (prefs.getBoolean(app.getString(R.string.update_app_key), false)
&& prefs.getBoolean(app.getString(R.string.update_check_consent_key), false)) {
// Start the worker which is checking all conditions
// and eventually searching for a new version.
NewVersionWorker.enqueueNewVersionCheckingWork(app, false);
@@ -546,14 +558,21 @@ public class MainActivity extends AppCompatActivity {
// interacts with a fragment inside fragment_holder so all back presses should be
// handled by it
if (bottomSheetHiddenOrCollapsed()) {
final Fragment fragment = getSupportFragmentManager()
.findFragmentById(R.id.fragment_holder);
final FragmentManager fm = getSupportFragmentManager();
final Fragment fragment = fm.findFragmentById(R.id.fragment_holder);
// If current fragment implements BackPressable (i.e. can/wanna handle back press)
// delegate the back press to it
if (fragment instanceof BackPressable) {
if (((BackPressable) fragment).onBackPressed()) {
return;
}
} else if (fragment instanceof CommentRepliesFragment) {
// expand DetailsFragment if CommentRepliesFragment was opened
// to show the top level comments again
// Expand DetailsFragment if CommentRepliesFragment was opened
// and no other CommentRepliesFragments are on top of the back stack
// to show the top level comments again.
openDetailFragmentFromCommentReplies(fm, false);
}
} else {
@@ -629,10 +648,17 @@ public class MainActivity extends AppCompatActivity {
* </pre>
*/
private void onHomeButtonPressed() {
// If search fragment wasn't found in the backstack...
if (!NavigationHelper.tryGotoSearchFragment(getSupportFragmentManager())) {
// ...go to the main fragment
NavigationHelper.gotoMainFragment(getSupportFragmentManager());
final FragmentManager fm = getSupportFragmentManager();
final Fragment fragment = fm.findFragmentById(R.id.fragment_holder);
if (fragment instanceof CommentRepliesFragment) {
// Expand DetailsFragment if CommentRepliesFragment was opened
// and no other CommentRepliesFragments are on top of the back stack
// to show the top level comments again.
openDetailFragmentFromCommentReplies(fm, true);
} else if (!NavigationHelper.tryGotoSearchFragment(fm)) {
// If search fragment wasn't found in the backstack go to the main fragment
NavigationHelper.gotoMainFragment(fm);
}
}
@@ -828,6 +854,68 @@ public class MainActivity extends AppCompatActivity {
}
}
private void openDetailFragmentFromCommentReplies(
@NonNull final FragmentManager fm,
final boolean popBackStack
) {
// obtain the name of the fragment under the replies fragment that's going to be popped
@Nullable final String fragmentUnderEntryName;
if (fm.getBackStackEntryCount() < 2) {
fragmentUnderEntryName = null;
} else {
fragmentUnderEntryName = fm.getBackStackEntryAt(fm.getBackStackEntryCount() - 2)
.getName();
}
// the root comment is the comment for which the user opened the replies page
@Nullable final CommentRepliesFragment repliesFragment =
(CommentRepliesFragment) fm.findFragmentByTag(CommentRepliesFragment.TAG);
@Nullable final CommentsInfoItem rootComment =
repliesFragment == null ? null : repliesFragment.getCommentsInfoItem();
// sometimes this function pops the backstack, other times it's handled by the system
if (popBackStack) {
fm.popBackStackImmediate();
}
// only expand the bottom sheet back if there are no more nested comment replies fragments
// stacked under the one that is currently being popped
if (CommentRepliesFragment.TAG.equals(fragmentUnderEntryName)) {
return;
}
final BottomSheetBehavior<FragmentContainerView> behavior = BottomSheetBehavior
.from(mainBinding.fragmentPlayerHolder);
// do not return to the comment if the details fragment was closed
if (behavior.getState() == BottomSheetBehavior.STATE_HIDDEN) {
return;
}
// scroll to the root comment once the bottom sheet expansion animation is finished
behavior.addBottomSheetCallback(new BottomSheetBehavior.BottomSheetCallback() {
@Override
public void onStateChanged(@NonNull final View bottomSheet,
final int newState) {
if (newState == BottomSheetBehavior.STATE_EXPANDED) {
final Fragment detailFragment = fm.findFragmentById(
R.id.fragment_player_holder);
if (detailFragment instanceof VideoDetailFragment && rootComment != null) {
// should always be the case
((VideoDetailFragment) detailFragment).scrollToComment(rootComment);
}
behavior.removeBottomSheetCallback(this);
}
}
@Override
public void onSlide(@NonNull final View bottomSheet, final float slideOffset) {
// not needed, listener is removed once the sheet is expanded
}
});
behavior.setState(BottomSheetBehavior.STATE_EXPANDED);
}
private boolean bottomSheetHiddenOrCollapsed() {
final BottomSheetBehavior<FrameLayout> bottomSheetBehavior =
BottomSheetBehavior.from(mainBinding.fragmentPlayerHolder);

View File

@@ -7,6 +7,8 @@ import static org.schabi.newpipe.database.Migrations.MIGRATION_3_4;
import static org.schabi.newpipe.database.Migrations.MIGRATION_4_5;
import static org.schabi.newpipe.database.Migrations.MIGRATION_5_6;
import static org.schabi.newpipe.database.Migrations.MIGRATION_6_7;
import static org.schabi.newpipe.database.Migrations.MIGRATION_7_8;
import static org.schabi.newpipe.database.Migrations.MIGRATION_8_9;
import android.content.Context;
import android.database.Cursor;
@@ -27,7 +29,7 @@ public final class NewPipeDatabase {
return Room
.databaseBuilder(context.getApplicationContext(), AppDatabase.class, DATABASE_NAME)
.addMigrations(MIGRATION_1_2, MIGRATION_2_3, MIGRATION_3_4, MIGRATION_4_5,
MIGRATION_5_6, MIGRATION_6_7)
MIGRATION_5_6, MIGRATION_6_7, MIGRATION_7_8, MIGRATION_8_9)
.build();
}

View File

@@ -20,9 +20,7 @@ import com.grack.nanojson.JsonParser
import com.grack.nanojson.JsonParserException
import org.schabi.newpipe.extractor.downloader.Response
import org.schabi.newpipe.extractor.exceptions.ReCaptchaException
import org.schabi.newpipe.util.ReleaseVersionUtil.coerceUpdateCheckExpiry
import org.schabi.newpipe.util.ReleaseVersionUtil.isLastUpdateCheckExpired
import org.schabi.newpipe.util.ReleaseVersionUtil.isReleaseApk
import org.schabi.newpipe.util.ReleaseVersionUtil
import java.io.IOException
class NewVersionWorker(
@@ -84,7 +82,7 @@ class NewVersionWorker(
@Throws(IOException::class, ReCaptchaException::class)
private fun checkNewVersion() {
// Check if the current apk is a github one or not.
if (!isReleaseApk()) {
if (!ReleaseVersionUtil.isReleaseApk) {
return
}
@@ -93,7 +91,7 @@ class NewVersionWorker(
// Check if the last request has happened a certain time ago
// to reduce the number of API requests.
val expiry = prefs.getLong(applicationContext.getString(R.string.update_expiry_key), 0)
if (!isLastUpdateCheckExpired(expiry)) {
if (!ReleaseVersionUtil.isLastUpdateCheckExpired(expiry)) {
return
}
}
@@ -108,7 +106,7 @@ class NewVersionWorker(
try {
// Store a timestamp which needs to be exceeded,
// before a new request to the API is made.
val newExpiry = coerceUpdateCheckExpiry(response.getHeader("expires"))
val newExpiry = ReleaseVersionUtil.coerceUpdateCheckExpiry(response.getHeader("expires"))
prefs.edit {
putLong(applicationContext.getString(R.string.update_expiry_key), newExpiry)
}

View File

@@ -116,7 +116,7 @@ class AboutActivity : AppCompatActivity() {
/**
* List of all software components.
*/
private val SOFTWARE_COMPONENTS = arrayOf(
private val SOFTWARE_COMPONENTS = arrayListOf(
SoftwareComponent(
"ACRA", "2013", "Kevin Gaudin",
"https://github.com/ACRA/acra", StandardLicenses.APACHE2

View File

@@ -18,6 +18,7 @@ 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
@@ -25,16 +26,15 @@ import org.schabi.newpipe.util.external_communication.ShareUtils
* Fragment containing the software licenses.
*/
class LicenseFragment : Fragment() {
private lateinit var softwareComponents: Array<SoftwareComponent>
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?.getParcelableArray(ARG_COMPONENTS) as Array<SoftwareComponent>
softwareComponents = arguments?.parcelableArrayList<SoftwareComponent>(ARG_COMPONENTS)!!
.sortedBy { it.name } // Sort components by name
activeSoftwareComponent = savedInstanceState?.getSerializable(SOFTWARE_COMPONENT_KEY) as? SoftwareComponent
// Sort components by name
softwareComponents.sortBy { it.name }
}
override fun onDestroy() {
@@ -130,7 +130,8 @@ class LicenseFragment : Fragment() {
StandardLicenses.GPL3,
BuildConfig.VERSION_NAME
)
fun newInstance(softwareComponents: Array<SoftwareComponent>): LicenseFragment {
fun newInstance(softwareComponents: ArrayList<SoftwareComponent>): LicenseFragment {
val fragment = LicenseFragment()
fragment.arguments = bundleOf(ARG_COMPONENTS to softwareComponents)
return fragment

View File

@@ -1,6 +1,6 @@
package org.schabi.newpipe.database;
import static org.schabi.newpipe.database.Migrations.DB_VER_7;
import static org.schabi.newpipe.database.Migrations.DB_VER_9;
import androidx.room.Database;
import androidx.room.RoomDatabase;
@@ -38,7 +38,7 @@ import org.schabi.newpipe.database.subscription.SubscriptionEntity;
FeedEntity.class, FeedGroupEntity.class, FeedGroupSubscriptionEntity.class,
FeedLastUpdatedEntity.class
},
version = DB_VER_7
version = DB_VER_9
)
public abstract class AppDatabase extends RoomDatabase {
public static final String DATABASE_NAME = "newpipe.db";

View File

@@ -7,7 +7,7 @@ import java.time.Instant
import java.time.OffsetDateTime
import java.time.ZoneOffset
object Converters {
class Converters {
/**
* Convert a long value to a [OffsetDateTime].
*
@@ -47,6 +47,6 @@ object Converters {
@TypeConverter
fun feedGroupIconOf(id: Int): FeedGroupIcon {
return FeedGroupIcon.values().first { it.id == id }
return FeedGroupIcon.entries.first { it.id == id }
}
}

View File

@@ -25,6 +25,8 @@ public final class Migrations {
public static final int DB_VER_5 = 5;
public static final int DB_VER_6 = 6;
public static final int DB_VER_7 = 7;
public static final int DB_VER_8 = 8;
public static final int DB_VER_9 = 9;
private static final String TAG = Migrations.class.getName();
public static final boolean DEBUG = MainActivity.DEBUG;
@@ -186,7 +188,7 @@ public final class Migrations {
@Override
public void migrate(@NonNull final SupportSQLiteDatabase database) {
database.execSQL("ALTER TABLE `subscriptions` ADD COLUMN `notification_mode` "
+ "INTEGER NOT NULL DEFAULT 0");
+ "INTEGER NOT NULL DEFAULT 0");
}
};
@@ -235,6 +237,71 @@ public final class Migrations {
}
};
public static final Migration MIGRATION_7_8 = new Migration(DB_VER_7, DB_VER_8) {
@Override
public void migrate(@NonNull final SupportSQLiteDatabase database) {
database.execSQL("DELETE FROM search_history WHERE id NOT IN (SELECT id FROM (SELECT "
+ "MIN(id) as id FROM search_history GROUP BY trim(search), service_id ) tmp)");
database.execSQL("UPDATE search_history SET search = trim(search)");
}
};
public static final Migration MIGRATION_8_9 = new Migration(DB_VER_8, DB_VER_9) {
@Override
public void migrate(@NonNull final SupportSQLiteDatabase database) {
try {
database.beginTransaction();
// Update playlists.
// Create a temp table to initialize display_index.
database.execSQL("CREATE TABLE `playlists_tmp` "
+ "(`uid` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, "
+ "`name` TEXT, `is_thumbnail_permanent` INTEGER NOT NULL, "
+ "`thumbnail_stream_id` INTEGER NOT NULL, "
+ "`display_index` INTEGER NOT NULL)");
database.execSQL("INSERT INTO `playlists_tmp` "
+ "(`uid`, `name`, `is_thumbnail_permanent`, `thumbnail_stream_id`, "
+ "`display_index`) "
+ "SELECT `uid`, `name`, `is_thumbnail_permanent`, `thumbnail_stream_id`, "
+ "-1 "
+ "FROM `playlists`");
// Replace the old table, note that this also removes the index on the name which
// we don't need anymore.
database.execSQL("DROP TABLE `playlists`");
database.execSQL("ALTER TABLE `playlists_tmp` RENAME TO `playlists`");
// Update remote_playlists.
// Create a temp table to initialize display_index.
database.execSQL("CREATE TABLE `remote_playlists_tmp` "
+ "(`uid` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, "
+ "`service_id` INTEGER NOT NULL, `name` TEXT, `url` TEXT, "
+ "`thumbnail_url` TEXT, `uploader` TEXT, "
+ "`display_index` INTEGER NOT NULL,"
+ "`stream_count` INTEGER)");
database.execSQL("INSERT INTO `remote_playlists_tmp` (`uid`, `service_id`, "
+ "`name`, `url`, `thumbnail_url`, `uploader`, `display_index`, "
+ "`stream_count`)"
+ "SELECT `uid`, `service_id`, `name`, `url`, `thumbnail_url`, `uploader`, "
+ "-1, `stream_count` FROM `remote_playlists`");
// Replace the old table, note that this also removes the index on the name which
// we don't need anymore.
database.execSQL("DROP TABLE `remote_playlists`");
database.execSQL("ALTER TABLE `remote_playlists_tmp` RENAME TO `remote_playlists`");
// Create index on the new table.
database.execSQL("CREATE UNIQUE INDEX `index_remote_playlists_service_id_url` "
+ "ON `remote_playlists` (`service_id`, `url`)");
database.setTransactionSuccessful();
} finally {
database.endTransaction();
}
}
};
private Migrations() {
}
}

View File

@@ -13,12 +13,17 @@ public class PlaylistDuplicatesEntry extends PlaylistMetadataEntry {
@ColumnInfo(name = PLAYLIST_TIMES_STREAM_IS_CONTAINED)
public final long timesStreamIsContained;
@SuppressWarnings("checkstyle:ParameterNumber")
public PlaylistDuplicatesEntry(final long uid,
final String name,
final String thumbnailUrl,
final boolean isThumbnailPermanent,
final long thumbnailStreamId,
final long displayIndex,
final long streamCount,
final long timesStreamIsContained) {
super(uid, name, thumbnailUrl, streamCount);
super(uid, name, thumbnailUrl, isThumbnailPermanent, thumbnailStreamId, displayIndex,
streamCount);
this.timesStreamIsContained = timesStreamIsContained;
}
}

View File

@@ -1,22 +1,13 @@
package org.schabi.newpipe.database.playlist;
import org.schabi.newpipe.database.LocalItem;
import org.schabi.newpipe.database.playlist.model.PlaylistRemoteEntity;
import java.util.Comparator;
import java.util.List;
import java.util.stream.Collectors;
import java.util.stream.Stream;
public interface PlaylistLocalItem extends LocalItem {
String getOrderingName();
static List<PlaylistLocalItem> merge(
final List<PlaylistMetadataEntry> localPlaylists,
final List<PlaylistRemoteEntity> remotePlaylists) {
return Stream.concat(localPlaylists.stream(), remotePlaylists.stream())
.sorted(Comparator.comparing(PlaylistLocalItem::getOrderingName,
Comparator.nullsLast(String.CASE_INSENSITIVE_ORDER)))
.collect(Collectors.toList());
}
long getDisplayIndex();
long getUid();
void setDisplayIndex(long displayIndex);
}

View File

@@ -2,27 +2,40 @@ package org.schabi.newpipe.database.playlist;
import androidx.room.ColumnInfo;
import static org.schabi.newpipe.database.playlist.model.PlaylistEntity.PLAYLIST_DISPLAY_INDEX;
import static org.schabi.newpipe.database.playlist.model.PlaylistEntity.PLAYLIST_ID;
import static org.schabi.newpipe.database.playlist.model.PlaylistEntity.PLAYLIST_NAME;
import static org.schabi.newpipe.database.playlist.model.PlaylistEntity.PLAYLIST_THUMBNAIL_PERMANENT;
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;
public class PlaylistMetadataEntry implements PlaylistLocalItem {
public static final String PLAYLIST_STREAM_COUNT = "streamCount";
@ColumnInfo(name = PLAYLIST_ID)
public final long uid;
private final long uid;
@ColumnInfo(name = PLAYLIST_NAME)
public final String name;
@ColumnInfo(name = PLAYLIST_THUMBNAIL_PERMANENT)
private final boolean isThumbnailPermanent;
@ColumnInfo(name = PLAYLIST_THUMBNAIL_STREAM_ID)
private final long thumbnailStreamId;
@ColumnInfo(name = PLAYLIST_THUMBNAIL_URL)
public final String thumbnailUrl;
@ColumnInfo(name = PLAYLIST_DISPLAY_INDEX)
private long displayIndex;
@ColumnInfo(name = PLAYLIST_STREAM_COUNT)
public final long streamCount;
public PlaylistMetadataEntry(final long uid, final String name, final String thumbnailUrl,
final long streamCount) {
final boolean isThumbnailPermanent, final long thumbnailStreamId,
final long displayIndex, final long streamCount) {
this.uid = uid;
this.name = name;
this.thumbnailUrl = thumbnailUrl;
this.isThumbnailPermanent = isThumbnailPermanent;
this.thumbnailStreamId = thumbnailStreamId;
this.displayIndex = displayIndex;
this.streamCount = streamCount;
}
@@ -35,4 +48,27 @@ public class PlaylistMetadataEntry implements PlaylistLocalItem {
public String getOrderingName() {
return name;
}
public boolean isThumbnailPermanent() {
return isThumbnailPermanent;
}
public long getThumbnailStreamId() {
return thumbnailStreamId;
}
@Override
public long getDisplayIndex() {
return displayIndex;
}
@Override
public long getUid() {
return uid;
}
@Override
public void setDisplayIndex(final long displayIndex) {
this.displayIndex = displayIndex;
}
}

View File

@@ -2,6 +2,7 @@ package org.schabi.newpipe.database.playlist.dao;
import androidx.room.Dao;
import androidx.room.Query;
import androidx.room.Transaction;
import org.schabi.newpipe.database.BasicDAO;
import org.schabi.newpipe.database.playlist.model.PlaylistEntity;
@@ -36,4 +37,17 @@ public interface PlaylistDAO extends BasicDAO<PlaylistEntity> {
@Query("SELECT COUNT(*) FROM " + PLAYLIST_TABLE)
Flowable<Long> getCount();
@Transaction
default long upsertPlaylist(final PlaylistEntity playlist) {
final long playlistId = playlist.getUid();
if (playlistId == -1) {
// This situation is probably impossible.
return insert(playlist);
} else {
update(playlist);
return playlistId;
}
}
}

View File

@@ -11,6 +11,7 @@ import java.util.List;
import io.reactivex.rxjava3.core.Flowable;
import static org.schabi.newpipe.database.playlist.model.PlaylistRemoteEntity.REMOTE_PLAYLIST_DISPLAY_INDEX;
import static org.schabi.newpipe.database.playlist.model.PlaylistRemoteEntity.REMOTE_PLAYLIST_ID;
import static org.schabi.newpipe.database.playlist.model.PlaylistRemoteEntity.REMOTE_PLAYLIST_SERVICE_ID;
import static org.schabi.newpipe.database.playlist.model.PlaylistRemoteEntity.REMOTE_PLAYLIST_TABLE;
@@ -31,10 +32,18 @@ public interface PlaylistRemoteDAO extends BasicDAO<PlaylistRemoteEntity> {
+ " WHERE " + REMOTE_PLAYLIST_SERVICE_ID + " = :serviceId")
Flowable<List<PlaylistRemoteEntity>> listByService(int serviceId);
@Query("SELECT * FROM " + REMOTE_PLAYLIST_TABLE + " WHERE "
+ REMOTE_PLAYLIST_ID + " = :playlistId")
Flowable<List<PlaylistRemoteEntity>> getPlaylist(long playlistId);
@Query("SELECT * FROM " + REMOTE_PLAYLIST_TABLE + " WHERE "
+ REMOTE_PLAYLIST_URL + " = :url AND " + REMOTE_PLAYLIST_SERVICE_ID + " = :serviceId")
Flowable<List<PlaylistRemoteEntity>> getPlaylist(long serviceId, String url);
@Query("SELECT * FROM " + REMOTE_PLAYLIST_TABLE
+ " ORDER BY " + REMOTE_PLAYLIST_DISPLAY_INDEX)
Flowable<List<PlaylistRemoteEntity>> getPlaylists();
@Query("SELECT " + REMOTE_PLAYLIST_ID + " FROM " + REMOTE_PLAYLIST_TABLE
+ " WHERE " + REMOTE_PLAYLIST_URL + " = :url "
+ "AND " + REMOTE_PLAYLIST_SERVICE_ID + " = :serviceId")

View File

@@ -18,10 +18,12 @@ import io.reactivex.rxjava3.core.Flowable;
import static org.schabi.newpipe.database.playlist.PlaylistDuplicatesEntry.PLAYLIST_TIMES_STREAM_IS_CONTAINED;
import static org.schabi.newpipe.database.playlist.PlaylistMetadataEntry.PLAYLIST_STREAM_COUNT;
import static org.schabi.newpipe.database.playlist.model.PlaylistEntity.PLAYLIST_DISPLAY_INDEX;
import static org.schabi.newpipe.database.playlist.model.PlaylistEntity.DEFAULT_THUMBNAIL;
import static org.schabi.newpipe.database.playlist.model.PlaylistEntity.PLAYLIST_ID;
import static org.schabi.newpipe.database.playlist.model.PlaylistEntity.PLAYLIST_NAME;
import static org.schabi.newpipe.database.playlist.model.PlaylistEntity.PLAYLIST_TABLE;
import static org.schabi.newpipe.database.playlist.model.PlaylistEntity.PLAYLIST_THUMBNAIL_PERMANENT;
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 static org.schabi.newpipe.database.playlist.model.PlaylistStreamEntity.JOIN_INDEX;
@@ -91,7 +93,9 @@ public interface PlaylistStreamDAO extends BasicDAO<PlaylistStreamEntity> {
Flowable<List<PlaylistStreamEntry>> getOrderedStreamsOf(long playlistId);
@Transaction
@Query("SELECT " + PLAYLIST_ID + ", " + PLAYLIST_NAME + ","
@Query("SELECT " + PLAYLIST_ID + ", " + PLAYLIST_NAME + ", "
+ PLAYLIST_THUMBNAIL_PERMANENT + ", " + PLAYLIST_THUMBNAIL_STREAM_ID + ", "
+ PLAYLIST_DISPLAY_INDEX + ", "
+ " CASE WHEN " + PLAYLIST_THUMBNAIL_STREAM_ID + " = "
+ PlaylistEntity.DEFAULT_THUMBNAIL_ID + " THEN " + "'" + DEFAULT_THUMBNAIL + "'"
@@ -105,7 +109,7 @@ public interface PlaylistStreamDAO extends BasicDAO<PlaylistStreamEntity> {
+ " LEFT JOIN " + PLAYLIST_STREAM_JOIN_TABLE
+ " ON " + PLAYLIST_TABLE + "." + PLAYLIST_ID + " = " + JOIN_PLAYLIST_ID
+ " GROUP BY " + PLAYLIST_ID
+ " ORDER BY " + PLAYLIST_NAME + " COLLATE NOCASE ASC")
+ " ORDER BY " + PLAYLIST_DISPLAY_INDEX)
Flowable<List<PlaylistMetadataEntry>> getPlaylistMetadata();
@RewriteQueriesToDropUnusedColumns
@@ -126,8 +130,9 @@ public interface PlaylistStreamDAO extends BasicDAO<PlaylistStreamEntity> {
Flowable<List<PlaylistStreamEntry>> getStreamsWithoutDuplicates(long playlistId);
@Transaction
@Query("SELECT " + PLAYLIST_TABLE + "." + PLAYLIST_ID + ", "
+ PLAYLIST_NAME + ", "
@Query("SELECT " + PLAYLIST_TABLE + "." + PLAYLIST_ID + ", " + PLAYLIST_NAME + ", "
+ PLAYLIST_THUMBNAIL_PERMANENT + ", " + PLAYLIST_THUMBNAIL_STREAM_ID + ", "
+ PLAYLIST_DISPLAY_INDEX + ", "
+ " CASE WHEN " + PLAYLIST_THUMBNAIL_STREAM_ID + " = "
+ PlaylistEntity.DEFAULT_THUMBNAIL_ID + " THEN " + "'" + DEFAULT_THUMBNAIL + "'"
@@ -149,6 +154,6 @@ public interface PlaylistStreamDAO extends BasicDAO<PlaylistStreamEntity> {
+ " AND :streamUrl = :streamUrl"
+ " GROUP BY " + JOIN_PLAYLIST_ID
+ " ORDER BY " + PLAYLIST_NAME + " COLLATE NOCASE ASC")
+ " ORDER BY " + PLAYLIST_DISPLAY_INDEX)
Flowable<List<PlaylistDuplicatesEntry>> getPlaylistDuplicatesMetadata(String streamUrl);
}

View File

@@ -2,16 +2,15 @@ package org.schabi.newpipe.database.playlist.model;
import androidx.room.ColumnInfo;
import androidx.room.Entity;
import androidx.room.Index;
import androidx.room.Ignore;
import androidx.room.PrimaryKey;
import static org.schabi.newpipe.database.playlist.model.PlaylistEntity.PLAYLIST_NAME;
import static org.schabi.newpipe.database.playlist.model.PlaylistEntity.PLAYLIST_TABLE;
import org.schabi.newpipe.R;
import org.schabi.newpipe.database.playlist.PlaylistMetadataEntry;
@Entity(tableName = PLAYLIST_TABLE,
indices = {@Index(value = {PLAYLIST_NAME})})
@Entity(tableName = PLAYLIST_TABLE)
public class PlaylistEntity {
public static final String DEFAULT_THUMBNAIL = "drawable://"
@@ -22,6 +21,7 @@ public class PlaylistEntity {
public static final String PLAYLIST_ID = "uid";
public static final String PLAYLIST_NAME = "name";
public static final String PLAYLIST_THUMBNAIL_URL = "thumbnail_url";
public static final String PLAYLIST_DISPLAY_INDEX = "display_index";
public static final String PLAYLIST_THUMBNAIL_PERMANENT = "is_thumbnail_permanent";
public static final String PLAYLIST_THUMBNAIL_STREAM_ID = "thumbnail_stream_id";
@@ -38,11 +38,24 @@ public class PlaylistEntity {
@ColumnInfo(name = PLAYLIST_THUMBNAIL_STREAM_ID)
private long thumbnailStreamId;
@ColumnInfo(name = PLAYLIST_DISPLAY_INDEX)
private long displayIndex;
public PlaylistEntity(final String name, final boolean isThumbnailPermanent,
final long thumbnailStreamId) {
final long thumbnailStreamId, final long displayIndex) {
this.name = name;
this.isThumbnailPermanent = isThumbnailPermanent;
this.thumbnailStreamId = thumbnailStreamId;
this.displayIndex = displayIndex;
}
@Ignore
public PlaylistEntity(final PlaylistMetadataEntry item) {
this.uid = item.getUid();
this.name = item.name;
this.isThumbnailPermanent = item.isThumbnailPermanent();
this.thumbnailStreamId = item.getThumbnailStreamId();
this.displayIndex = item.getDisplayIndex();
}
public long getUid() {
@@ -77,4 +90,11 @@ public class PlaylistEntity {
this.isThumbnailPermanent = isThumbnailSet;
}
public long getDisplayIndex() {
return displayIndex;
}
public void setDisplayIndex(final long displayIndex) {
this.displayIndex = displayIndex;
}
}

View File

@@ -21,7 +21,6 @@ import static org.schabi.newpipe.database.playlist.model.PlaylistRemoteEntity.RE
@Entity(tableName = REMOTE_PLAYLIST_TABLE,
indices = {
@Index(value = {REMOTE_PLAYLIST_NAME}),
@Index(value = {REMOTE_PLAYLIST_SERVICE_ID, REMOTE_PLAYLIST_URL}, unique = true)
})
public class PlaylistRemoteEntity implements PlaylistLocalItem {
@@ -32,6 +31,7 @@ public class PlaylistRemoteEntity implements PlaylistLocalItem {
public static final String REMOTE_PLAYLIST_URL = "url";
public static final String REMOTE_PLAYLIST_THUMBNAIL_URL = "thumbnail_url";
public static final String REMOTE_PLAYLIST_UPLOADER_NAME = "uploader";
public static final String REMOTE_PLAYLIST_DISPLAY_INDEX = "display_index";
public static final String REMOTE_PLAYLIST_STREAM_COUNT = "stream_count";
@PrimaryKey(autoGenerate = true)
@@ -53,6 +53,9 @@ public class PlaylistRemoteEntity implements PlaylistLocalItem {
@ColumnInfo(name = REMOTE_PLAYLIST_UPLOADER_NAME)
private String uploader;
@ColumnInfo(name = REMOTE_PLAYLIST_DISPLAY_INDEX)
private long displayIndex = -1; // Make sure the new item is on the top
@ColumnInfo(name = REMOTE_PLAYLIST_STREAM_COUNT)
private Long streamCount;
@@ -67,6 +70,19 @@ public class PlaylistRemoteEntity implements PlaylistLocalItem {
this.streamCount = streamCount;
}
@Ignore
public PlaylistRemoteEntity(final int serviceId, final String name, final String url,
final String thumbnailUrl, final String uploader,
final long displayIndex, final Long streamCount) {
this.serviceId = serviceId;
this.name = name;
this.url = url;
this.thumbnailUrl = thumbnailUrl;
this.uploader = uploader;
this.displayIndex = displayIndex;
this.streamCount = streamCount;
}
@Ignore
public PlaylistRemoteEntity(final PlaylistInfo info) {
this(info.getServiceId(), info.getName(), info.getUrl(),
@@ -93,6 +109,7 @@ public class PlaylistRemoteEntity implements PlaylistLocalItem {
&& TextUtils.equals(getUploader(), info.getUploaderName());
}
@Override
public long getUid() {
return uid;
}
@@ -141,6 +158,16 @@ public class PlaylistRemoteEntity implements PlaylistLocalItem {
this.uploader = uploader;
}
@Override
public long getDisplayIndex() {
return displayIndex;
}
@Override
public void setDisplayIndex(final long displayIndex) {
this.displayIndex = displayIndex;
}
public Long getStreamCount() {
return streamCount;
}

View File

@@ -1,6 +1,7 @@
package org.schabi.newpipe.database.subscription;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.room.ColumnInfo;
import androidx.room.Entity;
import androidx.room.Ignore;
@@ -95,11 +96,12 @@ public class SubscriptionEntity {
this.name = name;
}
@Nullable
public String getAvatarUrl() {
return avatarUrl;
}
public void setAvatarUrl(final String avatarUrl) {
public void setAvatarUrl(@Nullable final String avatarUrl) {
this.avatarUrl = avatarUrl;
}

View File

@@ -7,8 +7,6 @@ import static org.schabi.newpipe.util.Localization.assureCorrectAppLanguage;
import android.app.Activity;
import android.content.ComponentName;
import android.content.Context;
import android.content.DialogInterface;
import android.content.DialogInterface.OnDismissListener;
import android.content.Intent;
import android.content.ServiceConnection;
import android.content.SharedPreferences;
@@ -16,6 +14,7 @@ import android.net.Uri;
import android.os.Bundle;
import android.os.Environment;
import android.os.IBinder;
import android.provider.Settings;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
@@ -74,6 +73,7 @@ import org.schabi.newpipe.util.ThemeHelper;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.Locale;
import java.util.Objects;
@@ -111,14 +111,11 @@ public class DownloadDialog extends DialogFragment
@State
int selectedSubtitleIndex = 0; // default to the first item
@Nullable
private OnDismissListener onDismissListener = null;
private StoredDirectoryHelper mainStorageAudio = null;
private StoredDirectoryHelper mainStorageVideo = null;
private DownloadManager downloadManager = null;
private ActionMenuItemView okButton = null;
private Context context;
private Context context = null;
private boolean askForSavePath;
private AudioTrackAdapter audioTrackAdapter;
@@ -146,7 +143,6 @@ public class DownloadDialog extends DialogFragment
registerForActivityResult(
new StartActivityForResult(), this::requestDownloadPickVideoFolderResult);
/*//////////////////////////////////////////////////////////////////////////
// Instance creation
//////////////////////////////////////////////////////////////////////////*/
@@ -194,13 +190,6 @@ public class DownloadDialog extends DialogFragment
this.selectedVideoIndex = ListHelper.getDefaultResolutionIndex(context, videoStreams);
}
/**
* @param onDismissListener the listener to call in {@link #onDismiss(DialogInterface)}
*/
public void setOnDismissListener(@Nullable final OnDismissListener onDismissListener) {
this.onDismissListener = onDismissListener;
}
/*//////////////////////////////////////////////////////////////////////////
// Android lifecycle
@@ -220,6 +209,8 @@ public class DownloadDialog extends DialogFragment
return;
}
// context will remain null if dismiss() was called above, allowing to check whether the
// dialog is being dismissed in onViewCreated()
context = getContext();
setStyle(STYLE_NO_TITLE, ThemeHelper.getDialogTheme(context));
@@ -304,6 +295,9 @@ public class DownloadDialog extends DialogFragment
@Nullable final Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
dialogBinding = DownloadDialogBinding.bind(view);
if (context == null) {
return; // the dialog is being dismissed, see the call to dismiss() in onCreate()
}
dialogBinding.fileName.setText(FilenameUtils.createFilename(getContext(),
currentInfo.getName()));
@@ -363,14 +357,6 @@ public class DownloadDialog extends DialogFragment
});
}
@Override
public void onDismiss(@NonNull final DialogInterface dialog) {
super.onDismiss(dialog);
if (onDismissListener != null) {
onDismissListener.onDismiss(dialog);
}
}
@Override
public void onDestroy() {
super.onDestroy();
@@ -564,7 +550,6 @@ public class DownloadDialog extends DialogFragment
}
}
/*//////////////////////////////////////////////////////////////////////////
// Listeners
//////////////////////////////////////////////////////////////////////////*/
@@ -783,6 +768,7 @@ public class DownloadDialog extends DialogFragment
final StoredDirectoryHelper mainStorage;
final MediaFormat format;
final String selectedMediaType;
final long size;
// first, build the filename and get the output folder (if possible)
// later, run a very very very large file checking logic
@@ -794,6 +780,7 @@ public class DownloadDialog extends DialogFragment
selectedMediaType = getString(R.string.last_download_type_audio_key);
mainStorage = mainStorageAudio;
format = audioStreamsAdapter.getItem(selectedAudioIndex).getFormat();
size = getWrappedAudioStreams().getSizeInBytes(selectedAudioIndex);
if (format == MediaFormat.WEBMA_OPUS) {
mimeTmp = "audio/ogg";
filenameTmp += "opus";
@@ -806,6 +793,7 @@ public class DownloadDialog extends DialogFragment
selectedMediaType = getString(R.string.last_download_type_video_key);
mainStorage = mainStorageVideo;
format = videoStreamsAdapter.getItem(selectedVideoIndex).getFormat();
size = wrappedVideoStreams.getSizeInBytes(selectedVideoIndex);
if (format != null) {
mimeTmp = format.mimeType;
filenameTmp += format.getSuffix();
@@ -815,6 +803,7 @@ public class DownloadDialog extends DialogFragment
selectedMediaType = getString(R.string.last_download_type_subtitle_key);
mainStorage = mainStorageVideo; // subtitle & video files go together
format = subtitleStreamsAdapter.getItem(selectedSubtitleIndex).getFormat();
size = wrappedSubtitleStreams.getSizeInBytes(selectedSubtitleIndex);
if (format != null) {
mimeTmp = format.mimeType;
}
@@ -870,6 +859,21 @@ public class DownloadDialog extends DialogFragment
return;
}
// Check for free storage space
final long freeSpace = mainStorage.getFreeStorageSpace();
if (freeSpace <= size) {
Toast.makeText(context, getString(R.
string.error_insufficient_storage), Toast.LENGTH_LONG).show();
// move the user to storage setting tab
final Intent storageSettingsIntent = new Intent(Settings.
ACTION_INTERNAL_STORAGE_SETTINGS);
if (storageSettingsIntent.resolveActivity(context.getPackageManager())
!= null) {
startActivity(storageSettingsIntent);
}
return;
}
// check for existing file with the same name
checkSelectedDownload(mainStorage, mainStorage.findFile(filenameTmp), filenameTmp,
mimeTmp);
@@ -1052,7 +1056,7 @@ public class DownloadDialog extends DialogFragment
final char kind;
int threads = dialogBinding.threads.getProgress() + 1;
final String[] urls;
final MissionRecoveryInfo[] recoveryInfo;
final List<MissionRecoveryInfo> recoveryInfo;
String psName = null;
String[] psArgs = null;
long nearLength = 0;
@@ -1117,9 +1121,7 @@ public class DownloadDialog extends DialogFragment
urls = new String[] {
selectedStream.getContent()
};
recoveryInfo = new MissionRecoveryInfo[] {
new MissionRecoveryInfo(selectedStream)
};
recoveryInfo = List.of(new MissionRecoveryInfo(selectedStream));
} else {
if (secondaryStream.getDeliveryMethod() != PROGRESSIVE_HTTP) {
throw new IllegalArgumentException("Unsupported stream delivery format"
@@ -1129,12 +1131,14 @@ public class DownloadDialog extends DialogFragment
urls = new String[] {
selectedStream.getContent(), secondaryStream.getContent()
};
recoveryInfo = new MissionRecoveryInfo[] {new MissionRecoveryInfo(selectedStream),
new MissionRecoveryInfo(secondaryStream)};
recoveryInfo = List.of(
new MissionRecoveryInfo(selectedStream),
new MissionRecoveryInfo(secondaryStream)
);
}
DownloadManagerService.startMission(context, urls, storage, kind, threads,
currentInfo.getUrl(), psName, psArgs, nearLength, recoveryInfo);
currentInfo.getUrl(), psName, psArgs, nearLength, new ArrayList<>(recoveryInfo));
Toast.makeText(context, getString(R.string.download_has_started),
Toast.LENGTH_SHORT).show();

View File

@@ -17,6 +17,7 @@ import androidx.annotation.Nullable;
import androidx.appcompat.app.ActionBar;
import androidx.appcompat.app.AlertDialog;
import androidx.appcompat.app.AppCompatActivity;
import androidx.core.content.IntentCompat;
import com.grack.nanojson.JsonWriter;
@@ -105,7 +106,7 @@ public class ErrorActivity extends AppCompatActivity {
actionBar.setDisplayShowTitleEnabled(true);
}
errorInfo = intent.getParcelableExtra(ERROR_INFO);
errorInfo = IntentCompat.getParcelableExtra(intent, ERROR_INFO, ErrorInfo.class);
// important add guru meditation
addGuruMeditation();

View File

@@ -6,6 +6,7 @@ package org.schabi.newpipe.error;
public enum UserAction {
USER_REPORT("user report"),
UI_ERROR("ui error"),
DATABASE_IMPORT_EXPORT("database import or export"),
SUBSCRIPTION_CHANGE("subscription change"),
SUBSCRIPTION_UPDATE("subscription update"),
SUBSCRIPTION_GET("get subscription"),
@@ -19,6 +20,7 @@ public enum UserAction {
REQUESTED_PLAYLIST("requested playlist"),
REQUESTED_KIOSK("requested kiosk"),
REQUESTED_COMMENTS("requested comments"),
REQUESTED_COMMENT_REPLIES("requested comment replies"),
REQUESTED_FEED("requested feed"),
REQUESTED_BOOKMARK("bookmark"),
DELETE_FROM_HISTORY("delete from history"),

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