mirror of
https://github.com/TeamNewPipe/NewPipe
synced 2025-09-24 08:40:51 +02:00
Compare commits
100 Commits
Author | SHA1 | Date | |
---|---|---|---|
![]() |
a98c0bdec7 | ||
![]() |
cdfe686322 | ||
![]() |
553943ab93 | ||
![]() |
1281ea858c | ||
![]() |
30a303f873 | ||
![]() |
70b9330b61 | ||
![]() |
f1e8667945 | ||
![]() |
509f501696 | ||
![]() |
3fe0368486 | ||
![]() |
8f027e274e | ||
![]() |
f6bca68da2 | ||
![]() |
d921e2e61b | ||
![]() |
0f7ed0ec70 | ||
![]() |
49b12ea4f8 | ||
![]() |
69fc466323 | ||
![]() |
81d00f2e97 | ||
![]() |
ded6540422 | ||
![]() |
583a028529 | ||
![]() |
f1bb56e2fb | ||
![]() |
f583dd47ac | ||
![]() |
7e3b3453c0 | ||
![]() |
abc354f516 | ||
![]() |
79efffe12f | ||
![]() |
25130db371 | ||
![]() |
932eb94f9d | ||
![]() |
9bf4eff173 | ||
![]() |
9fc3ddeab7 | ||
![]() |
98fdbec442 | ||
![]() |
332b90d6c1 | ||
![]() |
db2e03eb14 | ||
![]() |
8ed8b94ec7 | ||
![]() |
63c9308f59 | ||
![]() |
1306a777fc | ||
![]() |
f739ed7581 | ||
![]() |
b4d6015464 | ||
![]() |
b9aaafdb30 | ||
![]() |
71aa6c6e92 | ||
![]() |
f98d2631e5 | ||
![]() |
9e94c81ef2 | ||
![]() |
d025ef11f8 | ||
![]() |
fe7536e374 | ||
![]() |
14256137e8 | ||
![]() |
bc3e43ac58 | ||
![]() |
d0d5373be9 | ||
![]() |
997267bad1 | ||
![]() |
ef6d0cc4b1 | ||
![]() |
ffad244e1e | ||
![]() |
fdee7c3d06 | ||
![]() |
142cde975f | ||
![]() |
004907d306 | ||
![]() |
05eb0d0fbe | ||
![]() |
f13a1b04e6 | ||
![]() |
fd4408e572 | ||
![]() |
a84ab7413c | ||
![]() |
62b593da08 | ||
![]() |
0eb69b6659 | ||
![]() |
67b83388b1 | ||
![]() |
ecc998aea8 | ||
![]() |
6956d16f0e | ||
![]() |
f1bc4f5c20 | ||
![]() |
f134e2d02a | ||
![]() |
6ec72ef945 | ||
![]() |
e8d518cd6c | ||
![]() |
b564433ff6 | ||
![]() |
79f7dcd1a3 | ||
![]() |
23ee9b7867 | ||
![]() |
afbf36900f | ||
![]() |
26c535db84 | ||
![]() |
ea1b910d7e | ||
![]() |
8f4c6fb6ac | ||
![]() |
9b1861417c | ||
![]() |
8080c32b1f | ||
![]() |
4b27aec196 | ||
![]() |
38fb510375 | ||
![]() |
6422e31b10 | ||
![]() |
c0f47195a2 | ||
![]() |
40f66977c7 | ||
![]() |
e518c0dc14 | ||
![]() |
2e161a1f45 | ||
![]() |
5ab6e84044 | ||
![]() |
e1a6347c4e | ||
![]() |
bf8e8798d9 | ||
![]() |
08949ee347 | ||
![]() |
92a67bb8cb | ||
![]() |
363bbf5fd3 | ||
![]() |
77f6940336 | ||
![]() |
e8eeac6735 | ||
![]() |
775fbc9a75 | ||
![]() |
8d0f2d371d | ||
![]() |
8efe2859b8 | ||
![]() |
441c68ead2 | ||
![]() |
882b235a78 | ||
![]() |
4cd1f201f5 | ||
![]() |
013c59f904 | ||
![]() |
57474e2dab | ||
![]() |
10b1da135e | ||
![]() |
b2b9938484 | ||
![]() |
a012e26d63 | ||
![]() |
4357e02c58 | ||
![]() |
67c0ceedc9 |
4
.github/CONTRIBUTING.md
vendored
4
.github/CONTRIBUTING.md
vendored
@@ -41,6 +41,6 @@ You'll see exactly what is sent, be able to add your comments, and then send it.
|
||||
|
||||
## Communication
|
||||
|
||||
* The [#newpipe](irc:irc.freenode.net/newpipe) channel on freenode has the core team and other developers in it. [Click here for webchat](https://webchat.freenode.net/?channels=newpipe)!
|
||||
* You can also use a Matrix account to join the Newpipe channel at [#freenode_#newpipe:matrix.org](https://matrix.to/#/#freenode_#newpipe:matrix.org).
|
||||
* The #newpipe channel on Libera Chat (`ircs://irc.libera.chat:6697/newpipe`) has the core team and other developers in it. [Click here for webchat](https://web.libera.chat/#newpipe)!
|
||||
* You can also use a Matrix account to join the NewPipe channel at [#newpipe:libera.chat](https://matrix.to/#/#newpipe:libera.chat).
|
||||
* Post suggestions, changes, ideas etc. on GitHub or IRC.
|
||||
|
4
.github/ISSUE_TEMPLATE/config.yml
vendored
4
.github/ISSUE_TEMPLATE/config.yml
vendored
@@ -1,8 +1,8 @@
|
||||
blank_issues_enabled: false
|
||||
contact_links:
|
||||
- name: 💬 IRC
|
||||
url: https://webchat.freenode.net/#newpipe
|
||||
url: https://web.libera.chat/#newpipe
|
||||
about: Chat with us via IRC for quick Q/A
|
||||
- name: 💬 Matrix
|
||||
url: https://matrix.to/#/#freenode_#newpipe:matrix.org
|
||||
url: https://matrix.to/#/#newpipe:libera.chat
|
||||
about: Chat with us via Matrix for quick Q/A
|
||||
|
7
.github/workflows/ci.yml
vendored
7
.github/workflows/ci.yml
vendored
@@ -4,6 +4,7 @@ on:
|
||||
pull_request:
|
||||
branches:
|
||||
- dev
|
||||
- master
|
||||
push:
|
||||
branches:
|
||||
- dev
|
||||
@@ -25,7 +26,7 @@ jobs:
|
||||
uses: actions/setup-java@v2
|
||||
with:
|
||||
java-version: 8
|
||||
distribution: "zulu"
|
||||
distribution: "adopt"
|
||||
|
||||
- name: Cache Gradle dependencies
|
||||
uses: actions/cache@v2
|
||||
@@ -54,7 +55,7 @@ jobs:
|
||||
uses: actions/setup-java@v2
|
||||
with:
|
||||
java-version: 8
|
||||
distribution: "zulu"
|
||||
distribution: "adopt"
|
||||
|
||||
- name: Cache Gradle dependencies
|
||||
uses: actions/cache@v2
|
||||
@@ -79,7 +80,7 @@ jobs:
|
||||
# uses: actions/setup-java@v2
|
||||
# with:
|
||||
# java-version: 11 # Sonar requires JDK 11
|
||||
# distribution: "zulu"
|
||||
# distribution: "adopt"
|
||||
|
||||
# - name: Cache SonarCloud packages
|
||||
# uses: actions/cache@v2
|
||||
|
@@ -9,7 +9,7 @@
|
||||
<a href="https://www.gnu.org/licenses/gpl-3.0" alt="License: GPLv3"><img src="https://img.shields.io/badge/Licencia-GPL%20v3-blue.svg"></a>
|
||||
<a href="https://github.com/TeamNewPipe/NewPipe/actions" alt="Build Status"><img src="https://github.com/TeamNewPipe/NewPipe/workflows/CI/badge.svg?branch=dev&event=push"></a>
|
||||
<a href="https://hosted.weblate.org/engage/newpipe/es/" alt="Estado de la traducción"><img src="https://hosted.weblate.org/widgets/newpipe/es/svg-badge.svg"></a>
|
||||
<a href="https://webchat.freenode.net/#newpipe" alt="IRC channel: #newpipe"><img src="https://img.shields.io/badge/Canal%20de%20IRC%20-%23newpipe-brightgreen.svg"></a>
|
||||
<a href="https://web.libera.chat/#newpipe" alt="IRC channel: #newpipe"><img src="https://img.shields.io/badge/Canal%20de%20IRC%20-%23newpipe-brightgreen.svg"></a>
|
||||
<a href="https://www.bountysource.com/teams/newpipe" alt="Bountysource bounties"><img src="https://img.shields.io/bountysource/team/newpipe/activity.svg?colorB=cd201f"></a>
|
||||
</p>
|
||||
<hr>
|
||||
|
@@ -9,7 +9,7 @@
|
||||
<a href="https://www.gnu.org/licenses/gpl-3.0" alt="ライセンス: GPLv3"><img src="https://img.shields.io/badge/License-GPL%20v3-blue.svg"></a>
|
||||
<a href="https://github.com/TeamNewPipe/NewPipe/actions" alt="ビルド状態"><img src="https://github.com/TeamNewPipe/NewPipe/workflows/CI/badge.svg?branch=dev&event=push"></a>
|
||||
<a href="https://hosted.weblate.org/engage/newpipe/" alt="翻訳状態"><img src="https://hosted.weblate.org/widgets/newpipe/-/svg-badge.svg"></a>
|
||||
<a href="https://webchat.freenode.net/#newpipe" alt="IRC チャンネル: #newpipe"><img src="https://img.shields.io/badge/IRC%20chat-%23newpipe-brightgreen.svg"></a>
|
||||
<a href="https://web.libera.chat/#newpipe" alt="IRC チャンネル: #newpipe"><img src="https://img.shields.io/badge/IRC%20chat-%23newpipe-brightgreen.svg"></a>
|
||||
<a href="https://www.bountysource.com/teams/newpipe" alt="Bountysource 寄付"><img src="https://img.shields.io/bountysource/team/newpipe/activity.svg?colorB=cd201f"></a>
|
||||
</p>
|
||||
<hr>
|
||||
|
@@ -9,7 +9,7 @@
|
||||
<a href="https://www.gnu.org/licenses/gpl-3.0" alt="License: GPLv3"><img src="https://img.shields.io/badge/License-GPL%20v3-blue.svg"></a>
|
||||
<a href="https://github.com/TeamNewPipe/NewPipe/actions" alt="Build Status"><img src="https://github.com/TeamNewPipe/NewPipe/workflows/CI/badge.svg?branch=dev&event=push"></a>
|
||||
<a href="https://hosted.weblate.org/engage/newpipe/" alt="Translation Status"><img src="https://hosted.weblate.org/widgets/newpipe/-/svg-badge.svg"></a>
|
||||
<a href="https://webchat.freenode.net/#newpipe" alt="IRC channel: #newpipe"><img src="https://img.shields.io/badge/IRC%20chat-%23newpipe-brightgreen.svg"></a>
|
||||
<a href="https://web.libera.chat/#newpipe" alt="IRC channel: #newpipe"><img src="https://img.shields.io/badge/IRC%20chat-%23newpipe-brightgreen.svg"></a>
|
||||
<a href="https://www.bountysource.com/teams/newpipe" alt="Bountysource bounties"><img src="https://img.shields.io/bountysource/team/newpipe/activity.svg?colorB=cd201f"></a>
|
||||
</p>
|
||||
<hr>
|
||||
|
@@ -9,7 +9,7 @@
|
||||
<a href="https://www.gnu.org/licenses/gpl-3.0" alt="License: GPLv3"><img src="https://img.shields.io/badge/License-GPL%20v3-blue.svg"></a>
|
||||
<a href="https://github.com/TeamNewPipe/NewPipe/actions" alt="Build Status"><img src="https://github.com/TeamNewPipe/NewPipe/workflows/CI/badge.svg?branch=dev&event=push"></a>
|
||||
<a href="https://hosted.weblate.org/engage/newpipe/" alt="Translation Status"><img src="https://hosted.weblate.org/widgets/newpipe/-/svg-badge.svg"></a>
|
||||
<a href="https://webchat.freenode.net/#newpipe" alt="IRC channel: #newpipe"><img src="https://img.shields.io/badge/IRC%20chat-%23newpipe-brightgreen.svg"></a>
|
||||
<a href="https://web.libera.chat/#newpipe" alt="IRC channel: #newpipe"><img src="https://img.shields.io/badge/IRC%20chat-%23newpipe-brightgreen.svg"></a>
|
||||
<a href="https://www.bountysource.com/teams/newpipe" alt="Bountysource bounties"><img src="https://img.shields.io/bountysource/team/newpipe/activity.svg?colorB=cd201f"></a>
|
||||
</p>
|
||||
<hr>
|
||||
|
@@ -10,7 +10,7 @@
|
||||
<a href="https://www.gnu.org/licenses/gpl-3.0" alt="License: GPLv3"><img src="https://img.shields.io/badge/License-GPL%20v3-blue.svg"></a>
|
||||
<a href="https://github.com/TeamNewPipe/NewPipe/actions" alt="Build Status"><img src="https://github.com/TeamNewPipe/NewPipe/workflows/CI/badge.svg?branch=dev&event=push"></a>
|
||||
<a href="https://hosted.weblate.org/engage/newpipe/" alt="Translation Status"><img src="https://hosted.weblate.org/widgets/newpipe/-/svg-badge.svg"></a>
|
||||
<a href="https://webchat.freenode.net/#newpipe" alt="IRC channel: #newpipe"><img src="https://img.shields.io/badge/IRC%20chat-%23newpipe-brightgreen.svg"></a>
|
||||
<a href="https://web.libera.chat/#newpipe" alt="IRC channel: #newpipe"><img src="https://img.shields.io/badge/IRC%20chat-%23newpipe-brightgreen.svg"></a>
|
||||
<a href="https://www.bountysource.com/teams/newpipe" alt="Bountysource bounties"><img src="https://img.shields.io/bountysource/team/newpipe/activity.svg?colorB=cd201f"></a>
|
||||
</p>
|
||||
<hr>
|
||||
|
@@ -9,7 +9,7 @@
|
||||
<a href="https://www.gnu.org/licenses/gpl-3.0" alt="License: GPLv3"><img src="https://img.shields.io/badge/License-GPL%20v3-blue.svg"></a>
|
||||
<a href="https://github.com/TeamNewPipe/NewPipe/actions" alt="Build Status"><img src="https://github.com/TeamNewPipe/NewPipe/workflows/CI/badge.svg?branch=dev&event=push"></a>
|
||||
<a href="https://hosted.weblate.org/engage/newpipe/" alt="Translation Status"><img src="https://hosted.weblate.org/widgets/newpipe/-/svg-badge.svg"></a>
|
||||
<a href="https://webchat.freenode.net/#newpipe" alt="IRC channel: #newpipe"><img src="https://img.shields.io/badge/IRC%20chat-%23newpipe-brightgreen.svg"></a>
|
||||
<a href="https://web.libera.chat/#newpipe" alt="IRC channel: #newpipe"><img src="https://img.shields.io/badge/IRC%20chat-%23newpipe-brightgreen.svg"></a>
|
||||
<a href="https://www.bountysource.com/teams/newpipe" alt="Bountysource bounties"><img src="https://img.shields.io/bountysource/team/newpipe/activity.svg?colorB=cd201f"></a>
|
||||
</p>
|
||||
<hr>
|
||||
|
@@ -9,7 +9,7 @@
|
||||
<a href="https://www.gnu.org/licenses/gpl-3.0" alt="Laysinka: GPLv3"><img src="https://img.shields.io/badge/License-GPL%20v3-blue.svg"></a>
|
||||
<a href="https://github.com/TeamNewPipe/NewPipe/actions" alt="Darajada Dhismaha"><img src="https://github.com/TeamNewPipe/NewPipe/workflows/CI/badge.svg?branch=dev&event=push"></a>
|
||||
<a href="https://hosted.weblate.org/engage/newpipe/" alt="Heerka Turjimaada"><img src="https://hosted.weblate.org/widgets/newpipe/-/svg-badge.svg"></a>
|
||||
<a href="https://webchat.freenode.net/#newpipe" alt="Kanaalka IRC: #newpipe"><img src="https://img.shields.io/badge/IRC%20chat-%23newpipe-brightgreen.svg"></a>
|
||||
<a href="https://web.libera.chat/#newpipe" alt="Kanaalka IRC: #newpipe"><img src="https://img.shields.io/badge/IRC%20chat-%23newpipe-brightgreen.svg"></a>
|
||||
<a href="https://www.bountysource.com/teams/newpipe" alt="Kuwa Bountysource "><img src="https://img.shields.io/bountysource/team/newpipe/activity.svg?colorB=cd201f"></a>
|
||||
</p>
|
||||
<hr>
|
||||
|
@@ -9,7 +9,7 @@
|
||||
<a href="https://www.gnu.org/licenses/gpl-3.0" alt="Lisans: GPLv3"><img src="https://img.shields.io/badge/License-GPL%20v3-blue.svg"></a>
|
||||
<a href="https://github.com/TeamNewPipe/NewPipe/actions" alt="Derleme Durumu"><img src="https://github.com/TeamNewPipe/NewPipe/workflows/CI/badge.svg?branch=dev&event=push"></a>
|
||||
<a href="https://hosted.weblate.org/engage/newpipe/" alt="Çeviri Durumu"><img src="https://hosted.weblate.org/widgets/newpipe/-/svg-badge.svg"></a>
|
||||
<a href="https://webchat.freenode.net/#newpipe" alt="IRC kanalı: #newpipe"><img src="https://img.shields.io/badge/IRC%20chat-%23newpipe-brightgreen.svg"></a>
|
||||
<a href="https://web.libera.chat/#newpipe" alt="IRC kanalı: #newpipe"><img src="https://img.shields.io/badge/IRC%20chat-%23newpipe-brightgreen.svg"></a>
|
||||
<a href="https://www.bountysource.com/teams/newpipe" alt="Bountysource ödülleri"><img src="https://img.shields.io/bountysource/team/newpipe/activity.svg?colorB=cd201f"></a>
|
||||
</p>
|
||||
<hr>
|
||||
|
@@ -17,8 +17,8 @@ android {
|
||||
resValue "string", "app_name", "NewPipe"
|
||||
minSdkVersion 19
|
||||
targetSdkVersion 29
|
||||
versionCode 969
|
||||
versionName "0.21.3"
|
||||
versionCode 971
|
||||
versionName "0.21.5"
|
||||
|
||||
multiDexEnabled true
|
||||
|
||||
@@ -178,12 +178,12 @@ sonarqube {
|
||||
|
||||
dependencies {
|
||||
/** Desugaring **/
|
||||
coreLibraryDesugaring 'com.android.tools:desugar_jdk_libs:1.1.1'
|
||||
coreLibraryDesugaring 'com.android.tools:desugar_jdk_libs:1.1.5'
|
||||
|
||||
/** NewPipe libraries **/
|
||||
// You can use a local version by uncommenting a few lines in settings.gradle
|
||||
implementation 'com.github.TeamNewPipe:nanojson:1d9e1aea9049fc9f85e68b43ba39fe7be1c1f751'
|
||||
implementation 'com.github.TeamNewPipe:NewPipeExtractor:v0.21.3'
|
||||
implementation 'com.github.TeamNewPipe:NewPipeExtractor:v0.21.4'
|
||||
|
||||
/** Checkstyle **/
|
||||
checkstyle "com.puppycrawl.tools:checkstyle:${checkstyleVersion}"
|
||||
@@ -258,7 +258,7 @@ dependencies {
|
||||
implementation "com.jakewharton.rxbinding4:rxbinding:4.0.0"
|
||||
|
||||
// Date and time formatting
|
||||
implementation "org.ocpsoft.prettytime:prettytime:5.0.0.Final"
|
||||
implementation "org.ocpsoft.prettytime:prettytime:5.0.1.Final"
|
||||
|
||||
/** Debugging **/
|
||||
// Memory leak detection
|
||||
@@ -270,7 +270,7 @@ dependencies {
|
||||
debugImplementation "com.facebook.stetho:stetho-okhttp3:${stethoVersion}"
|
||||
|
||||
/** Testing **/
|
||||
testImplementation 'junit:junit:4.13.1'
|
||||
testImplementation 'junit:junit:4.13.2'
|
||||
testImplementation "org.mockito:mockito-core:${mockitoVersion}"
|
||||
testImplementation "org.mockito:mockito-inline:${mockitoVersion}"
|
||||
|
||||
|
@@ -319,7 +319,7 @@
|
||||
<data android:pathPrefix="/video-channels/" />
|
||||
</intent-filter>
|
||||
|
||||
<!-- Bandcamp filter -->
|
||||
<!-- Bandcamp filter for tracks, albums and playlists -->
|
||||
<intent-filter>
|
||||
<action android:name="android.intent.action.VIEW"/>
|
||||
<action android:name="android.media.action.MEDIA_PLAY_FROM_SEARCH"/>
|
||||
@@ -330,10 +330,23 @@
|
||||
|
||||
<data android:scheme="http"/>
|
||||
<data android:scheme="https"/>
|
||||
<data android:host="bandcamp.com"/>
|
||||
<data android:host="*.bandcamp.com"/>
|
||||
<data android:pathPrefix="/"/>
|
||||
</intent-filter>
|
||||
|
||||
<!-- Bandcamp filter for radio -->
|
||||
<intent-filter>
|
||||
<action android:name="android.intent.action.VIEW"/>
|
||||
<action android:name="android.media.action.MEDIA_PLAY_FROM_SEARCH"/>
|
||||
<action android:name="android.nfc.action.NDEF_DISCOVERED"/>
|
||||
|
||||
<category android:name="android.intent.category.DEFAULT"/>
|
||||
<category android:name="android.intent.category.BROWSABLE"/>
|
||||
|
||||
<data android:scheme="http"/>
|
||||
<data android:scheme="https"/>
|
||||
<data android:sspPattern="bandcamp.com/?show=*"/>
|
||||
</intent-filter>
|
||||
|
||||
</activity>
|
||||
<service
|
||||
android:name=".RouterActivity$FetcherService"
|
||||
|
@@ -95,6 +95,7 @@ import static org.schabi.newpipe.util.Localization.assureCorrectAppLanguage;
|
||||
|
||||
public class MainActivity extends AppCompatActivity {
|
||||
private static final String TAG = "MainActivity";
|
||||
@SuppressWarnings("ConstantConditions")
|
||||
public static final boolean DEBUG = !BuildConfig.BUILD_TYPE.equals("release");
|
||||
|
||||
private ActivityMainBinding mainBinding;
|
||||
|
@@ -466,6 +466,11 @@ public class RouterActivity extends AppCompatActivity {
|
||||
if (capabilities.contains(AUDIO)) {
|
||||
returnList.add(backgroundPlayer);
|
||||
}
|
||||
// download is redundant for linkType CHANNEL AND PLAYLIST (till playlist downloading is
|
||||
// not supported )
|
||||
returnList.add(new AdapterChoiceItem(getString(R.string.download_key),
|
||||
getString(R.string.download),
|
||||
R.drawable.ic_file_download));
|
||||
|
||||
} else {
|
||||
returnList.add(showInfo);
|
||||
@@ -478,10 +483,6 @@ public class RouterActivity extends AppCompatActivity {
|
||||
}
|
||||
}
|
||||
|
||||
returnList.add(new AdapterChoiceItem(getString(R.string.download_key),
|
||||
getString(R.string.download),
|
||||
R.drawable.ic_file_download));
|
||||
|
||||
return returnList;
|
||||
}
|
||||
|
||||
|
@@ -312,25 +312,36 @@ public class DownloadDialog extends DialogFragment
|
||||
|
||||
private void fetchStreamsSize() {
|
||||
disposables.clear();
|
||||
|
||||
disposables.add(StreamSizeWrapper.fetchSizeForWrapper(wrappedVideoStreams)
|
||||
.subscribe(result -> {
|
||||
if (dialogBinding.videoAudioGroup.getCheckedRadioButtonId() == R.id.video_button) {
|
||||
setupVideoSpinner();
|
||||
}
|
||||
}));
|
||||
if (dialogBinding.videoAudioGroup.getCheckedRadioButtonId()
|
||||
== R.id.video_button) {
|
||||
setupVideoSpinner();
|
||||
}
|
||||
}, throwable -> ErrorActivity.reportErrorInSnackbar(context,
|
||||
new ErrorInfo(throwable, UserAction.DOWNLOAD_OPEN_DIALOG,
|
||||
"Downloading video stream size",
|
||||
currentInfo.getServiceId()))));
|
||||
disposables.add(StreamSizeWrapper.fetchSizeForWrapper(wrappedAudioStreams)
|
||||
.subscribe(result -> {
|
||||
if (dialogBinding.videoAudioGroup.getCheckedRadioButtonId() == R.id.audio_button) {
|
||||
setupAudioSpinner();
|
||||
}
|
||||
}));
|
||||
if (dialogBinding.videoAudioGroup.getCheckedRadioButtonId()
|
||||
== R.id.audio_button) {
|
||||
setupAudioSpinner();
|
||||
}
|
||||
}, throwable -> ErrorActivity.reportErrorInSnackbar(context,
|
||||
new ErrorInfo(throwable, UserAction.DOWNLOAD_OPEN_DIALOG,
|
||||
"Downloading audio stream size",
|
||||
currentInfo.getServiceId()))));
|
||||
disposables.add(StreamSizeWrapper.fetchSizeForWrapper(wrappedSubtitleStreams)
|
||||
.subscribe(result -> {
|
||||
if (dialogBinding.videoAudioGroup.getCheckedRadioButtonId() == R.id.subtitle_button) {
|
||||
setupSubtitleSpinner();
|
||||
}
|
||||
}));
|
||||
if (dialogBinding.videoAudioGroup.getCheckedRadioButtonId()
|
||||
== R.id.subtitle_button) {
|
||||
setupSubtitleSpinner();
|
||||
}
|
||||
}, throwable -> ErrorActivity.reportErrorInSnackbar(context,
|
||||
new ErrorInfo(throwable, UserAction.DOWNLOAD_OPEN_DIALOG,
|
||||
"Downloading subtitle stream size",
|
||||
currentInfo.getServiceId()))));
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@@ -11,15 +11,20 @@ import org.schabi.newpipe.BaseFragment;
|
||||
import org.schabi.newpipe.R;
|
||||
|
||||
public class EmptyFragment extends BaseFragment {
|
||||
final boolean showMessage;
|
||||
private static final String SHOW_MESSAGE = "SHOW_MESSAGE";
|
||||
|
||||
public EmptyFragment(final boolean showMessage) {
|
||||
this.showMessage = showMessage;
|
||||
public static final EmptyFragment newInstance(final boolean showMessage) {
|
||||
final EmptyFragment emptyFragment = new EmptyFragment();
|
||||
final Bundle bundle = new Bundle(1);
|
||||
bundle.putBoolean(SHOW_MESSAGE, showMessage);
|
||||
emptyFragment.setArguments(bundle);
|
||||
return emptyFragment;
|
||||
}
|
||||
|
||||
@Override
|
||||
public View onCreateView(final LayoutInflater inflater, @Nullable final ViewGroup container,
|
||||
final Bundle savedInstanceState) {
|
||||
final boolean showMessage = getArguments().getBoolean(SHOW_MESSAGE);
|
||||
final View view = inflater.inflate(R.layout.fragment_empty, container, false);
|
||||
view.findViewById(R.id.empty_state_view).setVisibility(
|
||||
showMessage ? View.VISIBLE : View.GONE);
|
||||
|
File diff suppressed because it is too large
Load Diff
@@ -929,20 +929,20 @@ public final class VideoDetailFragment
|
||||
|
||||
if (showRelatedItems && binding.relatedItemsLayout == null) {
|
||||
// temp empty fragment. will be updated in handleResult
|
||||
pageAdapter.addFragment(new EmptyFragment(false), RELATED_TAB_TAG);
|
||||
pageAdapter.addFragment(EmptyFragment.newInstance(false), RELATED_TAB_TAG);
|
||||
tabIcons.add(R.drawable.ic_art_track);
|
||||
tabContentDescriptions.add(R.string.related_items_tab_description);
|
||||
}
|
||||
|
||||
if (showDescription) {
|
||||
// temp empty fragment. will be updated in handleResult
|
||||
pageAdapter.addFragment(new EmptyFragment(false), DESCRIPTION_TAB_TAG);
|
||||
pageAdapter.addFragment(EmptyFragment.newInstance(false), DESCRIPTION_TAB_TAG);
|
||||
tabIcons.add(R.drawable.ic_description);
|
||||
tabContentDescriptions.add(R.string.description_tab_description);
|
||||
}
|
||||
|
||||
if (pageAdapter.getCount() == 0) {
|
||||
pageAdapter.addFragment(new EmptyFragment(true), EMPTY_TAB_TAG);
|
||||
pageAdapter.addFragment(EmptyFragment.newInstance(true), EMPTY_TAB_TAG);
|
||||
}
|
||||
pageAdapter.notifyDataSetUpdate();
|
||||
|
||||
|
@@ -370,10 +370,10 @@ public abstract class BaseListFragment<I, N> extends BaseStateFragment<I>
|
||||
StreamDialogEntry.share
|
||||
));
|
||||
}
|
||||
entries.add(StreamDialogEntry.open_in_browser);
|
||||
if (KoreUtil.shouldShowPlayWithKodi(context, item.getServiceId())) {
|
||||
entries.add(StreamDialogEntry.play_with_kodi);
|
||||
}
|
||||
|
||||
if (!isNullOrEmpty(item.getUploaderUrl())) {
|
||||
entries.add(StreamDialogEntry.show_channel_details);
|
||||
}
|
||||
|
@@ -59,6 +59,7 @@ import io.reactivex.rxjava3.core.Single;
|
||||
import io.reactivex.rxjava3.disposables.CompositeDisposable;
|
||||
import io.reactivex.rxjava3.disposables.Disposable;
|
||||
|
||||
import static org.schabi.newpipe.extractor.utils.Utils.isNullOrEmpty;
|
||||
import static org.schabi.newpipe.ktx.ViewUtils.animate;
|
||||
import static org.schabi.newpipe.ktx.ViewUtils.animateHideRecyclerViewAllowingScrolling;
|
||||
|
||||
@@ -160,9 +161,15 @@ public class PlaylistFragment extends BaseListInfoFragment<PlaylistInfo> {
|
||||
StreamDialogEntry.share
|
||||
));
|
||||
}
|
||||
entries.add(StreamDialogEntry.open_in_browser);
|
||||
if (KoreUtil.shouldShowPlayWithKodi(context, item.getServiceId())) {
|
||||
entries.add(StreamDialogEntry.play_with_kodi);
|
||||
}
|
||||
|
||||
if (!isNullOrEmpty(item.getUploaderUrl())) {
|
||||
entries.add(StreamDialogEntry.show_channel_details);
|
||||
}
|
||||
|
||||
StreamDialogEntry.setEnabledEntries(entries);
|
||||
|
||||
StreamDialogEntry.start_here_on_background.setCustomAction((fragment, infoItem) ->
|
||||
|
@@ -9,6 +9,7 @@ import android.text.Editable;
|
||||
import android.text.Html;
|
||||
import android.text.TextUtils;
|
||||
import android.text.TextWatcher;
|
||||
import android.text.style.CharacterStyle;
|
||||
import android.util.Log;
|
||||
import android.view.KeyEvent;
|
||||
import android.view.LayoutInflater;
|
||||
@@ -588,6 +589,11 @@ public class SearchFragment extends BaseListFragment<SearchInfo, ListExtractor.I
|
||||
|
||||
@Override
|
||||
public void afterTextChanged(final Editable s) {
|
||||
// Remove rich text formatting
|
||||
for (final CharacterStyle span : s.getSpans(0, s.length(), CharacterStyle.class)) {
|
||||
s.removeSpan(span);
|
||||
}
|
||||
|
||||
final String newText = searchEditText.getText().toString();
|
||||
suggestionPublisher.onNext(newText);
|
||||
}
|
||||
|
@@ -137,7 +137,10 @@ public class CommentsMiniInfoItemHolder extends InfoItemHolder {
|
||||
}
|
||||
|
||||
if (item.getLikeCount() >= 0) {
|
||||
itemLikesCountView.setText(String.valueOf(item.getLikeCount()));
|
||||
itemLikesCountView.setText(
|
||||
Localization.shortCount(
|
||||
itemBuilder.getContext(),
|
||||
item.getLikeCount()));
|
||||
} else {
|
||||
itemLikesCountView.setText("-");
|
||||
}
|
||||
|
@@ -53,6 +53,8 @@ import io.reactivex.rxjava3.android.schedulers.AndroidSchedulers;
|
||||
import io.reactivex.rxjava3.disposables.CompositeDisposable;
|
||||
import io.reactivex.rxjava3.disposables.Disposable;
|
||||
|
||||
import static org.schabi.newpipe.extractor.utils.Utils.isNullOrEmpty;
|
||||
|
||||
public class StatisticsPlaylistFragment
|
||||
extends BaseLocalListFragment<List<StreamStatisticsEntry>, Void> {
|
||||
private final CompositeDisposable disposables = new CompositeDisposable();
|
||||
@@ -356,9 +358,15 @@ public class StatisticsPlaylistFragment
|
||||
StreamDialogEntry.share
|
||||
));
|
||||
}
|
||||
entries.add(StreamDialogEntry.open_in_browser);
|
||||
if (KoreUtil.shouldShowPlayWithKodi(context, infoItem.getServiceId())) {
|
||||
entries.add(StreamDialogEntry.play_with_kodi);
|
||||
}
|
||||
|
||||
if (!isNullOrEmpty(infoItem.getUploaderUrl())) {
|
||||
entries.add(StreamDialogEntry.show_channel_details);
|
||||
}
|
||||
|
||||
StreamDialogEntry.setEnabledEntries(entries);
|
||||
|
||||
StreamDialogEntry.start_here_on_background.setCustomAction((fragment, infoItemDuplicate) ->
|
||||
|
@@ -66,6 +66,7 @@ import io.reactivex.rxjava3.disposables.Disposable;
|
||||
import io.reactivex.rxjava3.schedulers.Schedulers;
|
||||
import io.reactivex.rxjava3.subjects.PublishSubject;
|
||||
|
||||
import static org.schabi.newpipe.extractor.utils.Utils.isNullOrEmpty;
|
||||
import static org.schabi.newpipe.ktx.ViewUtils.animate;
|
||||
|
||||
public class LocalPlaylistFragment extends BaseLocalListFragment<List<PlaylistStreamEntry>, Void> {
|
||||
@@ -768,9 +769,15 @@ public class LocalPlaylistFragment extends BaseLocalListFragment<List<PlaylistSt
|
||||
StreamDialogEntry.share
|
||||
));
|
||||
}
|
||||
entries.add(StreamDialogEntry.open_in_browser);
|
||||
if (KoreUtil.shouldShowPlayWithKodi(context, infoItem.getServiceId())) {
|
||||
entries.add(StreamDialogEntry.play_with_kodi);
|
||||
}
|
||||
|
||||
if (!isNullOrEmpty(infoItem.getUploaderUrl())) {
|
||||
entries.add(StreamDialogEntry.show_channel_details);
|
||||
}
|
||||
|
||||
StreamDialogEntry.setEnabledEntries(entries);
|
||||
|
||||
StreamDialogEntry.start_here_on_background.setCustomAction((fragment, infoItemDuplicate) ->
|
||||
|
@@ -40,7 +40,7 @@ public class ImportConfirmationDialog extends DialogFragment {
|
||||
@Override
|
||||
public Dialog onCreateDialog(@Nullable final Bundle savedInstanceState) {
|
||||
assureCorrectAppLanguage(getContext());
|
||||
return new AlertDialog.Builder(getContext())
|
||||
return new AlertDialog.Builder(requireContext())
|
||||
.setMessage(R.string.import_network_expensive_warning)
|
||||
.setCancelable(true)
|
||||
.setNegativeButton(R.string.cancel, null)
|
||||
|
@@ -294,12 +294,16 @@ class SubscriptionFragment : BaseStateFragment<SubscriptionState>() {
|
||||
}
|
||||
|
||||
private fun showLongTapDialog(selectedItem: ChannelInfoItem) {
|
||||
val commands = arrayOf(getString(R.string.share), getString(R.string.unsubscribe))
|
||||
val commands = arrayOf(
|
||||
getString(R.string.share), getString(R.string.open_in_browser),
|
||||
getString(R.string.unsubscribe)
|
||||
)
|
||||
|
||||
val actions = DialogInterface.OnClickListener { _, i ->
|
||||
when (i) {
|
||||
0 -> ShareUtils.shareText(requireContext(), selectedItem.name, selectedItem.url)
|
||||
1 -> deleteChannel(selectedItem)
|
||||
1 -> ShareUtils.openUrlInBrowser(requireContext(), selectedItem.url)
|
||||
2 -> deleteChannel(selectedItem)
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -15,6 +15,7 @@ import android.view.ViewGroup;
|
||||
import android.widget.PopupMenu;
|
||||
import android.widget.SeekBar;
|
||||
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.appcompat.app.AppCompatActivity;
|
||||
import androidx.recyclerview.widget.ItemTouchHelper;
|
||||
import androidx.recyclerview.widget.LinearLayoutManager;
|
||||
@@ -456,6 +457,7 @@ public final class PlayQueueActivity extends AppCompatActivity
|
||||
final boolean playbackSkipSilence) {
|
||||
if (player != null) {
|
||||
player.setPlaybackParameters(playbackTempo, playbackPitch, playbackSkipSilence);
|
||||
onPlaybackParameterChanged(player.getPlaybackParameters());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -639,7 +641,7 @@ public final class PlayQueueActivity extends AppCompatActivity
|
||||
queueControlBinding.controlShuffle.setImageAlpha(shuffleAlpha);
|
||||
}
|
||||
|
||||
private void onPlaybackParameterChanged(final PlaybackParameters parameters) {
|
||||
private void onPlaybackParameterChanged(@Nullable final PlaybackParameters parameters) {
|
||||
if (parameters != null) {
|
||||
if (menu != null && player != null) {
|
||||
final MenuItem item = menu.findItem(R.id.action_playback_speed);
|
||||
|
@@ -3029,6 +3029,7 @@ public final class Player implements
|
||||
buildSegments();
|
||||
|
||||
binding.itemsListHeaderTitle.setVisibility(View.VISIBLE);
|
||||
binding.itemsListHeaderDuration.setVisibility(View.GONE);
|
||||
binding.shuffleButton.setVisibility(View.GONE);
|
||||
binding.repeatButton.setVisibility(View.GONE);
|
||||
|
||||
|
@@ -32,7 +32,8 @@ public class LoadController implements LoadControl {
|
||||
|
||||
final DefaultLoadControl.Builder builder = new DefaultLoadControl.Builder();
|
||||
builder.setBufferDurationsMs(minimumPlaybackBufferMs, optimalPlaybackBufferMs,
|
||||
initialPlaybackBufferMs, initialPlaybackBufferMs);
|
||||
initialPlaybackBufferMs,
|
||||
DefaultLoadControl.DEFAULT_BUFFER_FOR_PLAYBACK_AFTER_REBUFFER_MS);
|
||||
internalLoadControl = builder.build();
|
||||
}
|
||||
|
||||
|
@@ -40,29 +40,25 @@ import io.reactivex.rxjava3.subjects.BehaviorSubject;
|
||||
*/
|
||||
public abstract class PlayQueue implements Serializable {
|
||||
public static final boolean DEBUG = MainActivity.DEBUG;
|
||||
|
||||
private ArrayList<PlayQueueItem> backup;
|
||||
private ArrayList<PlayQueueItem> streams;
|
||||
|
||||
@NonNull
|
||||
private final AtomicInteger queueIndex;
|
||||
private final ArrayList<PlayQueueItem> history;
|
||||
private final List<PlayQueueItem> history = new ArrayList<>();
|
||||
|
||||
private List<PlayQueueItem> backup;
|
||||
private List<PlayQueueItem> streams;
|
||||
|
||||
private transient BehaviorSubject<PlayQueueEvent> eventBroadcast;
|
||||
private transient Flowable<PlayQueueEvent> broadcastReceiver;
|
||||
|
||||
private transient boolean disposed;
|
||||
private transient boolean disposed = false;
|
||||
|
||||
PlayQueue(final int index, final List<PlayQueueItem> startWith) {
|
||||
streams = new ArrayList<>();
|
||||
streams.addAll(startWith);
|
||||
history = new ArrayList<>();
|
||||
streams = new ArrayList<>(startWith);
|
||||
|
||||
if (streams.size() > index) {
|
||||
history.add(streams.get(index));
|
||||
}
|
||||
|
||||
queueIndex = new AtomicInteger(index);
|
||||
disposed = false;
|
||||
}
|
||||
|
||||
/*//////////////////////////////////////////////////////////////////////////
|
||||
@@ -137,18 +133,36 @@ public abstract class PlayQueue implements Serializable {
|
||||
public synchronized void setIndex(final int index) {
|
||||
final int oldIndex = getIndex();
|
||||
|
||||
int newIndex = index;
|
||||
final int newIndex;
|
||||
|
||||
if (index < 0) {
|
||||
newIndex = 0;
|
||||
} else if (index < streams.size()) {
|
||||
// Regular assignment for index in bounds
|
||||
newIndex = index;
|
||||
} else if (streams.isEmpty()) {
|
||||
// Out of bounds from here on
|
||||
// Need to check if stream is empty to prevent arithmetic error and negative index
|
||||
newIndex = 0;
|
||||
} else if (isComplete()) {
|
||||
// Circular indexing
|
||||
newIndex = index % streams.size();
|
||||
} else {
|
||||
// Index of last element
|
||||
newIndex = streams.size() - 1;
|
||||
}
|
||||
if (index >= streams.size()) {
|
||||
newIndex = isComplete() ? index % streams.size() : streams.size() - 1;
|
||||
}
|
||||
|
||||
queueIndex.set(newIndex);
|
||||
|
||||
if (oldIndex != newIndex) {
|
||||
history.add(streams.get(newIndex));
|
||||
}
|
||||
|
||||
queueIndex.set(newIndex);
|
||||
/*
|
||||
TODO: Documentation states that a SelectEvent will only be emitted if the new index is...
|
||||
different from the old one but this is emitted regardless? Not sure what this what it does
|
||||
exactly so I won't touch it
|
||||
*/
|
||||
broadcast(new SelectEvent(oldIndex, newIndex));
|
||||
}
|
||||
|
||||
@@ -180,8 +194,6 @@ public abstract class PlayQueue implements Serializable {
|
||||
* @return the index of the given item
|
||||
*/
|
||||
public int indexOf(@NonNull final PlayQueueItem item) {
|
||||
// referential equality, can't think of a better way to do this
|
||||
// todo: better than this
|
||||
return streams.indexOf(item);
|
||||
}
|
||||
|
||||
@@ -410,34 +422,42 @@ public abstract class PlayQueue implements Serializable {
|
||||
}
|
||||
|
||||
/**
|
||||
* Shuffles the current play queue.
|
||||
* Shuffles the current play queue
|
||||
* <p>
|
||||
* This method first backs up the existing play queue and item being played.
|
||||
* Then a newly shuffled play queue will be generated along with currently
|
||||
* playing item placed at the beginning of the queue.
|
||||
* This method first backs up the existing play queue and item being played. Then a newly
|
||||
* shuffled play queue will be generated along with currently playing item placed at the
|
||||
* beginning of the queue. This item will also be added to the history.
|
||||
* </p>
|
||||
* <p>
|
||||
* Will emit a {@link ReorderEvent} in any context.
|
||||
* Will emit a {@link ReorderEvent} if shuffled.
|
||||
* </p>
|
||||
*
|
||||
* @implNote Does nothing if the queue has a size <= 2 (the currently playing video must stay on
|
||||
* top, so shuffling a size-2 list does nothing)
|
||||
*/
|
||||
public synchronized void shuffle() {
|
||||
// Can't shuffle an list that's empty or only has one element
|
||||
if (size() <= 2) {
|
||||
return;
|
||||
}
|
||||
// Create a backup if it doesn't already exist
|
||||
if (backup == null) {
|
||||
backup = new ArrayList<>(streams);
|
||||
}
|
||||
final int originIndex = getIndex();
|
||||
final PlayQueueItem current = getItem();
|
||||
|
||||
final int originalIndex = getIndex();
|
||||
final PlayQueueItem currentItem = getItem();
|
||||
|
||||
Collections.shuffle(streams);
|
||||
|
||||
final int newIndex = streams.indexOf(current);
|
||||
if (newIndex != -1) {
|
||||
streams.add(0, streams.remove(newIndex));
|
||||
}
|
||||
// Move currentItem to the head of the queue
|
||||
streams.remove(currentItem);
|
||||
streams.add(0, currentItem);
|
||||
queueIndex.set(0);
|
||||
if (streams.size() > 0) {
|
||||
history.add(streams.get(0));
|
||||
}
|
||||
|
||||
broadcast(new ReorderEvent(originIndex, queueIndex.get()));
|
||||
history.add(currentItem);
|
||||
|
||||
broadcast(new ReorderEvent(originalIndex, 0));
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -457,7 +477,6 @@ public abstract class PlayQueue implements Serializable {
|
||||
final int originIndex = getIndex();
|
||||
final PlayQueueItem current = getItem();
|
||||
|
||||
streams.clear();
|
||||
streams = backup;
|
||||
backup = null;
|
||||
|
||||
@@ -500,22 +519,19 @@ public abstract class PlayQueue implements Serializable {
|
||||
* we don't have to do anything with new queue.
|
||||
* This method also gives a chance to track history of items in a queue in
|
||||
* VideoDetailFragment without duplicating items from two identical queues
|
||||
* */
|
||||
*/
|
||||
@Override
|
||||
public boolean equals(@Nullable final Object obj) {
|
||||
if (!(obj instanceof PlayQueue)
|
||||
|| getStreams().size() != ((PlayQueue) obj).getStreams().size()) {
|
||||
if (!(obj instanceof PlayQueue)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
final PlayQueue other = (PlayQueue) obj;
|
||||
for (int i = 0; i < getStreams().size(); i++) {
|
||||
if (!getItem(i).getUrl().equals(other.getItem(i).getUrl())) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return streams.equals(other.streams);
|
||||
}
|
||||
|
||||
return true;
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return streams.hashCode();
|
||||
}
|
||||
|
||||
public boolean isDisposed() {
|
||||
|
@@ -1,5 +1,6 @@
|
||||
package org.schabi.newpipe.settings;
|
||||
|
||||
import android.annotation.SuppressLint;
|
||||
import android.app.Activity;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
@@ -25,8 +26,8 @@ import org.schabi.newpipe.error.ReCaptchaActivity;
|
||||
import org.schabi.newpipe.extractor.NewPipe;
|
||||
import org.schabi.newpipe.extractor.localization.ContentCountry;
|
||||
import org.schabi.newpipe.extractor.localization.Localization;
|
||||
import org.schabi.newpipe.util.FilePickerActivityHelper;
|
||||
import org.schabi.newpipe.util.FilePathUtils;
|
||||
import org.schabi.newpipe.util.FilePickerActivityHelper;
|
||||
import org.schabi.newpipe.util.ZipHelper;
|
||||
|
||||
import java.io.File;
|
||||
@@ -177,17 +178,14 @@ public class ContentSettingsFragment extends BasePreferenceFragment {
|
||||
if ((requestCode == REQUEST_IMPORT_PATH || requestCode == REQUEST_EXPORT_PATH)
|
||||
&& resultCode == Activity.RESULT_OK && data.getData() != null) {
|
||||
final File file = Utils.getFileForUri(data.getData());
|
||||
final String path = file.getAbsolutePath();
|
||||
setImportExportDataPath(file);
|
||||
|
||||
if (requestCode == REQUEST_EXPORT_PATH) {
|
||||
final SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMdd_HHmmss", Locale.US);
|
||||
exportDatabase(path + "/NewPipeData-" + sdf.format(new Date()) + ".zip");
|
||||
exportDatabase(file);
|
||||
} else {
|
||||
final AlertDialog.Builder builder = new AlertDialog.Builder(requireActivity());
|
||||
builder.setMessage(R.string.override_current_data)
|
||||
.setPositiveButton(getString(R.string.finish),
|
||||
(d, id) -> importDatabase(path))
|
||||
(d, id) -> importDatabase(file))
|
||||
.setNegativeButton(android.R.string.cancel,
|
||||
(d, id) -> d.cancel());
|
||||
builder.create().show();
|
||||
@@ -195,26 +193,34 @@ public class ContentSettingsFragment extends BasePreferenceFragment {
|
||||
}
|
||||
}
|
||||
|
||||
private void exportDatabase(final String path) {
|
||||
private void exportDatabase(@NonNull final File folder) {
|
||||
try {
|
||||
final SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMdd_HHmmss", Locale.US);
|
||||
final String path = folder.getAbsolutePath() + "/NewPipeData-"
|
||||
+ sdf.format(new Date()) + ".zip";
|
||||
|
||||
//checkpoint before export
|
||||
NewPipeDatabase.checkpoint();
|
||||
|
||||
final SharedPreferences preferences = PreferenceManager
|
||||
.getDefaultSharedPreferences(requireContext());
|
||||
.getDefaultSharedPreferences(requireContext());
|
||||
manager.exportDatabase(preferences, path);
|
||||
|
||||
setImportExportDataPath(folder, false);
|
||||
|
||||
Toast.makeText(getContext(), R.string.export_complete_toast, Toast.LENGTH_SHORT).show();
|
||||
} catch (final Exception e) {
|
||||
ErrorActivity.reportUiErrorInSnackbar(this, "Exporting database", e);
|
||||
}
|
||||
}
|
||||
|
||||
private void importDatabase(final String filePath) {
|
||||
private void importDatabase(@NonNull final File file) {
|
||||
final String filePath = file.getAbsolutePath();
|
||||
|
||||
// check if file is supported
|
||||
if (!ZipHelper.isValidZipFile(filePath)) {
|
||||
Toast.makeText(getContext(), R.string.no_valid_zip_file, Toast.LENGTH_SHORT)
|
||||
.show();
|
||||
.show();
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -225,7 +231,7 @@ public class ContentSettingsFragment extends BasePreferenceFragment {
|
||||
|
||||
if (!manager.extractDb(filePath)) {
|
||||
Toast.makeText(getContext(), R.string.could_not_import_all_files, Toast.LENGTH_LONG)
|
||||
.show();
|
||||
.show();
|
||||
}
|
||||
|
||||
//If settings file exist, ask if it should be imported.
|
||||
@@ -235,27 +241,40 @@ public class ContentSettingsFragment extends BasePreferenceFragment {
|
||||
|
||||
alert.setNegativeButton(android.R.string.no, (dialog, which) -> {
|
||||
dialog.dismiss();
|
||||
// restart app to properly load db
|
||||
System.exit(0);
|
||||
finishImport(file);
|
||||
});
|
||||
alert.setPositiveButton(getString(R.string.finish), (dialog, which) -> {
|
||||
dialog.dismiss();
|
||||
manager.loadSharedPreferences(PreferenceManager
|
||||
.getDefaultSharedPreferences(requireContext()));
|
||||
// restart app to properly load db
|
||||
System.exit(0);
|
||||
.getDefaultSharedPreferences(requireContext()));
|
||||
finishImport(file);
|
||||
});
|
||||
alert.show();
|
||||
} else {
|
||||
// restart app to properly load db
|
||||
System.exit(0);
|
||||
finishImport(file);
|
||||
}
|
||||
} catch (final Exception e) {
|
||||
ErrorActivity.reportUiErrorInSnackbar(this, "Importing database", e);
|
||||
}
|
||||
}
|
||||
|
||||
private void setImportExportDataPath(final File file) {
|
||||
/**
|
||||
* Save import path and restart system.
|
||||
*
|
||||
* @param file The file of the created backup
|
||||
*/
|
||||
private void finishImport(@NonNull final File file) {
|
||||
if (file.getParentFile() != null) {
|
||||
//immediately because app is about to exit
|
||||
setImportExportDataPath(file.getParentFile(), true);
|
||||
}
|
||||
|
||||
// restart app to properly load db
|
||||
System.exit(0);
|
||||
}
|
||||
|
||||
@SuppressLint("ApplySharedPref")
|
||||
private void setImportExportDataPath(@NonNull final File file, final boolean immediately) {
|
||||
final String directoryPath;
|
||||
if (file.isDirectory()) {
|
||||
directoryPath = file.getAbsolutePath();
|
||||
@@ -267,6 +286,13 @@ public class ContentSettingsFragment extends BasePreferenceFragment {
|
||||
directoryPath = "";
|
||||
}
|
||||
}
|
||||
defaultPreferences.edit().putString(importExportDataPathKey, directoryPath).apply();
|
||||
final SharedPreferences.Editor editor = defaultPreferences
|
||||
.edit()
|
||||
.putString(importExportDataPathKey, directoryPath);
|
||||
if (immediately) {
|
||||
editor.commit();
|
||||
} else {
|
||||
editor.apply();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user