1
mirror of https://github.com/TeamNewPipe/NewPipe synced 2025-10-04 02:00:51 +02:00

Compare commits

..

90 Commits

Author SHA1 Message Date
Tobi
a95a5ed13e Merge pull request #9290 from TeamNewPipe/release/0.24.1
Release v0.24.1
2022-11-05 21:25:52 +01:00
Tobi
da61c9f915 Merge pull request #9298 from Stypox/fix-inconsistent-channel-groups
Fix inconsistent channel group list and items view mode
2022-11-05 21:11:51 +01:00
Stypox
9472c36cbd Merge pull request #9109 from TeamNewPipe/fix/overlayPlayQueueButton
Hide play queue button in VideoDetailsFragment when queue is empty
2022-11-05 20:28:14 +01:00
Stypox
49c12a31e9 Fix wrongly calculated channel groups span count 2022-11-05 20:05:59 +01:00
Stypox
fc061599f8 Fix inconsistent channel group list and item view mode 2022-11-04 18:21:35 +01:00
TobiGr
b066457ccf Update NewPipe to 0.24.1 (991) 2022-11-04 17:07:13 +01:00
Hosted Weblate
2c5c7dfe3a Translated using Weblate (Punjabi)
Currently translated at 100.0% (646 of 646 strings)

Translated using Weblate (Turkish)

Currently translated at 100.0% (646 of 646 strings)

Translated using Weblate (Punjabi (Pakistan))

Currently translated at 18.4% (119 of 646 strings)

Translated using Weblate (Slovak)

Currently translated at 9.7% (7 of 72 strings)

Translated using Weblate (Azerbaijani)

Currently translated at 97.2% (70 of 72 strings)

Translated using Weblate (Polish)

Currently translated at 59.7% (43 of 72 strings)

Translated using Weblate (Ukrainian)

Currently translated at 100.0% (72 of 72 strings)

Translated using Weblate (Turkish)

Currently translated at 99.8% (645 of 646 strings)

Translated using Weblate (German)

Currently translated at 100.0% (646 of 646 strings)

Translated using Weblate (Hungarian)

Currently translated at 9.8% (7 of 71 strings)

Translated using Weblate (Punjabi)

Currently translated at 5.6% (4 of 71 strings)

Translated using Weblate (Galician)

Currently translated at 100.0% (646 of 646 strings)

Translated using Weblate (Punjabi)

Currently translated at 100.0% (646 of 646 strings)

Translated using Weblate (Azerbaijani)

Currently translated at 100.0% (646 of 646 strings)

Translated using Weblate (Vietnamese)

Currently translated at 99.6% (644 of 646 strings)

Translated using Weblate (Portuguese)

Currently translated at 100.0% (646 of 646 strings)

Translated using Weblate (Italian)

Currently translated at 100.0% (646 of 646 strings)

Translated using Weblate (Hungarian)

Currently translated at 100.0% (646 of 646 strings)

Translated using Weblate (Asturian)

Currently translated at 2.8% (2 of 71 strings)

Translated using Weblate (Punjabi)

Currently translated at 99.6% (644 of 646 strings)

Translated using Weblate (Vietnamese)

Currently translated at 98.9% (639 of 646 strings)

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

Currently translated at 99.5% (643 of 646 strings)

Translated using Weblate (Italian)

Currently translated at 100.0% (646 of 646 strings)

Added translation using Weblate (English (Middle))

Added translation using Weblate (English (Old))

Added translation using Weblate (Sicilian)

Added translation using Weblate (Arabic (Najdi))

Added translation using Weblate (Kashmiri)

Added translation using Weblate (German (Low))

Added translation using Weblate (Aymará)

Added translation using Weblate (Kazakh)

Translated using Weblate (Bulgarian)

Currently translated at 2.8% (2 of 71 strings)

Translated using Weblate (Bengali)

Currently translated at 90.5% (585 of 646 strings)

Translated using Weblate (Punjabi)

Currently translated at 99.6% (644 of 646 strings)

Translated using Weblate (Azerbaijani)

Currently translated at 100.0% (646 of 646 strings)

Translated using Weblate (Lithuanian)

Currently translated at 100.0% (646 of 646 strings)

Translated using Weblate (Portuguese (Brazil))

Currently translated at 100.0% (646 of 646 strings)

Co-authored-by: Agnieszka C <aga_04@o2.pl>
Co-authored-by: Balázs Meskó <meskobalazs@mailbox.org>
Co-authored-by: Enol P <enolp@softastur.org>
Co-authored-by: Ergün Can Taş <erguntas1968@gmail.com>
Co-authored-by: Gediminas Murauskas <muziejusinfo@gmail.com>
Co-authored-by: Giovanni Donisi <giovannidonisi0701@gmail.com>
Co-authored-by: Hosted Weblate <hosted@weblate.org>
Co-authored-by: Ihor Hordiichuk <igor_ck@outlook.com>
Co-authored-by: Lyudmil Borisov <lyuskoborisov@abv.bg>
Co-authored-by: Marian Hanzel <marulinko@gmail.com>
Co-authored-by: Nizami <nizamismidov4@gmail.com>
Co-authored-by: Oğuz Ersen <oguz@ersen.moe>
Co-authored-by: Ray <ray.cfu@protonmail.com>
Co-authored-by: Rohan Deb Sarkar <rohandebsarkar+git@gmail.com>
Co-authored-by: SC <lalocas@protonmail.com>
Co-authored-by: ShareASmile <aapshergill@gmail.com>
Co-authored-by: TXRdev Archive <lckphanaf9999@gmail.com>
Co-authored-by: Thọ Bùi Nguyễn Hoàng <buitho061997@gmail.com>
Co-authored-by: Vri 🌈 <weblate@vrifox.cc>
Co-authored-by: Weblate <noreply@weblate.org>
Co-authored-by: bgo-eiu <huyaqoob+toolforge@gmail.com>
Co-authored-by: gallegonovato <fran-carro@hotmail.es>
Co-authored-by: pjammo <adrianoghr@hotmail.it>
Co-authored-by: zaioti <zaioti@tuta.io>
Translate-URL: https://hosted.weblate.org/projects/newpipe/metadata/ast/
Translate-URL: https://hosted.weblate.org/projects/newpipe/metadata/az/
Translate-URL: https://hosted.weblate.org/projects/newpipe/metadata/bg/
Translate-URL: https://hosted.weblate.org/projects/newpipe/metadata/hu/
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/sk/
Translate-URL: https://hosted.weblate.org/projects/newpipe/metadata/uk/
Translation: NewPipe/Metadata
2022-11-04 17:06:26 +01:00
Tobi
4573407fc7 Merge pull request #9291 from AudricV/support-yt-handles-and-update-extractor
Support YouTube handles and update NewPipe Extractor
2022-11-04 12:48:54 +01:00
AudricV
9912c11043 Update NewPipe Extractor to support handles 2022-11-04 12:26:42 +01:00
AudricV
231c5e515f [YouTube] Support opening handles from external apps 2022-11-04 12:26:42 +01:00
Tobi
e9870d9e1d Merge pull request #9286 from TeamNewPipe/changelog/0.24.1
Add changelog for 0.24.1 (991)
2022-11-03 19:56:43 +01:00
TobiGr
c274ee9873 Add changelog for 0.24.1 (991) 2022-11-03 17:28:22 +01:00
Tobi
c8caf48cda Merge pull request #9230 from Stypox/duplicate-feed-videos
Fix duplicate videos in feed group "All"
2022-11-03 17:23:05 +01:00
Tobi
1de662f779 Merge pull request #9272 from TeamNewPipe/prettytime
Update PrettyTime from 5.0.3 to 5.0.6 to include new localizations
2022-11-03 16:17:02 +01:00
Isira Seneviratne
84887395f8 Merge pull request #8655 from Isira-Seneviratne/Use_TextViewCompat_setCompoundDrawableTIntList
Use TextViewCompat.setCompoundDrawableTintList().
2022-11-03 20:13:17 +05:30
TobiGr
bf766f1670 Update PrettyTime from 5.0.3 to 5.0.6 to include new localizations 2022-11-01 19:32:31 +01:00
Isira Seneviratne
51bdc30ed0 Use TextViewCompat.setCompoundDrawableTintList(). 2022-11-01 06:31:35 +05:30
Isira Seneviratne
4b892e2b30 Update AppCompat to 1.5.1. 2022-11-01 06:29:08 +05:30
Tobi
43b2176956 Merge pull request #9256 from TeamNewPipe/weblate
Update translations and remove empty localizations
2022-10-31 13:00:53 +01:00
TobiGr
00283fac30 Remove Kazakh from language picker 2022-10-31 12:20:40 +01:00
Hosted Weblate
78f6a86645 Translated using Weblate (Dutch (Middle))
Currently translated at 4.6% (30 of 646 strings)

Deleted translation using Weblate (Sicilian)

Deleted translation using Weblate (Kazakh)

Deleted translation using Weblate (Kashmiri)

Deleted translation using Weblate (German (Low))

Deleted translation using Weblate (English (Old))

Deleted translation using Weblate (English (Middle))

Deleted translation using Weblate (Aymará)

Deleted translation using Weblate (Arabic (Najdi))

Translated using Weblate (Chinese (Traditional))

Currently translated at 100.0% (646 of 646 strings)

Translated using Weblate (Arabic)

Currently translated at 100.0% (646 of 646 strings)

Translated using Weblate (Slovak)

Currently translated at 100.0% (646 of 646 strings)

Translated using Weblate (French)

Currently translated at 100.0% (646 of 646 strings)

Translated using Weblate (German)

Currently translated at 100.0% (646 of 646 strings)

Translated using Weblate (Hebrew)

Currently translated at 53.5% (38 of 71 strings)

Translated using Weblate (Portuguese (Portugal))

Currently translated at 99.5% (643 of 646 strings)

Translated using Weblate (Sardinian)

Currently translated at 100.0% (646 of 646 strings)

Translated using Weblate (Estonian)

Currently translated at 100.0% (646 of 646 strings)

Translated using Weblate (Azerbaijani)

Currently translated at 100.0% (646 of 646 strings)

Translated using Weblate (Hebrew)

Currently translated at 100.0% (646 of 646 strings)

Translated using Weblate (Chinese (Simplified))

Currently translated at 100.0% (646 of 646 strings)

Translated using Weblate (Portuguese (Brazil))

Currently translated at 100.0% (646 of 646 strings)

Translated using Weblate (Polish)

Currently translated at 100.0% (646 of 646 strings)

Translated using Weblate (Turkish)

Currently translated at 100.0% (646 of 646 strings)

Translated using Weblate (Ukrainian)

Currently translated at 100.0% (646 of 646 strings)

Translated using Weblate (Indonesian)

Currently translated at 100.0% (646 of 646 strings)

Translated using Weblate (Czech)

Currently translated at 100.0% (646 of 646 strings)

Translated using Weblate (Greek)

Currently translated at 100.0% (646 of 646 strings)

Translated using Weblate (Russian)

Currently translated at 100.0% (646 of 646 strings)

Translated using Weblate (Portuguese)

Currently translated at 69.0% (49 of 71 strings)

Translated using Weblate (Sardinian)

Currently translated at 100.0% (645 of 645 strings)

Translated using Weblate (Galician)

Currently translated at 100.0% (645 of 645 strings)

Translated using Weblate (Azerbaijani)

Currently translated at 100.0% (645 of 645 strings)

Translated using Weblate (Croatian)

Currently translated at 99.5% (642 of 645 strings)

Translated using Weblate (Lithuanian)

Currently translated at 100.0% (645 of 645 strings)

Translated using Weblate (Chinese (Simplified))

Currently translated at 100.0% (645 of 645 strings)

Translated using Weblate (Portuguese (Brazil))

Currently translated at 100.0% (645 of 645 strings)

Translated using Weblate (Portuguese (Brazil))

Currently translated at 100.0% (645 of 645 strings)

Translated using Weblate (Polish)

Currently translated at 100.0% (645 of 645 strings)

Translated using Weblate (Turkish)

Currently translated at 100.0% (645 of 645 strings)

Translated using Weblate (Ukrainian)

Currently translated at 100.0% (645 of 645 strings)

Translated using Weblate (Indonesian)

Currently translated at 100.0% (645 of 645 strings)

Translated using Weblate (Arabic)

