mirror of
https://github.com/TeamNewPipe/NewPipe
synced 2025-09-22 21:40:52 +02:00
Compare commits
321 Commits
Author | SHA1 | Date | |
---|---|---|---|
![]() |
7d4c45c4c0 | ||
![]() |
f65f2da890 | ||
![]() |
30ab58c33d | ||
![]() |
87ba5a7eb6 | ||
![]() |
6e8593af91 | ||
![]() |
0ab1d3fc40 | ||
![]() |
f22d13e695 | ||
![]() |
cdde61a460 | ||
![]() |
989ce126f1 | ||
![]() |
28618e822e | ||
![]() |
6772381afc | ||
![]() |
75b45beabc | ||
![]() |
56d53e9b01 | ||
![]() |
3a8b04e2d1 | ||
![]() |
1ce7d66fb1 | ||
![]() |
7b5a9b69fe | ||
![]() |
837b22ccac | ||
![]() |
7146719393 | ||
![]() |
71ee604c69 | ||
![]() |
9945a5b813 | ||
![]() |
7254387042 | ||
![]() |
3a7f2a94a6 | ||
![]() |
6bea4aa96b | ||
![]() |
fa262bbceb | ||
![]() |
3139fe0170 | ||
![]() |
ef6c5de65b | ||
![]() |
07799563b5 | ||
![]() |
b1de4b7bd6 | ||
![]() |
2b8ae9a5ea | ||
![]() |
7c52d3ec5d | ||
![]() |
aefaa7619e | ||
![]() |
ca202290bf | ||
![]() |
cbdbc4cba2 | ||
![]() |
8abf904a78 | ||
![]() |
ecf7969c46 | ||
![]() |
a473e3d623 | ||
![]() |
1f8e90858e | ||
![]() |
2c2edca8fa | ||
![]() |
50e86ff1ca | ||
![]() |
02ecc5011a | ||
![]() |
6e666a018b | ||
![]() |
66fbb2ce1e | ||
![]() |
b00722ec0a | ||
![]() |
77b1413319 | ||
![]() |
87b8d60c9d | ||
![]() |
db5203e1ff | ||
![]() |
ea022670c4 | ||
![]() |
54b009cc49 | ||
![]() |
80c3acace9 | ||
![]() |
cea9428b47 | ||
![]() |
f8ffbfabbe | ||
![]() |
836a1e652b | ||
![]() |
d8544e0b84 | ||
![]() |
4817d7fddc | ||
![]() |
e6a385a85e | ||
![]() |
3634f68364 | ||
![]() |
f17ffa94fe | ||
![]() |
d52bcd46a1 | ||
![]() |
7e58b0b6fe | ||
![]() |
f451f1f65d | ||
![]() |
4d12e71fba | ||
![]() |
66fde7a212 | ||
![]() |
86eccf219d | ||
![]() |
677865f347 | ||
![]() |
eb4b3810e9 | ||
![]() |
5f26501ddf | ||
![]() |
b33a72f864 | ||
![]() |
675f43b968 | ||
![]() |
9f117a2e59 | ||
![]() |
a0844229a3 | ||
![]() |
114fcc144c | ||
![]() |
43372ff648 | ||
![]() |
b8ebbc5404 | ||
![]() |
28309f82f3 | ||
![]() |
c70fa391b6 | ||
![]() |
caab589dce | ||
![]() |
20370054e7 | ||
![]() |
f1882cb1e1 | ||
![]() |
2ed149852d | ||
![]() |
ac7226a0df | ||
![]() |
5705650ca8 | ||
![]() |
60855ca7c5 | ||
![]() |
b8d8d181f3 | ||
![]() |
6309160fc6 | ||
![]() |
fc0e6ed273 | ||
![]() |
ada0cee656 | ||
![]() |
6dde524d2c | ||
![]() |
6a631e1915 | ||
![]() |
bb6fa343cf | ||
![]() |
7557acde6c | ||
![]() |
25ed8952f9 | ||
![]() |
b93d94b0bd | ||
![]() |
33d75fd2fb | ||
![]() |
28a9855fd2 | ||
![]() |
9aad07621c | ||
![]() |
384cde6eaa | ||
![]() |
5ae98661ad | ||
![]() |
8f4d9ceca9 | ||
![]() |
83d9a1233e | ||
![]() |
522a287d79 | ||
![]() |
e052d4660d | ||
![]() |
39b0b2f032 | ||
![]() |
0223d6d200 | ||
![]() |
808ce72078 | ||
![]() |
3a84c47176 | ||
![]() |
20c2426128 | ||
![]() |
bf11d4c9fa | ||
![]() |
783c0f79d7 | ||
![]() |
98b94bd9c4 | ||
![]() |
ff0178f965 | ||
![]() |
7f88c3d0a9 | ||
![]() |
11e8e38f2c | ||
![]() |
50c5314eaf | ||
![]() |
a7a76d4f58 | ||
![]() |
4df4f68fe1 | ||
![]() |
7db8d37137 | ||
![]() |
b7503a7d81 | ||
![]() |
9f5d4034e3 | ||
![]() |
3c941f6c4b | ||
![]() |
ec8fff421a | ||
![]() |
a47a0b5432 | ||
![]() |
96ba46f21d | ||
![]() |
90f48d5817 | ||
![]() |
7288dd097a | ||
![]() |
0119d62a35 | ||
![]() |
4d6ab73fa9 | ||
![]() |
f58c95840a | ||
![]() |
ecf24f81ec | ||
![]() |
dd3306a940 | ||
![]() |
bbb2b98f27 | ||
![]() |
bc7332780d | ||
![]() |
6f3bc3ac8f | ||
![]() |
cd04d869b7 | ||
![]() |
909e15cbdd | ||
![]() |
33fa30ab78 | ||
![]() |
44933ac17a | ||
![]() |
bb2af96deb | ||
![]() |
1fe6da14ea | ||
![]() |
b7b9653c21 | ||
![]() |
8adc5918f8 | ||
![]() |
0db593b1bb | ||
![]() |
a0c9dbeb78 | ||
![]() |
61d5546d89 | ||
![]() |
f97b7c943b | ||
![]() |
97549b633b | ||
![]() |
1949e4a9d4 | ||
![]() |
ecb5f7a5ba | ||
![]() |
6021f72cf0 | ||
![]() |
c00ef74f96 | ||
![]() |
962e070150 | ||
![]() |
221cbf5e07 | ||
![]() |
a72d37ab69 | ||
![]() |
f92227e5df | ||
![]() |
c50617452f | ||
![]() |
3957eca94d | ||
![]() |
70111cf614 | ||
![]() |
f9e03c9a40 | ||
![]() |
88fbdf1cc4 | ||
![]() |
7b76bd79e8 | ||
![]() |
f4b58e649d | ||
![]() |
91ff301d53 | ||
![]() |
f5e1c99259 | ||
![]() |
abdcd3cc30 | ||
![]() |
23615a39ac | ||
![]() |
5fa5fc39fc | ||
![]() |
01b3c7e91b | ||
![]() |
e4e364af3f | ||
![]() |
f2358692af | ||
![]() |
26ed6299e3 | ||
![]() |
3a85187111 | ||
![]() |
4261a2eed3 | ||
![]() |
fef17163a9 | ||
![]() |
9dd447a14f | ||
![]() |
ecf4407ba4 | ||
![]() |
039c0d3ee6 | ||
![]() |
5808aead55 | ||
![]() |
e797e2e7f1 | ||
![]() |
23cacbfe65 | ||
![]() |
4f94ee9b72 | ||
![]() |
0d1a26298a | ||
![]() |
8ccd0b23e9 | ||
![]() |
9d8b991354 | ||
![]() |
d273f69852 | ||
![]() |
eee3ccafc3 | ||
![]() |
3686e90e81 | ||
![]() |
f5f8371865 | ||
![]() |
1191455d37 | ||
![]() |
1a5d9da2bf | ||
![]() |
011e151c91 | ||
![]() |
54aa40eac1 | ||
![]() |
21a7a73f6d | ||
![]() |
5090b41eef | ||
![]() |
0e55aa6249 | ||
![]() |
dd2dcf4df2 | ||
![]() |
2e84b28998 | ||
![]() |
e6cbfea5a7 | ||
![]() |
641d662944 | ||
![]() |
09208e183b | ||
![]() |
fba3ece688 | ||
![]() |
f7d849a3cc | ||
![]() |
709c700cc6 | ||
![]() |
2da411c1ec | ||
![]() |
d6e4f3c809 | ||
![]() |
1bb08db8ba | ||
![]() |
2ba116b1e6 | ||
![]() |
7088de0fb9 | ||
![]() |
7084f73d6c | ||
![]() |
69374e25fe | ||
![]() |
5e16969d61 | ||
![]() |
0fe5a44e5a | ||
![]() |
98e617001d | ||
![]() |
979bd09b29 | ||
![]() |
77678b8f31 | ||
![]() |
3575cac9d7 | ||
![]() |
8cdeaf1b27 | ||
![]() |
08a8c6c414 | ||
![]() |
fa5c1b22ae | ||
![]() |
a99e7f3288 | ||
![]() |
a29506ed2f | ||
![]() |
1434b40d03 | ||
![]() |
6d6609187b | ||
![]() |
9682eaae2a | ||
![]() |
1cdb4ccc17 | ||
![]() |
2a878dffbc | ||
![]() |
49f4fb7ed7 | ||
![]() |
caa985660a | ||
![]() |
3842a1e4fb | ||
![]() |
e06d83cb93 | ||
![]() |
67df894448 | ||
![]() |
d1ec6cf21b | ||
![]() |
537c561cee | ||
![]() |
a65ddc5b36 | ||
![]() |
1fb1b3a784 | ||
![]() |
b80879765c | ||
![]() |
10919fe15b | ||
![]() |
9e5fe1edca | ||
![]() |
03ee3f3d2a | ||
![]() |
4113283069 | ||
![]() |
56c5f696df | ||
![]() |
9beb76e641 | ||
![]() |
f71403be58 | ||
![]() |
d0e5d36b1b | ||
![]() |
fdeb7543ca | ||
![]() |
90716f4f5b | ||
![]() |
54d41bc288 | ||
![]() |
d63c7a9042 | ||
![]() |
cd5b60cbed | ||
![]() |
6d60e6698a | ||
![]() |
d53cb01396 | ||
![]() |
8baaecab1b | ||
![]() |
1368f9f89e | ||
![]() |
ce36f3ae3b | ||
![]() |
cf147aa161 | ||
![]() |
7700cff5e5 | ||
![]() |
b883f313ba | ||
![]() |
b1ee22cde6 | ||
![]() |
b32f149a1b | ||
![]() |
1d136c6c35 | ||
![]() |
b8a17580c5 | ||
![]() |
87febf8679 | ||
![]() |
38b2ffd450 | ||
![]() |
01e031e7e7 | ||
![]() |
0b1eda3050 | ||
![]() |
52cdf96dfe | ||
![]() |
1f5eba59c5 | ||
![]() |
372c2f2be0 | ||
![]() |
25e0b46396 | ||
![]() |
621a1909ec | ||
![]() |
d3332583b6 | ||
![]() |
cb5cf9bb09 | ||
![]() |
6cb2c2a84e | ||
![]() |
633137fd79 | ||
![]() |
9627fdf33f | ||
![]() |
b39366c80a | ||
![]() |
ac01c49666 | ||
![]() |
80d16ea407 | ||
![]() |
4f44f26333 | ||
![]() |
a21bdb1487 | ||
![]() |
4d6a2f40d3 | ||
![]() |
e6773aac0e | ||
![]() |
997381d0c3 | ||
![]() |
ac53eeb76d | ||
![]() |
a09c8934fc | ||
![]() |
b4120c39e6 | ||
![]() |
5d6320d925 | ||
![]() |
985bf50f7f | ||
![]() |
84d21af644 | ||
![]() |
267cd99b04 | ||
![]() |
401960079c | ||
![]() |
1fbc8a2850 | ||
![]() |
16fe5a94ac | ||
![]() |
1c20a4d9eb | ||
![]() |
3a9f30d954 | ||
![]() |
856aacf8ce | ||
![]() |
441b510775 | ||
![]() |
88a10b5af1 | ||
![]() |
65205ace95 | ||
![]() |
1a4ef06ee9 | ||
![]() |
64ac631040 | ||
![]() |
4e4cabb929 | ||
![]() |
b242c86869 | ||
![]() |
d37fee346a | ||
![]() |
cc52d3b0af | ||
![]() |
d5b1bae305 | ||
![]() |
04e22faf85 | ||
![]() |
48cb3ed138 | ||
![]() |
ebdeee8b3c | ||
![]() |
6449d7d4ee | ||
![]() |
4b775d15a2 | ||
![]() |
e4d6a453b0 | ||
![]() |
9dcbcd57cb | ||
![]() |
17aa44c88b | ||
![]() |
60dc266e13 | ||
![]() |
60ed308caa | ||
![]() |
c485e7e167 | ||
![]() |
71a8361580 | ||
![]() |
3d1cc348c8 | ||
![]() |
25db3c2940 | ||
![]() |
442290d7f0 | ||
![]() |
a6eb871f5e | ||
![]() |
b500c3f526 |
2
.github/CONTRIBUTING.md
vendored
2
.github/CONTRIBUTING.md
vendored
@@ -32,7 +32,7 @@ Do not report crashes in the GitHub issue tracker. NewPipe has an automated cras
|
|||||||
* Please test (compile and run) your code before you submit changes! Ideally, provide test feedback in the PR description. Untested code will **not** be merged!
|
* Please test (compile and run) your code before you submit changes! Ideally, provide test feedback in the PR description. Untested code will **not** be merged!
|
||||||
* Try to figure out yourself why builds on our CI fail.
|
* Try to figure out yourself why builds on our CI fail.
|
||||||
* Make sure your PR is up-to-date with the rest of the code. Often, a simple click on "Update branch" will do the job, but if not, you are asked to merge the master branch manually and resolve the problems on your own. That will make the maintainers' jobs way easier.
|
* Make sure your PR is up-to-date with the rest of the code. Often, a simple click on "Update branch" will do the job, but if not, you are asked to merge the master branch manually and resolve the problems on your own. That will make the maintainers' jobs way easier.
|
||||||
* Please show intention to maintain your features and code after you contributed it. Unmaintained code is a hassle for the core developers, and just adds work. If you do not intend to maintain features you contributed, please think again about sumission, or clearly state that in the description of your PR.
|
* Please show intention to maintain your features and code after you contributed it. Unmaintained code is a hassle for the core developers, and just adds work. If you do not intend to maintain features you contributed, please think again about submission, or clearly state that in the description of your PR.
|
||||||
* Respond yourselves if someone requests changes or otherwise raises issues about your PRs.
|
* Respond yourselves if someone requests changes or otherwise raises issues about your PRs.
|
||||||
* Check if your contributions align with the [fdroid inclusion guidelines](https://f-droid.org/en/docs/Inclusion_Policy/).
|
* Check if your contributions align with the [fdroid inclusion guidelines](https://f-droid.org/en/docs/Inclusion_Policy/).
|
||||||
* Check if your submission can be build with the current fdroid build server setup.
|
* Check if your submission can be build with the current fdroid build server setup.
|
||||||
|
2
.github/PULL_REQUEST_TEMPLATE.md
vendored
2
.github/PULL_REQUEST_TEMPLATE.md
vendored
@@ -1 +1 @@
|
|||||||
- [ ] I carefully reed the [contribution guidelines](https://github.com/TeamNewPipe/NewPipe/blob/HEAD/.github/CONTRIBUTING.md) and agree to them.
|
- [ ] I carefully read the [contribution guidelines](https://github.com/TeamNewPipe/NewPipe/blob/HEAD/.github/CONTRIBUTING.md) and agree to them.
|
||||||
|
1
.gitignore
vendored
1
.gitignore
vendored
@@ -10,3 +10,4 @@
|
|||||||
gradle.properties
|
gradle.properties
|
||||||
*~
|
*~
|
||||||
.weblate
|
.weblate
|
||||||
|
*.class
|
||||||
|
@@ -5,11 +5,13 @@ android:
|
|||||||
components:
|
components:
|
||||||
# The BuildTools version used by NewPipe
|
# The BuildTools version used by NewPipe
|
||||||
- tools
|
- tools
|
||||||
- build-tools-26.0.1
|
- build-tools-27.0.1
|
||||||
|
|
||||||
# The SDK version used to compile NewPipe
|
# The SDK version used to compile NewPipe
|
||||||
- android-26
|
- android-27
|
||||||
|
|
||||||
|
before_install:
|
||||||
|
- yes | sdkmanager "platforms;android-27"
|
||||||
script: ./gradlew -Dorg.gradle.jvmargs=-Xmx1536m assembleDebug lintDebug testDebugUnitTest
|
script: ./gradlew -Dorg.gradle.jvmargs=-Xmx1536m assembleDebug lintDebug testDebugUnitTest
|
||||||
|
|
||||||
licenses:
|
licenses:
|
||||||
|
170
CheckTranslations.java
Normal file
170
CheckTranslations.java
Normal file
@@ -0,0 +1,170 @@
|
|||||||
|
import java.io.BufferedReader;
|
||||||
|
import java.io.File;
|
||||||
|
import java.io.FileReader;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.util.regex.*;
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.nio.file.Files;
|
||||||
|
import java.nio.charset.Charset;
|
||||||
|
|
||||||
|
public final class CheckTranslations {
|
||||||
|
|
||||||
|
private static boolean debug = false;
|
||||||
|
private static boolean plurals = false;
|
||||||
|
private static boolean empty = false;
|
||||||
|
private static boolean remove = false;
|
||||||
|
private static int checks = 0;
|
||||||
|
private static int matches = 0;
|
||||||
|
private static int changes = 0;
|
||||||
|
private static Pattern p, pb, pe, e, o;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Search translated strings.xml files for empty item / plural tags
|
||||||
|
* and remove them.
|
||||||
|
* @param args directories which contain string.xml files (in any subdirectory)
|
||||||
|
* -e option to find all empty string tags
|
||||||
|
* -p option to find all empty plurals and item tags
|
||||||
|
* -r option to remove all occurrences from the files
|
||||||
|
* -d option to see more details
|
||||||
|
*/
|
||||||
|
public static void main(String[] args) {
|
||||||
|
if (args.length < 1 || (args[0].equals("-d") && args.length < 2)) {
|
||||||
|
System.out.println("Not enough arguments");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
for (int i = 0; i < args.length; i++) {
|
||||||
|
switch (args[i]) {
|
||||||
|
case "-d":
|
||||||
|
debug = true;
|
||||||
|
break;
|
||||||
|
case "-p":
|
||||||
|
plurals = true;
|
||||||
|
break;
|
||||||
|
case "-e":
|
||||||
|
empty = true;
|
||||||
|
break;
|
||||||
|
case "-r":
|
||||||
|
remove = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!plurals && !empty) {
|
||||||
|
plurals = true;
|
||||||
|
empty = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
p = Pattern.compile("(<item quantity=\")(zero|one|two|three|few|many|other)(\"></item>|\"/>)");
|
||||||
|
pb = Pattern.compile("(<plurals[\\sa-zA-Z=\"]*>)");
|
||||||
|
pe = Pattern.compile("(</plurals>)");
|
||||||
|
e = Pattern.compile("(<string[\\sa-z_\\\"=]*)((><\\/string>|\\/>){1})");
|
||||||
|
o = Pattern.compile("(<item quantity=\"other\">)[^</>]*(<\\/item>)");
|
||||||
|
|
||||||
|
for (int i = 0; i < args.length; i++) {
|
||||||
|
if (!args[i].equals("-d") && !args[i].equals("-p") && !args[i].equals("-e") && !args[i].equals("-r")) {
|
||||||
|
File f = new File(args[i]);
|
||||||
|
if (f.exists() && !f.isDirectory()) {
|
||||||
|
checkFile(f);
|
||||||
|
} else if (f.isDirectory()) {
|
||||||
|
checkFiles(f.listFiles());
|
||||||
|
} else {
|
||||||
|
System.out.println("'" + args[i] + "' does not exist!");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
System.out.println(checks + " files were checked.");
|
||||||
|
System.out.println(matches + " corrupt lines detected.");
|
||||||
|
if (remove) {
|
||||||
|
System.out.println(matches + " corrupt lines removed and " + changes + " lines fixed.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private static void checkFiles(File[] f) {
|
||||||
|
for (int i = 0; i < f.length; i++) {
|
||||||
|
if (f[i].exists() && !f[i].isDirectory()) {
|
||||||
|
if (f[i].toString().contains("strings.xml")) {
|
||||||
|
checkFile(f[i]);
|
||||||
|
}
|
||||||
|
} else if (f[i].isDirectory()) {
|
||||||
|
checkFiles(f[i].listFiles());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void checkFile(File f) {
|
||||||
|
// Do not check our original English strings to cause no unwanted changes
|
||||||
|
// Btw. there should not be empty plural/item tags
|
||||||
|
if (f.toString().contains("values/strings.xml")) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (debug) System.out.println("Checking " + f.toString());
|
||||||
|
checks++;
|
||||||
|
|
||||||
|
|
||||||
|
List<String> lines = new ArrayList<String>();
|
||||||
|
boolean checkFailed = false;
|
||||||
|
boolean otherDetected = false;
|
||||||
|
boolean inPlurals = false;
|
||||||
|
try (BufferedReader br = new BufferedReader(new FileReader(f))) {
|
||||||
|
String line;
|
||||||
|
int ln = 0;
|
||||||
|
while ((line = br.readLine()) != null) {
|
||||||
|
ln++;
|
||||||
|
if (plurals && p.matcher(line).find()) {
|
||||||
|
matches++;
|
||||||
|
if (debug) System.out.println(" Line " + ln + " was " + ((remove) ? "removed" : "detected") + ": '" + line + "'");
|
||||||
|
checkFailed = true;
|
||||||
|
} else if (empty && e.matcher(line).find()) {
|
||||||
|
matches++;
|
||||||
|
checkFailed = true;
|
||||||
|
if (debug) System.out.println(" Line " + ln + " was " + ((remove) ? "removed" : "detected") + ": '" + line + "'");
|
||||||
|
} else {
|
||||||
|
if (remove) lines.add(line);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
br.close();
|
||||||
|
int pluralsLine = 0;
|
||||||
|
for (int i = 0; i < lines.size(); i++) {
|
||||||
|
if (o.matcher(lines.get(i)).find()) {
|
||||||
|
otherDetected = true;
|
||||||
|
}
|
||||||
|
if (plurals && pb.matcher(lines.get(i)).find()) {
|
||||||
|
inPlurals = true;
|
||||||
|
pluralsLine = i;
|
||||||
|
} else if (plurals && pe.matcher(lines.get(i)).find()) {
|
||||||
|
inPlurals = false;
|
||||||
|
if (!otherDetected) {
|
||||||
|
boolean b = false;
|
||||||
|
check: for(int j = pluralsLine; j < i; j++) {
|
||||||
|
if (lines.get(j).contains("many")) {
|
||||||
|
b = true;
|
||||||
|
pluralsLine = j;
|
||||||
|
break check;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (remove && b) {
|
||||||
|
if (debug) System.out.println(" Line " + (pluralsLine + 1) + " was " + ((remove) ? "changed" : "detected") + ": '" + lines.get(pluralsLine) + "'");
|
||||||
|
lines.set(pluralsLine, lines.get(pluralsLine).replace("many", "other"));
|
||||||
|
changes++;
|
||||||
|
checkFailed = true;
|
||||||
|
} else if (debug) {
|
||||||
|
if (debug) System.out.println(" WARNING: Line " + (i + 1) + " - No <item quantity=\"other\"> found!");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
otherDetected = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
if (remove && checkFailed) {
|
||||||
|
Files.write(f.toPath(), lines, Charset.forName("UTF-8"));
|
||||||
|
}
|
||||||
|
} catch (IOException e) {
|
||||||
|
System.out.println(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
21
README.md
21
README.md
@@ -13,21 +13,22 @@
|
|||||||
</p>
|
</p>
|
||||||
<hr />
|
<hr />
|
||||||
<p align="center"><a href="#screenshots">Screenshots</a> • <a href="#description">Description</a> • <a href="#features">Features</a> • <a href="#contribution">Contribution</a> • <a href="#donate">Donate</a> • <a href="#license">License</a></p>
|
<p align="center"><a href="#screenshots">Screenshots</a> • <a href="#description">Description</a> • <a href="#features">Features</a> • <a href="#contribution">Contribution</a> • <a href="#donate">Donate</a> • <a href="#license">License</a></p>
|
||||||
|
<p align="center"><a href="https://newpipe.schabi.org">Website</a> • <a href="https://newpipe.schabi.org/blog/">Blog</a> • <a href="https://newpipe.schabi.org/press/">Press</a></p>
|
||||||
<hr />
|
<hr />
|
||||||
WARNING: PUTTING NEWPIPE OR ANY FORK OF IT INTO GOOGLE PLAYSTORE VIOLATES THEIR TERMS OF CONDITIONS.
|
WARNING: PUTTING NEWPIPE OR ANY FORK OF IT INTO GOOGLE PLAYSTORE VIOLATES THEIR TERMS OF CONDITIONS.
|
||||||
|
|
||||||
## Screenshots
|
## Screenshots
|
||||||
|
|
||||||
[<img src="screenshots/shot_1.png" width=160>](screenshots/shot_1.png)
|
[<img src="fastlane/metadata/android/en-US/images/phoneScreenshots/shot_1.png" width=160>](fastlane/metadata/android/en-US/images/phoneScreenshots/shot_1.png)
|
||||||
[<img src="screenshots/shot_2.png" width=160>](screenshots/shot_2.png)
|
[<img src="fastlane/metadata/android/en-US/images/phoneScreenshots/shot_2.png" width=160>](fastlane/metadata/android/en-US/images/phoneScreenshots/shot_2.png)
|
||||||
[<img src="screenshots/shot_3.png" width=160>](screenshots/shot_3.png)
|
[<img src="fastlane/metadata/android/en-US/images/phoneScreenshots/shot_3.png" width=160>](fastlane/metadata/android/en-US/images/phoneScreenshots/shot_3.png)
|
||||||
[<img src="screenshots/shot_4.png" width=160>](screenshots/shot_4.png)
|
[<img src="fastlane/metadata/android/en-US/images/phoneScreenshots/shot_4.png" width=160>](fastlane/metadata/android/en-US/images/phoneScreenshots/shot_4.png)
|
||||||
[<img src="screenshots/shot_5.png" width=160>](screenshots/shot_5.png)
|
[<img src="fastlane/metadata/android/en-US/images/phoneScreenshots/shot_5.png" width=160>](fastlane/metadata/android/en-US/images/phoneScreenshots/shot_5.png)
|
||||||
[<img src="screenshots/shot_6.png" width=160>](screenshots/shot_6.png)
|
[<img src="fastlane/metadata/android/en-US/images/phoneScreenshots/shot_6.png" width=160>](fastlane/metadata/android/en-US/images/phoneScreenshots/shot_6.png)
|
||||||
[<img src="screenshots/shot_7.png" width=160>](screenshots/shot_7.png)
|
[<img src="fastlane/metadata/android/en-US/images/phoneScreenshots/shot_7.png" width=160>](fastlane/metadata/android/en-US/images/phoneScreenshots/shot_7.png)
|
||||||
[<img src="screenshots/shot_8.png" width=160>](screenshots/shot_8.png)
|
[<img src="fastlane/metadata/android/en-US/images/phoneScreenshots/shot_8.png" width=160>](fastlane/metadata/android/en-US/images/phoneScreenshots/shot_8.png)
|
||||||
[<img src="screenshots/shot_9.png" width=160>](screenshots/shot_9.png)
|
[<img src="fastlane/metadata/android/en-US/images/phoneScreenshots/shot_9.png" width=160>](fastlane/metadata/android/en-US/images/phoneScreenshots/shot_9.png)
|
||||||
[<img src="screenshots/shot_10.png" width=160>](screenshots/shot_10.png)
|
[<img src="fastlane/metadata/android/en-US/images/phoneScreenshots/shot_10.png" width=160>](fastlane/metadata/android/en-US/images/phoneScreenshots/shot_10.png)
|
||||||
|
|
||||||
## Description
|
## Description
|
||||||
|
|
||||||
|
@@ -1,15 +1,15 @@
|
|||||||
apply plugin: 'com.android.application'
|
apply plugin: 'com.android.application'
|
||||||
|
|
||||||
android {
|
android {
|
||||||
compileSdkVersion 26
|
compileSdkVersion 27
|
||||||
buildToolsVersion '26.0.1'
|
buildToolsVersion '27.0.1'
|
||||||
|
|
||||||
defaultConfig {
|
defaultConfig {
|
||||||
applicationId "org.schabi.newpipe"
|
applicationId "org.schabi.newpipe"
|
||||||
minSdkVersion 15
|
minSdkVersion 15
|
||||||
targetSdkVersion 26
|
targetSdkVersion 27
|
||||||
versionCode 41
|
versionCode 47
|
||||||
versionName "0.11.0"
|
versionName "0.11.6"
|
||||||
|
|
||||||
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
|
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
|
||||||
vectorDrawables.useSupportLibrary = true
|
vectorDrawables.useSupportLibrary = true
|
||||||
@@ -27,6 +27,10 @@ android {
|
|||||||
applicationIdSuffix ".debug"
|
applicationIdSuffix ".debug"
|
||||||
}
|
}
|
||||||
beta {
|
beta {
|
||||||
|
minifyEnabled true
|
||||||
|
shrinkResources true
|
||||||
|
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
|
||||||
|
|
||||||
applicationIdSuffix ".beta"
|
applicationIdSuffix ".beta"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -38,48 +42,51 @@ android {
|
|||||||
abortOnError false
|
abortOnError false
|
||||||
}
|
}
|
||||||
compileOptions {
|
compileOptions {
|
||||||
sourceCompatibility JavaVersion.VERSION_1_7
|
sourceCompatibility JavaVersion.VERSION_1_8
|
||||||
targetCompatibility JavaVersion.VERSION_1_7
|
targetCompatibility JavaVersion.VERSION_1_8
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ext {
|
||||||
|
supportLibVersion = '27.0.2'
|
||||||
|
}
|
||||||
dependencies {
|
dependencies {
|
||||||
androidTestCompile('com.android.support.test.espresso:espresso-core:2.2.2') {
|
androidTestImplementation('com.android.support.test.espresso:espresso-core:2.2.2') {
|
||||||
exclude module: 'support-annotations'
|
exclude module: 'support-annotations'
|
||||||
}
|
}
|
||||||
|
|
||||||
compile 'com.github.TeamNewPipe:NewPipeExtractor:b9d0941'
|
implementation 'com.github.TeamNewPipe:NewPipeExtractor:7fd21ec08581d'
|
||||||
|
|
||||||
testCompile 'junit:junit:4.12'
|
testImplementation 'junit:junit:4.12'
|
||||||
testCompile 'org.mockito:mockito-core:1.10.19'
|
testImplementation 'org.mockito:mockito-core:1.10.19'
|
||||||
|
|
||||||
compile 'com.android.support:appcompat-v7:26.0.1'
|
implementation "com.android.support:appcompat-v7:$supportLibVersion"
|
||||||
compile 'com.android.support:support-v4:26.0.1'
|
implementation "com.android.support:support-v4:$supportLibVersion"
|
||||||
compile 'com.android.support:design:26.0.1'
|
implementation "com.android.support:design:$supportLibVersion"
|
||||||
compile 'com.android.support:recyclerview-v7:26.0.1'
|
implementation "com.android.support:recyclerview-v7:$supportLibVersion"
|
||||||
compile 'com.android.support:preference-v14:26.0.1'
|
implementation "com.android.support:preference-v14:$supportLibVersion"
|
||||||
|
|
||||||
compile 'com.google.code.gson:gson:2.7'
|
implementation 'com.google.code.gson:gson:2.8.2'
|
||||||
compile 'ch.acra:acra:4.9.0'
|
implementation 'ch.acra:acra:4.9.2'
|
||||||
|
|
||||||
compile 'com.nostra13.universalimageloader:universal-image-loader:1.9.5'
|
implementation 'com.nostra13.universalimageloader:universal-image-loader:1.9.5'
|
||||||
compile 'de.hdodenhof:circleimageview:2.1.0'
|
implementation 'de.hdodenhof:circleimageview:2.2.0'
|
||||||
compile 'com.github.nirhart:parallaxscroll:1.0'
|
implementation 'com.github.nirhart:ParallaxScroll:dd53d1f9d1'
|
||||||
compile 'com.nononsenseapps:filepicker:3.0.1'
|
implementation 'com.nononsenseapps:filepicker:3.0.1'
|
||||||
compile 'com.google.android.exoplayer:exoplayer:r2.5.4'
|
implementation 'com.google.android.exoplayer:exoplayer:r2.5.4'
|
||||||
|
|
||||||
debugCompile 'com.facebook.stetho:stetho:1.5.0'
|
debugImplementation 'com.facebook.stetho:stetho:1.5.0'
|
||||||
debugCompile 'com.facebook.stetho:stetho-urlconnection:1.5.0'
|
debugImplementation 'com.facebook.stetho:stetho-urlconnection:1.5.0'
|
||||||
debugCompile 'com.android.support:multidex:1.0.1'
|
debugImplementation 'com.android.support:multidex:1.0.2'
|
||||||
|
|
||||||
compile 'io.reactivex.rxjava2:rxjava:2.1.2'
|
implementation 'io.reactivex.rxjava2:rxjava:2.1.7'
|
||||||
compile 'io.reactivex.rxjava2:rxandroid:2.0.1'
|
implementation 'io.reactivex.rxjava2:rxandroid:2.0.1'
|
||||||
compile 'com.jakewharton.rxbinding2:rxbinding:2.0.0'
|
implementation 'com.jakewharton.rxbinding2:rxbinding:2.0.0'
|
||||||
|
|
||||||
compile 'android.arch.persistence.room:runtime:1.0.0-alpha8'
|
implementation 'android.arch.persistence.room:runtime:1.0.0'
|
||||||
compile 'android.arch.persistence.room:rxjava2:1.0.0-alpha8'
|
implementation 'android.arch.persistence.room:rxjava2:1.0.0'
|
||||||
annotationProcessor 'android.arch.persistence.room:compiler:1.0.0-alpha8'
|
annotationProcessor 'android.arch.persistence.room:compiler:1.0.0'
|
||||||
|
|
||||||
compile 'frankiesardo:icepick:3.2.0'
|
implementation 'frankiesardo:icepick:3.2.0'
|
||||||
provided 'frankiesardo:icepick-processor:3.2.0'
|
annotationProcessor 'frankiesardo:icepick-processor:3.2.0'
|
||||||
}
|
}
|
||||||
|
@@ -16,7 +16,7 @@
|
|||||||
android:icon="@mipmap/ic_launcher"
|
android:icon="@mipmap/ic_launcher"
|
||||||
android:label="@string/app_name"
|
android:label="@string/app_name"
|
||||||
android:logo="@mipmap/ic_launcher"
|
android:logo="@mipmap/ic_launcher"
|
||||||
android:theme="@style/DarkTheme"
|
android:theme="@style/OpeningTheme"
|
||||||
tools:ignore="AllowBackup">
|
tools:ignore="AllowBackup">
|
||||||
<activity
|
<activity
|
||||||
android:name=".MainActivity"
|
android:name=".MainActivity"
|
||||||
@@ -31,7 +31,7 @@
|
|||||||
<activity
|
<activity
|
||||||
android:name=".player.old.PlayVideoActivity"
|
android:name=".player.old.PlayVideoActivity"
|
||||||
android:configChanges="orientation|keyboardHidden|screenSize"
|
android:configChanges="orientation|keyboardHidden|screenSize"
|
||||||
android:theme="@style/VideoPlayerTheme"
|
android:theme="@style/OldVideoPlayerTheme"
|
||||||
tools:ignore="UnusedAttribute"/>
|
tools:ignore="UnusedAttribute"/>
|
||||||
|
|
||||||
<service
|
<service
|
||||||
@@ -56,8 +56,7 @@
|
|||||||
android:name=".player.MainVideoPlayer"
|
android:name=".player.MainVideoPlayer"
|
||||||
android:configChanges="keyboard|keyboardHidden|orientation|screenSize"
|
android:configChanges="keyboard|keyboardHidden|orientation|screenSize"
|
||||||
android:label="@string/app_name"
|
android:label="@string/app_name"
|
||||||
android:launchMode="singleTask"
|
android:launchMode="singleTask"/>
|
||||||
android:theme="@style/PlayerTheme"/>
|
|
||||||
|
|
||||||
<activity
|
<activity
|
||||||
android:name=".settings.SettingsActivity"
|
android:name=".settings.SettingsActivity"
|
||||||
@@ -124,7 +123,7 @@
|
|||||||
<activity
|
<activity
|
||||||
android:name=".RouterActivity"
|
android:name=".RouterActivity"
|
||||||
android:taskAffinity=""
|
android:taskAffinity=""
|
||||||
android:theme="@android:style/Theme.NoDisplay">
|
android:theme="@style/RouterActivityThemeDark">
|
||||||
<intent-filter>
|
<intent-filter>
|
||||||
<action android:name="android.intent.action.VIEW"/>
|
<action android:name="android.intent.action.VIEW"/>
|
||||||
<action android:name="android.media.action.MEDIA_PLAY_FROM_SEARCH"/>
|
<action android:name="android.media.action.MEDIA_PLAY_FROM_SEARCH"/>
|
||||||
@@ -175,17 +174,21 @@
|
|||||||
</intent-filter>
|
</intent-filter>
|
||||||
<intent-filter>
|
<intent-filter>
|
||||||
<action android:name="android.intent.action.SEND"/>
|
<action android:name="android.intent.action.SEND"/>
|
||||||
|
|
||||||
<category android:name="android.intent.category.DEFAULT"/>
|
<category android:name="android.intent.category.DEFAULT"/>
|
||||||
|
|
||||||
<data android:mimeType="text/plain"/>
|
<data android:mimeType="text/plain"/>
|
||||||
</intent-filter>
|
</intent-filter>
|
||||||
</activity>
|
</activity>
|
||||||
|
|
||||||
|
<service
|
||||||
|
android:name=".RouterPlayerActivity$FetcherService"
|
||||||
|
android:exported="false"/>
|
||||||
|
|
||||||
<activity
|
<activity
|
||||||
android:name=".RouterPopupActivity"
|
android:name=".RouterPlayerActivity"
|
||||||
android:label="@string/popup_mode_share_menu_title"
|
android:excludeFromRecents="true"
|
||||||
|
android:label="@string/preferred_player_share_menu_title"
|
||||||
android:taskAffinity=""
|
android:taskAffinity=""
|
||||||
android:theme="@android:style/Theme.NoDisplay">
|
android:theme="@style/RouterActivityThemeDark">
|
||||||
<intent-filter>
|
<intent-filter>
|
||||||
<action android:name="android.intent.action.VIEW"/>
|
<action android:name="android.intent.action.VIEW"/>
|
||||||
<action android:name="android.media.action.MEDIA_PLAY_FROM_SEARCH"/>
|
<action android:name="android.media.action.MEDIA_PLAY_FROM_SEARCH"/>
|
||||||
@@ -204,6 +207,11 @@
|
|||||||
<data android:pathPrefix="/embed/"/>
|
<data android:pathPrefix="/embed/"/>
|
||||||
<data android:pathPrefix="/watch"/>
|
<data android:pathPrefix="/watch"/>
|
||||||
<data android:pathPrefix="/attribution_link"/>
|
<data android:pathPrefix="/attribution_link"/>
|
||||||
|
<!-- channel prefix -->
|
||||||
|
<data android:pathPrefix="/channel/"/>
|
||||||
|
<data android:pathPrefix="/user/"/>
|
||||||
|
<!-- playlist prefix -->
|
||||||
|
<data android:pathPrefix="/playlist"/>
|
||||||
</intent-filter>
|
</intent-filter>
|
||||||
<intent-filter>
|
<intent-filter>
|
||||||
<action android:name="android.intent.action.VIEW"/>
|
<action android:name="android.intent.action.VIEW"/>
|
||||||
|
@@ -1,9 +1,12 @@
|
|||||||
package org.schabi.newpipe;
|
package org.schabi.newpipe;
|
||||||
|
|
||||||
|
import android.app.AlarmManager;
|
||||||
import android.app.Application;
|
import android.app.Application;
|
||||||
import android.app.NotificationChannel;
|
import android.app.NotificationChannel;
|
||||||
import android.app.NotificationManager;
|
import android.app.NotificationManager;
|
||||||
|
import android.app.PendingIntent;
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
|
import android.content.Intent;
|
||||||
import android.os.Build;
|
import android.os.Build;
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
|
|
||||||
@@ -116,7 +119,6 @@ public class App extends Application {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
private void initACRA() {
|
private void initACRA() {
|
||||||
try {
|
try {
|
||||||
final ACRAConfiguration acraConfig = new ConfigurationBuilder(this)
|
final ACRAConfiguration acraConfig = new ConfigurationBuilder(this)
|
||||||
@@ -149,4 +151,5 @@ public class App extends Application {
|
|||||||
NotificationManager mNotificationManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
|
NotificationManager mNotificationManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
|
||||||
mNotificationManager.createNotificationChannel(mChannel);
|
mNotificationManager.createNotificationChannel(mChannel);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@@ -77,17 +77,6 @@ public abstract class BaseFragment extends Fragment {
|
|||||||
protected void initListeners() {
|
protected void initListeners() {
|
||||||
}
|
}
|
||||||
|
|
||||||
/*//////////////////////////////////////////////////////////////////////////
|
|
||||||
// Utils
|
|
||||||
//////////////////////////////////////////////////////////////////////////*/
|
|
||||||
|
|
||||||
protected final int resolveResourceIdFromAttr(@AttrRes int attr) {
|
|
||||||
TypedArray a = activity.getTheme().obtainStyledAttributes(new int[]{attr});
|
|
||||||
int attributeResourceId = a.getResourceId(0, 0);
|
|
||||||
a.recycle();
|
|
||||||
return attributeResourceId;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*//////////////////////////////////////////////////////////////////////////
|
/*//////////////////////////////////////////////////////////////////////////
|
||||||
// DisplayImageOptions default configurations
|
// DisplayImageOptions default configurations
|
||||||
//////////////////////////////////////////////////////////////////////////*/
|
//////////////////////////////////////////////////////////////////////////*/
|
||||||
|
@@ -28,8 +28,12 @@ import android.os.Looper;
|
|||||||
import android.preference.PreferenceManager;
|
import android.preference.PreferenceManager;
|
||||||
import android.support.annotation.NonNull;
|
import android.support.annotation.NonNull;
|
||||||
import android.support.annotation.Nullable;
|
import android.support.annotation.Nullable;
|
||||||
|
import android.support.design.widget.NavigationView;
|
||||||
import android.support.v4.app.Fragment;
|
import android.support.v4.app.Fragment;
|
||||||
|
import android.support.v4.view.GravityCompat;
|
||||||
|
import android.support.v4.widget.DrawerLayout;
|
||||||
import android.support.v7.app.ActionBar;
|
import android.support.v7.app.ActionBar;
|
||||||
|
import android.support.v7.app.ActionBarDrawerToggle;
|
||||||
import android.support.v7.app.AppCompatActivity;
|
import android.support.v7.app.AppCompatActivity;
|
||||||
import android.support.v7.widget.Toolbar;
|
import android.support.v7.widget.Toolbar;
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
@@ -50,11 +54,13 @@ import org.schabi.newpipe.extractor.stream.AudioStream;
|
|||||||
import org.schabi.newpipe.extractor.stream.StreamInfo;
|
import org.schabi.newpipe.extractor.stream.StreamInfo;
|
||||||
import org.schabi.newpipe.extractor.stream.VideoStream;
|
import org.schabi.newpipe.extractor.stream.VideoStream;
|
||||||
import org.schabi.newpipe.fragments.BackPressable;
|
import org.schabi.newpipe.fragments.BackPressable;
|
||||||
|
import org.schabi.newpipe.fragments.MainFragment;
|
||||||
import org.schabi.newpipe.fragments.detail.VideoDetailFragment;
|
import org.schabi.newpipe.fragments.detail.VideoDetailFragment;
|
||||||
import org.schabi.newpipe.fragments.list.search.SearchFragment;
|
import org.schabi.newpipe.fragments.list.search.SearchFragment;
|
||||||
import org.schabi.newpipe.history.HistoryListener;
|
import org.schabi.newpipe.history.HistoryListener;
|
||||||
import org.schabi.newpipe.util.Constants;
|
import org.schabi.newpipe.util.Constants;
|
||||||
import org.schabi.newpipe.util.NavigationHelper;
|
import org.schabi.newpipe.util.NavigationHelper;
|
||||||
|
import org.schabi.newpipe.util.ServiceHelper;
|
||||||
import org.schabi.newpipe.util.StateSaver;
|
import org.schabi.newpipe.util.StateSaver;
|
||||||
import org.schabi.newpipe.util.ThemeHelper;
|
import org.schabi.newpipe.util.ThemeHelper;
|
||||||
|
|
||||||
@@ -67,8 +73,10 @@ import io.reactivex.subjects.PublishSubject;
|
|||||||
|
|
||||||
public class MainActivity extends AppCompatActivity implements HistoryListener {
|
public class MainActivity extends AppCompatActivity implements HistoryListener {
|
||||||
private static final String TAG = "MainActivity";
|
private static final String TAG = "MainActivity";
|
||||||
public static final boolean DEBUG = false;
|
public static final boolean DEBUG = !BuildConfig.BUILD_TYPE.equals("release");
|
||||||
|
|
||||||
private SharedPreferences sharedPreferences;
|
private SharedPreferences sharedPreferences;
|
||||||
|
private ActionBarDrawerToggle toggle = null;
|
||||||
|
|
||||||
/*//////////////////////////////////////////////////////////////////////////
|
/*//////////////////////////////////////////////////////////////////////////
|
||||||
// Activity's LifeCycle
|
// Activity's LifeCycle
|
||||||
@@ -77,7 +85,10 @@ public class MainActivity extends AppCompatActivity implements HistoryListener {
|
|||||||
@Override
|
@Override
|
||||||
protected void onCreate(Bundle savedInstanceState) {
|
protected void onCreate(Bundle savedInstanceState) {
|
||||||
if (DEBUG) Log.d(TAG, "onCreate() called with: savedInstanceState = [" + savedInstanceState + "]");
|
if (DEBUG) Log.d(TAG, "onCreate() called with: savedInstanceState = [" + savedInstanceState + "]");
|
||||||
ThemeHelper.setTheme(this);
|
|
||||||
|
sharedPreferences = PreferenceManager.getDefaultSharedPreferences(this);
|
||||||
|
ThemeHelper.setTheme(this, ServiceHelper.getSelectedServiceId(this));
|
||||||
|
|
||||||
super.onCreate(savedInstanceState);
|
super.onCreate(savedInstanceState);
|
||||||
setContentView(R.layout.activity_main);
|
setContentView(R.layout.activity_main);
|
||||||
|
|
||||||
@@ -85,13 +96,53 @@ public class MainActivity extends AppCompatActivity implements HistoryListener {
|
|||||||
initFragments();
|
initFragments();
|
||||||
}
|
}
|
||||||
|
|
||||||
Toolbar toolbar = findViewById(R.id.toolbar);
|
setSupportActionBar(findViewById(R.id.toolbar));
|
||||||
setSupportActionBar(toolbar);
|
setupDrawer();
|
||||||
sharedPreferences = PreferenceManager.getDefaultSharedPreferences(this);
|
|
||||||
|
|
||||||
initHistory();
|
initHistory();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void setupDrawer() {
|
||||||
|
final Toolbar toolbar = findViewById(R.id.toolbar);
|
||||||
|
final DrawerLayout drawer = findViewById(R.id.drawer_layout);
|
||||||
|
final NavigationView drawerItems = findViewById(R.id.navigation);
|
||||||
|
|
||||||
|
//drawerItems.setItemIconTintList(null); // Set null to use the original icon
|
||||||
|
drawerItems.getMenu().getItem(ServiceHelper.getSelectedServiceId(this)).setChecked(true);
|
||||||
|
|
||||||
|
if (!BuildConfig.BUILD_TYPE.equals("release")) {
|
||||||
|
toggle = new ActionBarDrawerToggle(this, drawer, toolbar, R.string.drawer_open, R.string.drawer_close);
|
||||||
|
toggle.syncState();
|
||||||
|
drawer.addDrawerListener(toggle);
|
||||||
|
drawer.addDrawerListener(new DrawerLayout.SimpleDrawerListener() {
|
||||||
|
private int lastService;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onDrawerOpened(View drawerView) {
|
||||||
|
lastService = ServiceHelper.getSelectedServiceId(MainActivity.this);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onDrawerClosed(View drawerView) {
|
||||||
|
if (lastService != ServiceHelper.getSelectedServiceId(MainActivity.this)) {
|
||||||
|
new Handler(Looper.getMainLooper()).post(MainActivity.this::recreate);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
drawerItems.setNavigationItemSelectedListener(item -> {
|
||||||
|
if (item.getGroupId() == R.id.menu_services_group) {
|
||||||
|
drawerItems.getMenu().getItem(ServiceHelper.getSelectedServiceId(this)).setChecked(false);
|
||||||
|
ServiceHelper.setSelectedServiceId(this, item.getTitle().toString());
|
||||||
|
drawerItems.getMenu().getItem(ServiceHelper.getSelectedServiceId(this)).setChecked(true);
|
||||||
|
}
|
||||||
|
drawer.closeDrawers();
|
||||||
|
return true;
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
drawer.setDrawerLockMode(DrawerLayout.LOCK_MODE_LOCKED_CLOSED);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void onDestroy() {
|
protected void onDestroy() {
|
||||||
super.onDestroy();
|
super.onDestroy();
|
||||||
@@ -112,20 +163,14 @@ public class MainActivity extends AppCompatActivity implements HistoryListener {
|
|||||||
sharedPreferences.edit().putBoolean(Constants.KEY_THEME_CHANGE, false).apply();
|
sharedPreferences.edit().putBoolean(Constants.KEY_THEME_CHANGE, false).apply();
|
||||||
// https://stackoverflow.com/questions/10844112/runtimeexception-performing-pause-of-activity-that-is-not-resumed
|
// https://stackoverflow.com/questions/10844112/runtimeexception-performing-pause-of-activity-that-is-not-resumed
|
||||||
// Briefly, let the activity resume properly posting the recreate call to end of the message queue
|
// Briefly, let the activity resume properly posting the recreate call to end of the message queue
|
||||||
new Handler(Looper.getMainLooper()).post(new Runnable() {
|
new Handler(Looper.getMainLooper()).post(MainActivity.this::recreate);
|
||||||
@Override
|
|
||||||
public void run() {
|
|
||||||
MainActivity.this.recreate();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if(sharedPreferences.getBoolean(Constants.KEY_MAIN_PAGE_CHANGE, false)) {
|
if (sharedPreferences.getBoolean(Constants.KEY_MAIN_PAGE_CHANGE, false)) {
|
||||||
if (DEBUG) Log.d(TAG, "main page has changed, recreating main fragment...");
|
if (DEBUG) Log.d(TAG, "main page has changed, recreating main fragment...");
|
||||||
sharedPreferences.edit().putBoolean(Constants.KEY_MAIN_PAGE_CHANGE, false).apply();
|
sharedPreferences.edit().putBoolean(Constants.KEY_MAIN_PAGE_CHANGE, false).apply();
|
||||||
NavigationHelper.openMainActivity(this);
|
NavigationHelper.openMainActivity(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -159,6 +204,38 @@ public class MainActivity extends AppCompatActivity implements HistoryListener {
|
|||||||
} else super.onBackPressed();
|
} else super.onBackPressed();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Implement the following diagram behavior for the up button:
|
||||||
|
* <pre>
|
||||||
|
* +---------------+
|
||||||
|
* | Main Screen +----+
|
||||||
|
* +-------+-------+ |
|
||||||
|
* | |
|
||||||
|
* ▲ Up | Search Button
|
||||||
|
* | |
|
||||||
|
* +----+-----+ |
|
||||||
|
* +------------+ Search |◄-----+
|
||||||
|
* | +----+-----+
|
||||||
|
* | Open |
|
||||||
|
* | something ▲ Up
|
||||||
|
* | |
|
||||||
|
* | +------------+-------------+
|
||||||
|
* | | |
|
||||||
|
* | | Video <-> Channel |
|
||||||
|
* +---►| Channel <-> Playlist |
|
||||||
|
* | Video <-> .... |
|
||||||
|
* | |
|
||||||
|
* +--------------------------+
|
||||||
|
* </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());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/*//////////////////////////////////////////////////////////////////////////
|
/*//////////////////////////////////////////////////////////////////////////
|
||||||
// Menu
|
// Menu
|
||||||
//////////////////////////////////////////////////////////////////////////*/
|
//////////////////////////////////////////////////////////////////////////*/
|
||||||
@@ -184,6 +261,9 @@ public class MainActivity extends AppCompatActivity implements HistoryListener {
|
|||||||
if (actionBar != null) {
|
if (actionBar != null) {
|
||||||
actionBar.setDisplayHomeAsUpEnabled(false);
|
actionBar.setDisplayHomeAsUpEnabled(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
updateDrawerNavigation();
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -194,7 +274,7 @@ public class MainActivity extends AppCompatActivity implements HistoryListener {
|
|||||||
|
|
||||||
switch (id) {
|
switch (id) {
|
||||||
case android.R.id.home:
|
case android.R.id.home:
|
||||||
NavigationHelper.gotoMainFragment(getSupportFragmentManager());
|
onHomeButtonPressed();
|
||||||
return true;
|
return true;
|
||||||
case R.id.action_settings:
|
case R.id.action_settings:
|
||||||
NavigationHelper.openSettings(this);
|
NavigationHelper.openSettings(this);
|
||||||
@@ -228,6 +308,27 @@ public class MainActivity extends AppCompatActivity implements HistoryListener {
|
|||||||
// Utils
|
// Utils
|
||||||
//////////////////////////////////////////////////////////////////////////*/
|
//////////////////////////////////////////////////////////////////////////*/
|
||||||
|
|
||||||
|
private void updateDrawerNavigation() {
|
||||||
|
if (getSupportActionBar() == null) return;
|
||||||
|
|
||||||
|
final Toolbar toolbar = findViewById(R.id.toolbar);
|
||||||
|
final DrawerLayout drawer = findViewById(R.id.drawer_layout);
|
||||||
|
|
||||||
|
final Fragment fragment = getSupportFragmentManager().findFragmentById(R.id.fragment_holder);
|
||||||
|
if (fragment instanceof MainFragment) {
|
||||||
|
getSupportActionBar().setDisplayHomeAsUpEnabled(false);
|
||||||
|
if (toggle != null) {
|
||||||
|
toggle.syncState();
|
||||||
|
toolbar.setNavigationOnClickListener(v -> drawer.openDrawer(GravityCompat.START));
|
||||||
|
drawer.setDrawerLockMode(DrawerLayout.LOCK_MODE_UNDEFINED);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
drawer.setDrawerLockMode(DrawerLayout.LOCK_MODE_LOCKED_CLOSED);
|
||||||
|
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
|
||||||
|
toolbar.setNavigationOnClickListener(v -> onHomeButtonPressed());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private void handleIntent(Intent intent) {
|
private void handleIntent(Intent intent) {
|
||||||
if (DEBUG) Log.d(TAG, "handleIntent() called with: intent = [" + intent + "]");
|
if (DEBUG) Log.d(TAG, "handleIntent() called with: intent = [" + intent + "]");
|
||||||
|
|
||||||
|
@@ -3,14 +3,25 @@ package org.schabi.newpipe;
|
|||||||
import android.content.Intent;
|
import android.content.Intent;
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
import android.support.v7.app.AppCompatActivity;
|
import android.support.v7.app.AppCompatActivity;
|
||||||
|
import android.text.TextUtils;
|
||||||
import android.widget.Toast;
|
import android.widget.Toast;
|
||||||
|
|
||||||
|
import org.schabi.newpipe.extractor.exceptions.ExtractionException;
|
||||||
|
import org.schabi.newpipe.report.UserAction;
|
||||||
|
import org.schabi.newpipe.util.ExtractorHelper;
|
||||||
import org.schabi.newpipe.util.NavigationHelper;
|
import org.schabi.newpipe.util.NavigationHelper;
|
||||||
|
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
import java.util.HashSet;
|
import java.util.HashSet;
|
||||||
|
|
||||||
/**
|
import icepick.Icepick;
|
||||||
|
import icepick.State;
|
||||||
|
import io.reactivex.Observable;
|
||||||
|
import io.reactivex.android.schedulers.AndroidSchedulers;
|
||||||
|
import io.reactivex.disposables.CompositeDisposable;
|
||||||
|
import io.reactivex.schedulers.Schedulers;
|
||||||
|
|
||||||
|
/*
|
||||||
* Copyright (C) Christian Schabesberger 2017 <chris.schabesberger@mailbox.org>
|
* Copyright (C) Christian Schabesberger 2017 <chris.schabesberger@mailbox.org>
|
||||||
* RouterActivity.java is part of NewPipe.
|
* RouterActivity.java is part of NewPipe.
|
||||||
*
|
*
|
||||||
@@ -34,23 +45,71 @@ import java.util.HashSet;
|
|||||||
*/
|
*/
|
||||||
public class RouterActivity extends AppCompatActivity {
|
public class RouterActivity extends AppCompatActivity {
|
||||||
|
|
||||||
|
@State
|
||||||
|
protected String currentUrl;
|
||||||
|
protected CompositeDisposable disposables = new CompositeDisposable();
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void onCreate(Bundle savedInstanceState) {
|
protected void onCreate(Bundle savedInstanceState) {
|
||||||
super.onCreate(savedInstanceState);
|
super.onCreate(savedInstanceState);
|
||||||
|
Icepick.restoreInstanceState(this, savedInstanceState);
|
||||||
|
|
||||||
String videoUrl = getUrl(getIntent());
|
if (TextUtils.isEmpty(currentUrl)) {
|
||||||
handleUrl(videoUrl);
|
currentUrl = getUrl(getIntent());
|
||||||
|
|
||||||
|
if (TextUtils.isEmpty(currentUrl)) {
|
||||||
|
Toast.makeText(this, R.string.invalid_url_toast, Toast.LENGTH_LONG).show();
|
||||||
|
finish();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void onSaveInstanceState(Bundle outState) {
|
||||||
|
super.onSaveInstanceState(outState);
|
||||||
|
Icepick.saveInstanceState(this, outState);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void onStart() {
|
||||||
|
super.onStart();
|
||||||
|
handleUrl(currentUrl);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void handleUrl(String url) {
|
protected void handleUrl(String url) {
|
||||||
boolean success = NavigationHelper.openByLink(this, url);
|
disposables.add(Observable
|
||||||
if (!success) {
|
.fromCallable(() -> NavigationHelper.getIntentByLink(this, url))
|
||||||
|
.subscribeOn(Schedulers.io())
|
||||||
|
.observeOn(AndroidSchedulers.mainThread())
|
||||||
|
.subscribe(intent -> {
|
||||||
|
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
|
||||||
|
intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK);
|
||||||
|
startActivity(intent);
|
||||||
|
|
||||||
|
finish();
|
||||||
|
}, this::handleError)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void handleError(Throwable error) {
|
||||||
|
error.printStackTrace();
|
||||||
|
|
||||||
|
if (error instanceof ExtractionException) {
|
||||||
Toast.makeText(this, R.string.url_not_supported_toast, Toast.LENGTH_LONG).show();
|
Toast.makeText(this, R.string.url_not_supported_toast, Toast.LENGTH_LONG).show();
|
||||||
|
} else {
|
||||||
|
ExtractorHelper.handleGeneralException(this, -1, null, error, UserAction.SOMETHING_ELSE, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
finish();
|
finish();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void onDestroy() {
|
||||||
|
super.onDestroy();
|
||||||
|
|
||||||
|
disposables.clear();
|
||||||
|
}
|
||||||
|
|
||||||
/*//////////////////////////////////////////////////////////////////////////
|
/*//////////////////////////////////////////////////////////////////////////
|
||||||
// Utils
|
// Utils
|
||||||
//////////////////////////////////////////////////////////////////////////*/
|
//////////////////////////////////////////////////////////////////////////*/
|
||||||
@@ -71,7 +130,8 @@ public class RouterActivity extends AppCompatActivity {
|
|||||||
} else if (intent.getStringExtra(Intent.EXTRA_TEXT) != null) {
|
} else if (intent.getStringExtra(Intent.EXTRA_TEXT) != null) {
|
||||||
//this means that vidoe was called through share menu
|
//this means that vidoe was called through share menu
|
||||||
String extraText = intent.getStringExtra(Intent.EXTRA_TEXT);
|
String extraText = intent.getStringExtra(Intent.EXTRA_TEXT);
|
||||||
videoUrl = getUris(extraText)[0];
|
final String[] uris = getUris(extraText);
|
||||||
|
videoUrl = uris.length > 0 ? uris[0] : null;
|
||||||
}
|
}
|
||||||
|
|
||||||
return videoUrl;
|
return videoUrl;
|
||||||
|
413
app/src/main/java/org/schabi/newpipe/RouterPlayerActivity.java
Normal file
413
app/src/main/java/org/schabi/newpipe/RouterPlayerActivity.java
Normal file
File diff suppressed because it is too large
Load Diff
@@ -1,49 +0,0 @@
|
|||||||
package org.schabi.newpipe;
|
|
||||||
|
|
||||||
import android.content.Intent;
|
|
||||||
import android.os.Build;
|
|
||||||
import android.widget.Toast;
|
|
||||||
|
|
||||||
import org.schabi.newpipe.extractor.NewPipe;
|
|
||||||
import org.schabi.newpipe.extractor.StreamingService;
|
|
||||||
import org.schabi.newpipe.extractor.exceptions.ExtractionException;
|
|
||||||
import org.schabi.newpipe.player.PopupVideoPlayer;
|
|
||||||
import org.schabi.newpipe.util.Constants;
|
|
||||||
import org.schabi.newpipe.util.PermissionHelper;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get the url from the intent and open a popup player
|
|
||||||
*/
|
|
||||||
public class RouterPopupActivity extends RouterActivity {
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void handleUrl(String url) {
|
|
||||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M
|
|
||||||
&& !PermissionHelper.checkSystemAlertWindowPermission(this)) {
|
|
||||||
Toast.makeText(this, R.string.msg_popup_permission, Toast.LENGTH_LONG).show();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
StreamingService service;
|
|
||||||
try {
|
|
||||||
service = NewPipe.getServiceByUrl(url);
|
|
||||||
} catch (ExtractionException e) {
|
|
||||||
Toast.makeText(this, R.string.url_not_supported_toast, Toast.LENGTH_LONG).show();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
Intent callIntent = new Intent(this, PopupVideoPlayer.class);
|
|
||||||
switch (service.getLinkTypeByUrl(url)) {
|
|
||||||
case STREAM:
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
Toast.makeText(this, R.string.url_not_supported_toast, Toast.LENGTH_LONG).show();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
callIntent.putExtra(Constants.KEY_URL, url);
|
|
||||||
callIntent.putExtra(Constants.KEY_SERVICE_ID, service.getServiceId());
|
|
||||||
startService(callIntent);
|
|
||||||
|
|
||||||
finish();
|
|
||||||
}
|
|
||||||
}
|
|
@@ -135,8 +135,12 @@ public class AboutActivity extends AppCompatActivity {
|
|||||||
View githubLink = rootView.findViewById(R.id.github_link);
|
View githubLink = rootView.findViewById(R.id.github_link);
|
||||||
githubLink.setOnClickListener(new OnGithubLinkClickListener());
|
githubLink.setOnClickListener(new OnGithubLinkClickListener());
|
||||||
|
|
||||||
View licenseLink = rootView.findViewById(R.id.app_read_license);
|
View donationLink = rootView.findViewById(R.id.donation_link);
|
||||||
licenseLink.setOnClickListener(new OnReadFullLicenseClickListener());
|
donationLink.setOnClickListener(new OnDonationLinkClickListener());
|
||||||
|
|
||||||
|
View websiteLink = rootView.findViewById(R.id.website_link);
|
||||||
|
websiteLink.setOnClickListener(new OnWebsiteLinkClickListener());
|
||||||
|
|
||||||
return rootView;
|
return rootView;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -149,10 +153,21 @@ public class AboutActivity extends AppCompatActivity {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static class OnReadFullLicenseClickListener implements View.OnClickListener {
|
private static class OnDonationLinkClickListener implements View.OnClickListener {
|
||||||
@Override
|
@Override
|
||||||
public void onClick(View v) {
|
public void onClick(final View view) {
|
||||||
LicenseFragment.showLicense(v.getContext(), StandardLicenses.GPL3);
|
final Context context = view.getContext();
|
||||||
|
Intent intent = new Intent(Intent.ACTION_VIEW, Uri.parse(context.getString(R.string.donation_url)));
|
||||||
|
context.startActivity(intent);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static class OnWebsiteLinkClickListener implements View.OnClickListener {
|
||||||
|
@Override
|
||||||
|
public void onClick(final View view) {
|
||||||
|
final Context context = view.getContext();
|
||||||
|
Intent intent = new Intent(Intent.ACTION_VIEW, Uri.parse(context.getString(R.string.website_url)));
|
||||||
|
context.startActivity(intent);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -62,6 +62,9 @@ public class LicenseFragment extends Fragment {
|
|||||||
View rootView = inflater.inflate(R.layout.fragment_licenses, container, false);
|
View rootView = inflater.inflate(R.layout.fragment_licenses, container, false);
|
||||||
ViewGroup softwareComponentsView = rootView.findViewById(R.id.software_components);
|
ViewGroup softwareComponentsView = rootView.findViewById(R.id.software_components);
|
||||||
|
|
||||||
|
View licenseLink = rootView.findViewById(R.id.app_read_license);
|
||||||
|
licenseLink.setOnClickListener(new OnReadFullLicenseClickListener());
|
||||||
|
|
||||||
for (final SoftwareComponent component : softwareComponents) {
|
for (final SoftwareComponent component : softwareComponents) {
|
||||||
View componentView = inflater.inflate(R.layout.item_software_component, container, false);
|
View componentView = inflater.inflate(R.layout.item_software_component, container, false);
|
||||||
TextView softwareName = componentView.findViewById(R.id.name);
|
TextView softwareName = componentView.findViewById(R.id.name);
|
||||||
@@ -119,4 +122,11 @@ public class LicenseFragment extends Fragment {
|
|||||||
Intent browserIntent = new Intent(Intent.ACTION_VIEW, Uri.parse(componentLink));
|
Intent browserIntent = new Intent(Intent.ACTION_VIEW, Uri.parse(componentLink));
|
||||||
startActivity(browserIntent);
|
startActivity(browserIntent);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static class OnReadFullLicenseClickListener implements View.OnClickListener {
|
||||||
|
@Override
|
||||||
|
public void onClick(View v) {
|
||||||
|
LicenseFragment.showLicense(v.getContext(), StandardLicenses.GPL3);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@@ -48,7 +48,7 @@ public class WatchHistoryEntry extends HistoryEntry {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public WatchHistoryEntry(StreamInfo streamInfo) {
|
public WatchHistoryEntry(StreamInfo streamInfo) {
|
||||||
this(new Date(), streamInfo.service_id, streamInfo.name, streamInfo.url,
|
this(new Date(), streamInfo.getServiceId(), streamInfo.getName(), streamInfo.getUrl(),
|
||||||
streamInfo.id, streamInfo.thumbnail_url, streamInfo.uploader_name, streamInfo.duration);
|
streamInfo.id, streamInfo.thumbnail_url, streamInfo.uploader_name, streamInfo.duration);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -116,10 +116,7 @@ public class SubscriptionEntity {
|
|||||||
|
|
||||||
@Ignore
|
@Ignore
|
||||||
public ChannelInfoItem toChannelInfoItem() {
|
public ChannelInfoItem toChannelInfoItem() {
|
||||||
ChannelInfoItem item = new ChannelInfoItem();
|
ChannelInfoItem item = new ChannelInfoItem(getServiceId(), getUrl(), getName());
|
||||||
item.url = getUrl();
|
|
||||||
item.service_id = getServiceId();
|
|
||||||
item.name = getName();
|
|
||||||
item.thumbnail_url = getAvatarUrl();
|
item.thumbnail_url = getAvatarUrl();
|
||||||
item.subscriber_count = getSubscriberCount();
|
item.subscriber_count = getSubscriberCount();
|
||||||
item.description = getDescription();
|
item.description = getDescription();
|
||||||
|
@@ -108,8 +108,8 @@ public class DownloadDialog extends DialogFragment implements RadioGroup.OnCheck
|
|||||||
public void onViewCreated(View view, @Nullable Bundle savedInstanceState) {
|
public void onViewCreated(View view, @Nullable Bundle savedInstanceState) {
|
||||||
super.onViewCreated(view, savedInstanceState);
|
super.onViewCreated(view, savedInstanceState);
|
||||||
nameEditText = view.findViewById(R.id.file_name);
|
nameEditText = view.findViewById(R.id.file_name);
|
||||||
nameEditText.setText(FilenameUtils.createFilename(getContext(), currentInfo.name));
|
nameEditText.setText(FilenameUtils.createFilename(getContext(), currentInfo.getName()));
|
||||||
selectedAudioIndex = ListHelper.getDefaultAudioFormat(getContext(), currentInfo.audio_streams);
|
selectedAudioIndex = ListHelper.getDefaultAudioFormat(getContext(), currentInfo.getAudioStreams());
|
||||||
|
|
||||||
streamsSpinner = view.findViewById(R.id.quality_spinner);
|
streamsSpinner = view.findViewById(R.id.quality_spinner);
|
||||||
streamsSpinner.setOnItemSelectedListener(this);
|
streamsSpinner.setOnItemSelectedListener(this);
|
||||||
@@ -183,7 +183,7 @@ public class DownloadDialog extends DialogFragment implements RadioGroup.OnCheck
|
|||||||
String[] items = new String[audioStreams.size()];
|
String[] items = new String[audioStreams.size()];
|
||||||
for (int i = 0; i < audioStreams.size(); i++) {
|
for (int i = 0; i < audioStreams.size(); i++) {
|
||||||
AudioStream audioStream = audioStreams.get(i);
|
AudioStream audioStream = audioStreams.get(i);
|
||||||
items[i] = MediaFormat.getNameById(audioStream.format) + " " + audioStream.average_bitrate + "kbps";
|
items[i] = audioStream.getFormat().getName() + " " + audioStream.getAverageBitrate() + "kbps";
|
||||||
}
|
}
|
||||||
|
|
||||||
ArrayAdapter<String> itemAdapter = new ArrayAdapter<>(getContext(), android.R.layout.simple_spinner_dropdown_item, items);
|
ArrayAdapter<String> itemAdapter = new ArrayAdapter<>(getContext(), android.R.layout.simple_spinner_dropdown_item, items);
|
||||||
@@ -242,7 +242,7 @@ public class DownloadDialog extends DialogFragment implements RadioGroup.OnCheck
|
|||||||
RadioButton audioButton = view.findViewById(R.id.audio_button);
|
RadioButton audioButton = view.findViewById(R.id.audio_button);
|
||||||
RadioButton videoButton = view.findViewById(R.id.video_button);
|
RadioButton videoButton = view.findViewById(R.id.video_button);
|
||||||
|
|
||||||
if (currentInfo.audio_streams == null || currentInfo.audio_streams.size() == 0) {
|
if (currentInfo.getAudioStreams() == null || currentInfo.getAudioStreams().size() == 0) {
|
||||||
audioButton.setVisibility(View.GONE);
|
audioButton.setVisibility(View.GONE);
|
||||||
videoButton.setChecked(true);
|
videoButton.setChecked(true);
|
||||||
} else if (sortedStreamVideosList == null || sortedStreamVideosList.size() == 0) {
|
} else if (sortedStreamVideosList == null || sortedStreamVideosList.size() == 0) {
|
||||||
@@ -256,14 +256,18 @@ public class DownloadDialog extends DialogFragment implements RadioGroup.OnCheck
|
|||||||
String url, location;
|
String url, location;
|
||||||
|
|
||||||
String fileName = nameEditText.getText().toString().trim();
|
String fileName = nameEditText.getText().toString().trim();
|
||||||
if (fileName.isEmpty()) fileName = FilenameUtils.createFilename(getContext(), currentInfo.name);
|
if (fileName.isEmpty()) fileName = FilenameUtils.createFilename(getContext(), currentInfo.getName());
|
||||||
|
|
||||||
boolean isAudio = radioVideoAudioGroup.getCheckedRadioButtonId() == R.id.audio_button;
|
boolean isAudio = radioVideoAudioGroup.getCheckedRadioButtonId() == R.id.audio_button;
|
||||||
url = isAudio ? currentInfo.audio_streams.get(selectedAudioIndex).url : sortedStreamVideosList.get(selectedVideoIndex).url;
|
if (isAudio) {
|
||||||
location = isAudio ? NewPipeSettings.getAudioDownloadPath(getContext()) : NewPipeSettings.getVideoDownloadPath(getContext());
|
url = currentInfo.getAudioStreams().get(selectedAudioIndex).getUrl();
|
||||||
|
location = NewPipeSettings.getAudioDownloadPath(getContext());
|
||||||
if (isAudio) fileName += "." + MediaFormat.getSuffixById(currentInfo.audio_streams.get(selectedAudioIndex).format);
|
fileName += "." + currentInfo.getAudioStreams().get(selectedAudioIndex).getFormat().getSuffix();
|
||||||
else fileName += "." + MediaFormat.getSuffixById(sortedStreamVideosList.get(selectedVideoIndex).format);
|
} else {
|
||||||
|
url = sortedStreamVideosList.get(selectedVideoIndex).getUrl();
|
||||||
|
location = NewPipeSettings.getVideoDownloadPath(getContext());
|
||||||
|
fileName += "." + sortedStreamVideosList.get(selectedVideoIndex).getFormat().getSuffix();
|
||||||
|
}
|
||||||
|
|
||||||
DownloadManagerService.startMission(getContext(), url, location, fileName, isAudio, threadsSeekBar.getProgress() + 1);
|
DownloadManagerService.startMission(getContext(), url, location, fileName, isAudio, threadsSeekBar.getProgress() + 1);
|
||||||
getDialog().dismiss();
|
getDialog().dismiss();
|
||||||
|
@@ -1,6 +1,7 @@
|
|||||||
package org.schabi.newpipe.fragments;
|
package org.schabi.newpipe.fragments;
|
||||||
|
|
||||||
import android.content.Intent;
|
import android.content.Intent;
|
||||||
|
import android.net.Uri;
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
import android.support.annotation.Nullable;
|
import android.support.annotation.Nullable;
|
||||||
import android.support.annotation.StringRes;
|
import android.support.annotation.StringRes;
|
||||||
@@ -50,6 +51,7 @@ public abstract class BaseStateFragment<I> extends BaseFragment implements ViewC
|
|||||||
protected Button errorButtonRetry;
|
protected Button errorButtonRetry;
|
||||||
protected TextView errorTextView;
|
protected TextView errorTextView;
|
||||||
|
|
||||||
|
@State
|
||||||
protected boolean useAsFrontPage = false;
|
protected boolean useAsFrontPage = false;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -218,6 +220,7 @@ public abstract class BaseStateFragment<I> extends BaseFragment implements ViewC
|
|||||||
|
|
||||||
if (serviceName == null) serviceName = "none";
|
if (serviceName == null) serviceName = "none";
|
||||||
if (request == null) request = "none";
|
if (request == null) request = "none";
|
||||||
|
|
||||||
ErrorActivity.reportError(getContext(), exception, MainActivity.class, null, ErrorActivity.ErrorInfo.make(userAction, serviceName, request, errorId));
|
ErrorActivity.reportError(getContext(), exception, MainActivity.class, null, ErrorActivity.ErrorInfo.make(userAction, serviceName, request, errorId));
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -238,4 +241,28 @@ public abstract class BaseStateFragment<I> extends BaseFragment implements ViewC
|
|||||||
|
|
||||||
ErrorActivity.reportError(getContext(), exception, MainActivity.class, rootView, ErrorActivity.ErrorInfo.make(userAction, serviceName, request, errorId));
|
ErrorActivity.reportError(getContext(), exception, MainActivity.class, rootView, ErrorActivity.ErrorInfo.make(userAction, serviceName, request, errorId));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*//////////////////////////////////////////////////////////////////////////
|
||||||
|
// Utils
|
||||||
|
//////////////////////////////////////////////////////////////////////////*/
|
||||||
|
|
||||||
|
public void setTitle(String title) {
|
||||||
|
if (DEBUG) Log.d(TAG, "setTitle() called with: title = [" + title + "]");
|
||||||
|
if (activity != null && activity.getSupportActionBar() != null) {
|
||||||
|
activity.getSupportActionBar().setTitle(title);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void openUrlInBrowser(String url) {
|
||||||
|
Intent intent = new Intent(Intent.ACTION_VIEW, Uri.parse(url));
|
||||||
|
startActivity(Intent.createChooser(intent, activity.getString(R.string.share_dialog_title)));
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void shareUrl(String subject, String url) {
|
||||||
|
Intent intent = new Intent(Intent.ACTION_SEND);
|
||||||
|
intent.setType("text/plain");
|
||||||
|
intent.putExtra(Intent.EXTRA_SUBJECT, subject);
|
||||||
|
intent.putExtra(Intent.EXTRA_TEXT, url);
|
||||||
|
startActivity(Intent.createChooser(intent, getString(R.string.share_dialog_title)));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@@ -2,6 +2,7 @@ package org.schabi.newpipe.fragments;
|
|||||||
|
|
||||||
import android.content.SharedPreferences;
|
import android.content.SharedPreferences;
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
|
import android.support.annotation.NonNull;
|
||||||
import android.support.annotation.Nullable;
|
import android.support.annotation.Nullable;
|
||||||
import android.support.design.widget.TabLayout;
|
import android.support.design.widget.TabLayout;
|
||||||
import android.support.v4.app.Fragment;
|
import android.support.v4.app.Fragment;
|
||||||
@@ -22,6 +23,7 @@ import android.view.ViewGroup;
|
|||||||
import org.schabi.newpipe.BaseFragment;
|
import org.schabi.newpipe.BaseFragment;
|
||||||
import org.schabi.newpipe.R;
|
import org.schabi.newpipe.R;
|
||||||
import org.schabi.newpipe.extractor.NewPipe;
|
import org.schabi.newpipe.extractor.NewPipe;
|
||||||
|
import org.schabi.newpipe.extractor.ServiceList;
|
||||||
import org.schabi.newpipe.extractor.StreamingService;
|
import org.schabi.newpipe.extractor.StreamingService;
|
||||||
import org.schabi.newpipe.extractor.kiosk.KioskList;
|
import org.schabi.newpipe.extractor.kiosk.KioskList;
|
||||||
import org.schabi.newpipe.fragments.list.channel.ChannelFragment;
|
import org.schabi.newpipe.fragments.list.channel.ChannelFragment;
|
||||||
@@ -30,30 +32,25 @@ import org.schabi.newpipe.fragments.list.kiosk.KioskFragment;
|
|||||||
import org.schabi.newpipe.fragments.subscription.SubscriptionFragment;
|
import org.schabi.newpipe.fragments.subscription.SubscriptionFragment;
|
||||||
import org.schabi.newpipe.report.ErrorActivity;
|
import org.schabi.newpipe.report.ErrorActivity;
|
||||||
import org.schabi.newpipe.report.UserAction;
|
import org.schabi.newpipe.report.UserAction;
|
||||||
import org.schabi.newpipe.util.Constants;
|
|
||||||
import org.schabi.newpipe.util.KioskTranslator;
|
import org.schabi.newpipe.util.KioskTranslator;
|
||||||
import org.schabi.newpipe.util.NavigationHelper;
|
import org.schabi.newpipe.util.NavigationHelper;
|
||||||
|
import org.schabi.newpipe.util.ServiceHelper;
|
||||||
import org.schabi.newpipe.util.ThemeHelper;
|
import org.schabi.newpipe.util.ThemeHelper;
|
||||||
|
|
||||||
import java.util.concurrent.ExecutionException;
|
|
||||||
|
|
||||||
public class MainFragment extends BaseFragment implements TabLayout.OnTabSelectedListener {
|
public class MainFragment extends BaseFragment implements TabLayout.OnTabSelectedListener {
|
||||||
private ViewPager viewPager;
|
|
||||||
private boolean showBlankTab = false;
|
|
||||||
|
|
||||||
private static final int FALLBACK_SERVICE_ID = 0; // Youtbe
|
|
||||||
private static final String FALLBACK_CHANNEL_URL =
|
|
||||||
"https://www.youtube.com/channel/UC-9-kyTW8ZkZNDHQJ6FgpwQ";
|
|
||||||
private static final String FALLBACK_CHANNEL_NAME = "Music";
|
|
||||||
private static final String FALLBACK_KIOSK_ID = "Trending";
|
|
||||||
|
|
||||||
public int currentServiceId = -1;
|
public int currentServiceId = -1;
|
||||||
|
private ViewPager viewPager;
|
||||||
|
|
||||||
/*//////////////////////////////////////////////////////////////////////////
|
/*//////////////////////////////////////////////////////////////////////////
|
||||||
// Konst
|
// Constants
|
||||||
//////////////////////////////////////////////////////////////////////////*/
|
//////////////////////////////////////////////////////////////////////////*/
|
||||||
|
|
||||||
private static final int KIOSK_MENU_OFFSETT = 2000;
|
private static final int FALLBACK_SERVICE_ID = ServiceList.YouTube.getId();
|
||||||
|
private static final String FALLBACK_CHANNEL_URL = "https://www.youtube.com/channel/UC-9-kyTW8ZkZNDHQJ6FgpwQ";
|
||||||
|
private static final String FALLBACK_CHANNEL_NAME = "Music";
|
||||||
|
private static final String FALLBACK_KIOSK_ID = "Trending";
|
||||||
|
private static final int KIOSK_MENU_OFFSET = 2000;
|
||||||
|
|
||||||
/*//////////////////////////////////////////////////////////////////////////
|
/*//////////////////////////////////////////////////////////////////////////
|
||||||
// Fragment's LifeCycle
|
// Fragment's LifeCycle
|
||||||
@@ -66,9 +63,8 @@ public class MainFragment extends BaseFragment implements TabLayout.OnTabSelecte
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
|
public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
|
||||||
currentServiceId = Integer.parseInt(PreferenceManager.getDefaultSharedPreferences(getActivity())
|
currentServiceId = ServiceHelper.getSelectedServiceId(activity);
|
||||||
.getString(getString(R.string.current_service_key), "0"));
|
|
||||||
return inflater.inflate(R.layout.fragment_main, container, false);
|
return inflater.inflate(R.layout.fragment_main, container, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -86,27 +82,15 @@ public class MainFragment extends BaseFragment implements TabLayout.OnTabSelecte
|
|||||||
|
|
||||||
tabLayout.setupWithViewPager(viewPager);
|
tabLayout.setupWithViewPager(viewPager);
|
||||||
|
|
||||||
if(ThemeHelper.isLightThemeSelected(getActivity())) {
|
int channelIcon = ThemeHelper.resolveResourceIdFromAttr(activity, R.attr.ic_channel);
|
||||||
tabLayout.setBackgroundColor(getResources().getColor(R.color.light_youtube_primary_color));
|
int whatsHotIcon = ThemeHelper.resolveResourceIdFromAttr(activity, R.attr.ic_hot);
|
||||||
}
|
|
||||||
|
|
||||||
if(PreferenceManager.getDefaultSharedPreferences(getActivity())
|
if (isSubscriptionsPageOnlySelected()) {
|
||||||
.getString(getString(R.string.main_page_content_key), getString(R.string.blank_page_key))
|
tabLayout.getTabAt(0).setIcon(channelIcon);
|
||||||
.equals(getString(R.string.subscription_page_key))) {
|
} else {
|
||||||
if(ThemeHelper.isLightThemeSelected(getActivity())) {
|
tabLayout.getTabAt(0).setIcon(whatsHotIcon);
|
||||||
tabLayout.getTabAt(0).setIcon(R.drawable.ic_channel_black_24dp);
|
tabLayout.getTabAt(1).setIcon(channelIcon);
|
||||||
} else{
|
}
|
||||||
tabLayout.getTabAt(0).setIcon(R.drawable.ic_channel_white_24dp);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
if(ThemeHelper.isLightThemeSelected(getActivity())) {
|
|
||||||
tabLayout.getTabAt(0).setIcon(R.drawable.ic_whatshot_black_24dp);
|
|
||||||
tabLayout.getTabAt(1).setIcon(R.drawable.ic_channel_black_24dp);
|
|
||||||
} else {
|
|
||||||
tabLayout.getTabAt(0).setIcon(R.drawable.ic_whatshot_white_24dp);
|
|
||||||
tabLayout.getTabAt(1).setIcon(R.drawable.ic_channel_white_24dp);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*//////////////////////////////////////////////////////////////////////////
|
/*//////////////////////////////////////////////////////////////////////////
|
||||||
@@ -139,7 +123,7 @@ public class MainFragment extends BaseFragment implements TabLayout.OnTabSelecte
|
|||||||
public boolean onOptionsItemSelected(MenuItem item) {
|
public boolean onOptionsItemSelected(MenuItem item) {
|
||||||
switch (item.getItemId()) {
|
switch (item.getItemId()) {
|
||||||
case R.id.action_search:
|
case R.id.action_search:
|
||||||
NavigationHelper.openSearchFragment(getFragmentManager(), 0, "");
|
NavigationHelper.openSearchFragment(getFragmentManager(), ServiceHelper.getSelectedServiceId(activity), "");
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
return super.onOptionsItemSelected(item);
|
return super.onOptionsItemSelected(item);
|
||||||
@@ -164,11 +148,6 @@ public class MainFragment extends BaseFragment implements TabLayout.OnTabSelecte
|
|||||||
|
|
||||||
private class PagerAdapter extends FragmentPagerAdapter {
|
private class PagerAdapter extends FragmentPagerAdapter {
|
||||||
|
|
||||||
private int[] tabTitles = new int[]{
|
|
||||||
R.string.tab_main,
|
|
||||||
R.string.tab_subscriptions
|
|
||||||
};
|
|
||||||
|
|
||||||
PagerAdapter(FragmentManager fm) {
|
PagerAdapter(FragmentManager fm) {
|
||||||
super(fm);
|
super(fm);
|
||||||
}
|
}
|
||||||
@@ -177,13 +156,7 @@ public class MainFragment extends BaseFragment implements TabLayout.OnTabSelecte
|
|||||||
public Fragment getItem(int position) {
|
public Fragment getItem(int position) {
|
||||||
switch (position) {
|
switch (position) {
|
||||||
case 0:
|
case 0:
|
||||||
if(PreferenceManager.getDefaultSharedPreferences(getActivity())
|
return isSubscriptionsPageOnlySelected() ? new SubscriptionFragment() : getMainPageFragment();
|
||||||
.getString(getString(R.string.main_page_content_key), getString(R.string.blank_page_key))
|
|
||||||
.equals(getString(R.string.subscription_page_key))) {
|
|
||||||
return new SubscriptionFragment();
|
|
||||||
} else {
|
|
||||||
return getMainPageFramgent();
|
|
||||||
}
|
|
||||||
case 1:
|
case 1:
|
||||||
return new SubscriptionFragment();
|
return new SubscriptionFragment();
|
||||||
default:
|
default:
|
||||||
@@ -199,13 +172,7 @@ public class MainFragment extends BaseFragment implements TabLayout.OnTabSelecte
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int getCount() {
|
public int getCount() {
|
||||||
if(PreferenceManager.getDefaultSharedPreferences(getActivity())
|
return isSubscriptionsPageOnlySelected() ? 1 : 2;
|
||||||
.getString(getString(R.string.main_page_content_key), getString(R.string.blank_page_key))
|
|
||||||
.equals(getString(R.string.subscription_page_key))) {
|
|
||||||
return 1;
|
|
||||||
} else {
|
|
||||||
return 2;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -213,28 +180,33 @@ public class MainFragment extends BaseFragment implements TabLayout.OnTabSelecte
|
|||||||
// Main page content
|
// Main page content
|
||||||
//////////////////////////////////////////////////////////////////////////*/
|
//////////////////////////////////////////////////////////////////////////*/
|
||||||
|
|
||||||
private Fragment getMainPageFramgent() {
|
private boolean isSubscriptionsPageOnlySelected() {
|
||||||
|
return PreferenceManager.getDefaultSharedPreferences(activity)
|
||||||
|
.getString(getString(R.string.main_page_content_key), getString(R.string.blank_page_key))
|
||||||
|
.equals(getString(R.string.subscription_page_key));
|
||||||
|
}
|
||||||
|
|
||||||
|
private Fragment getMainPageFragment() {
|
||||||
try {
|
try {
|
||||||
SharedPreferences preferences =
|
SharedPreferences preferences =
|
||||||
PreferenceManager.getDefaultSharedPreferences(getActivity());
|
PreferenceManager.getDefaultSharedPreferences(getActivity());
|
||||||
final String setMainPage = preferences.getString(getString(R.string.main_page_content_key),
|
final String setMainPage = preferences.getString(getString(R.string.main_page_content_key),
|
||||||
getString(R.string.main_page_selectd_kiosk_id));
|
getString(R.string.main_page_selectd_kiosk_id));
|
||||||
if(setMainPage.equals(getString(R.string.blank_page_key))) {
|
if (setMainPage.equals(getString(R.string.blank_page_key))) {
|
||||||
return new BlankFragment();
|
return new BlankFragment();
|
||||||
} else if(setMainPage.equals(getString(R.string.kiosk_page_key))) {
|
} else if (setMainPage.equals(getString(R.string.kiosk_page_key))) {
|
||||||
int serviceId = preferences.getInt(getString(R.string.main_page_selected_service),
|
int serviceId = preferences.getInt(getString(R.string.main_page_selected_service),
|
||||||
FALLBACK_SERVICE_ID);
|
FALLBACK_SERVICE_ID);
|
||||||
String kioskId = preferences.getString(getString(R.string.main_page_selectd_kiosk_id),
|
String kioskId = preferences.getString(getString(R.string.main_page_selectd_kiosk_id),
|
||||||
FALLBACK_KIOSK_ID);
|
FALLBACK_KIOSK_ID);
|
||||||
KioskFragment fragment = KioskFragment.getInstance(serviceId, kioskId
|
KioskFragment fragment = KioskFragment.getInstance(serviceId, kioskId);
|
||||||
);
|
|
||||||
fragment.useAsFrontPage(true);
|
fragment.useAsFrontPage(true);
|
||||||
return fragment;
|
return fragment;
|
||||||
} else if(setMainPage.equals(getString(R.string.feed_page_key))) {
|
} else if (setMainPage.equals(getString(R.string.feed_page_key))) {
|
||||||
FeedFragment fragment = new FeedFragment();
|
FeedFragment fragment = new FeedFragment();
|
||||||
fragment.useAsFrontPage(true);
|
fragment.useAsFrontPage(true);
|
||||||
return fragment;
|
return fragment;
|
||||||
} else if(setMainPage.equals(getString(R.string.channel_page_key))) {
|
} else if (setMainPage.equals(getString(R.string.channel_page_key))) {
|
||||||
int serviceId = preferences.getInt(getString(R.string.main_page_selected_service),
|
int serviceId = preferences.getInt(getString(R.string.main_page_selected_service),
|
||||||
FALLBACK_SERVICE_ID);
|
FALLBACK_SERVICE_ID);
|
||||||
String url = preferences.getString(getString(R.string.main_page_selected_channel_url),
|
String url = preferences.getString(getString(R.string.main_page_selected_channel_url),
|
||||||
@@ -267,8 +239,8 @@ public class MainFragment extends BaseFragment implements TabLayout.OnTabSelecte
|
|||||||
StreamingService service = NewPipe.getService(currentServiceId);
|
StreamingService service = NewPipe.getService(currentServiceId);
|
||||||
KioskList kl = service.getKioskList();
|
KioskList kl = service.getKioskList();
|
||||||
int i = 0;
|
int i = 0;
|
||||||
for(final String ks : kl.getAvailableKiosks()) {
|
for (final String ks : kl.getAvailableKiosks()) {
|
||||||
menu.add(0, KIOSK_MENU_OFFSETT + i, Menu.NONE,
|
menu.add(0, KIOSK_MENU_OFFSET + i, Menu.NONE,
|
||||||
KioskTranslator.getTranslatedKioskName(ks, getContext()))
|
KioskTranslator.getTranslatedKioskName(ks, getContext()))
|
||||||
.setOnMenuItemClickListener(new MenuItem.OnMenuItemClickListener() {
|
.setOnMenuItemClickListener(new MenuItem.OnMenuItemClickListener() {
|
||||||
@Override
|
@Override
|
||||||
|
@@ -60,7 +60,7 @@ public class SpinnerToolbarAdapter extends BaseAdapter {
|
|||||||
ImageView woSoundIcon = convertView.findViewById(R.id.wo_sound_icon);
|
ImageView woSoundIcon = convertView.findViewById(R.id.wo_sound_icon);
|
||||||
TextView text = convertView.findViewById(android.R.id.text1);
|
TextView text = convertView.findViewById(android.R.id.text1);
|
||||||
VideoStream item = (VideoStream) getItem(position);
|
VideoStream item = (VideoStream) getItem(position);
|
||||||
text.setText(MediaFormat.getNameById(item.format) + " " + item.resolution);
|
text.setText(item.getFormat().getName() + " " + item.getResolution());
|
||||||
|
|
||||||
int visibility = !showIconNoAudio ? View.GONE
|
int visibility = !showIconNoAudio ? View.GONE
|
||||||
: item.isVideoOnly ? View.VISIBLE
|
: item.isVideoOnly ? View.VISIBLE
|
||||||
|
@@ -4,7 +4,8 @@ import java.io.Serializable;
|
|||||||
|
|
||||||
class StackItem implements Serializable {
|
class StackItem implements Serializable {
|
||||||
private int serviceId;
|
private int serviceId;
|
||||||
private String title, url;
|
private String title;
|
||||||
|
private String url;
|
||||||
|
|
||||||
StackItem(int serviceId, String url, String title) {
|
StackItem(int serviceId, String url, String title) {
|
||||||
this.serviceId = serviceId;
|
this.serviceId = serviceId;
|
||||||
|
File diff suppressed because it is too large
Load Diff
@@ -1,15 +1,21 @@
|
|||||||
package org.schabi.newpipe.fragments.list;
|
package org.schabi.newpipe.fragments.list;
|
||||||
|
|
||||||
|
import android.app.Activity;
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
|
import android.content.DialogInterface;
|
||||||
|
import android.os.Build;
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
import android.support.annotation.NonNull;
|
import android.support.annotation.NonNull;
|
||||||
import android.support.v7.app.ActionBar;
|
import android.support.v7.app.ActionBar;
|
||||||
import android.support.v7.widget.LinearLayoutManager;
|
import android.support.v7.widget.LinearLayoutManager;
|
||||||
import android.support.v7.widget.RecyclerView;
|
import android.support.v7.widget.RecyclerView;
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
|
import android.view.Gravity;
|
||||||
import android.view.Menu;
|
import android.view.Menu;
|
||||||
import android.view.MenuInflater;
|
import android.view.MenuInflater;
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
|
import android.widget.TextView;
|
||||||
|
import android.widget.Toast;
|
||||||
|
|
||||||
import org.schabi.newpipe.R;
|
import org.schabi.newpipe.R;
|
||||||
import org.schabi.newpipe.extractor.InfoItem;
|
import org.schabi.newpipe.extractor.InfoItem;
|
||||||
@@ -19,8 +25,11 @@ import org.schabi.newpipe.extractor.stream.StreamInfoItem;
|
|||||||
import org.schabi.newpipe.fragments.BaseStateFragment;
|
import org.schabi.newpipe.fragments.BaseStateFragment;
|
||||||
import org.schabi.newpipe.fragments.OnScrollBelowItemsListener;
|
import org.schabi.newpipe.fragments.OnScrollBelowItemsListener;
|
||||||
import org.schabi.newpipe.info_list.InfoItemBuilder;
|
import org.schabi.newpipe.info_list.InfoItemBuilder;
|
||||||
|
import org.schabi.newpipe.info_list.InfoItemDialog;
|
||||||
import org.schabi.newpipe.info_list.InfoListAdapter;
|
import org.schabi.newpipe.info_list.InfoListAdapter;
|
||||||
|
import org.schabi.newpipe.playlist.SinglePlayQueue;
|
||||||
import org.schabi.newpipe.util.NavigationHelper;
|
import org.schabi.newpipe.util.NavigationHelper;
|
||||||
|
import org.schabi.newpipe.util.PermissionHelper;
|
||||||
import org.schabi.newpipe.util.StateSaver;
|
import org.schabi.newpipe.util.StateSaver;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
@@ -137,7 +146,12 @@ public abstract class BaseListFragment<I, N> extends BaseStateFragment<I> implem
|
|||||||
onItemSelected(selectedItem);
|
onItemSelected(selectedItem);
|
||||||
NavigationHelper.openVideoDetailFragment(
|
NavigationHelper.openVideoDetailFragment(
|
||||||
useAsFrontPage?getParentFragment().getFragmentManager():getFragmentManager(),
|
useAsFrontPage?getParentFragment().getFragmentManager():getFragmentManager(),
|
||||||
selectedItem.service_id, selectedItem.url, selectedItem.name);
|
selectedItem.getServiceId(), selectedItem.getUrl(), selectedItem.getName());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void held(StreamInfoItem selectedItem) {
|
||||||
|
showStreamDialog(selectedItem);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -147,8 +161,11 @@ public abstract class BaseListFragment<I, N> extends BaseStateFragment<I> implem
|
|||||||
onItemSelected(selectedItem);
|
onItemSelected(selectedItem);
|
||||||
NavigationHelper.openChannelFragment(
|
NavigationHelper.openChannelFragment(
|
||||||
useAsFrontPage?getParentFragment().getFragmentManager():getFragmentManager(),
|
useAsFrontPage?getParentFragment().getFragmentManager():getFragmentManager(),
|
||||||
selectedItem.service_id, selectedItem.url, selectedItem.name);
|
selectedItem.getServiceId(), selectedItem.getUrl(), selectedItem.getName());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void held(ChannelInfoItem selectedItem) {}
|
||||||
});
|
});
|
||||||
|
|
||||||
infoListAdapter.setOnPlaylistSelectedListener(new InfoItemBuilder.OnInfoItemSelectedListener<PlaylistInfoItem>() {
|
infoListAdapter.setOnPlaylistSelectedListener(new InfoItemBuilder.OnInfoItemSelectedListener<PlaylistInfoItem>() {
|
||||||
@@ -157,8 +174,11 @@ public abstract class BaseListFragment<I, N> extends BaseStateFragment<I> implem
|
|||||||
onItemSelected(selectedItem);
|
onItemSelected(selectedItem);
|
||||||
NavigationHelper.openPlaylistFragment(
|
NavigationHelper.openPlaylistFragment(
|
||||||
useAsFrontPage?getParentFragment().getFragmentManager():getFragmentManager(),
|
useAsFrontPage?getParentFragment().getFragmentManager():getFragmentManager(),
|
||||||
selectedItem.service_id, selectedItem.url, selectedItem.name);
|
selectedItem.getServiceId(), selectedItem.getUrl(), selectedItem.getName());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void held(PlaylistInfoItem selectedItem) {}
|
||||||
});
|
});
|
||||||
|
|
||||||
itemsList.clearOnScrollListeners();
|
itemsList.clearOnScrollListeners();
|
||||||
@@ -176,6 +196,34 @@ public abstract class BaseListFragment<I, N> extends BaseStateFragment<I> implem
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected void showStreamDialog(final StreamInfoItem item) {
|
||||||
|
final Context context = getContext();
|
||||||
|
final Activity activity = getActivity();
|
||||||
|
if (context == null || context.getResources() == null || getActivity() == null) return;
|
||||||
|
|
||||||
|
final String[] commands = new String[]{
|
||||||
|
context.getResources().getString(R.string.enqueue_on_background),
|
||||||
|
context.getResources().getString(R.string.enqueue_on_popup)
|
||||||
|
};
|
||||||
|
|
||||||
|
final DialogInterface.OnClickListener actions = new DialogInterface.OnClickListener() {
|
||||||
|
@Override
|
||||||
|
public void onClick(DialogInterface dialogInterface, int i) {
|
||||||
|
switch (i) {
|
||||||
|
case 0:
|
||||||
|
NavigationHelper.enqueueOnBackgroundPlayer(context, new SinglePlayQueue(item));
|
||||||
|
break;
|
||||||
|
case 1:
|
||||||
|
NavigationHelper.enqueueOnPopupPlayer(activity, new SinglePlayQueue(item));
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
new InfoItemDialog(getActivity(), item, commands, actions).show();
|
||||||
|
}
|
||||||
/*//////////////////////////////////////////////////////////////////////////
|
/*//////////////////////////////////////////////////////////////////////////
|
||||||
// Menu
|
// Menu
|
||||||
//////////////////////////////////////////////////////////////////////////*/
|
//////////////////////////////////////////////////////////////////////////*/
|
||||||
|
@@ -84,17 +84,6 @@ public abstract class BaseListInfoFragment<I extends ListInfo> extends BaseListF
|
|||||||
currentNextItemsUrl = (String) savedObjects.poll();
|
currentNextItemsUrl = (String) savedObjects.poll();
|
||||||
}
|
}
|
||||||
|
|
||||||
/*//////////////////////////////////////////////////////////////////////////
|
|
||||||
// Utils
|
|
||||||
//////////////////////////////////////////////////////////////////////////*/
|
|
||||||
|
|
||||||
public void setTitle(String title) {
|
|
||||||
Log.d(TAG, "setTitle() called with: title = [" + title + "]");
|
|
||||||
if (activity.getSupportActionBar() != null) {
|
|
||||||
activity.getSupportActionBar().setTitle(title);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/*//////////////////////////////////////////////////////////////////////////
|
/*//////////////////////////////////////////////////////////////////////////
|
||||||
// Load and handle
|
// Load and handle
|
||||||
//////////////////////////////////////////////////////////////////////////*/
|
//////////////////////////////////////////////////////////////////////////*/
|
||||||
@@ -124,20 +113,12 @@ public abstract class BaseListInfoFragment<I extends ListInfo> extends BaseListF
|
|||||||
currentWorker = loadResult(forceLoad)
|
currentWorker = loadResult(forceLoad)
|
||||||
.subscribeOn(Schedulers.io())
|
.subscribeOn(Schedulers.io())
|
||||||
.observeOn(AndroidSchedulers.mainThread())
|
.observeOn(AndroidSchedulers.mainThread())
|
||||||
.subscribe(new Consumer<I>() {
|
.subscribe((@NonNull I result) -> {
|
||||||
@Override
|
isLoading.set(false);
|
||||||
public void accept(@NonNull I result) throws Exception {
|
currentInfo = result;
|
||||||
isLoading.set(false);
|
currentNextItemsUrl = result.next_streams_url;
|
||||||
currentInfo = result;
|
handleResult(result);
|
||||||
currentNextItemsUrl = result.next_streams_url;
|
}, (@NonNull Throwable throwable) -> onError(throwable));
|
||||||
handleResult(result);
|
|
||||||
}
|
|
||||||
}, new Consumer<Throwable>() {
|
|
||||||
@Override
|
|
||||||
public void accept(@NonNull Throwable throwable) throws Exception {
|
|
||||||
onError(throwable);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -153,18 +134,12 @@ public abstract class BaseListInfoFragment<I extends ListInfo> extends BaseListF
|
|||||||
currentWorker = loadMoreItemsLogic()
|
currentWorker = loadMoreItemsLogic()
|
||||||
.subscribeOn(Schedulers.io())
|
.subscribeOn(Schedulers.io())
|
||||||
.observeOn(AndroidSchedulers.mainThread())
|
.observeOn(AndroidSchedulers.mainThread())
|
||||||
.subscribe(new Consumer<ListExtractor.NextItemsResult>() {
|
.subscribe((@io.reactivex.annotations.NonNull ListExtractor.NextItemsResult nextItemsResult) -> {
|
||||||
@Override
|
isLoading.set(false);
|
||||||
public void accept(@io.reactivex.annotations.NonNull ListExtractor.NextItemsResult nextItemsResult) throws Exception {
|
handleNextItems(nextItemsResult);
|
||||||
isLoading.set(false);
|
}, (@io.reactivex.annotations.NonNull Throwable throwable) -> {
|
||||||
handleNextItems(nextItemsResult);
|
isLoading.set(false);
|
||||||
}
|
onError(throwable);
|
||||||
}, new Consumer<Throwable>() {
|
|
||||||
@Override
|
|
||||||
public void accept(@io.reactivex.annotations.NonNull Throwable throwable) throws Exception {
|
|
||||||
isLoading.set(false);
|
|
||||||
onError(throwable);
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -190,8 +165,8 @@ public abstract class BaseListInfoFragment<I extends ListInfo> extends BaseListF
|
|||||||
public void handleResult(@NonNull I result) {
|
public void handleResult(@NonNull I result) {
|
||||||
super.handleResult(result);
|
super.handleResult(result);
|
||||||
|
|
||||||
url = result.url;
|
url = result.getUrl();
|
||||||
name = result.name;
|
name = result.getName();
|
||||||
setTitle(name);
|
setTitle(name);
|
||||||
|
|
||||||
if (infoListAdapter.getItemsList().size() == 0) {
|
if (infoListAdapter.getItemsList().size() == 0) {
|
||||||
|
File diff suppressed because it is too large
Load Diff
@@ -297,12 +297,12 @@ public class FeedFragment extends BaseListFragment<List<SubscriptionEntity>, Voi
|
|||||||
// Called only when response is non-empty
|
// Called only when response is non-empty
|
||||||
@Override
|
@Override
|
||||||
public void onSuccess(final ChannelInfo channelInfo) {
|
public void onSuccess(final ChannelInfo channelInfo) {
|
||||||
if (infoListAdapter == null || channelInfo.related_streams.isEmpty()) {
|
if (infoListAdapter == null || channelInfo.getRelatedStreams().isEmpty()) {
|
||||||
onDone();
|
onDone();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
final InfoItem item = channelInfo.related_streams.get(0);
|
final InfoItem item = channelInfo.getRelatedStreams().get(0);
|
||||||
// Keep requesting new items if the current one already exists
|
// Keep requesting new items if the current one already exists
|
||||||
boolean itemExists = doesItemExist(infoListAdapter.getItemsList(), item);
|
boolean itemExists = doesItemExist(infoListAdapter.getItemsList(), item);
|
||||||
if (!itemExists) {
|
if (!itemExists) {
|
||||||
@@ -412,9 +412,9 @@ public class FeedFragment extends BaseListFragment<List<SubscriptionEntity>, Voi
|
|||||||
private boolean doesItemExist(final List<InfoItem> items, final InfoItem item) {
|
private boolean doesItemExist(final List<InfoItem> items, final InfoItem item) {
|
||||||
for (final InfoItem existingItem : items) {
|
for (final InfoItem existingItem : items) {
|
||||||
if (existingItem.info_type == item.info_type &&
|
if (existingItem.info_type == item.info_type &&
|
||||||
existingItem.service_id == item.service_id &&
|
existingItem.getServiceId() == item.getServiceId() &&
|
||||||
existingItem.name.equals(item.name) &&
|
existingItem.getName().equals(item.getName()) &&
|
||||||
existingItem.url.equals(item.url)) return true;
|
existingItem.getUrl().equals(item.getUrl())) return true;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@@ -5,6 +5,7 @@ import android.preference.PreferenceManager;
|
|||||||
import android.support.annotation.NonNull;
|
import android.support.annotation.NonNull;
|
||||||
import android.support.annotation.Nullable;
|
import android.support.annotation.Nullable;
|
||||||
import android.support.v7.app.ActionBar;
|
import android.support.v7.app.ActionBar;
|
||||||
|
import android.util.Log;
|
||||||
import android.view.LayoutInflater;
|
import android.view.LayoutInflater;
|
||||||
import android.view.Menu;
|
import android.view.Menu;
|
||||||
import android.view.MenuInflater;
|
import android.view.MenuInflater;
|
||||||
@@ -27,6 +28,7 @@ import org.schabi.newpipe.util.ExtractorHelper;
|
|||||||
import org.schabi.newpipe.util.KioskTranslator;
|
import org.schabi.newpipe.util.KioskTranslator;
|
||||||
import org.schabi.newpipe.util.NavigationHelper;
|
import org.schabi.newpipe.util.NavigationHelper;
|
||||||
|
|
||||||
|
import icepick.State;
|
||||||
import io.reactivex.Single;
|
import io.reactivex.Single;
|
||||||
|
|
||||||
import static org.schabi.newpipe.util.AnimationUtils.animateView;
|
import static org.schabi.newpipe.util.AnimationUtils.animateView;
|
||||||
@@ -53,16 +55,14 @@ import static org.schabi.newpipe.util.AnimationUtils.animateView;
|
|||||||
|
|
||||||
public class KioskFragment extends BaseListInfoFragment<KioskInfo> {
|
public class KioskFragment extends BaseListInfoFragment<KioskInfo> {
|
||||||
|
|
||||||
private String kioskId = "";
|
@State
|
||||||
|
protected String kioskId = "";
|
||||||
|
protected String kioskTranslatedName;
|
||||||
|
|
||||||
/*//////////////////////////////////////////////////////////////////////////
|
/*//////////////////////////////////////////////////////////////////////////
|
||||||
// Views
|
// Views
|
||||||
//////////////////////////////////////////////////////////////////////////*/
|
//////////////////////////////////////////////////////////////////////////*/
|
||||||
|
|
||||||
private View headerRootLayout;
|
|
||||||
private TextView headerTitleView;
|
|
||||||
|
|
||||||
public static KioskFragment getInstance(int serviceId)
|
public static KioskFragment getInstance(int serviceId)
|
||||||
throws ExtractionException {
|
throws ExtractionException {
|
||||||
return getInstance(serviceId, NewPipe.getService(serviceId)
|
return getInstance(serviceId, NewPipe.getService(serviceId)
|
||||||
@@ -87,20 +87,30 @@ public class KioskFragment extends BaseListInfoFragment<KioskInfo> {
|
|||||||
// LifeCycle
|
// LifeCycle
|
||||||
//////////////////////////////////////////////////////////////////////////*/
|
//////////////////////////////////////////////////////////////////////////*/
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onCreate(Bundle savedInstanceState) {
|
||||||
|
super.onCreate(savedInstanceState);
|
||||||
|
|
||||||
|
kioskTranslatedName = KioskTranslator.getTranslatedKioskName(kioskId, activity);
|
||||||
|
name = kioskTranslatedName;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void setUserVisibleHint(boolean isVisibleToUser) {
|
public void setUserVisibleHint(boolean isVisibleToUser) {
|
||||||
super.setUserVisibleHint(isVisibleToUser);
|
super.setUserVisibleHint(isVisibleToUser);
|
||||||
if(useAsFrontPage && isVisibleToUser) {
|
if(useAsFrontPage && isVisibleToUser && activity != null) {
|
||||||
try {
|
try {
|
||||||
activity.getSupportActionBar().setTitle(KioskTranslator.getTranslatedKioskName(kioskId, getActivity()));
|
setTitle(kioskTranslatedName);
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
onError(e);
|
onUnrecoverableError(e, UserAction.UI_ERROR,
|
||||||
|
"none",
|
||||||
|
"none", R.string.app_ui_crash);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
|
public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
|
||||||
return inflater.inflate(R.layout.fragment_kiosk, container, false);
|
return inflater.inflate(R.layout.fragment_kiosk, container, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -125,14 +135,18 @@ public class KioskFragment extends BaseListInfoFragment<KioskInfo> {
|
|||||||
public Single<KioskInfo> loadResult(boolean forceReload) {
|
public Single<KioskInfo> loadResult(boolean forceReload) {
|
||||||
String contentCountry = PreferenceManager
|
String contentCountry = PreferenceManager
|
||||||
.getDefaultSharedPreferences(activity)
|
.getDefaultSharedPreferences(activity)
|
||||||
.getString(getString(R.string.search_language_key),
|
.getString(getString(R.string.content_country_key),
|
||||||
getString(R.string.default_language_value));
|
getString(R.string.default_country_value));
|
||||||
return ExtractorHelper.getKioskInfo(serviceId, url, contentCountry, forceReload);
|
return ExtractorHelper.getKioskInfo(serviceId, url, contentCountry, forceReload);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Single<ListExtractor.NextItemsResult> loadMoreItemsLogic() {
|
public Single<ListExtractor.NextItemsResult> loadMoreItemsLogic() {
|
||||||
return ExtractorHelper.getMoreKioskItems(serviceId, url, currentNextItemsUrl);
|
String contentCountry = PreferenceManager
|
||||||
|
.getDefaultSharedPreferences(activity)
|
||||||
|
.getString(getString(R.string.content_country_key),
|
||||||
|
getString(R.string.default_country_value));
|
||||||
|
return ExtractorHelper.getMoreKioskItems(serviceId, url, currentNextItemsUrl, contentCountry);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*//////////////////////////////////////////////////////////////////////////
|
/*//////////////////////////////////////////////////////////////////////////
|
||||||
@@ -149,14 +163,13 @@ public class KioskFragment extends BaseListInfoFragment<KioskInfo> {
|
|||||||
public void handleResult(@NonNull final KioskInfo result) {
|
public void handleResult(@NonNull final KioskInfo result) {
|
||||||
super.handleResult(result);
|
super.handleResult(result);
|
||||||
|
|
||||||
String title = KioskTranslator.getTranslatedKioskName(result.id, getActivity());
|
name = kioskTranslatedName;
|
||||||
ActionBar supportActionBar = activity.getSupportActionBar();
|
setTitle(kioskTranslatedName);
|
||||||
supportActionBar.setTitle(title);
|
|
||||||
|
|
||||||
if (!result.errors.isEmpty()) {
|
if (!result.getErrors().isEmpty()) {
|
||||||
showSnackBarError(result.errors,
|
showSnackBarError(result.getErrors(),
|
||||||
UserAction.REQUESTED_PLAYLIST,
|
UserAction.REQUESTED_PLAYLIST,
|
||||||
NewPipe.getNameOfService(result.service_id), result.url, 0);
|
NewPipe.getNameOfService(result.getServiceId()), result.getUrl(), 0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -164,8 +177,8 @@ public class KioskFragment extends BaseListInfoFragment<KioskInfo> {
|
|||||||
public void handleNextItems(ListExtractor.NextItemsResult result) {
|
public void handleNextItems(ListExtractor.NextItemsResult result) {
|
||||||
super.handleNextItems(result);
|
super.handleNextItems(result);
|
||||||
|
|
||||||
if (!result.errors.isEmpty()) {
|
if (!result.getErrors().isEmpty()) {
|
||||||
showSnackBarError(result.errors,
|
showSnackBarError(result.getErrors(),
|
||||||
UserAction.REQUESTED_PLAYLIST, NewPipe.getNameOfService(serviceId)
|
UserAction.REQUESTED_PLAYLIST, NewPipe.getNameOfService(serviceId)
|
||||||
, "Get next page of: " + url, 0);
|
, "Get next page of: " + url, 0);
|
||||||
}
|
}
|
||||||
|
@@ -1,38 +1,36 @@
|
|||||||
package org.schabi.newpipe.fragments.list.playlist;
|
package org.schabi.newpipe.fragments.list.playlist;
|
||||||
|
|
||||||
import android.content.Intent;
|
import android.app.Activity;
|
||||||
import android.os.Build;
|
import android.content.Context;
|
||||||
|
import android.content.DialogInterface;
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
import android.support.annotation.NonNull;
|
import android.support.annotation.NonNull;
|
||||||
import android.support.annotation.Nullable;
|
import android.support.annotation.Nullable;
|
||||||
import android.text.TextUtils;
|
import android.text.TextUtils;
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
import android.view.Gravity;
|
|
||||||
import android.view.LayoutInflater;
|
import android.view.LayoutInflater;
|
||||||
import android.view.Menu;
|
import android.view.Menu;
|
||||||
import android.view.MenuInflater;
|
import android.view.MenuInflater;
|
||||||
|
import android.view.MenuItem;
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
import android.view.ViewGroup;
|
import android.view.ViewGroup;
|
||||||
import android.widget.Button;
|
|
||||||
import android.widget.ImageView;
|
import android.widget.ImageView;
|
||||||
import android.widget.TextView;
|
import android.widget.TextView;
|
||||||
import android.widget.Toast;
|
|
||||||
|
|
||||||
import org.schabi.newpipe.R;
|
import org.schabi.newpipe.R;
|
||||||
import org.schabi.newpipe.extractor.ListExtractor;
|
import org.schabi.newpipe.extractor.ListExtractor;
|
||||||
import org.schabi.newpipe.extractor.NewPipe;
|
import org.schabi.newpipe.extractor.NewPipe;
|
||||||
import org.schabi.newpipe.extractor.exceptions.ExtractionException;
|
import org.schabi.newpipe.extractor.exceptions.ExtractionException;
|
||||||
import org.schabi.newpipe.extractor.playlist.PlaylistInfo;
|
import org.schabi.newpipe.extractor.playlist.PlaylistInfo;
|
||||||
|
import org.schabi.newpipe.extractor.stream.StreamInfoItem;
|
||||||
import org.schabi.newpipe.fragments.list.BaseListInfoFragment;
|
import org.schabi.newpipe.fragments.list.BaseListInfoFragment;
|
||||||
import org.schabi.newpipe.player.BackgroundPlayer;
|
import org.schabi.newpipe.info_list.InfoItemDialog;
|
||||||
import org.schabi.newpipe.player.MainVideoPlayer;
|
|
||||||
import org.schabi.newpipe.player.PopupVideoPlayer;
|
|
||||||
import org.schabi.newpipe.playlist.ExternalPlayQueue;
|
|
||||||
import org.schabi.newpipe.playlist.PlayQueue;
|
import org.schabi.newpipe.playlist.PlayQueue;
|
||||||
|
import org.schabi.newpipe.playlist.PlaylistPlayQueue;
|
||||||
|
import org.schabi.newpipe.playlist.SinglePlayQueue;
|
||||||
import org.schabi.newpipe.report.UserAction;
|
import org.schabi.newpipe.report.UserAction;
|
||||||
import org.schabi.newpipe.util.ExtractorHelper;
|
import org.schabi.newpipe.util.ExtractorHelper;
|
||||||
import org.schabi.newpipe.util.NavigationHelper;
|
import org.schabi.newpipe.util.NavigationHelper;
|
||||||
import org.schabi.newpipe.util.PermissionHelper;
|
|
||||||
|
|
||||||
import io.reactivex.Single;
|
import io.reactivex.Single;
|
||||||
|
|
||||||
@@ -50,10 +48,11 @@ public class PlaylistFragment extends BaseListInfoFragment<PlaylistInfo> {
|
|||||||
private TextView headerUploaderName;
|
private TextView headerUploaderName;
|
||||||
private ImageView headerUploaderAvatar;
|
private ImageView headerUploaderAvatar;
|
||||||
private TextView headerStreamCount;
|
private TextView headerStreamCount;
|
||||||
|
private View playlistCtrl;
|
||||||
|
|
||||||
private Button headerPlayAllButton;
|
private View headerPlayAllButton;
|
||||||
private Button headerPopupButton;
|
private View headerPopupButton;
|
||||||
private Button headerBackgroundButton;
|
private View headerBackgroundButton;
|
||||||
|
|
||||||
public static PlaylistFragment getInstance(int serviceId, String url, String name) {
|
public static PlaylistFragment getInstance(int serviceId, String url, String name) {
|
||||||
PlaylistFragment instance = new PlaylistFragment();
|
PlaylistFragment instance = new PlaylistFragment();
|
||||||
@@ -81,10 +80,11 @@ public class PlaylistFragment extends BaseListInfoFragment<PlaylistInfo> {
|
|||||||
headerUploaderName = headerRootLayout.findViewById(R.id.uploader_name);
|
headerUploaderName = headerRootLayout.findViewById(R.id.uploader_name);
|
||||||
headerUploaderAvatar = headerRootLayout.findViewById(R.id.uploader_avatar_view);
|
headerUploaderAvatar = headerRootLayout.findViewById(R.id.uploader_avatar_view);
|
||||||
headerStreamCount = headerRootLayout.findViewById(R.id.playlist_stream_count);
|
headerStreamCount = headerRootLayout.findViewById(R.id.playlist_stream_count);
|
||||||
|
playlistCtrl = headerRootLayout.findViewById(R.id.playlist_control);
|
||||||
|
|
||||||
headerPlayAllButton = headerRootLayout.findViewById(R.id.playlist_play_all_button);
|
headerPlayAllButton = headerRootLayout.findViewById(R.id.playlist_ctrl_play_all_button);
|
||||||
headerPopupButton = headerRootLayout.findViewById(R.id.playlist_play_popup_button);
|
headerPopupButton = headerRootLayout.findViewById(R.id.playlist_ctrl_play_popup_button);
|
||||||
headerBackgroundButton = headerRootLayout.findViewById(R.id.playlist_play_bg_button);
|
headerBackgroundButton = headerRootLayout.findViewById(R.id.playlist_ctrl_play_bg_button);
|
||||||
|
|
||||||
return headerRootLayout;
|
return headerRootLayout;
|
||||||
}
|
}
|
||||||
@@ -96,6 +96,49 @@ public class PlaylistFragment extends BaseListInfoFragment<PlaylistInfo> {
|
|||||||
infoListAdapter.useMiniItemVariants(true);
|
infoListAdapter.useMiniItemVariants(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void showStreamDialog(final StreamInfoItem item) {
|
||||||
|
final Context context = getContext();
|
||||||
|
final Activity activity = getActivity();
|
||||||
|
if (context == null || context.getResources() == null || getActivity() == null) return;
|
||||||
|
|
||||||
|
final String[] commands = new String[]{
|
||||||
|
context.getResources().getString(R.string.enqueue_on_background),
|
||||||
|
context.getResources().getString(R.string.enqueue_on_popup),
|
||||||
|
context.getResources().getString(R.string.start_here_on_main),
|
||||||
|
context.getResources().getString(R.string.start_here_on_background),
|
||||||
|
context.getResources().getString(R.string.start_here_on_popup),
|
||||||
|
};
|
||||||
|
|
||||||
|
final DialogInterface.OnClickListener actions = new DialogInterface.OnClickListener() {
|
||||||
|
@Override
|
||||||
|
public void onClick(DialogInterface dialogInterface, int i) {
|
||||||
|
final int index = Math.max(infoListAdapter.getItemsList().indexOf(item), 0);
|
||||||
|
switch (i) {
|
||||||
|
case 0:
|
||||||
|
NavigationHelper.enqueueOnBackgroundPlayer(context, new SinglePlayQueue(item));
|
||||||
|
break;
|
||||||
|
case 1:
|
||||||
|
NavigationHelper.enqueueOnPopupPlayer(activity, new SinglePlayQueue(item));
|
||||||
|
break;
|
||||||
|
case 2:
|
||||||
|
NavigationHelper.playOnMainPlayer(context, getPlayQueue(index));
|
||||||
|
break;
|
||||||
|
case 3:
|
||||||
|
NavigationHelper.playOnBackgroundPlayer(context, getPlayQueue(index));
|
||||||
|
break;
|
||||||
|
case 4:
|
||||||
|
NavigationHelper.playOnPopupPlayer(activity, getPlayQueue(index));
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
new InfoItemDialog(getActivity(), item, commands, actions).show();
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
|
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
|
||||||
if (DEBUG) Log.d(TAG, "onCreateOptionsMenu() called with: menu = [" + menu + "], inflater = [" + inflater + "]");
|
if (DEBUG) Log.d(TAG, "onCreateOptionsMenu() called with: menu = [" + menu + "], inflater = [" + inflater + "]");
|
||||||
@@ -117,6 +160,23 @@ public class PlaylistFragment extends BaseListInfoFragment<PlaylistInfo> {
|
|||||||
return ExtractorHelper.getPlaylistInfo(serviceId, url, forceLoad);
|
return ExtractorHelper.getPlaylistInfo(serviceId, url, forceLoad);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean onOptionsItemSelected(MenuItem item) {
|
||||||
|
switch (item.getItemId()) {
|
||||||
|
case R.id.menu_item_openInBrowser:
|
||||||
|
openUrlInBrowser(url);
|
||||||
|
break;
|
||||||
|
case R.id.menu_item_share: {
|
||||||
|
shareUrl(name, url);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
return super.onOptionsItemSelected(item);
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/*//////////////////////////////////////////////////////////////////////////
|
/*//////////////////////////////////////////////////////////////////////////
|
||||||
// Contract
|
// Contract
|
||||||
//////////////////////////////////////////////////////////////////////////*/
|
//////////////////////////////////////////////////////////////////////////*/
|
||||||
@@ -138,69 +198,67 @@ public class PlaylistFragment extends BaseListInfoFragment<PlaylistInfo> {
|
|||||||
animateView(headerRootLayout, true, 100);
|
animateView(headerRootLayout, true, 100);
|
||||||
animateView(headerUploaderLayout, true, 300);
|
animateView(headerUploaderLayout, true, 300);
|
||||||
headerUploaderLayout.setOnClickListener(null);
|
headerUploaderLayout.setOnClickListener(null);
|
||||||
if (!TextUtils.isEmpty(result.uploader_name)) {
|
if (!TextUtils.isEmpty(result.getUploaderName())) {
|
||||||
headerUploaderName.setText(result.uploader_name);
|
headerUploaderName.setText(result.getUploaderName());
|
||||||
if (!TextUtils.isEmpty(result.uploader_url)) {
|
if (!TextUtils.isEmpty(result.getUploaderUrl())) {
|
||||||
headerUploaderLayout.setOnClickListener(new View.OnClickListener() {
|
headerUploaderLayout.setOnClickListener(new View.OnClickListener() {
|
||||||
@Override
|
@Override
|
||||||
public void onClick(View v) {
|
public void onClick(View v) {
|
||||||
NavigationHelper.openChannelFragment(getFragmentManager(), result.service_id, result.uploader_url, result.uploader_name);
|
NavigationHelper.openChannelFragment(getFragmentManager(), result.getServiceId(), result.getUploaderUrl(), result.getUploaderName());
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
imageLoader.displayImage(result.uploader_avatar_url, headerUploaderAvatar, DISPLAY_AVATAR_OPTIONS);
|
playlistCtrl.setVisibility(View.VISIBLE);
|
||||||
|
|
||||||
|
imageLoader.displayImage(result.getUploaderAvatarUrl(), headerUploaderAvatar, DISPLAY_AVATAR_OPTIONS);
|
||||||
headerStreamCount.setText(getResources().getQuantityString(R.plurals.videos, (int) result.stream_count, (int) result.stream_count));
|
headerStreamCount.setText(getResources().getQuantityString(R.plurals.videos, (int) result.stream_count, (int) result.stream_count));
|
||||||
|
|
||||||
if (!result.errors.isEmpty()) {
|
if (!result.getErrors().isEmpty()) {
|
||||||
showSnackBarError(result.errors, UserAction.REQUESTED_PLAYLIST, NewPipe.getNameOfService(result.service_id), result.url, 0);
|
showSnackBarError(result.getErrors(), UserAction.REQUESTED_PLAYLIST, NewPipe.getNameOfService(result.getServiceId()), result.getUrl(), 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
headerPlayAllButton.setOnClickListener(new View.OnClickListener() {
|
headerPlayAllButton.setOnClickListener(new View.OnClickListener() {
|
||||||
@Override
|
@Override
|
||||||
public void onClick(View view) {
|
public void onClick(View view) {
|
||||||
startActivity(buildPlaylistIntent(MainVideoPlayer.class));
|
NavigationHelper.playOnMainPlayer(activity, getPlayQueue());
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
headerPopupButton.setOnClickListener(new View.OnClickListener() {
|
headerPopupButton.setOnClickListener(new View.OnClickListener() {
|
||||||
@Override
|
@Override
|
||||||
public void onClick(View view) {
|
public void onClick(View view) {
|
||||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M && !PermissionHelper.checkSystemAlertWindowPermission(activity)) {
|
NavigationHelper.playOnPopupPlayer(activity, getPlayQueue());
|
||||||
Toast toast = Toast.makeText(activity, R.string.msg_popup_permission, Toast.LENGTH_LONG);
|
|
||||||
TextView messageView = toast.getView().findViewById(android.R.id.message);
|
|
||||||
if (messageView != null) messageView.setGravity(Gravity.CENTER);
|
|
||||||
toast.show();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
activity.startService(buildPlaylistIntent(PopupVideoPlayer.class));
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
headerBackgroundButton.setOnClickListener(new View.OnClickListener() {
|
headerBackgroundButton.setOnClickListener(new View.OnClickListener() {
|
||||||
@Override
|
@Override
|
||||||
public void onClick(View view) {
|
public void onClick(View view) {
|
||||||
activity.startService(buildPlaylistIntent(BackgroundPlayer.class));
|
NavigationHelper.playOnBackgroundPlayer(activity, getPlayQueue());
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
private Intent buildPlaylistIntent(final Class targetClazz) {
|
private PlayQueue getPlayQueue() {
|
||||||
final PlayQueue playQueue = new ExternalPlayQueue(
|
return getPlayQueue(0);
|
||||||
currentInfo.service_id,
|
}
|
||||||
currentInfo.url,
|
|
||||||
currentInfo.next_streams_url,
|
private PlayQueue getPlayQueue(final int index) {
|
||||||
|
return new PlaylistPlayQueue(
|
||||||
|
currentInfo.getServiceId(),
|
||||||
|
currentInfo.getUrl(),
|
||||||
|
currentInfo.getNextStreamsUrl(),
|
||||||
infoListAdapter.getItemsList(),
|
infoListAdapter.getItemsList(),
|
||||||
0
|
index
|
||||||
);
|
);
|
||||||
return NavigationHelper.getPlayerIntent(activity, targetClazz, playQueue);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void handleNextItems(ListExtractor.NextItemsResult result) {
|
public void handleNextItems(ListExtractor.NextItemsResult result) {
|
||||||
super.handleNextItems(result);
|
super.handleNextItems(result);
|
||||||
|
|
||||||
if (!result.errors.isEmpty()) {
|
if (!result.getErrors().isEmpty()) {
|
||||||
showSnackBarError(result.errors, UserAction.REQUESTED_PLAYLIST, NewPipe.getNameOfService(serviceId)
|
showSnackBarError(result.getErrors(), UserAction.REQUESTED_PLAYLIST, NewPipe.getNameOfService(serviceId)
|
||||||
, "Get next page of: " + url, 0);
|
, "Get next page of: " + url, 0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -111,7 +111,7 @@ public class SearchFragment extends BaseListFragment<SearchResult, ListExtractor
|
|||||||
|
|
||||||
private int currentPage = 0;
|
private int currentPage = 0;
|
||||||
private int currentNextPage = 0;
|
private int currentNextPage = 0;
|
||||||
private String searchLanguage;
|
private String contentCountry;
|
||||||
private boolean isSuggestionsEnabled = true;
|
private boolean isSuggestionsEnabled = true;
|
||||||
private boolean isSearchHistoryEnabled = true;
|
private boolean isSearchHistoryEnabled = true;
|
||||||
|
|
||||||
@@ -165,7 +165,7 @@ public class SearchFragment extends BaseListFragment<SearchResult, ListExtractor
|
|||||||
suggestionListAdapter = new SuggestionListAdapter(activity);
|
suggestionListAdapter = new SuggestionListAdapter(activity);
|
||||||
SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(activity);
|
SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(activity);
|
||||||
isSearchHistoryEnabled = preferences.getBoolean(getString(R.string.enable_search_history_key), true);
|
isSearchHistoryEnabled = preferences.getBoolean(getString(R.string.enable_search_history_key), true);
|
||||||
suggestionListAdapter.setShowSugestinHistory(isSearchHistoryEnabled);
|
suggestionListAdapter.setShowSuggestionHistory(isSearchHistoryEnabled);
|
||||||
|
|
||||||
searchHistoryDAO = NewPipeDatabase.getInstance().searchHistoryDAO();
|
searchHistoryDAO = NewPipeDatabase.getInstance().searchHistoryDAO();
|
||||||
}
|
}
|
||||||
@@ -176,7 +176,7 @@ public class SearchFragment extends BaseListFragment<SearchResult, ListExtractor
|
|||||||
|
|
||||||
SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(activity);
|
SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(activity);
|
||||||
isSuggestionsEnabled = preferences.getBoolean(getString(R.string.show_search_suggestions_key), true);
|
isSuggestionsEnabled = preferences.getBoolean(getString(R.string.show_search_suggestions_key), true);
|
||||||
searchLanguage = preferences.getString(getString(R.string.search_language_key), getString(R.string.default_language_value));
|
contentCountry = preferences.getString(getString(R.string.content_country_key), getString(R.string.default_country_value));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -446,6 +446,12 @@ public class SearchFragment extends BaseListFragment<SearchResult, ListExtractor
|
|||||||
searchEditText.setText(item.query);
|
searchEditText.setText(item.query);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onSuggestionItemInserted(SuggestionItem item) {
|
||||||
|
searchEditText.setText(item.query);
|
||||||
|
searchEditText.setSelection(searchEditText.getText().length());
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onSuggestionItemLongClick(SuggestionItem item) {
|
public void onSuggestionItemLongClick(SuggestionItem item) {
|
||||||
if (item.fromHistory) showDeleteSuggestionDialog(item);
|
if (item.fromHistory) showDeleteSuggestionDialog(item);
|
||||||
@@ -613,7 +619,7 @@ public class SearchFragment extends BaseListFragment<SearchResult, ListExtractor
|
|||||||
return local.materialize();
|
return local.materialize();
|
||||||
}
|
}
|
||||||
|
|
||||||
final Observable<List<SuggestionItem>> network = ExtractorHelper.suggestionsFor(serviceId, query, searchLanguage).toObservable()
|
final Observable<List<SuggestionItem>> network = ExtractorHelper.suggestionsFor(serviceId, query, contentCountry).toObservable()
|
||||||
.map(new Function<List<String>, List<SuggestionItem>>() {
|
.map(new Function<List<String>, List<SuggestionItem>>() {
|
||||||
@Override
|
@Override
|
||||||
public List<SuggestionItem> apply(@io.reactivex.annotations.NonNull List<String> strings) throws Exception {
|
public List<SuggestionItem> apply(@io.reactivex.annotations.NonNull List<String> strings) throws Exception {
|
||||||
@@ -725,7 +731,7 @@ public class SearchFragment extends BaseListFragment<SearchResult, ListExtractor
|
|||||||
super.startLoading(forceLoad);
|
super.startLoading(forceLoad);
|
||||||
if (disposables != null) disposables.clear();
|
if (disposables != null) disposables.clear();
|
||||||
if (searchDisposable != null) searchDisposable.dispose();
|
if (searchDisposable != null) searchDisposable.dispose();
|
||||||
searchDisposable = ExtractorHelper.searchFor(serviceId, searchQuery, currentPage, searchLanguage, filter)
|
searchDisposable = ExtractorHelper.searchFor(serviceId, searchQuery, currentPage, contentCountry, filter)
|
||||||
.subscribeOn(Schedulers.io())
|
.subscribeOn(Schedulers.io())
|
||||||
.observeOn(AndroidSchedulers.mainThread())
|
.observeOn(AndroidSchedulers.mainThread())
|
||||||
.subscribe(new Consumer<SearchResult>() {
|
.subscribe(new Consumer<SearchResult>() {
|
||||||
@@ -749,7 +755,7 @@ public class SearchFragment extends BaseListFragment<SearchResult, ListExtractor
|
|||||||
showListFooter(true);
|
showListFooter(true);
|
||||||
if (searchDisposable != null) searchDisposable.dispose();
|
if (searchDisposable != null) searchDisposable.dispose();
|
||||||
currentNextPage = currentPage + 1;
|
currentNextPage = currentPage + 1;
|
||||||
searchDisposable = ExtractorHelper.getMoreSearchItems(serviceId, searchQuery, currentNextPage, searchLanguage, filter)
|
searchDisposable = ExtractorHelper.getMoreSearchItems(serviceId, searchQuery, currentNextPage, contentCountry, filter)
|
||||||
.subscribeOn(Schedulers.io())
|
.subscribeOn(Schedulers.io())
|
||||||
.observeOn(AndroidSchedulers.mainThread())
|
.observeOn(AndroidSchedulers.mainThread())
|
||||||
.subscribe(new Consumer<ListExtractor.NextItemsResult>() {
|
.subscribe(new Consumer<ListExtractor.NextItemsResult>() {
|
||||||
@@ -855,8 +861,8 @@ public class SearchFragment extends BaseListFragment<SearchResult, ListExtractor
|
|||||||
lastSearchedQuery = searchQuery;
|
lastSearchedQuery = searchQuery;
|
||||||
|
|
||||||
if (infoListAdapter.getItemsList().size() == 0) {
|
if (infoListAdapter.getItemsList().size() == 0) {
|
||||||
if (result.resultList.size() > 0) {
|
if (!result.getResults().isEmpty()) {
|
||||||
infoListAdapter.addInfoItemList(result.resultList);
|
infoListAdapter.addInfoItemList(result.getResults());
|
||||||
} else {
|
} else {
|
||||||
infoListAdapter.clearStreamItemList();
|
infoListAdapter.clearStreamItemList();
|
||||||
showEmptyState();
|
showEmptyState();
|
||||||
@@ -870,11 +876,11 @@ public class SearchFragment extends BaseListFragment<SearchResult, ListExtractor
|
|||||||
@Override
|
@Override
|
||||||
public void handleNextItems(ListExtractor.NextItemsResult result) {
|
public void handleNextItems(ListExtractor.NextItemsResult result) {
|
||||||
showListFooter(false);
|
showListFooter(false);
|
||||||
currentPage = Integer.parseInt(result.nextItemsUrl);
|
currentPage = Integer.parseInt(result.getNextItemsUrl());
|
||||||
infoListAdapter.addInfoItemList(result.nextItemsList);
|
infoListAdapter.addInfoItemList(result.getNextItemsList());
|
||||||
|
|
||||||
if (!result.errors.isEmpty()) {
|
if (!result.getErrors().isEmpty()) {
|
||||||
showSnackBarError(result.errors, UserAction.SEARCHED, NewPipe.getNameOfService(serviceId)
|
showSnackBarError(result.getErrors(), UserAction.SEARCHED, NewPipe.getNameOfService(serviceId)
|
||||||
, "\"" + searchQuery + "\" → page " + currentPage, 0);
|
, "\"" + searchQuery + "\" → page " + currentPage, 0);
|
||||||
}
|
}
|
||||||
super.handleNextItems(result);
|
super.handleNextItems(result);
|
||||||
|
@@ -19,10 +19,11 @@ public class SuggestionListAdapter extends RecyclerView.Adapter<SuggestionListAd
|
|||||||
private final ArrayList<SuggestionItem> items = new ArrayList<>();
|
private final ArrayList<SuggestionItem> items = new ArrayList<>();
|
||||||
private final Context context;
|
private final Context context;
|
||||||
private OnSuggestionItemSelected listener;
|
private OnSuggestionItemSelected listener;
|
||||||
private boolean showSugestinHistory = true;
|
private boolean showSuggestionHistory = true;
|
||||||
|
|
||||||
public interface OnSuggestionItemSelected {
|
public interface OnSuggestionItemSelected {
|
||||||
void onSuggestionItemSelected(SuggestionItem item);
|
void onSuggestionItemSelected(SuggestionItem item);
|
||||||
|
void onSuggestionItemInserted(SuggestionItem item);
|
||||||
void onSuggestionItemLongClick(SuggestionItem item);
|
void onSuggestionItemLongClick(SuggestionItem item);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -32,7 +33,7 @@ public class SuggestionListAdapter extends RecyclerView.Adapter<SuggestionListAd
|
|||||||
|
|
||||||
public void setItems(List<SuggestionItem> items) {
|
public void setItems(List<SuggestionItem> items) {
|
||||||
this.items.clear();
|
this.items.clear();
|
||||||
if (showSugestinHistory) {
|
if (showSuggestionHistory) {
|
||||||
this.items.addAll(items);
|
this.items.addAll(items);
|
||||||
} else {
|
} else {
|
||||||
// remove history items if history is disabled
|
// remove history items if history is disabled
|
||||||
@@ -49,8 +50,8 @@ public class SuggestionListAdapter extends RecyclerView.Adapter<SuggestionListAd
|
|||||||
this.listener = listener;
|
this.listener = listener;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setShowSugestinHistory(boolean v) {
|
public void setShowSuggestionHistory(boolean v) {
|
||||||
showSugestinHistory = v;
|
showSuggestionHistory = v;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -62,19 +63,25 @@ public class SuggestionListAdapter extends RecyclerView.Adapter<SuggestionListAd
|
|||||||
public void onBindViewHolder(SuggestionItemHolder holder, int position) {
|
public void onBindViewHolder(SuggestionItemHolder holder, int position) {
|
||||||
final SuggestionItem currentItem = getItem(position);
|
final SuggestionItem currentItem = getItem(position);
|
||||||
holder.updateFrom(currentItem);
|
holder.updateFrom(currentItem);
|
||||||
holder.itemView.setOnClickListener(new View.OnClickListener() {
|
holder.queryView.setOnClickListener(new View.OnClickListener() {
|
||||||
@Override
|
@Override
|
||||||
public void onClick(View v) {
|
public void onClick(View v) {
|
||||||
if (listener != null) listener.onSuggestionItemSelected(currentItem);
|
if (listener != null) listener.onSuggestionItemSelected(currentItem);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
holder.itemView.setOnLongClickListener(new View.OnLongClickListener() {
|
holder.queryView.setOnLongClickListener(new View.OnLongClickListener() {
|
||||||
@Override
|
@Override
|
||||||
public boolean onLongClick(View v) {
|
public boolean onLongClick(View v) {
|
||||||
if (listener != null) listener.onSuggestionItemLongClick(currentItem);
|
if (listener != null) listener.onSuggestionItemLongClick(currentItem);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
holder.insertView.setOnClickListener(new View.OnClickListener() {
|
||||||
|
@Override
|
||||||
|
public void onClick(View v) {
|
||||||
|
if (listener != null) listener.onSuggestionItemInserted(currentItem);
|
||||||
|
}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
private SuggestionItem getItem(int position) {
|
private SuggestionItem getItem(int position) {
|
||||||
@@ -93,6 +100,8 @@ public class SuggestionListAdapter extends RecyclerView.Adapter<SuggestionListAd
|
|||||||
public static class SuggestionItemHolder extends RecyclerView.ViewHolder {
|
public static class SuggestionItemHolder extends RecyclerView.ViewHolder {
|
||||||
private final TextView itemSuggestionQuery;
|
private final TextView itemSuggestionQuery;
|
||||||
private final ImageView suggestionIcon;
|
private final ImageView suggestionIcon;
|
||||||
|
private final View queryView;
|
||||||
|
private final View insertView;
|
||||||
|
|
||||||
// Cache some ids, as they can potentially be constantly updated/recycled
|
// Cache some ids, as they can potentially be constantly updated/recycled
|
||||||
private final int historyResId;
|
private final int historyResId;
|
||||||
@@ -103,6 +112,9 @@ public class SuggestionListAdapter extends RecyclerView.Adapter<SuggestionListAd
|
|||||||
suggestionIcon = rootView.findViewById(R.id.item_suggestion_icon);
|
suggestionIcon = rootView.findViewById(R.id.item_suggestion_icon);
|
||||||
itemSuggestionQuery = rootView.findViewById(R.id.item_suggestion_query);
|
itemSuggestionQuery = rootView.findViewById(R.id.item_suggestion_query);
|
||||||
|
|
||||||
|
queryView = rootView.findViewById(R.id.suggestion_search);
|
||||||
|
insertView = rootView.findViewById(R.id.suggestion_insert);
|
||||||
|
|
||||||
historyResId = resolveResourceIdFromAttr(rootView.getContext(), R.attr.history);
|
historyResId = resolveResourceIdFromAttr(rootView.getContext(), R.attr.history);
|
||||||
searchResId = resolveResourceIdFromAttr(rootView.getContext(), R.attr.search);
|
searchResId = resolveResourceIdFromAttr(rootView.getContext(), R.attr.search);
|
||||||
}
|
}
|
||||||
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user