Currently translated at 100.0% (645 of 645 strings)

Translated using Weblate (Czech)

Currently translated at 100.0% (645 of 645 strings)

Translated using Weblate (Portuguese)

Currently translated at 100.0% (645 of 645 strings)

Translated using Weblate (Dutch)

Currently translated at 100.0% (645 of 645 strings)

Translated using Weblate (French)

Currently translated at 100.0% (645 of 645 strings)

Translated using Weblate (Spanish)

Currently translated at 100.0% (645 of 645 strings)

Translated using Weblate (German)

Currently translated at 100.0% (645 of 645 strings)

Co-authored-by: Agnieszka C <aga_04@o2.pl>
Co-authored-by: Ajeje Brazorf <lmelonimamo@yahoo.it>
Co-authored-by: Eric <hamburger1024@mailbox.org>
Co-authored-by: Fjuro <ifjuro@proton.me>
Co-authored-by: Gediminas Murauskas <muziejusinfo@gmail.com>
Co-authored-by: Hosted Weblate <hosted@weblate.org>
Co-authored-by: Igor Rückert <igorruckert@yahoo.com.br>
Co-authored-by: Ihor Hordiichuk <igor_ck@outlook.com>
Co-authored-by: Jeff Huang <s8321414@gmail.com>
Co-authored-by: Linerly <linerly@protonmail.com>
Co-authored-by: Milo Ivir <mail@milotype.de>
Co-authored-by: Nizami <nizamismidov4@gmail.com>
Co-authored-by: Oğuz Ersen <oguz@ersen.moe>
Co-authored-by: Priit Jõerüüt <hwlate@joeruut.com>
Co-authored-by: Retrial <giwrgosmant@gmail.com>
Co-authored-by: Rex_sa <rex.sa@pm.me>
Co-authored-by: SC <lalocas@protonmail.com>
Co-authored-by: Samuel Carvalho de Araújo <samuelnegro12345@gmail.com>
Co-authored-by: Terry Louwers <t.louwers@gmail.com>
Co-authored-by: TobiGr <tobigr@mail.de>
Co-authored-by: Translator <kvb@tuta.io>
Co-authored-by: William <eduardo.957@hotmail.com>
Co-authored-by: Yaron Shahrabani <sh.yaron@gmail.com>
Co-authored-by: bomzhellino <adm.bomzh@gmail.com>
Co-authored-by: gallegonovato <fran-carro@hotmail.es>
Co-authored-by: nautilusx <translate@disroot.org>
Co-authored-by: sonix-github <sonix.internet@gmail.com>
Co-authored-by: ssantos <ssantos@web.de>
Translate-URL: https://hosted.weblate.org/projects/newpipe/metadata/he/
Translate-URL: https://hosted.weblate.org/projects/newpipe/metadata/pt/
Translation: NewPipe/Metadata
2022-10-31 12:10:21 +01:00
Stypox
9d2ab61993 Merge pull request #9203 from Callisto404/add-chapter-timestamp-share
Added timestamped link sharing from the start of a chapter with a long hold press
2022-10-30 22:31:09 +01:00
Stypox
8fdd828de4 Merge pull request #8739 from Isira-Seneviratne/Stream_average
Calculate search score using streams.
2022-10-30 22:09:55 +01:00
Stypox
25795c3a96 Merge pull request #8706 from Isira-Seneviratne/Improve_LocalPlaylistFragment
Refactor removeWatchedStreams() in LocalPlaylistFragment.
2022-10-30 22:03:39 +01:00
Daniel M
7f3da04fee Added an "isYouTube" check to start of long click handler 2022-10-30 13:48:03 +11:00
Stypox
7864521cb4 Merge pull request #8767 from Isira-Seneviratne/Use_ByteString
Use Okio's ByteString for download checksums.
2022-10-29 11:16:44 +02:00
Tobi
31b83ba47a Add info on date + time localization to contribution guidelines (#9229)
Dates and times are localized using PrettyTime. Added a note to guide translators to also localize that library to create a fully localized experience.

Co-authored-by: opusforlife2 <53176348+opusforlife2@users.noreply.github.com>
2022-10-28 17:35:56 +02:00
Stypox
9524c6245d Merge pull request #8747 from Isira-Seneviratne/Range_limit
Use range-limiting methods in more places.
2022-10-28 10:34:04 +02:00
Stypox
57d2fe113a Fix duplicate videos in feed "All" 2022-10-27 23:43:39 +02:00
Stypox
2f6cb87bba Use GROUP_ALL_ID instead of hardcoded -1 2022-10-27 23:32:19 +02:00
Stypox
3cef7f3201 Merge pull request #9207 from cern1710/list-view-alt-alt-implementation
undefined
2022-10-27 22:48:03 +02:00
Tobi
2225933946 Merge pull request #9179 from OneGuitars/9094-add-translations
Added Icelandic, Latvian, Malayalam to language selector
2022-10-27 20:57:28 +02:00
Zhuojun Xiao
47259ef152 Added Icelandic, Latvian, Malayalam to language selector in alphabetical order 2022-10-27 20:26:37 +02:00
Zhuojun Xiao
b2eb631a97 Added Icelandic,Latvian,Malayalam to language selector 2022-10-27 20:26:37 +02:00
Hosted Weblate
9e0f37a2de Translated using Weblate (Greek)
Currently translated at 100.0% (645 of 645 strings)

Translated using Weblate (French)

Currently translated at 100.0% (645 of 645 strings)

Translated using Weblate (Greek)

Currently translated at 100.0% (645 of 645 strings)

Translated using Weblate (Greek)

Currently translated at 100.0% (645 of 645 strings)

Translated using Weblate (French)

Currently translated at 99.5% (642 of 645 strings)

Translated using Weblate (Greek)

Currently translated at 99.6% (643 of 645 strings)

Translated using Weblate (Icelandic)

Currently translated at 99.0% (636 of 642 strings)

Translated using Weblate (Polish)

Currently translated at 59.1% (42 of 71 strings)

Translated using Weblate (Lithuanian)

Currently translated at 100.0% (642 of 642 strings)

Translated using Weblate (Japanese)

Currently translated at 100.0% (642 of 642 strings)

Translated using Weblate (Icelandic)

Currently translated at 83.1% (534 of 642 strings)

Translated using Weblate (Punjabi (Pakistan))

Currently translated at 18.3% (118 of 642 strings)

Translated using Weblate (Punjabi (Pakistan))

Currently translated at 1.4% (1 of 71 strings)

Translated using Weblate (Icelandic)

Currently translated at 83.0% (533 of 642 strings)

Translated using Weblate (Aymara (Southern))

Currently translated at 0.1% (1 of 642 strings)

Translated using Weblate (Swedish)

Currently translated at 60.5% (43 of 71 strings)

Translated using Weblate (Russian)

Currently translated at 30.9% (22 of 71 strings)

Translated using Weblate (Lithuanian)

Currently translated at 100.0% (642 of 642 strings)

Translated using Weblate (Swedish)

Currently translated at 100.0% (642 of 642 strings)

Translated using Weblate (Turkish)

Currently translated at 100.0% (642 of 642 strings)

Translated using Weblate (French)

Currently translated at 100.0% (642 of 642 strings)

Added translation using Weblate (Punjabi (Pakistan))

Translated using Weblate (Icelandic)

Currently translated at 70.0% (450 of 642 strings)

Translated using Weblate (Undetermined)

Currently translated at 21.4% (138 of 642 strings)

Translated using Weblate (Azerbaijani)

Currently translated at 100.0% (642 of 642 strings)

Translated using Weblate (Undetermined)

Currently translated at 18.3% (118 of 642 strings)

Translated using Weblate (Icelandic)

Currently translated at 2.8% (2 of 71 strings)

Translated using Weblate (Icelandic)

Currently translated at 51.5% (331 of 642 strings)

Translated using Weblate (French)

Currently translated at 91.5% (65 of 71 strings)

Translated using Weblate (Spanish)

Currently translated at 100.0% (71 of 71 strings)

Translated using Weblate (Italian)

Currently translated at 43.6% (31 of 71 strings)

Translated using Weblate (Basque)

Currently translated at 45.0% (32 of 71 strings)

Translated using Weblate (Punjabi)

Currently translated at 84.7% (544 of 642 strings)

Translated using Weblate (Azerbaijani)

Currently translated at 100.0% (642 of 642 strings)

Translated using Weblate (Tamil)

Currently translated at 54.8% (352 of 642 strings)

Translated using Weblate (Tamil)

Currently translated at 54.8% (352 of 642 strings)

Translated using Weblate (Turkish)

Currently translated at 100.0% (642 of 642 strings)

Translated using Weblate (Indonesian)

Currently translated at 100.0% (642 of 642 strings)

Translated using Weblate (Czech)

Currently translated at 100.0% (642 of 642 strings)

Translated using Weblate (Portuguese)

Currently translated at 100.0% (642 of 642 strings)

Translated using Weblate (Korean)

Currently translated at 100.0% (642 of 642 strings)

Translated using Weblate (Spanish)

Currently translated at 100.0% (642 of 642 strings)

Added translation using Weblate (Undetermined)

Translated using Weblate (Icelandic)

Currently translated at 7.3% (47 of 642 strings)

Translated using Weblate (Icelandic)

Currently translated at 4.6% (30 of 642 strings)

Added translation using Weblate (Icelandic)

Co-authored-by: Alex25820 <alexs25820@gmail.com>
Co-authored-by: Chitraarasu <chitraarasu@kirshi.co>
Co-authored-by: Chitraarasu.k <kchitraarasu@gmail.com>
Co-authored-by: Fjuro <ifjuro@proton.me>
Co-authored-by: Florian <flo.site@zaclys.net>
Co-authored-by: Gediminas Murauskas <muziejusinfo@gmail.com>
Co-authored-by: GnuPGを使うべきだ <dieeeazpnnqbpddh@cock.email>
Co-authored-by: Gontzal Manuel Pujana Onaindia <thadahdenyse@gmail.com>
Co-authored-by: Hoseok Seo <ddinghoya@gmail.com>
Co-authored-by: Hosted Weblate <hosted@weblate.org>
Co-authored-by: Linerly <linerly@protonmail.com>
Co-authored-by: Mehmet Ali <2045uuttb@relay.firefox.com>
Co-authored-by: Nizami <nizamismidov4@gmail.com>
Co-authored-by: OneGuitars <xiaozhuojun1125@gmail.com>
Co-authored-by: Retrial <giwrgosmant@gmail.com>
Co-authored-by: SC <lalocas@protonmail.com>
Co-authored-by: Translator <kvb@tuta.io>
Co-authored-by: Trendyne <eiko@chiru.no>
Co-authored-by: Vasilis K <skyhirules@gmail.com>
Co-authored-by: atilluF <atilluf@outlook.com>
Co-authored-by: bgo-eiu <huyaqoob+toolforge@gmail.com>
Co-authored-by: gallegonovato <fran-carro@hotmail.es>
Co-authored-by: julboudin <boudin.julie@orange.fr>
Co-authored-by: rehork <cooky@e.email>
Co-authored-by: Артём Нефедов <artem10397g@gmail.com>
Translate-URL: https://hosted.weblate.org/projects/newpipe/metadata/es/
Translate-URL: https://hosted.weblate.org/projects/newpipe/metadata/eu/
Translate-URL: https://hosted.weblate.org/projects/newpipe/metadata/fr/
Translate-URL: https://hosted.weblate.org/projects/newpipe/metadata/is/
Translate-URL: https://hosted.weblate.org/projects/newpipe/metadata/it/
Translate-URL: https://hosted.weblate.org/projects/newpipe/metadata/pa_PK/
Translate-URL: https://hosted.weblate.org/projects/newpipe/metadata/pl/
Translate-URL: https://hosted.weblate.org/projects/newpipe/metadata/ru/
Translate-URL: https://hosted.weblate.org/projects/newpipe/metadata/sv/
Translation: NewPipe/Metadata
2022-10-27 20:25:47 +02:00
Samuel Wu
f712ea34e0 Merge remote-tracking branch 'origin/list-view-alt-alt-implementation' into list-view-alt-alt-implementation 2022-10-28 04:54:42 +11:00
Samuel Wu
a44b7c9c9e Disabled animations for subscription fragment 2022-10-28 04:54:33 +11:00
Stypox
4b32890b5f Fix random crash in SubscriptionFragment 2022-10-27 18:45:06 +02:00
Stypox
a41aa01461 Solve two SonarCloud smells 2022-10-27 17:52:17 +02:00
Stypox
2ed6819e2c Make channel groups button sizes larger 2022-10-27 17:35:55 +02:00
Stypox
ea875c59af Deduplicate isGridLayout calls 2022-10-27 17:25:06 +02:00
YonghaoDeng
a22162ffac Add an Open in browser button on error panel (#9180)
* add a open in browser button

* Corrected a few things that needed to be changed

* Remove unneeded changes.

* Remove unneeded changes.

* Add showAndSetOpenInBrowserButtonAction function

* modify some codes
2022-10-27 14:38:08 +02:00
Stypox
83d16dc656 Fix flickering in channel groups list 2022-10-27 14:01:04 +02:00
Stypox
8ceefee1e3 Put "New feed group" item at the top 2022-10-27 13:51:56 +02:00
Samuel Wu
8f157be7e0 Revert changes 2022-10-27 12:15:36 +11:00
Stypox
38579e9a29 Merge pull request #9214 from Stypox/update-extractor
Update extractor to fix Jitpack failures in CI
2022-10-26 23:47:36 +02:00
Stypox
30a91f59ae Update extractor to fix Jitpack failures in CI
Jitpack seems to have deleted the previous commit form their servers (5c710da160f488bb40ab2cf4469bec9bd4cefd38)
2022-10-26 23:38:23 +02:00
Stypox
0e169951f7 Fix grid/list toggle implementation of feed 2022-10-26 23:20:32 +02:00
Samuel Wu
8b9db369f6 Resized add new item button 2022-10-26 21:23:50 +11:00
Samuel Wu
f7e10eb094 Fully working card and list view 2022-10-26 21:05:55 +11:00
Jfax510
0d73d193ad Added Toast Notification "Hold to enqueue" (#9196)
* Added Toast Notification "Hold to enqueue"

* Check if enqueue tips are enabled

* created function showHoldToAppendTipIfNeeded() for toast message
2022-10-26 11:35:03 +02:00
plasticanu
40815086ad Fix crash when the user clicks download then quits the history fragment (#9143)
* Fix crash when the user clicks download then quits the history fragment

* add a nonnull annotation to the context parameter in the DownloadDialog constructor.

* Revert "Merge branch 'TeamNewPipe:dev' into fix/HistoryFragmentDownloadDialogCrash"

This reverts commit 968d7a7603.

* Revert "Merge branch 'TeamNewPipe:dev' into fix/HistoryFragmentDownloadDialogCrash"

This reverts commit 968d7a7603, reversing
changes made to 52963ba37d.

Reverted merge

jlhzxc

* update project to the latest dev branch

* Revert "update project to the latest dev branch"

This reverts commit fb3ed83d51.

revert changes to build files

* Revert "Revert "Merge branch 'TeamNewPipe:dev' into fix/HistoryFragmentDownloadDialogCrash""

This reverts commit f9e1835e71.
2022-10-26 11:22:32 +02:00
Yuuu2990
16860603fd Add Link to FAQ in the app (#9164)
* Link to FAQ in the app #4447

* remove redundant comments produced by me.

* Update app/src/main/res/values/strings.xml

Update FAQ description

Co-authored-by: opusforlife2 <53176348+opusforlife2@users.noreply.github.com>

* Format the CodeStyle and readjust the layout.

* Update app/src/main/res/layout/fragment_about.xml

Remove redundant id.

Co-authored-by: Stypox <stypox@pm.me>

* Update app/src/main/res/layout/fragment_about.xml

Remove redundant id.

Co-authored-by: Stypox <stypox@pm.me>

* Update app/src/main/res/values/strings.xml

Keep the uppercase for consistency.

Co-authored-by: Stypox <stypox@pm.me>

* Update app/src/main/res/values/strings.xml

Modify the description of FAQ.

Co-authored-by: Stypox <stypox@pm.me>

Co-authored-by: opusforlife2 <53176348+opusforlife2@users.noreply.github.com>
Co-authored-by: Stypox <stypox@pm.me>
2022-10-26 09:59:51 +02:00
Samuel Wu
c607089cbb Altered grid view similar to Youtube app layout 2022-10-26 00:06:48 +11:00
Samuel Wu
28464344c1 Finalized design for vertical card view and removed unneeded variables in SubscriptionFragment.kt 2022-10-25 11:43:25 +11:00
Samuel Wu
ed68e3bd46 Fully working toggle button that change between vertical and horizontal view 2022-10-25 10:54:27 +11:00
Samuel Wu
082d7a3f18 Added working binding for a "new" button that works in the list layout. 2022-10-25 02:38:31 +11:00
Samuel Wu
6eddaa0d38 Added boolean to handle feed groups. May need a better solution for this 2022-10-25 02:20:14 +11:00
Samuel Wu
1aa1a0287e Could toggle between list view and grid view...once. Requires bug fixing on refreshing 2022-10-25 02:01:57 +11:00
Samuel Wu
3bfcb16f9a Bug: SubscriptionViewModel.kt did not map values for FeedGroupCardVerticalItem in line 26 2022-10-25 00:32:21 +11:00
Samuel Wu
f37d869ea2 Button can be toggled but not all strings have been fed 2022-10-24 23:01:02 +11:00
Samuel Wu
78547b4fa4 Created a list view for channel group. 2022-10-24 18:55:08 +11:00
Samuel Wu
29e56b9f2d Created a button in SubscriptionFragment.kt that reads whether button is clicked 2022-10-24 16:55:12 +11:00
Daniel M
83357ca67e Added sharing a link with timestamp from a chapter into the long click for each chapter 2022-10-24 14:14:41 +11:00
Samuel Wu
8482bf9fed Created a non-functional button in HeaderWithMenuItem.kt 2022-10-23 23:43:52 +11:00
Tobi
2a98cca801 Merge pull request #8986 from Isira-Seneviratne/AGP_7.3
Update Android Gradle Plugin to 7.3.0.
2022-10-18 23:03:01 +02:00
Isira Seneviratne
6277d4981c Update Android Gradle Plugin to 7.3.0. 2022-10-15 04:09:08 +05:30
opusforlife2
02deaa0f1a Update label to 'feature request' 2022-10-14 19:40:04 +02:00
TobiGr
4a278ef102 Hide play queue button in VideoDetailsFragment mini player when the play queue is empty
Related PR introducing the button: #8946
2022-10-11 21:27:04 +02:00
Tobi
7ab8f9f112 Merge pull request #9079 from devlearner/fix-screen-rotate
Fix `DownloadDialog` crash on screen rotation
2022-10-10 11:18:50 +02:00
Tobi
7fca0e0786 Merge pull request #9065 from devlearner/fix-spannable-cast
Fix potential cast exception in comments text
2022-10-10 10:51:32 +02:00
Tobi
0b0dfd0a37 Merge pull request #9092 from TeamNewPipe/weblate
Update translations
2022-10-09 20:09:14 +02:00
Hosted Weblate
dd07bd91a4 Translated using Weblate (Korean)
Currently translated at 100.0% (642 of 642 strings)

Translated using Weblate (Korean)

Currently translated at 100.0% (642 of 642 strings)

Translated using Weblate (Portuguese (Portugal))

Currently translated at 67.6% (48 of 71 strings)

Translated using Weblate (Portuguese)

Currently translated at 67.6% (48 of 71 strings)

Translated using Weblate (Bengali)

Currently translated at 90.9% (584 of 642 strings)

Translated using Weblate (Portuguese (Portugal))

Currently translated at 99.8% (641 of 642 strings)

Translated using Weblate (Danish)

Currently translated at 91.4% (587 of 642 strings)

Translated using Weblate (Galician)

Currently translated at 100.0% (642 of 642 strings)

Translated using Weblate (Estonian)

Currently translated at 100.0% (642 of 642 strings)

Translated using Weblate (Bengali (Bangladesh))

Currently translated at 64.4% (414 of 642 strings)

Translated using Weblate (Romanian)

Currently translated at 100.0% (642 of 642 strings)

Translated using Weblate (Portuguese)

Currently translated at 99.8% (641 of 642 strings)

Translated using Weblate (Korean)

Currently translated at 100.0% (642 of 642 strings)

Translated using Weblate (Korean)

Currently translated at 100.0% (642 of 642 strings)

Translated using Weblate (Korean)

Currently translated at 100.0% (642 of 642 strings)

Translated using Weblate (Spanish)

Currently translated at 100.0% (642 of 642 strings)

Added translation using Weblate (Aymara (Southern))

Added translation using Weblate (Aymará)

Translated using Weblate (Bengali)

Currently translated at 88.9% (571 of 642 strings)

Translated using Weblate (Portuguese)

Currently translated at 99.6% (640 of 642 strings)

Translated using Weblate (Spanish)

Currently translated at 100.0% (71 of 71 strings)

Translated using Weblate (Portuguese (Brazil))

Currently translated at 28.1% (20 of 71 strings)

Translated using Weblate (Turkish)

Currently translated at 32.3% (23 of 71 strings)

Translated using Weblate (Galician)

Currently translated at 100.0% (642 of 642 strings)

Translated using Weblate (Azerbaijani)

Currently translated at 100.0% (642 of 642 strings)

Translated using Weblate (Hindi)

Currently translated at 70.2% (451 of 642 strings)

Translated using Weblate (Chinese (Traditional))

Currently translated at 100.0% (642 of 642 strings)

Translated using Weblate (Portuguese (Brazil))

Currently translated at 100.0% (642 of 642 strings)

Translated using Weblate (Portuguese (Brazil))

Currently translated at 100.0% (642 of 642 strings)

Translated using Weblate (Persian)

Currently translated at 100.0% (642 of 642 strings)

Translated using Weblate (Turkish)

Currently translated at 100.0% (642 of 642 strings)

Translated using Weblate (Indonesian)

Currently translated at 100.0% (642 of 642 strings)

Translated using Weblate (Arabic)

Currently translated at 100.0% (642 of 642 strings)

Translated using Weblate (Czech)

Currently translated at 100.0% (642 of 642 strings)

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

Currently translated at 100.0% (642 of 642 strings)

Translated using Weblate (Basque)

Currently translated at 100.0% (642 of 642 strings)

Translated using Weblate (Italian)

Currently translated at 100.0% (642 of 642 strings)

Translated using Weblate (Japanese)

Currently translated at 99.6% (640 of 642 strings)

Translated using Weblate (Russian)

Currently translated at 100.0% (642 of 642 strings)

Translated using Weblate (Russian)

Currently translated at 100.0% (642 of 642 strings)

Translated using Weblate (Dutch)

Currently translated at 98.9% (635 of 642 strings)

Translated using Weblate (French)

Currently translated at 100.0% (642 of 642 strings)

Translated using Weblate (Spanish)

Currently translated at 100.0% (642 of 642 strings)

Translated using Weblate (Spanish)

Currently translated at 100.0% (642 of 642 strings)

Translated using Weblate (Japanese)

Currently translated at 99.6% (640 of 642 strings)

Translated using Weblate (Japanese)

Currently translated at 99.6% (640 of 642 strings)

Translated using Weblate (Sardinian)

Currently translated at 100.0% (642 of 642 strings)

Translated using Weblate (Hebrew)

Currently translated at 100.0% (642 of 642 strings)

Translated using Weblate (Chinese (Simplified))

Currently translated at 100.0% (642 of 642 strings)

Translated using Weblate (Chinese (Simplified))

Currently translated at 100.0% (642 of 642 strings)

Translated using Weblate (Polish)

Currently translated at 100.0% (642 of 642 strings)

Translated using Weblate (Ukrainian)

Currently translated at 100.0% (642 of 642 strings)

Translated using Weblate (Czech)

Currently translated at 100.0% (642 of 642 strings)

Translated using Weblate (Slovak)

Currently translated at 100.0% (642 of 642 strings)

Translated using Weblate (Greek)

Currently translated at 100.0% (642 of 642 strings)

Translated using Weblate (Italian)

Currently translated at 100.0% (642 of 642 strings)

Translated using Weblate (Japanese)

Currently translated at 99.6% (640 of 642 strings)

Translated using Weblate (Japanese)

Currently translated at 99.6% (640 of 642 strings)

Translated using Weblate (German)

Currently translated at 100.0% (642 of 642 strings)

Merge branch 'origin/dev' into Weblate.

Translated using Weblate (Tamil)

Currently translated at 52.6% (337 of 640 strings)

Translated using Weblate (Vietnamese)

Currently translated at 99.5% (637 of 640 strings)

Translated using Weblate (Swedish)

Currently translated at 100.0% (640 of 640 strings)

Translated using Weblate (Spanish)

Currently translated at 100.0% (640 of 640 strings)

Translated using Weblate (Portuguese)

Currently translated at 60.5% (43 of 71 strings)

Translated using Weblate (Azerbaijani)

Currently translated at 100.0% (640 of 640 strings)

Translated using Weblate (Tamil)

Currently translated at 52.5% (336 of 640 strings)

Translated using Weblate (Hebrew)

Currently translated at 100.0% (640 of 640 strings)

Translated using Weblate (Portuguese)

Currently translated at 100.0% (640 of 640 strings)

Translated using Weblate (Slovak)

Currently translated at 8.4% (6 of 71 strings)

Translated using Weblate (Kurdish (Central))

Currently translated at 98.1% (628 of 640 strings)

Translated using Weblate (Galician)

Currently translated at 99.6% (638 of 640 strings)

Translated using Weblate (Chinese (Simplified))

Currently translated at 100.0% (640 of 640 strings)

Translated using Weblate (Slovak)

Currently translated at 100.0% (640 of 640 strings)

Translated using Weblate (German)

Currently translated at 100.0% (640 of 640 strings)

Translated using Weblate (Spanish)

Currently translated at 88.7% (63 of 71 strings)

Translated using Weblate (Hindi)

Currently translated at 4.2% (3 of 71 strings)

Translated using Weblate (Portuguese)

Currently translated at 60.5% (43 of 71 strings)

Translated using Weblate (Hindi)

Currently translated at 68.7% (440 of 640 strings)

Translated using Weblate (Chinese (Traditional))

Currently translated at 100.0% (640 of 640 strings)

Translated using Weblate (Turkish)

Currently translated at 100.0% (640 of 640 strings)

Translated using Weblate (Ukrainian)

Currently translated at 100.0% (640 of 640 strings)

Translated using Weblate (Indonesian)

Currently translated at 100.0% (640 of 640 strings)

Translated using Weblate (Arabic)

Currently translated at 100.0% (640 of 640 strings)

Translated using Weblate (Czech)

Currently translated at 100.0% (640 of 640 strings)

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

Currently translated at 100.0% (640 of 640 strings)

Translated using Weblate (Italian)

Currently translated at 100.0% (640 of 640 strings)

Translated using Weblate (Russian)

Currently translated at 100.0% (640 of 640 strings)

Translated using Weblate (Dutch)

Currently translated at 99.3% (636 of 640 strings)

Translated using Weblate (English)

Currently translated at 100.0% (640 of 640 strings)

Translated using Weblate (Chinese (Simplified))

Currently translated at 100.0% (71 of 71 strings)

Translated using Weblate (Chinese (Traditional))

Currently translated at 63.3% (45 of 71 strings)

Translated using Weblate (Swedish)

Currently translated at 47.8% (34 of 71 strings)

Translated using Weblate (French)

Currently translated at 90.1% (64 of 71 strings)

Translated using Weblate (Spanish)

Currently translated at 57.7% (41 of 71 strings)

Translated using Weblate (Polish)

Currently translated at 57.7% (41 of 71 strings)

Translated using Weblate (Czech)

Currently translated at 100.0% (71 of 71 strings)

Translated using Weblate (Ukrainian)

Currently translated at 100.0% (71 of 71 strings)

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

Currently translated at 15.4% (11 of 71 strings)

Translated using Weblate (Portuguese (Portugal))

Currently translated at 100.0% (640 of 640 strings)

Translated using Weblate (Swedish)

Currently translated at 100.0% (640 of 640 strings)

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

Currently translated at 100.0% (640 of 640 strings)

Translated using Weblate (Korean)

Currently translated at 100.0% (640 of 640 strings)

Translated using Weblate (Dutch)

Currently translated at 100.0% (640 of 640 strings)

Translated using Weblate (French)

Currently translated at 100.0% (640 of 640 strings)

Co-authored-by: Agnieszka C <aga_04@o2.pl>
Co-authored-by: AioiLight <info@aioilight.space>
Co-authored-by: Ajeje Brazorf <lmelonimamo@yahoo.it>
Co-authored-by: Alex25820 <alexs25820@gmail.com>
Co-authored-by: Allan Kimmer Jensen <mail@akj.io>
Co-authored-by: Andrew Boonin <catassasin331@gmail.com>
Co-authored-by: Danial Behzadi <dani.behzi@ubuntu.com>
Co-authored-by: Denys Nykula <vegan@libre.net.ua>
Co-authored-by: Eduardo Malaspina <vaio0@swismail.com>
Co-authored-by: Elias Quispe Chura <ilaies_2012@hotmail.com>
Co-authored-by: Eric <hamburger1024@mailbox.org>
Co-authored-by: Error Specialist <errorspecialist02@gmail.com>
Co-authored-by: Fjuro <ifjuro@proton.me>
Co-authored-by: Florin Voicu <florin.bkk@gmail.com>
Co-authored-by: GnuPGを使うべきだ <dieeeazpnnqbpddh@cock.email>
Co-authored-by: Gontzal Manuel Pujana Onaindia <thadahdenyse@gmail.com>
Co-authored-by: Hasan <hasanyildiz0@yaani.com>
Co-authored-by: Hoseok Seo <ddinghoya@gmail.com>
Co-authored-by: Hossain Rizbi <rsajib387@gmail.com>
Co-authored-by: Hosted Weblate <hosted@weblate.org>
Co-authored-by: Igor Nedoboy <i.nedoboy@mail.ru>
Co-authored-by: Igor Rückert <igorruckert@yahoo.com.br>
Co-authored-by: Ihor Hordiichuk <igor_ck@outlook.com>
Co-authored-by: JS Ahn <freirepublik@gmail.com>
Co-authored-by: JY3 <GeeyunJY3@gmail.com>
Co-authored-by: Jeff Huang <s8321414@gmail.com>
Co-authored-by: Leonardo Brauna <leonardo_brauna@hotmail.com.br>
Co-authored-by: Linerly <linerly@protonmail.com>
Co-authored-by: Maday <royalcoolness7898@gmail.com>
Co-authored-by: Marc Barten <mwbarten@hotmail.com>
Co-authored-by: Marian Hanzel <marulinko@gmail.com>
Co-authored-by: Max Xie <monyxie@gmail.com>
Co-authored-by: MohammedSR Vevo <mohammednajmidin@gmail.com>
Co-authored-by: NTFSynergy <ntfsynergy@gmail.com>
Co-authored-by: Nico Guo <fewis64883@herrain.com>
Co-authored-by: Oymate <dhruboadittya96@gmail.com>
Co-authored-by: Oğuz Ersen <oguz@ersen.moe>
Co-authored-by: Priit Jõerüüt <hwlate@joeruut.com>
Co-authored-by: Ray <ray.cfu@protonmail.com>
Co-authored-by: Rex_sa <rex.sa@pm.me>
Co-authored-by: S3aBreeze <paperwork@evilcorp.ltd>
Co-authored-by: SC <lalocas@protonmail.com>
Co-authored-by: SEENUVASAN T <seenuthiruvpm@gmail.com>
Co-authored-by: TXRdev Archive <lckphanaf9999@gmail.com>
Co-authored-by: Terry Louwers <t.louwers@gmail.com>
Co-authored-by: TiA4f8R <avdivers84@gmail.com>
Co-authored-by: Tom Sawyer <weblate@grymkoll.se>
Co-authored-by: Translator <kvb@tuta.io>
Co-authored-by: Vas R <mrkomododragon1234@gmail.com>
Co-authored-by: Vasilis K <skyhirules@gmail.com>
Co-authored-by: VfBFan <drop0815@posteo.de>
Co-authored-by: Yaron Shahrabani <sh.yaron@gmail.com>
Co-authored-by: atilluF <atilluf@outlook.com>
Co-authored-by: gallegonovato <fran-carro@hotmail.es>
Co-authored-by: gonzalo <misctrashy@gmail.com>
Co-authored-by: komiratsu19273240ad76c354986 <2011945@naver.com>
Co-authored-by: nautilusx <translate@disroot.org>
Co-authored-by: pitachips <hjkim3323@gmail.com>
Co-authored-by: pjammo <adrianoghr@hotmail.it>
Co-authored-by: ssantos <ssantos@web.de>
Co-authored-by: variable virus <variablevirus@gmail.com>
Co-authored-by: weughgh <ahmedhuntingpro@proton.me>
Co-authored-by: zaioti <zaioti@tuta.io>
Co-authored-by: zmni <zmni@outlook.com>
Co-authored-by: 이정희 <daemul72@gmail.com>
Co-authored-by: 정주찬 <ju1801@outlook.com>
Translate-URL: https://hosted.weblate.org/projects/newpipe/metadata/cs/
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/pl/
Translate-URL: https://hosted.weblate.org/projects/newpipe/metadata/pt/
Translate-URL: https://hosted.weblate.org/projects/newpipe/metadata/pt_BR/
Translate-URL: https://hosted.weblate.org/projects/newpipe/metadata/pt_PT/
Translate-URL: https://hosted.weblate.org/projects/newpipe/metadata/sk/
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/zh_Hans/
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
2022-10-09 19:53:02 +02:00
Tobi
ed4eb124e4 Merge pull request #8734 from Stypox/feed-group-factory
Improve `FeedGroupDialogViewModel` factory
2022-10-09 19:35:47 +02:00
Tobi
4070007c93 Merge pull request #9011 from TacoTheDank/useSimpleSummaryProvider
Utilize useSimpleSummaryProvider attribute
2022-10-09 19:23:26 +02:00
Tobi
5b213a19e4 Merge pull request #8934 from Isira-Seneviratne/LinkifyCompat
Use LinkifyCompat.
2022-10-09 12:07:50 +02:00
Tobi
34d81d3bf2 Merge pull request #8987 from Sandelinos/themed-icons
Add monochrome icon
2022-10-09 11:40:20 +02:00
Tobi
8bc8355b68 Merge pull request #8946 from HybridAU/add_play_queue_button_to_video_details_fragment
Add play queue button to video details fragment
2022-10-06 18:55:50 +02:00
devlearner
ab99c14fd2 Fix crash on screen rotation 2022-10-06 18:15:36 +08:00
devlearner
1047158a66 Fix potential cast exception
when casting to `Spannable` in `CommentTextOnTouchListener`
2022-10-04 17:31:35 +08:00
TacoTheDank
fe227d5b94 Utilize useSimpleSummaryProvider attribute 2022-09-23 01:46:34 -04:00
Sandelinos
cb80891a5f Add monochrome icon 2022-09-17 17:18:15 +03:00
HybridAU
9db0133a5b Add play queue button to video details fragment
* Add play queue button to video details fragment

* Use existing ic_list icon

* Still open play queue even when queue is empty

* Change app:srcCompat to android:src
2022-09-14 21:00:44 +08:00
Isira Seneviratne
464a646671 Use LinkifyCompat. 2022-09-06 09:27:50 +05:30
Isira Seneviratne
408a71cfdc Calculate search score using streams.
Co-authored-by: Stypox <stypox@pm.me>
2022-08-15 07:26:56 +05:30
Isira Seneviratne
6399e39507 Remove from playlist only upon selecting the option and not afterwards. 2022-08-15 07:26:36 +05:30
Isira Seneviratne
f9443f7421 Refactor removeWatchedStreams() in LocalPlaylistFragment. 2022-08-15 07:26:36 +05:30
Isira Seneviratne
697b8411df Use Okio's ByteString. 2022-08-13 08:27:55 +05:30
Isira Seneviratne
e136a6f915 Use range-limiting methods in more places. 2022-08-08 07:10:16 +05:30
Stypox
8dce66d76f Improve FeedGroupDialogViewModel factory 2022-08-04 10:49:33 +02:00
184 changed files with 3626 additions and 1123 deletions

View File

@@ -22,6 +22,7 @@ You'll see *exactly* what is sent, be able to add **your comments**, and then se
* NewPipe is translated via [Weblate](https://hosted.weblate.org/projects/newpipe/strings/). Log in there with your GitHub account, or register.
* Add the language you want to translate if it is not there already: see [How to add a new language](https://github.com/TeamNewPipe/NewPipe/wiki/How-to-add-a-new-language-to-NewPipe) in the wiki.
* NewPipe uses the [PrettyTime](https://github.com/ocpsoft/prettytime) library to display localized versions of dates and times. It needs to be translated, too. Read [these instructions to add a new language](https://www.ocpsoft.org/prettytime/#section-14) and [this issue](https://github.com/TeamNewPipe/NewPipe/issues/9134) for more info.
## Code contribution

View File

@@ -1,6 +1,6 @@
name: Feature request
description: Suggest an idea for this project
labels: [enhancement, needs triage]
labels: [feature request, needs triage]
body:
- type: markdown
attributes:

View File

@@ -8,16 +8,16 @@ plugins {
}
android {
compileSdk 31
buildToolsVersion '31.0.0'
compileSdk 32
namespace 'org.schabi.newpipe'
defaultConfig {
applicationId "org.schabi.newpipe"
resValue "string", "app_name", "NewPipe"
minSdk 21
targetSdk 29
versionCode 990
versionName "0.24.0"
versionCode 991
versionName "0.24.1"
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
@@ -187,7 +187,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:5c710da160f488bb40ab2cf4469bec9bd4cefd38'
implementation 'com.github.TeamNewPipe:NewPipeExtractor:eb07d70a2ce03bee3cc74fc33b2e4173e1c21436'
implementation 'com.github.TeamNewPipe:NoNonsense-FilePicker:5.0.0'
/** Checkstyle **/
@@ -198,7 +198,7 @@ dependencies {
implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk8:${kotlin_version}"
/** AndroidX **/
implementation 'androidx.appcompat:appcompat:1.4.2'
implementation 'androidx.appcompat:appcompat:1.5.1'
implementation 'androidx.cardview:cardview:1.0.0'
implementation 'androidx.constraintlayout:constraintlayout:2.1.4'
implementation 'androidx.core:core-ktx:1.8.0'
@@ -271,7 +271,7 @@ dependencies {
implementation "com.jakewharton.rxbinding4:rxbinding:4.0.0"
// Date and time formatting
implementation "org.ocpsoft.prettytime:prettytime:5.0.3.Final"
implementation "org.ocpsoft.prettytime:prettytime:5.0.6.Final"
/** Debugging **/
// Memory leak detection

View File

@@ -1,8 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<manifest
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
package="org.schabi.newpipe">
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools">
<application
android:name=".DebugApp"

View File

@@ -1,7 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
package="org.schabi.newpipe"
android:installLocation="auto">
<uses-permission android:name="android.permission.INTERNET" />
@@ -14,6 +13,9 @@
<uses-feature
android:name="android.hardware.touchscreen"
android:required="false" />
<uses-feature
android:name="android.software.leanback"
android:required="false" />
<application
android:name=".App"
@@ -151,6 +153,7 @@
<data android:pathPrefix="/channel/" />
<data android:pathPrefix="/user/" />
<data android:pathPrefix="/c/" />
<data android:pathPrefix="/@" />
<!-- playlist prefix -->
<data android:pathPrefix="/playlist" />
</intent-filter>

View File

@@ -78,6 +78,7 @@ class AboutActivity : AppCompatActivity() {
aboutDonationLink.openLink(R.string.donation_url)
aboutWebsiteLink.openLink(R.string.website_url)
aboutPrivacyPolicyLink.openLink(R.string.privacy_policy_url)
faqLink.openLink(R.string.faq_url)
return root
}
}

View File

@@ -48,7 +48,10 @@ abstract class FeedDAO {
ON s.uid = f.stream_id
LEFT JOIN feed_group_subscription_join fgs
ON fgs.subscription_id = f.subscription_id
ON (
:groupId <> ${FeedGroupEntity.GROUP_ALL_ID}
AND fgs.subscription_id = f.subscription_id
)
WHERE (
:groupId = ${FeedGroupEntity.GROUP_ALL_ID}

View File

@@ -145,6 +145,12 @@ public class DownloadDialog extends DialogFragment
// Instance creation
//////////////////////////////////////////////////////////////////////////*/
public DownloadDialog() {
// Just an empty default no-arg ctor to keep Fragment.instantiate() happy
// otherwise InstantiationException will be thrown when fragment is recreated
// TODO: Maybe use a custom FragmentFactory instead?
}
/**
* Create a new download dialog with the video, audio and subtitle streams from the provided
* stream info. Video streams and video-only streams will be put into a single list menu,
@@ -153,7 +159,7 @@ public class DownloadDialog extends DialogFragment
* @param context the context to use just to obtain preferences and strings (will not be stored)
* @param info the info from which to obtain downloadable streams and other info (e.g. title)
*/
public DownloadDialog(final Context context, @NonNull final StreamInfo info) {
public DownloadDialog(@NonNull final Context context, @NonNull final StreamInfo info) {
this.currentInfo = info;
// TODO: Adapt this code when the downloader support other types of stream deliveries

View File

@@ -30,6 +30,7 @@ import org.schabi.newpipe.ktx.animate
import org.schabi.newpipe.ktx.isInterruptedCaused
import org.schabi.newpipe.ktx.isNetworkRelated
import org.schabi.newpipe.util.ServiceHelper
import org.schabi.newpipe.util.external_communication.ShareUtils
import java.util.concurrent.TimeUnit
class ErrorPanelHelper(
@@ -52,6 +53,8 @@ class ErrorPanelHelper(
errorPanelRoot.findViewById(R.id.error_action_button)
private val errorRetryButton: Button =
errorPanelRoot.findViewById(R.id.error_retry_button)
private val errorOpenInBrowserButton: Button =
errorPanelRoot.findViewById(R.id.error_open_in_browser)
private var errorDisposable: Disposable? = null
@@ -69,6 +72,7 @@ class ErrorPanelHelper(
errorServiceExplanationTextView.isVisible = false
errorActionButton.isVisible = false
errorRetryButton.isVisible = false
errorOpenInBrowserButton.isVisible = false
}
fun showError(errorInfo: ErrorInfo) {
@@ -99,6 +103,7 @@ class ErrorPanelHelper(
}
errorRetryButton.isVisible = true
showAndSetOpenInBrowserButtonAction(errorInfo)
} else if (errorInfo.throwable is AccountTerminatedException) {
errorTextView.setText(R.string.account_terminated)
@@ -128,6 +133,7 @@ class ErrorPanelHelper(
// show retry button only for content which is not unavailable or unsupported
errorRetryButton.isVisible = true
}
showAndSetOpenInBrowserButtonAction(errorInfo)
}
setRootVisible()
@@ -145,6 +151,15 @@ class ErrorPanelHelper(
errorActionButton.setOnClickListener(listener)
}
fun showAndSetOpenInBrowserButtonAction(
errorInfo: ErrorInfo
) {
errorOpenInBrowserButton.isVisible = true
errorOpenInBrowserButton.setOnClickListener {
ShareUtils.openUrlInBrowser(context, errorInfo.request, true)
}
}
fun showTextError(errorString: String) {
ensureDefaultVisibility()

View File

@@ -248,6 +248,7 @@ public final class VideoDetailFragment
autoPlayEnabled = true; // forcefully start playing
openVideoPlayerAutoFullscreen();
}
updateOverlayPlayQueueButtonVisibility();
}
@Override
@@ -337,6 +338,8 @@ public final class VideoDetailFragment
activity.sendBroadcast(new Intent(ACTION_VIDEO_FRAGMENT_RESUMED));
updateOverlayPlayQueueButtonVisibility();
setupBrightness();
if (tabSettingsChanged) {
@@ -526,6 +529,9 @@ public final class VideoDetailFragment
case R.id.overlay_buttons_layout:
bottomSheetBehavior.setState(BottomSheetBehavior.STATE_EXPANDED);
break;
case R.id.overlay_play_queue_button:
NavigationHelper.openPlayQueue(getContext());
break;
case R.id.overlay_play_pause_button:
if (playerIsNotStopped()) {
player.playPause();
@@ -684,6 +690,7 @@ public final class VideoDetailFragment
binding.overlayMetadataLayout.setOnClickListener(this);
binding.overlayMetadataLayout.setOnLongClickListener(this);
binding.overlayButtonsLayout.setOnClickListener(this);
binding.overlayPlayQueueButton.setOnClickListener(this);
binding.overlayCloseButton.setOnClickListener(this);
binding.overlayPlayPauseButton.setOnClickListener(this);
@@ -1816,6 +1823,14 @@ public final class VideoDetailFragment
+ title + "], playQueue = [" + playQueue + "]");
}
// Register broadcast receiver to listen to playQueue changes
// and hide the overlayPlayQueueButton when the playQueue is empty / destroyed.
if (playQueue != null && playQueue.getBroadcastReceiver() != null) {
playQueue.getBroadcastReceiver().subscribe(
event -> updateOverlayPlayQueueButtonVisibility()
);
}
// This should be the only place where we push data to stack.
// It will allow to have live instance of PlayQueue with actual information about
// deleted/added items inside Channel/Playlist queue and makes possible to have
@@ -1922,6 +1937,7 @@ public final class VideoDetailFragment
currentInfo.getUploaderName(),
currentInfo.getThumbnailUrl());
}
updateOverlayPlayQueueButtonVisibility();
}
@Override
@@ -2388,6 +2404,18 @@ public final class VideoDetailFragment
});
}
private void updateOverlayPlayQueueButtonVisibility() {
final boolean isPlayQueueEmpty =
player == null // no player => no play queue :)
|| player.getPlayQueue() == null
|| player.getPlayQueue().isEmpty();
if (binding != null) {
// binding is null when rotating the device...
binding.overlayPlayQueueButton.setVisibility(
isPlayQueueEmpty ? View.GONE : View.VISIBLE);
}
}
private void updateOverlayData(@Nullable final String overlayTitle,
@Nullable final String uploader,
@Nullable final String thumbnailUrl) {
@@ -2426,6 +2454,7 @@ public final class VideoDetailFragment
binding.overlayMetadataLayout.setClickable(enable);
binding.overlayMetadataLayout.setLongClickable(enable);
binding.overlayButtonsLayout.setClickable(enable);
binding.overlayPlayQueueButton.setClickable(enable);
binding.overlayPlayPauseButton.setClickable(enable);
binding.overlayCloseButton.setClickable(enable);
}

View File

@@ -5,7 +5,6 @@ import static org.schabi.newpipe.ktx.ViewUtils.animateHideRecyclerViewAllowingSc
import android.content.Context;
import android.content.SharedPreferences;
import android.content.res.Configuration;
import android.content.res.Resources;
import android.os.Bundle;
import android.util.Log;
@@ -31,6 +30,7 @@ import org.schabi.newpipe.info_list.dialog.InfoItemDialog;
import org.schabi.newpipe.util.NavigationHelper;
import org.schabi.newpipe.util.OnClickGesture;
import org.schabi.newpipe.util.StateSaver;
import org.schabi.newpipe.util.ThemeHelper;
import org.schabi.newpipe.views.SuperScrollLayoutManager;
import java.util.List;
@@ -476,15 +476,6 @@ public abstract class BaseListFragment<I, N> extends BaseStateFragment<I>
}
protected boolean isGridLayout() {
final String listMode = PreferenceManager.getDefaultSharedPreferences(activity)
.getString(getString(R.string.list_view_mode_key),
getString(R.string.list_view_mode_value));
if ("auto".equals(listMode)) {
final Configuration configuration = getResources().getConfiguration();
return configuration.orientation == Configuration.ORIENTATION_LANDSCAPE
&& configuration.isLayoutSizeAtLeast(Configuration.SCREENLAYOUT_SIZE_LARGE);
} else {
return "grid".equals(listMode);
}
return ThemeHelper.shouldUseGridLayout(activity);
}
}

View File

@@ -61,5 +61,6 @@ class StreamSegmentAdapter(
interface StreamSegmentListener {
fun onItemClick(item: StreamSegmentItem, seconds: Int)
fun onItemLongClick(item: StreamSegmentItem, seconds: Int)
}
}

View File

@@ -41,6 +41,7 @@ class StreamSegmentItem(
viewHolder.root.findViewById<TextView>(R.id.textViewStartSeconds).text =
Localization.getDurationString(item.startTimeSeconds.toLong())
viewHolder.root.setOnClickListener { onClick.onItemClick(this, item.startTimeSeconds) }
viewHolder.root.setOnLongClickListener { onClick.onItemLongClick(this, item.startTimeSeconds); true }
viewHolder.root.isSelected = isSelected
}

View File

@@ -112,12 +112,19 @@ public enum StreamDialogDefaultEntry {
ShareUtils.shareText(fragment.requireContext(), item.getName(), item.getUrl(),
item.getThumbnailUrl())),
/**
* Opens a {@link DownloadDialog} after fetching some stream info.
* If the user quits the current fragment, it will not open a DownloadDialog.
*/
DOWNLOAD(R.string.download, (fragment, item) ->
fetchStreamInfoAndSaveToDatabase(fragment.requireContext(), item.getServiceId(),
item.getUrl(), info -> {
final DownloadDialog downloadDialog =
new DownloadDialog(fragment.requireContext(), info);
downloadDialog.show(fragment.getChildFragmentManager(), "downloadDialog");
if (fragment.getContext() != null) {
final DownloadDialog downloadDialog =
new DownloadDialog(fragment.requireContext(), info);
downloadDialog.show(fragment.getChildFragmentManager(),
"downloadDialog");
}
})
),

View File

@@ -12,6 +12,7 @@ import android.widget.RelativeLayout;
import android.widget.TextView;
import androidx.appcompat.app.AppCompatActivity;
import androidx.core.text.util.LinkifyCompat;
import org.schabi.newpipe.R;
import org.schabi.newpipe.error.ErrorUtil;
@@ -27,7 +28,7 @@ import org.schabi.newpipe.util.PicassoHelper;
import org.schabi.newpipe.util.external_communication.ShareUtils;
import org.schabi.newpipe.util.external_communication.TimestampExtractor;
import java.util.regex.Matcher;
import java.util.Objects;
public class CommentsMiniInfoItemHolder extends InfoItemHolder {
private static final String TAG = "CommentsMiniIIHolder";
@@ -39,7 +40,7 @@ public class CommentsMiniInfoItemHolder extends InfoItemHolder {
private final int commentVerticalPadding;
private final RelativeLayout itemRoot;
public final ImageView itemThumbnailView;
private final ImageView itemThumbnailView;
private final TextView itemContentView;
private final TextView itemLikesCountView;
private final TextView itemPublishedTime;
@@ -47,27 +48,6 @@ public class CommentsMiniInfoItemHolder extends InfoItemHolder {
private String commentText;
private String streamUrl;
private final Linkify.TransformFilter timestampLink = new Linkify.TransformFilter() {
@Override
public String transformUrl(final Matcher match, final String url) {
try {
final TimestampExtractor.TimestampMatchDTO timestampMatchDTO =
TimestampExtractor.getTimestampFromMatcher(match, commentText);
if (timestampMatchDTO == null) {
return url;
}
return streamUrl + url.replace(
match.group(0),
"#timestamp=" + timestampMatchDTO.seconds());
} catch (final Exception ex) {
Log.e(TAG, "Unable to process url='" + url + "' as timestampLink", ex);
return url;
}
}
};
CommentsMiniInfoItemHolder(final InfoItemBuilder infoItemBuilder, final int layoutId,
final ViewGroup parent) {
super(infoItemBuilder, layoutId, parent);
@@ -115,7 +95,7 @@ public class CommentsMiniInfoItemHolder extends InfoItemHolder {
itemContentView.setLines(COMMENT_DEFAULT_LINES);
commentText = item.getCommentText();
itemContentView.setText(commentText);
itemContentView.setText(commentText, TextView.BufferType.SPANNABLE);
itemContentView.setOnTouchListener(CommentTextOnTouchListener.INSTANCE);
if (itemContentView.getLineCount() == 0) {
@@ -243,14 +223,21 @@ public class CommentsMiniInfoItemHolder extends InfoItemHolder {
}
private void linkify() {
Linkify.addLinks(
itemContentView,
Linkify.WEB_URLS);
Linkify.addLinks(
itemContentView,
TimestampExtractor.TIMESTAMPS_PATTERN,
null,
null,
timestampLink);
LinkifyCompat.addLinks(itemContentView, Linkify.WEB_URLS);
LinkifyCompat.addLinks(itemContentView, TimestampExtractor.TIMESTAMPS_PATTERN, null, null,
(match, url) -> {
try {
final var timestampMatch = TimestampExtractor
.getTimestampFromMatcher(match, commentText);
if (timestampMatch == null) {
return url;
}
return streamUrl + url.replace(Objects.requireNonNull(match.group(0)),
"#timestamp=" + timestampMatch.seconds());
} catch (final Exception ex) {
Log.e(TAG, "Unable to process url='" + url + "' as timestampLink", ex);
return url;
}
});
}
}

View File

@@ -40,6 +40,7 @@ import androidx.annotation.Nullable
import androidx.appcompat.app.AlertDialog
import androidx.appcompat.content.res.AppCompatResources
import androidx.core.content.edit
import androidx.core.math.MathUtils
import androidx.core.os.bundleOf
import androidx.core.view.MenuItemCompat
import androidx.core.view.isVisible
@@ -603,7 +604,7 @@ class FeedFragment : BaseStateFragment<FeedState>() {
// state until the user scrolls them out of the visible area which causes a update/bind-call
groupAdapter.notifyItemRangeChanged(
0,
minOf(groupAdapter.itemCount, maxOf(highlightCount, lastNewItemsCount))
MathUtils.clamp(highlightCount, lastNewItemsCount, groupAdapter.itemCount)
)
if (highlightCount > 0) {

View File

@@ -11,6 +11,7 @@ import android.os.Parcelable;
import android.text.InputType;
import android.text.TextUtils;
import android.util.Log;
import android.util.Pair;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuInflater;
@@ -22,6 +23,7 @@ import android.widget.Toast;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.appcompat.app.AlertDialog;
import androidx.preference.PreferenceManager;
import androidx.recyclerview.widget.ItemTouchHelper;
import androidx.recyclerview.widget.RecyclerView;
import androidx.viewbinding.ViewBinding;
@@ -34,7 +36,6 @@ import org.schabi.newpipe.database.LocalItem;
import org.schabi.newpipe.database.history.model.StreamHistoryEntry;
import org.schabi.newpipe.database.playlist.PlaylistStreamEntry;
import org.schabi.newpipe.database.stream.model.StreamEntity;
import org.schabi.newpipe.database.stream.model.StreamStateEntity;
import org.schabi.newpipe.databinding.DialogEditTextBinding;
import org.schabi.newpipe.databinding.LocalPlaylistHeaderBinding;
import org.schabi.newpipe.databinding.PlaylistControlBinding;
@@ -55,7 +56,6 @@ import org.schabi.newpipe.util.external_communication.ShareUtils;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Iterator;
import java.util.List;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicBoolean;
@@ -63,7 +63,6 @@ import java.util.stream.Collectors;
import icepick.State;
import io.reactivex.rxjava3.android.schedulers.AndroidSchedulers;
import io.reactivex.rxjava3.core.Flowable;
import io.reactivex.rxjava3.core.Single;
import io.reactivex.rxjava3.disposables.CompositeDisposable;
import io.reactivex.rxjava3.disposables.Disposable;
@@ -309,7 +308,7 @@ public class LocalPlaylistFragment extends BaseLocalListFragment<List<PlaylistSt
///////////////////////////////////////////////////////////////////////////
private Subscriber<List<PlaylistStreamEntry>> getPlaylistObserver() {
return new Subscriber<List<PlaylistStreamEntry>>() {
return new Subscriber<>() {
@Override
public void onSubscribe(final Subscription s) {
showLoading();
@@ -395,31 +394,21 @@ public class LocalPlaylistFragment extends BaseLocalListFragment<List<PlaylistSt
isRemovingWatched = true;
showLoading();
disposables.add(playlistManager.getPlaylistStreams(playlistId)
.subscribeOn(Schedulers.io())
.map((List<PlaylistStreamEntry> playlist) -> {
// Playlist data
final Iterator<PlaylistStreamEntry> playlistIter = playlist.iterator();
// History data
final HistoryRecordManager recordManager =
new HistoryRecordManager(getContext());
final Iterator<StreamHistoryEntry> historyIter = recordManager
.getStreamHistorySortedById().blockingFirst().iterator();
final var recordManager = new HistoryRecordManager(getContext());
final var historyIdsMaybe = recordManager.getStreamHistorySortedById()
.firstElement()
// already sorted by ^ getStreamHistorySortedById(), binary search can be used
.map(historyList -> historyList.stream().map(StreamHistoryEntry::getStreamId)
.collect(Collectors.toList()));
final var streamsMaybe = playlistManager.getPlaylistStreams(playlistId)
.firstElement()
.zipWith(historyIdsMaybe, (playlist, historyStreamIds) -> {
// Remove Watched, Functionality data
final List<PlaylistStreamEntry> notWatchedItems = new ArrayList<>();
boolean thumbnailVideoRemoved = false;
// already sorted by ^ getStreamHistorySortedById(), binary search can be used
final ArrayList<Long> historyStreamIds = new ArrayList<>();
while (historyIter.hasNext()) {
historyStreamIds.add(historyIter.next().getStreamId());
}
if (removePartiallyWatched) {
while (playlistIter.hasNext()) {
final PlaylistStreamEntry playlistItem = playlistIter.next();
for (final var playlistItem : playlist) {
final int indexInHistory = Collections.binarySearch(historyStreamIds,
playlistItem.getStreamId());
@@ -432,14 +421,15 @@ public class LocalPlaylistFragment extends BaseLocalListFragment<List<PlaylistSt
}
}
} else {
final Iterator<StreamStateEntity> streamStatesIter = recordManager
.loadLocalStreamStateBatch(playlist).blockingGet().iterator();
final var streamStates = recordManager
.loadLocalStreamStateBatch(playlist).blockingGet();
for (int i = 0; i < playlist.size(); i++) {
final var playlistItem = playlist.get(i);
final var streamStateEntity = streamStates.get(i);
while (playlistIter.hasNext()) {
final PlaylistStreamEntry playlistItem = playlistIter.next();
final int indexInHistory = Collections.binarySearch(historyStreamIds,
playlistItem.getStreamId());
final StreamStateEntity streamStateEntity = streamStatesIter.next();
final long duration = playlistItem.toStreamInfoItem().getDuration();
if (indexInHistory < 0 || (streamStateEntity != null
@@ -453,19 +443,19 @@ public class LocalPlaylistFragment extends BaseLocalListFragment<List<PlaylistSt
}
}
return Flowable.just(notWatchedItems, thumbnailVideoRemoved);
})
return new Pair<>(notWatchedItems, thumbnailVideoRemoved);
});
disposables.add(streamsMaybe.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(flow -> {
final List<PlaylistStreamEntry> notWatchedItems =
(List<PlaylistStreamEntry>) flow.blockingFirst();
final boolean thumbnailVideoRemoved = (Boolean) flow.blockingLast();
final List<PlaylistStreamEntry> notWatchedItems = flow.first;
final boolean thumbnailVideoRemoved = flow.second;
itemListAdapter.clearStreamItemList();
itemListAdapter.addItems(notWatchedItems);
saveChanges();
if (thumbnailVideoRemoved) {
updateThumbnailUrl();
}
@@ -503,13 +493,18 @@ public class LocalPlaylistFragment extends BaseLocalListFragment<List<PlaylistSt
}
setVideoCount(itemListAdapter.getItemsList().size());
playlistControlBinding.playlistCtrlPlayAllButton.setOnClickListener(view ->
NavigationHelper.playOnMainPlayer(activity, getPlayQueue()));
playlistControlBinding.playlistCtrlPlayPopupButton.setOnClickListener(view ->
NavigationHelper.playOnPopupPlayer(activity, getPlayQueue(), false));
playlistControlBinding.playlistCtrlPlayBgButton.setOnClickListener(view ->
NavigationHelper.playOnBackgroundPlayer(activity, getPlayQueue(), false));
playlistControlBinding.playlistCtrlPlayAllButton.setOnClickListener(view -> {
NavigationHelper.playOnMainPlayer(activity, getPlayQueue());
showHoldToAppendTipIfNeeded();
});
playlistControlBinding.playlistCtrlPlayPopupButton.setOnClickListener(view -> {
NavigationHelper.playOnPopupPlayer(activity, getPlayQueue(), false);
showHoldToAppendTipIfNeeded();
});
playlistControlBinding.playlistCtrlPlayBgButton.setOnClickListener(view -> {
NavigationHelper.playOnBackgroundPlayer(activity, getPlayQueue(), false);
showHoldToAppendTipIfNeeded();
});
playlistControlBinding.playlistCtrlPlayPopupButton.setOnLongClickListener(view -> {
NavigationHelper.enqueueOnPlayer(activity, getPlayQueue(), PlayerType.POPUP);
return true;
@@ -523,6 +518,13 @@ public class LocalPlaylistFragment extends BaseLocalListFragment<List<PlaylistSt
hideLoading();
}
private void showHoldToAppendTipIfNeeded() {
if (PreferenceManager.getDefaultSharedPreferences(activity)
.getBoolean(getString(R.string.show_hold_to_append_key), true)) {
Toast.makeText(activity, R.string.hold_to_append, Toast.LENGTH_SHORT).show();
}
}
///////////////////////////////////////////////////////////////////////////
// Fragment Error Handling
///////////////////////////////////////////////////////////////////////////

View File

@@ -5,25 +5,45 @@ import androidx.lifecycle.AndroidViewModel
import androidx.lifecycle.LiveData
import androidx.lifecycle.MutableLiveData
import com.xwray.groupie.Group
import io.reactivex.rxjava3.core.Flowable
import io.reactivex.rxjava3.processors.BehaviorProcessor
import io.reactivex.rxjava3.schedulers.Schedulers
import org.schabi.newpipe.local.feed.FeedDatabaseManager
import org.schabi.newpipe.local.subscription.item.ChannelItem
import org.schabi.newpipe.local.subscription.item.FeedGroupCardGridItem
import org.schabi.newpipe.local.subscription.item.FeedGroupCardItem
import org.schabi.newpipe.util.DEFAULT_THROTTLE_TIMEOUT
import org.schabi.newpipe.util.ThemeHelper
import java.util.concurrent.TimeUnit
class SubscriptionViewModel(application: Application) : AndroidViewModel(application) {
private var feedDatabaseManager: FeedDatabaseManager = FeedDatabaseManager(application)
private var subscriptionManager = SubscriptionManager(application)
private val mutableStateLiveData = MutableLiveData<SubscriptionState>()
private val mutableFeedGroupsLiveData = MutableLiveData<List<Group>>()
val stateLiveData: LiveData<SubscriptionState> = mutableStateLiveData
val feedGroupsLiveData: LiveData<List<Group>> = mutableFeedGroupsLiveData
// true -> list view, false -> grid view
private val listViewMode = BehaviorProcessor.createDefault(
!ThemeHelper.shouldUseGridLayout(application)
)
private val listViewModeFlowable = listViewMode.distinctUntilChanged()
private var feedGroupItemsDisposable = feedDatabaseManager.groups()
private val mutableStateLiveData = MutableLiveData<SubscriptionState>()
private val mutableFeedGroupsLiveData = MutableLiveData<Pair<List<Group>, Boolean>>()
val stateLiveData: LiveData<SubscriptionState> = mutableStateLiveData
val feedGroupsLiveData: LiveData<Pair<List<Group>, Boolean>> = mutableFeedGroupsLiveData
private var feedGroupItemsDisposable = Flowable
.combineLatest(
feedDatabaseManager.groups(),
listViewModeFlowable,
::Pair
)
.throttleLatest(DEFAULT_THROTTLE_TIMEOUT, TimeUnit.MILLISECONDS)
.map { it.map(::FeedGroupCardItem) }
.map { (feedGroups, listViewMode) ->
Pair(
feedGroups.map(if (listViewMode) ::FeedGroupCardItem else ::FeedGroupCardGridItem),
listViewMode
)
}
.subscribeOn(Schedulers.io())
.subscribe(
{ mutableFeedGroupsLiveData.postValue(it) },
@@ -45,6 +65,14 @@ class SubscriptionViewModel(application: Application) : AndroidViewModel(applica
feedGroupItemsDisposable.dispose()
}
fun setListViewMode(newListViewMode: Boolean) {
listViewMode.onNext(newListViewMode)
}
fun getListViewMode(): Boolean {
return listViewMode.value ?: true
}
sealed class SubscriptionState {
data class LoadedState(val subscriptions: List<Group>) : SubscriptionState()
data class ErrorState(val error: Throwable? = null) : SubscriptionState()

View File

@@ -1,35 +0,0 @@
package org.schabi.newpipe.local.subscription.decoration
import android.content.Context
import android.graphics.Rect
import android.view.View
import androidx.recyclerview.widget.RecyclerView
import org.schabi.newpipe.R
class FeedGroupCarouselDecoration(context: Context) : RecyclerView.ItemDecoration() {
private val marginStartEnd: Int
private val marginTopBottom: Int
private val marginBetweenItems: Int
init {
with(context.resources) {
marginStartEnd = getDimensionPixelOffset(R.dimen.feed_group_carousel_start_end_margin)
marginTopBottom = getDimensionPixelOffset(R.dimen.feed_group_carousel_top_bottom_margin)
marginBetweenItems = getDimensionPixelOffset(R.dimen.feed_group_carousel_between_items_margin)
}
}
override fun getItemOffsets(outRect: Rect, child: View, parent: RecyclerView, state: RecyclerView.State) {
val childAdapterPosition = parent.getChildAdapterPosition(child)
val childAdapterCount = parent.adapter?.itemCount ?: 0
outRect.set(marginBetweenItems, marginTopBottom, 0, marginTopBottom)
if (childAdapterPosition == 0) {
outRect.left = marginStartEnd
} else if (childAdapterPosition == childAdapterCount - 1) {
outRect.right = marginStartEnd
}
}
}

View File

@@ -124,11 +124,13 @@ class FeedGroupDialog : DialogFragment(), BackPressable {
viewModel = ViewModelProvider(
this,
FeedGroupDialogViewModel.Factory(
FeedGroupDialogViewModel.getFactory(
requireContext(),
groupId, subscriptionsCurrentSearchQuery, subscriptionsShowOnlyUngrouped
groupId,
subscriptionsCurrentSearchQuery,
subscriptionsShowOnlyUngrouped
)
).get(FeedGroupDialogViewModel::class.java)
)[FeedGroupDialogViewModel::class.java]
viewModel.groupLiveData.observe(viewLifecycleOwner, Observer(::handleGroup))
viewModel.subscriptionsLiveData.observe(viewLifecycleOwner) {

View File

@@ -4,7 +4,8 @@ import android.content.Context
import androidx.lifecycle.LiveData
import androidx.lifecycle.MutableLiveData
import androidx.lifecycle.ViewModel
import androidx.lifecycle.ViewModelProvider
import androidx.lifecycle.viewmodel.initializer
import androidx.lifecycle.viewmodel.viewModelFactory
import io.reactivex.rxjava3.core.Completable
import io.reactivex.rxjava3.core.Flowable
import io.reactivex.rxjava3.disposables.Disposable
@@ -115,18 +116,18 @@ class FeedGroupDialogViewModel(
data class Filter(val query: String, val showOnlyUngrouped: Boolean)
class Factory(
private val context: Context,
private val groupId: Long = FeedGroupEntity.GROUP_ALL_ID,
private val initialQuery: String = "",
private val initialShowOnlyUngrouped: Boolean = false
) : ViewModelProvider.Factory {
@Suppress("UNCHECKED_CAST")
override fun <T : ViewModel> create(modelClass: Class<T>): T {
return FeedGroupDialogViewModel(
context.applicationContext,
groupId, initialQuery, initialShowOnlyUngrouped
) as T
companion object {
fun getFactory(
context: Context,
groupId: Long,
initialQuery: String,
initialShowOnlyUngrouped: Boolean
) = viewModelFactory {
initializer {
FeedGroupDialogViewModel(
context.applicationContext, groupId, initialQuery, initialShowOnlyUngrouped
)
}
}
}
}

View File

@@ -0,0 +1,14 @@
package org.schabi.newpipe.local.subscription.item
import android.view.View
import com.xwray.groupie.viewbinding.BindableItem
import org.schabi.newpipe.R
import org.schabi.newpipe.databinding.FeedGroupAddNewGridItemBinding
class FeedGroupAddNewGridItem : BindableItem<FeedGroupAddNewGridItemBinding>() {
override fun getLayout(): Int = R.layout.feed_group_add_new_grid_item
override fun initializeViewBinding(view: View) = FeedGroupAddNewGridItemBinding.bind(view)
override fun bind(viewBinding: FeedGroupAddNewGridItemBinding, position: Int) {
// this is a static item, nothing to do here
}
}

View File

@@ -5,8 +5,10 @@ import com.xwray.groupie.viewbinding.BindableItem
import org.schabi.newpipe.R
import org.schabi.newpipe.databinding.FeedGroupAddNewItemBinding
class FeedGroupAddItem : BindableItem<FeedGroupAddNewItemBinding>() {
class FeedGroupAddNewItem : BindableItem<FeedGroupAddNewItemBinding>() {
override fun getLayout(): Int = R.layout.feed_group_add_new_item
override fun bind(viewBinding: FeedGroupAddNewItemBinding, position: Int) {}
override fun initializeViewBinding(view: View) = FeedGroupAddNewItemBinding.bind(view)
override fun bind(viewBinding: FeedGroupAddNewItemBinding, position: Int) {
// this is a static item, nothing to do here
}
}

View File

@@ -0,0 +1,32 @@
package org.schabi.newpipe.local.subscription.item
import android.view.View
import com.xwray.groupie.viewbinding.BindableItem
import org.schabi.newpipe.R
import org.schabi.newpipe.database.feed.model.FeedGroupEntity
import org.schabi.newpipe.databinding.FeedGroupCardGridItemBinding
import org.schabi.newpipe.local.subscription.FeedGroupIcon
data class FeedGroupCardGridItem(
val groupId: Long = FeedGroupEntity.GROUP_ALL_ID,
val name: String,
val icon: FeedGroupIcon,
) : BindableItem<FeedGroupCardGridItemBinding>() {
constructor (feedGroupEntity: FeedGroupEntity) : this(feedGroupEntity.uid, feedGroupEntity.name, feedGroupEntity.icon)
override fun getId(): Long {
return when (groupId) {
FeedGroupEntity.GROUP_ALL_ID -> super.getId()
else -> groupId
}
}
override fun getLayout(): Int = R.layout.feed_group_card_grid_item
override fun bind(viewBinding: FeedGroupCardGridItemBinding, position: Int) {
viewBinding.title.text = name
viewBinding.icon.setImageResource(icon.getDrawableRes())
}
override fun initializeViewBinding(view: View) = FeedGroupCardGridItemBinding.bind(view)
}

View File

@@ -1,60 +1,82 @@
package org.schabi.newpipe.local.subscription.item
import android.content.Context
import android.os.Parcelable
import android.view.View
import androidx.recyclerview.widget.GridLayoutManager
import androidx.recyclerview.widget.LinearLayoutManager
import androidx.recyclerview.widget.RecyclerView
import com.xwray.groupie.GroupAdapter
import com.xwray.groupie.viewbinding.BindableItem
import com.xwray.groupie.viewbinding.GroupieViewHolder
import org.schabi.newpipe.R
import org.schabi.newpipe.databinding.FeedItemCarouselBinding
import org.schabi.newpipe.local.subscription.decoration.FeedGroupCarouselDecoration
import org.schabi.newpipe.util.DeviceUtils
import org.schabi.newpipe.util.ThemeHelper.getGridSpanCount
class FeedGroupCarouselItem(
context: Context,
private val carouselAdapter: GroupAdapter<GroupieViewHolder<FeedItemCarouselBinding>>
private val carouselAdapter: GroupAdapter<GroupieViewHolder<FeedItemCarouselBinding>>,
var listViewMode: Boolean
) : BindableItem<FeedItemCarouselBinding>() {
private val feedGroupCarouselDecoration = FeedGroupCarouselDecoration(context)
companion object {
const val PAYLOAD_UPDATE_LIST_VIEW_MODE = 2
}
private var linearLayoutManager: LinearLayoutManager? = null
private var carouselLayoutManager: LinearLayoutManager? = null
private var listState: Parcelable? = null
override fun getLayout() = R.layout.feed_item_carousel
fun onSaveInstanceState(): Parcelable? {
listState = linearLayoutManager?.onSaveInstanceState()
listState = carouselLayoutManager?.onSaveInstanceState()
return listState
}
fun onRestoreInstanceState(state: Parcelable?) {
linearLayoutManager?.onRestoreInstanceState(state)
carouselLayoutManager?.onRestoreInstanceState(state)
listState = state
}
override fun initializeViewBinding(view: View): FeedItemCarouselBinding {
val viewHolder = FeedItemCarouselBinding.bind(view)
val viewBinding = FeedItemCarouselBinding.bind(view)
updateViewMode(viewBinding)
return viewBinding
}
linearLayoutManager = LinearLayoutManager(view.context, RecyclerView.HORIZONTAL, false)
viewHolder.recyclerView.apply {
layoutManager = linearLayoutManager
adapter = carouselAdapter
addItemDecoration(feedGroupCarouselDecoration)
override fun bind(
viewBinding: FeedItemCarouselBinding,
position: Int,
payloads: MutableList<Any>
) {
if (payloads.contains(PAYLOAD_UPDATE_LIST_VIEW_MODE)) {
updateViewMode(viewBinding)
return
}
return viewHolder
super.bind(viewBinding, position, payloads)
}
override fun bind(viewBinding: FeedItemCarouselBinding, position: Int) {
viewBinding.recyclerView.apply { adapter = carouselAdapter }
linearLayoutManager?.onRestoreInstanceState(listState)
carouselLayoutManager?.onRestoreInstanceState(listState)
}
override fun unbind(viewHolder: GroupieViewHolder<FeedItemCarouselBinding>) {
super.unbind(viewHolder)
listState = carouselLayoutManager?.onSaveInstanceState()
}
listState = linearLayoutManager?.onSaveInstanceState()
private fun updateViewMode(viewBinding: FeedItemCarouselBinding) {
viewBinding.recyclerView.apply { adapter = carouselAdapter }
val context = viewBinding.root.context
carouselLayoutManager = if (listViewMode) {
LinearLayoutManager(context)
} else {
GridLayoutManager(context, getGridSpanCount(context, DeviceUtils.dpToPx(112, context)))
}
viewBinding.recyclerView.apply {
layoutManager = carouselLayoutManager
adapter = carouselAdapter
}
}
}

View File

@@ -0,0 +1,50 @@
package org.schabi.newpipe.local.subscription.item
import android.view.View
import androidx.core.view.isVisible
import com.xwray.groupie.viewbinding.BindableItem
import org.schabi.newpipe.R
import org.schabi.newpipe.databinding.SubscriptionGroupsHeaderBinding
class GroupsHeader(
private val title: String,
private val onSortClicked: () -> Unit,
private val onToggleListViewModeClicked: () -> Unit,
var showSortButton: Boolean = true,
var listViewMode: Boolean = true
) : BindableItem<SubscriptionGroupsHeaderBinding>() {
companion object {
const val PAYLOAD_UPDATE_ICONS = 1
}
override fun getLayout(): Int = R.layout.subscription_groups_header
override fun bind(
viewBinding: SubscriptionGroupsHeaderBinding,
position: Int,
payloads: MutableList<Any>
) {
if (payloads.contains(PAYLOAD_UPDATE_ICONS)) {
updateIcons(viewBinding)
return
}
super.bind(viewBinding, position, payloads)
}
override fun bind(viewBinding: SubscriptionGroupsHeaderBinding, position: Int) {
viewBinding.headerTitle.text = title
viewBinding.headerSort.setOnClickListener { onSortClicked() }
viewBinding.headerToggleViewMode.setOnClickListener { onToggleListViewModeClicked() }
updateIcons(viewBinding)
}
override fun initializeViewBinding(view: View) = SubscriptionGroupsHeaderBinding.bind(view)
private fun updateIcons(viewBinding: SubscriptionGroupsHeaderBinding) {
viewBinding.headerToggleViewMode.setImageResource(
if (listViewMode) R.drawable.ic_apps else R.drawable.ic_list
)
viewBinding.headerSort.isVisible = showSortButton
}
}

View File

@@ -0,0 +1,17 @@
package org.schabi.newpipe.local.subscription.item
import android.view.View
import com.xwray.groupie.viewbinding.BindableItem
import org.schabi.newpipe.R
import org.schabi.newpipe.databinding.SubscriptionHeaderBinding
class Header(private val title: String) : BindableItem<SubscriptionHeaderBinding>() {
override fun getLayout(): Int = R.layout.subscription_header
override fun bind(viewBinding: SubscriptionHeaderBinding, position: Int) {
viewBinding.root.text = title
}
override fun initializeViewBinding(view: View) = SubscriptionHeaderBinding.bind(view)
}

View File

@@ -1,50 +0,0 @@
package org.schabi.newpipe.local.subscription.item
import android.view.View
import android.view.View.OnClickListener
import androidx.annotation.DrawableRes
import androidx.core.view.isVisible
import com.xwray.groupie.viewbinding.BindableItem
import org.schabi.newpipe.R
import org.schabi.newpipe.databinding.HeaderWithMenuItemBinding
class HeaderWithMenuItem(
val title: String,
@DrawableRes val itemIcon: Int = 0,
var showMenuItem: Boolean = true,
private val onClickListener: (() -> Unit)? = null,
private val menuItemOnClickListener: (() -> Unit)? = null
) : BindableItem<HeaderWithMenuItemBinding>() {
companion object {
const val PAYLOAD_UPDATE_VISIBILITY_MENU_ITEM = 1
}
override fun getLayout(): Int = R.layout.header_with_menu_item
override fun bind(viewBinding: HeaderWithMenuItemBinding, position: Int, payloads: MutableList<Any>) {
if (payloads.contains(PAYLOAD_UPDATE_VISIBILITY_MENU_ITEM)) {
updateMenuItemVisibility(viewBinding)
return
}
super.bind(viewBinding, position, payloads)
}
override fun bind(viewBinding: HeaderWithMenuItemBinding, position: Int) {
viewBinding.headerTitle.text = title
viewBinding.headerMenuItem.setImageResource(itemIcon)
val listener = onClickListener?.let { OnClickListener { onClickListener.invoke() } }
viewBinding.root.setOnClickListener(listener)
val menuItemListener = menuItemOnClickListener?.let { OnClickListener { menuItemOnClickListener.invoke() } }
viewBinding.headerMenuItem.setOnClickListener(menuItemListener)
updateMenuItemVisibility(viewBinding)
}
override fun initializeViewBinding(view: View) = HeaderWithMenuItemBinding.bind(view)
private fun updateMenuItemVisibility(viewBinding: HeaderWithMenuItemBinding) {
viewBinding.headerMenuItem.isVisible = showMenuItem
}
}

View File

@@ -212,7 +212,6 @@ public final class PlayQueueActivity extends AppCompatActivity
if (player == null || player.getPlayQueue() == null || player.exoPlayerIsNull()) {
unbind();
finish();
} else {
onQueueUpdate(player.getPlayQueue());
buildComponents();

View File

@@ -7,6 +7,7 @@ import android.view.View.OnTouchListener
import android.widget.ProgressBar
import androidx.appcompat.app.AppCompatActivity
import androidx.appcompat.content.res.AppCompatResources
import androidx.core.math.MathUtils
import androidx.core.view.isVisible
import org.schabi.newpipe.MainActivity
import org.schabi.newpipe.R
@@ -18,8 +19,6 @@ import org.schabi.newpipe.player.helper.PlayerHelper
import org.schabi.newpipe.player.ui.MainPlayerUi
import org.schabi.newpipe.util.ThemeHelper.getAndroidDimenPx
import kotlin.math.abs
import kotlin.math.max
import kotlin.math.min
/**
* GestureListener for the player
@@ -114,7 +113,7 @@ class MainPlayerGestureListener(
// Update progress bar
val oldBrightness = layoutParams.screenBrightness
bar.progress = (bar.max * max(0f, min(1f, oldBrightness))).toInt()
bar.progress = (bar.max * MathUtils.clamp(oldBrightness, 0f, 1f)).toInt()
bar.incrementProgressBy(distanceY.toInt())
// Update brightness

View File

@@ -3,6 +3,7 @@ package org.schabi.newpipe.player.ui;
import static android.view.ViewGroup.LayoutParams.MATCH_PARENT;
import static org.schabi.newpipe.MainActivity.DEBUG;
import static org.schabi.newpipe.QueueItemMenuUtil.openPopupMenu;
import static org.schabi.newpipe.extractor.ServiceList.YouTube;
import static org.schabi.newpipe.ktx.ViewUtils.animate;
import static org.schabi.newpipe.player.Player.STATE_COMPLETED;
import static org.schabi.newpipe.player.Player.STATE_PAUSED;
@@ -52,6 +53,7 @@ import org.schabi.newpipe.extractor.stream.StreamSegment;
import org.schabi.newpipe.fragments.OnScrollBelowItemsListener;
import org.schabi.newpipe.fragments.detail.VideoDetailFragment;
import org.schabi.newpipe.info_list.StreamSegmentAdapter;
import org.schabi.newpipe.info_list.StreamSegmentItem;
import org.schabi.newpipe.ktx.AnimationType;
import org.schabi.newpipe.local.dialog.PlaylistDialog;
import org.schabi.newpipe.player.Player;
@@ -60,6 +62,7 @@ import org.schabi.newpipe.player.gesture.BasePlayerGestureListener;
import org.schabi.newpipe.player.gesture.MainPlayerGestureListener;
import org.schabi.newpipe.player.helper.PlaybackParameterDialog;
import org.schabi.newpipe.player.helper.PlayerHelper;
import org.schabi.newpipe.player.mediaitem.MediaItemTag;
import org.schabi.newpipe.player.playqueue.PlayQueue;
import org.schabi.newpipe.player.playqueue.PlayQueueAdapter;
import org.schabi.newpipe.player.playqueue.PlayQueueItem;
@@ -69,6 +72,7 @@ import org.schabi.newpipe.player.playqueue.PlayQueueItemTouchCallback;
import org.schabi.newpipe.util.DeviceUtils;
import org.schabi.newpipe.util.NavigationHelper;
import org.schabi.newpipe.util.external_communication.KoreUtils;
import org.schabi.newpipe.util.external_communication.ShareUtils;
import java.util.List;
import java.util.Objects;
@@ -644,7 +648,7 @@ public final class MainPlayerUi extends VideoPlayerUi implements View.OnLayoutCh
private void buildSegments() {
binding.itemsList.setAdapter(segmentAdapter);
binding.itemsList.setClickable(true);
binding.itemsList.setLongClickable(false);
binding.itemsList.setLongClickable(true);
binding.itemsList.clearOnScrollListeners();
if (itemTouchHelper != null) {
@@ -696,10 +700,30 @@ public final class MainPlayerUi extends VideoPlayerUi implements View.OnLayoutCh
}
private StreamSegmentAdapter.StreamSegmentListener getStreamSegmentListener() {
return (item, seconds) -> {
segmentAdapter.selectSegment(item);
player.seekTo(seconds * 1000L);
player.triggerProgressUpdate();
return new StreamSegmentAdapter.StreamSegmentListener() {
@Override
public void onItemClick(@NonNull final StreamSegmentItem item, final int seconds) {
segmentAdapter.selectSegment(item);
player.seekTo(seconds * 1000L);
player.triggerProgressUpdate();
}
@Override
public void onItemLongClick(@NonNull final StreamSegmentItem item, final int seconds) {
@Nullable final MediaItemTag currentMetadata = player.getCurrentMetadata();
if (currentMetadata == null
|| currentMetadata.getServiceId() != YouTube.getServiceId()) {
return;
}
final PlayQueueItem currentItem = player.getCurrentItem();
if (currentItem != null) {
String videoUrl = player.getVideoUrl();
videoUrl += ("&t=" + seconds);
ShareUtils.shareText(context, currentItem.getTitle(),
videoUrl, currentItem.getThumbnailUrl());
}
}
};
}

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