diff --git a/.travis.yml b/.travis.yml index d5d3aed9c..d6f97ab55 100644 --- a/.travis.yml +++ b/.travis.yml @@ -5,13 +5,13 @@ android: components: # The BuildTools version used by NewPipe - tools - - build-tools-27.0.3 + - build-tools-28.0.3 # The SDK version used to compile NewPipe - - android-27 + - android-28 before_install: - - yes | sdkmanager "platforms;android-27" + - yes | sdkmanager "platforms;android-28" script: ./gradlew -Dorg.gradle.jvmargs=-Xmx1536m assembleDebug lintDebug testDebugUnitTest licenses: diff --git a/README.md b/README.md index b154fad58..6a563dfd8 100644 --- a/README.md +++ b/README.md @@ -1,21 +1,22 @@ -

+

NewPipe

-

A free lightweight YouTube frontend for Android.

-

+

A libre lightweight streaming frontend for Android.

+

- - - - - - + + + + + +

-
+

ScreenshotsDescriptionFeaturesContributionDonateLicense

WebsiteBlogPress

-
-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 @@ -29,46 +30,48 @@ WARNING: PUTTING NEWPIPE OR ANY FORK OF IT INTO GOOGLE PLAYSTORE VIOLATES THEIR [](fastlane/metadata/android/en-US/images/phoneScreenshots/shot_8.png) [](fastlane/metadata/android/en-US/images/phoneScreenshots/shot_9.png) [](fastlane/metadata/android/en-US/images/phoneScreenshots/shot_10.png) +[](fastlane/metadata/android/en-US/images/tenInchScreenshots/shot_11.png) +[](fastlane/metadata/android/en-US/images/tenInchScreenshots/shot_12.png) ## Description -NewPipe does not use any Google framework libraries, or the YouTube API. It only parses the website in order to gain the information it needs. Therefore this app can be used on devices without Google Services installed. Also, you don't need a YouTube account to use NewPipe, and it's FLOSS. +NewPipe does not use any Google framework libraries, nor the YouTube API. Websites are only parsed to fetch required info, so this app can be used on devices without Google services installed. Also, you don't need a YouTube account to use NewPipe, which is copylefted libre software. ### Features * Search videos -* Display general information about a video +* Display general info about videos * Watch YouTube videos * Listen to YouTube videos * Popup mode (floating player) -* Select the streaming player to watch the video with -* Download videos +* Select streaming player to watch video with +* Download videos * Download audio only * Open a video in Kodi -* Show Next/Related videos +* Show next/related videos * Search YouTube in a specific language * Watch/Block age restricted material -* Display general information about channels +* Display general info about channels * Search channels * Watch videos from a channel * Orbot/Tor support (not yet directly) -* 1080p/2k/4k support +* 1080p/2K/4K support * View history * Subscribe to channels * Search history -* Search/Watch Playlists -* Watch as queues Playlists -* Queuing videos +* Search/watch playlists +* Watch as enqueued playlists +* Enqueue videos * Local playlists * Subtitles -* Multi-service support (eg. SoundCloud in NewPipe Beta) +* Multi-service support (e.g. SoundCloud \[beta\]) +* Livestream support ### Coming Features -* Livestream support * Cast to UPnP and Cast * Show comments -* ... and many more +* … and many more ## Contribution Whether you have ideas, translations, design changes, code cleaning, or real heavy code changes, help is always welcome. @@ -77,26 +80,31 @@ The more is done the better it gets! If you'd like to get involved, check our [contribution notes](.github/CONTRIBUTING.md). ## Donate -If you like NewPipe we'd be happy about a donation. You can either donate via Bitcoin, Bountysource or Liberapay. For further information about donating to NewPipe, please visit our [website](https://newpipe.schabi.org/donate). +If you like NewPipe we'd be happy about a donation. You can either send bitcoin or donate via Bountysource or Liberapay. For further info on donating to NewPipe, please visit our [website](https://newpipe.schabi.org/donate). - - + + - - - + + + - - - + + +
BitcoinBitcoin QR CodeBitcoinBitcoin QR code 16A9J59ahMRqkLSZjhYj33n9j3fMztFxnh
LiberapayVisit NewPipe at liberapay.comDonate via LiberapayLiberapayVisit NewPipe at liberapay.comDonate via Liberapay
BountysourceVisit NewPipe at bountysource.comCheck out how many bounties you can earn.BountysourceVisit NewPipe at bountysource.comCheck out how many bounties you can earn.
+## Privacy Policy + +The NewPipe project aims to provide a private, anonymous experience for using media web services. +Therefore, the app does not collect any data without your consent. NewPipe's privacy policy explains in detail what data is sent and stored when you send a crash report, or comment in our blog. You can find the document [here](https://newpipe.schabi.org/legal/privacy/). + ## License [![GNU GPLv3 Image](https://www.gnu.org/graphics/gplv3-127x51.png)](http://www.gnu.org/licenses/gpl-3.0.en.html) diff --git a/app/build.gradle b/app/build.gradle index 4b717cafc..b507fd860 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -1,15 +1,15 @@ apply plugin: 'com.android.application' android { - compileSdkVersion 27 - buildToolsVersion '27.0.3' + compileSdkVersion 28 + buildToolsVersion '28.0.3' defaultConfig { applicationId "org.schabi.newpipe" minSdkVersion 15 - targetSdkVersion 27 - versionCode 68 - versionName "0.14.1" + targetSdkVersion 28 + versionCode 69 + versionName "0.14.2" testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner" vectorDrawables.useSupportLibrary = true @@ -22,7 +22,6 @@ android { } debug { multiDexEnabled true - debuggable true applicationIdSuffix ".debug" } @@ -41,62 +40,61 @@ android { } ext { - supportLibVersion = '27.1.1' - exoPlayerLibVersion = '2.8.2' + supportLibVersion = '28.0.0' + exoPlayerLibVersion = '2.8.4' //2.9.0 roomDbLibVersion = '1.1.1' - leakCanaryLibVersion = '1.5.4' - okHttpLibVersion = '3.10.0' + leakCanaryLibVersion = '1.5.4' //1.6.1 + okHttpLibVersion = '3.11.0' icepickLibVersion = '3.2.0' stethoLibVersion = '1.5.0' } dependencies { - androidTestImplementation('com.android.support.test.espresso:espresso-core:2.2.2') { + androidTestImplementation('com.android.support.test.espresso:espresso-core:3.0.2', { exclude module: 'support-annotations' - } + }) - implementation 'com.github.TeamNewPipe:NewPipeExtractor:66c3c3f45241d4b0c909' + implementation 'com.github.TeamNewPipe:NewPipeExtractor:32d316330c26' testImplementation 'junit:junit:4.12' - testImplementation 'org.mockito:mockito-core:2.8.9' + testImplementation 'org.mockito:mockito-core:2.23.0' - implementation "com.android.support:appcompat-v7:$supportLibVersion" - implementation "com.android.support:support-v4:$supportLibVersion" - implementation "com.android.support:design:$supportLibVersion" - implementation "com.android.support:recyclerview-v7:$supportLibVersion" - implementation "com.android.support:preference-v14:$supportLibVersion" + implementation "com.android.support:appcompat-v7:${supportLibVersion}" + implementation "com.android.support:support-v4:${supportLibVersion}" + implementation "com.android.support:design:${supportLibVersion}" + implementation "com.android.support:recyclerview-v7:${supportLibVersion}" + implementation "com.android.support:preference-v14:${supportLibVersion}" + implementation "com.android.support:cardview-v7:${supportLibVersion}" + implementation 'com.android.support.constraint:constraint-layout:1.1.3' - implementation 'ch.acra:acra:4.9.2' + implementation 'ch.acra:acra:4.9.2' //4.11 implementation 'com.nostra13.universalimageloader:universal-image-loader:1.9.5' implementation 'de.hdodenhof:circleimageview:2.2.0' implementation 'com.github.nirhart:ParallaxScroll:dd53d1f9d1' implementation 'com.nononsenseapps:filepicker:4.2.1' - implementation "com.google.android.exoplayer:exoplayer:$exoPlayerLibVersion" - implementation "com.google.android.exoplayer:extension-mediasession:$exoPlayerLibVersion" + implementation "com.google.android.exoplayer:exoplayer:${exoPlayerLibVersion}" + implementation "com.google.android.exoplayer:extension-mediasession:${exoPlayerLibVersion}" - debugImplementation "com.facebook.stetho:stetho:$stethoLibVersion" - debugImplementation "com.facebook.stetho:stetho-urlconnection:$stethoLibVersion" + debugImplementation "com.facebook.stetho:stetho:${stethoLibVersion}" + debugImplementation "com.facebook.stetho:stetho-urlconnection:${stethoLibVersion}" debugImplementation 'com.android.support:multidex:1.0.3' - implementation 'io.reactivex.rxjava2:rxjava:2.1.14' - implementation 'io.reactivex.rxjava2:rxandroid:2.0.2' + implementation 'io.reactivex.rxjava2:rxjava:2.2.2' + implementation 'io.reactivex.rxjava2:rxandroid:2.1.0' implementation 'com.jakewharton.rxbinding2:rxbinding:2.1.1' - implementation "android.arch.persistence.room:runtime:$roomDbLibVersion" - implementation "android.arch.persistence.room:rxjava2:$roomDbLibVersion" - annotationProcessor "android.arch.persistence.room:compiler:$roomDbLibVersion" + implementation "android.arch.persistence.room:runtime:${roomDbLibVersion}" + implementation "android.arch.persistence.room:rxjava2:${roomDbLibVersion}" + annotationProcessor "android.arch.persistence.room:compiler:${roomDbLibVersion}" - implementation "frankiesardo:icepick:$icepickLibVersion" - annotationProcessor "frankiesardo:icepick-processor:$icepickLibVersion" + implementation "frankiesardo:icepick:${icepickLibVersion}" + annotationProcessor "frankiesardo:icepick-processor:${icepickLibVersion}" - debugImplementation "com.squareup.leakcanary:leakcanary-android:$leakCanaryLibVersion" - releaseImplementation "com.squareup.leakcanary:leakcanary-android-no-op:$leakCanaryLibVersion" + debugImplementation "com.squareup.leakcanary:leakcanary-android:${leakCanaryLibVersion}" + releaseImplementation "com.squareup.leakcanary:leakcanary-android-no-op:${leakCanaryLibVersion}" - - implementation "com.squareup.okhttp3:okhttp:$okHttpLibVersion" - debugImplementation "com.facebook.stetho:stetho-okhttp3:$stethoLibVersion" - implementation 'com.android.support.constraint:constraint-layout:1.1.2' - implementation 'com.android.support:cardview-v7:27.1.1' + implementation "com.squareup.okhttp3:okhttp:${okHttpLibVersion}" + debugImplementation "com.facebook.stetho:stetho-okhttp3:${stethoLibVersion}" } diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index e4d448184..1bc205f33 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -9,6 +9,7 @@ + - \ No newline at end of file + diff --git a/app/src/main/java/org/schabi/newpipe/App.java b/app/src/main/java/org/schabi/newpipe/App.java index f436a26b8..314c95c8d 100644 --- a/app/src/main/java/org/schabi/newpipe/App.java +++ b/app/src/main/java/org/schabi/newpipe/App.java @@ -5,6 +5,7 @@ import android.app.NotificationChannel; import android.app.NotificationManager; import android.content.Context; import android.os.Build; +import android.preference.PreferenceManager; import android.support.annotation.Nullable; import android.util.Log; @@ -21,6 +22,7 @@ import org.acra.config.ConfigurationBuilder; import org.acra.sender.ReportSenderFactory; import org.schabi.newpipe.extractor.Downloader; import org.schabi.newpipe.extractor.NewPipe; +import org.schabi.newpipe.extractor.utils.Localization; import org.schabi.newpipe.report.AcraReportSenderFactory; import org.schabi.newpipe.report.ErrorActivity; import org.schabi.newpipe.report.UserAction; @@ -65,7 +67,8 @@ public class App extends Application { private RefWatcher refWatcher; @SuppressWarnings("unchecked") - private static final Class[] reportSenderFactoryClasses = new Class[]{AcraReportSenderFactory.class}; + private static final Class[] + reportSenderFactoryClasses = new Class[]{AcraReportSenderFactory.class}; @Override protected void attachBaseContext(Context base) { @@ -88,7 +91,8 @@ public class App extends Application { // Initialize settings first because others inits can use its values SettingsActivity.initSettings(this); - NewPipe.init(getDownloader()); + NewPipe.init(getDownloader(), + org.schabi.newpipe.util.Localization.getPreferredExtractorLocal(this)); StateSaver.init(this); initNotificationChannel(); @@ -106,7 +110,7 @@ public class App extends Application { // https://github.com/ReactiveX/RxJava/wiki/What's-different-in-2.0#error-handling RxJavaPlugins.setErrorHandler(new Consumer() { @Override - public void accept(@NonNull Throwable throwable) throws Exception { + public void accept(@NonNull Throwable throwable) { Log.e(TAG, "RxJavaPlugins.ErrorHandler called with -> : " + "throwable = [" + throwable.getClass().getName() + "]"); @@ -180,7 +184,11 @@ public class App extends Application { ACRA.init(this, acraConfig); } catch (ACRAConfigurationException ace) { ace.printStackTrace(); - ErrorActivity.reportError(this, ace, null, null, ErrorActivity.ErrorInfo.make(UserAction.SOMETHING_ELSE, "none", + ErrorActivity.reportError(this, + ace, + null, + null, + ErrorActivity.ErrorInfo.make(UserAction.SOMETHING_ELSE, "none", "Could not initialize ACRA crash report", R.string.app_ui_crash)); } } @@ -200,7 +208,8 @@ public class App extends Application { NotificationChannel mChannel = new NotificationChannel(id, name, importance); mChannel.setDescription(description); - NotificationManager mNotificationManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE); + NotificationManager mNotificationManager = + (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE); mNotificationManager.createNotificationChannel(mChannel); } diff --git a/app/src/main/java/org/schabi/newpipe/BaseFragment.java b/app/src/main/java/org/schabi/newpipe/BaseFragment.java index b125ab02f..4e4cdcc0d 100644 --- a/app/src/main/java/org/schabi/newpipe/BaseFragment.java +++ b/app/src/main/java/org/schabi/newpipe/BaseFragment.java @@ -12,14 +12,12 @@ import android.view.View; import com.nostra13.universalimageloader.core.ImageLoader; import com.squareup.leakcanary.RefWatcher; -import org.schabi.newpipe.report.UserAction; - import icepick.Icepick; import icepick.State; public abstract class BaseFragment extends Fragment { protected final String TAG = getClass().getSimpleName() + "@" + Integer.toHexString(hashCode()); - protected boolean DEBUG = MainActivity.DEBUG; + protected final boolean DEBUG = MainActivity.DEBUG; protected AppCompatActivity activity; public static final ImageLoader imageLoader = ImageLoader.getInstance(); diff --git a/app/src/main/java/org/schabi/newpipe/Downloader.java b/app/src/main/java/org/schabi/newpipe/Downloader.java index 17dc5859d..62c7d1671 100644 --- a/app/src/main/java/org/schabi/newpipe/Downloader.java +++ b/app/src/main/java/org/schabi/newpipe/Downloader.java @@ -4,6 +4,7 @@ import android.support.annotation.Nullable; import android.text.TextUtils; import org.schabi.newpipe.extractor.exceptions.ReCaptchaException; +import org.schabi.newpipe.extractor.utils.Localization; import java.io.IOException; import java.io.InputStream; @@ -43,7 +44,7 @@ public class Downloader implements org.schabi.newpipe.extractor.Downloader { private static Downloader instance; private String mCookies; - private OkHttpClient client; + private final OkHttpClient client; private Downloader(OkHttpClient.Builder builder) { this.client = builder @@ -103,13 +104,13 @@ public class Downloader implements org.schabi.newpipe.extractor.Downloader { * but set the HTTP header field "Accept-Language" to the supplied string. * * @param siteUrl the URL of the text file to return the contents of - * @param language the language (usually a 2-character code) to set as the preferred language + * @param localization the language and country (usually a 2-character code) to set * @return the contents of the specified text file */ @Override - public String download(String siteUrl, String language) throws IOException, ReCaptchaException { + public String download(String siteUrl, Localization localization) throws IOException, ReCaptchaException { Map requestProperties = new HashMap<>(); - requestProperties.put("Accept-Language", language); + requestProperties.put("Accept-Language", localization.getLanguage()); return download(siteUrl, requestProperties); } diff --git a/app/src/main/java/org/schabi/newpipe/MainActivity.java b/app/src/main/java/org/schabi/newpipe/MainActivity.java index 7c77bff3d..a9f2e9622 100644 --- a/app/src/main/java/org/schabi/newpipe/MainActivity.java +++ b/app/src/main/java/org/schabi/newpipe/MainActivity.java @@ -23,7 +23,6 @@ package org.schabi.newpipe; import android.content.Intent; import android.content.SharedPreferences; import android.content.pm.PackageManager; -import android.net.Uri; import android.os.Build; import android.os.Bundle; import android.os.Handler; @@ -66,8 +65,6 @@ import org.schabi.newpipe.util.ServiceHelper; import org.schabi.newpipe.util.StateSaver; import org.schabi.newpipe.util.ThemeHelper; -import static org.schabi.newpipe.extractor.InfoItem.InfoType.PLAYLIST; - public class MainActivity extends AppCompatActivity { private static final String TAG = "MainActivity"; public static final boolean DEBUG = !BuildConfig.BUILD_TYPE.equals("release"); diff --git a/app/src/main/java/org/schabi/newpipe/ReCaptchaActivity.java b/app/src/main/java/org/schabi/newpipe/ReCaptchaActivity.java index a4e6730da..74c818bf9 100644 --- a/app/src/main/java/org/schabi/newpipe/ReCaptchaActivity.java +++ b/app/src/main/java/org/schabi/newpipe/ReCaptchaActivity.java @@ -85,7 +85,7 @@ public class ReCaptchaActivity extends AppCompatActivity { } private class ReCaptchaWebViewClient extends WebViewClient { - private Activity context; + private final Activity context; private String mCookies; ReCaptchaWebViewClient(Activity ctx) { diff --git a/app/src/main/java/org/schabi/newpipe/RouterActivity.java b/app/src/main/java/org/schabi/newpipe/RouterActivity.java index 4f1fdeab2..e22e2f474 100644 --- a/app/src/main/java/org/schabi/newpipe/RouterActivity.java +++ b/app/src/main/java/org/schabi/newpipe/RouterActivity.java @@ -1,7 +1,6 @@ package org.schabi.newpipe; import android.annotation.SuppressLint; -import android.app.FragmentManager; import android.app.IntentService; import android.content.Context; import android.content.DialogInterface; @@ -13,7 +12,6 @@ import android.preference.PreferenceManager; import android.support.annotation.DrawableRes; import android.support.annotation.NonNull; import android.support.annotation.Nullable; -import android.support.v4.app.Fragment; import android.support.v4.app.NotificationCompat; import android.support.v7.app.AlertDialog; import android.support.v7.app.AppCompatActivity; @@ -38,7 +36,6 @@ import org.schabi.newpipe.extractor.exceptions.ExtractionException; import org.schabi.newpipe.extractor.playlist.PlaylistInfo; import org.schabi.newpipe.extractor.stream.StreamInfo; import org.schabi.newpipe.extractor.stream.VideoStream; -import org.schabi.newpipe.fragments.detail.VideoDetailFragment; import org.schabi.newpipe.player.helper.PlayerHelper; import org.schabi.newpipe.player.playqueue.ChannelPlayQueue; import org.schabi.newpipe.player.playqueue.PlayQueue; @@ -51,14 +48,12 @@ import org.schabi.newpipe.util.NavigationHelper; import org.schabi.newpipe.util.PermissionHelper; import org.schabi.newpipe.util.ThemeHelper; -import java.io.IOException; import java.io.Serializable; import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; import java.util.HashSet; import java.util.List; -import java.util.Observer; import icepick.Icepick; import icepick.State; @@ -86,7 +81,7 @@ public class RouterActivity extends AppCompatActivity { protected int selectedPreviously = -1; protected String currentUrl; - protected CompositeDisposable disposables = new CompositeDisposable(); + protected final CompositeDisposable disposables = new CompositeDisposable(); private boolean selectionIsDownload = false; @@ -184,12 +179,16 @@ public class RouterActivity extends AppCompatActivity { if (selectedChoiceKey.equals(alwaysAskKey)) { final List choices = getChoicesForService(currentService, currentLinkType); - if (choices.size() == 1) { - handleChoice(choices.get(0).key); - } else if (choices.size() == 0) { - handleChoice(showInfoKey); - } else { - showDialog(choices); + switch (choices.size()) { + case 1: + handleChoice(choices.get(0).key); + break; + case 0: + handleChoice(showInfoKey); + break; + default: + showDialog(choices); + break; } } else if (selectedChoiceKey.equals(showInfoKey)) { handleChoice(showInfoKey); diff --git a/app/src/main/java/org/schabi/newpipe/about/LicenseFragmentHelper.java b/app/src/main/java/org/schabi/newpipe/about/LicenseFragmentHelper.java index 701e18cbf..09d33bd8a 100644 --- a/app/src/main/java/org/schabi/newpipe/about/LicenseFragmentHelper.java +++ b/app/src/main/java/org/schabi/newpipe/about/LicenseFragmentHelper.java @@ -4,7 +4,6 @@ import android.app.Activity; import android.content.Context; import android.content.DialogInterface; import android.os.AsyncTask; -import android.support.annotation.NonNull; import android.support.annotation.Nullable; import android.support.v7.app.AlertDialog; import android.webkit.WebView; @@ -17,7 +16,7 @@ import java.lang.ref.WeakReference; public class LicenseFragmentHelper extends AsyncTask { - WeakReference weakReference; + final WeakReference weakReference; private License license; public LicenseFragmentHelper(@Nullable Activity activity) { @@ -78,18 +77,18 @@ public class LicenseFragmentHelper extends AsyncTask { throw new NullPointerException("license is null"); } - String licenseContent = ""; + StringBuilder licenseContent = new StringBuilder(); String webViewData; try { BufferedReader in = new BufferedReader(new InputStreamReader(context.getAssets().open(license.getFilename()), "UTF-8")); String str; while ((str = in.readLine()) != null) { - licenseContent += str; + licenseContent.append(str); } in.close(); // split the HTML file and insert the stylesheet into the HEAD of the file - String[] insert = licenseContent.split(""); + String[] insert = licenseContent.toString().split(""); webViewData = insert[0] + "" + insert[1]; diff --git a/app/src/main/java/org/schabi/newpipe/database/BasicDAO.java b/app/src/main/java/org/schabi/newpipe/database/BasicDAO.java index 425c122ca..13117145a 100644 --- a/app/src/main/java/org/schabi/newpipe/database/BasicDAO.java +++ b/app/src/main/java/org/schabi/newpipe/database/BasicDAO.java @@ -30,7 +30,7 @@ public interface BasicDAO { /* Deletes */ @Delete - int delete(final Entity entity); + void delete(final Entity entity); @Delete int delete(final Collection entities); @@ -42,5 +42,5 @@ public interface BasicDAO { int update(final Entity entity); @Update - int update(final Collection entities); + void update(final Collection entities); } diff --git a/app/src/main/java/org/schabi/newpipe/database/history/dao/SearchHistoryDAO.java b/app/src/main/java/org/schabi/newpipe/database/history/dao/SearchHistoryDAO.java index b0a3c3a3c..83e629e48 100644 --- a/app/src/main/java/org/schabi/newpipe/database/history/dao/SearchHistoryDAO.java +++ b/app/src/main/java/org/schabi/newpipe/database/history/dao/SearchHistoryDAO.java @@ -4,7 +4,6 @@ import android.arch.persistence.room.Dao; import android.arch.persistence.room.Query; import android.support.annotation.Nullable; -import org.schabi.newpipe.database.BasicDAO; import org.schabi.newpipe.database.history.model.SearchHistoryEntry; import java.util.List; diff --git a/app/src/main/java/org/schabi/newpipe/database/history/dao/StreamHistoryDAO.java b/app/src/main/java/org/schabi/newpipe/database/history/dao/StreamHistoryDAO.java index fd7a1b96f..847153e12 100644 --- a/app/src/main/java/org/schabi/newpipe/database/history/dao/StreamHistoryDAO.java +++ b/app/src/main/java/org/schabi/newpipe/database/history/dao/StreamHistoryDAO.java @@ -5,7 +5,6 @@ import android.arch.persistence.room.Dao; import android.arch.persistence.room.Query; import android.support.annotation.Nullable; -import org.schabi.newpipe.database.BasicDAO; import org.schabi.newpipe.database.history.model.StreamHistoryEntry; import org.schabi.newpipe.database.stream.StreamStatisticsEntry; import org.schabi.newpipe.database.history.model.StreamHistoryEntity; diff --git a/app/src/main/java/org/schabi/newpipe/database/playlist/dao/PlaylistDAO.java b/app/src/main/java/org/schabi/newpipe/database/playlist/dao/PlaylistDAO.java index 88d5645af..7a6282f96 100644 --- a/app/src/main/java/org/schabi/newpipe/database/playlist/dao/PlaylistDAO.java +++ b/app/src/main/java/org/schabi/newpipe/database/playlist/dao/PlaylistDAO.java @@ -2,7 +2,6 @@ package org.schabi.newpipe.database.playlist.dao; import android.arch.persistence.room.Dao; import android.arch.persistence.room.Query; -import android.arch.persistence.room.Transaction; import org.schabi.newpipe.database.BasicDAO; import org.schabi.newpipe.database.playlist.model.PlaylistEntity; @@ -12,7 +11,6 @@ import java.util.List; import io.reactivex.Flowable; import static org.schabi.newpipe.database.playlist.model.PlaylistEntity.PLAYLIST_ID; -import static org.schabi.newpipe.database.playlist.model.PlaylistEntity.PLAYLIST_NAME; import static org.schabi.newpipe.database.playlist.model.PlaylistEntity.PLAYLIST_TABLE; @Dao diff --git a/app/src/main/java/org/schabi/newpipe/database/playlist/dao/PlaylistStreamDAO.java b/app/src/main/java/org/schabi/newpipe/database/playlist/dao/PlaylistStreamDAO.java index 8bf1ea696..8b6d62ca4 100644 --- a/app/src/main/java/org/schabi/newpipe/database/playlist/dao/PlaylistStreamDAO.java +++ b/app/src/main/java/org/schabi/newpipe/database/playlist/dao/PlaylistStreamDAO.java @@ -8,7 +8,6 @@ import org.schabi.newpipe.database.BasicDAO; import org.schabi.newpipe.database.playlist.PlaylistMetadataEntry; import org.schabi.newpipe.database.playlist.PlaylistStreamEntry; import org.schabi.newpipe.database.playlist.model.PlaylistStreamEntity; -import org.schabi.newpipe.database.stream.model.StreamEntity; import java.util.List; diff --git a/app/src/main/java/org/schabi/newpipe/database/playlist/model/PlaylistEntity.java b/app/src/main/java/org/schabi/newpipe/database/playlist/model/PlaylistEntity.java index a3ec1b5f2..bfda8eeec 100644 --- a/app/src/main/java/org/schabi/newpipe/database/playlist/model/PlaylistEntity.java +++ b/app/src/main/java/org/schabi/newpipe/database/playlist/model/PlaylistEntity.java @@ -5,8 +5,6 @@ import android.arch.persistence.room.Entity; import android.arch.persistence.room.Index; import android.arch.persistence.room.PrimaryKey; -import java.util.Date; - import static org.schabi.newpipe.database.playlist.model.PlaylistEntity.PLAYLIST_NAME; import static org.schabi.newpipe.database.playlist.model.PlaylistEntity.PLAYLIST_TABLE; diff --git a/app/src/main/java/org/schabi/newpipe/database/playlist/model/PlaylistRemoteEntity.java b/app/src/main/java/org/schabi/newpipe/database/playlist/model/PlaylistRemoteEntity.java index e2f2c8b08..ab917a22b 100644 --- a/app/src/main/java/org/schabi/newpipe/database/playlist/model/PlaylistRemoteEntity.java +++ b/app/src/main/java/org/schabi/newpipe/database/playlist/model/PlaylistRemoteEntity.java @@ -6,7 +6,6 @@ import android.arch.persistence.room.Ignore; import android.arch.persistence.room.Index; import android.arch.persistence.room.PrimaryKey; -import org.schabi.newpipe.database.LocalItem; import org.schabi.newpipe.database.playlist.PlaylistLocalItem; import org.schabi.newpipe.extractor.playlist.PlaylistInfo; import org.schabi.newpipe.util.Constants; diff --git a/app/src/main/java/org/schabi/newpipe/database/stream/dao/StreamDAO.java b/app/src/main/java/org/schabi/newpipe/database/stream/dao/StreamDAO.java index 63f9e5940..396a29fca 100644 --- a/app/src/main/java/org/schabi/newpipe/database/stream/dao/StreamDAO.java +++ b/app/src/main/java/org/schabi/newpipe/database/stream/dao/StreamDAO.java @@ -10,7 +10,6 @@ import org.schabi.newpipe.database.BasicDAO; import org.schabi.newpipe.database.playlist.model.PlaylistStreamEntity; import org.schabi.newpipe.database.stream.model.StreamEntity; import org.schabi.newpipe.database.history.model.StreamHistoryEntity; -import org.schabi.newpipe.database.stream.model.StreamStateEntity; import java.util.ArrayList; import java.util.List; @@ -23,7 +22,6 @@ import static org.schabi.newpipe.database.stream.model.StreamEntity.STREAM_SERVI import static org.schabi.newpipe.database.stream.model.StreamEntity.STREAM_TABLE; import static org.schabi.newpipe.database.stream.model.StreamEntity.STREAM_URL; import static org.schabi.newpipe.database.history.model.StreamHistoryEntity.STREAM_HISTORY_TABLE; -import static org.schabi.newpipe.database.stream.model.StreamStateEntity.STREAM_STATE_TABLE; @Dao public abstract class StreamDAO implements BasicDAO { diff --git a/app/src/main/java/org/schabi/newpipe/download/DeleteDownloadManager.java b/app/src/main/java/org/schabi/newpipe/download/DeleteDownloadManager.java index f2912a6fa..5a2d4a486 100644 --- a/app/src/main/java/org/schabi/newpipe/download/DeleteDownloadManager.java +++ b/app/src/main/java/org/schabi/newpipe/download/DeleteDownloadManager.java @@ -28,11 +28,11 @@ public class DeleteDownloadManager { private static final String KEY_STATE = "delete_manager_state"; - private View mView; - private HashSet mPendingMap; - private List mDisposableList; + private final View mView; + private final HashSet mPendingMap; + private final List mDisposableList; private DownloadManager mDownloadManager; - private PublishSubject publishSubject = PublishSubject.create(); + private final PublishSubject publishSubject = PublishSubject.create(); DeleteDownloadManager(Activity activity) { mPendingMap = new HashSet<>(); diff --git a/app/src/main/java/org/schabi/newpipe/download/DownloadDialog.java b/app/src/main/java/org/schabi/newpipe/download/DownloadDialog.java index 75f05cd16..9bbda6032 100644 --- a/app/src/main/java/org/schabi/newpipe/download/DownloadDialog.java +++ b/app/src/main/java/org/schabi/newpipe/download/DownloadDialog.java @@ -55,7 +55,7 @@ public class DownloadDialog extends DialogFragment implements RadioGroup.OnCheck private StreamItemAdapter audioStreamsAdapter; private StreamItemAdapter videoStreamsAdapter; - private CompositeDisposable disposables = new CompositeDisposable(); + private final CompositeDisposable disposables = new CompositeDisposable(); private EditText nameEditText; private Spinner streamsSpinner; diff --git a/app/src/main/java/org/schabi/newpipe/fragments/BaseStateFragment.java b/app/src/main/java/org/schabi/newpipe/fragments/BaseStateFragment.java index 589d15bd4..acee1f111 100644 --- a/app/src/main/java/org/schabi/newpipe/fragments/BaseStateFragment.java +++ b/app/src/main/java/org/schabi/newpipe/fragments/BaseStateFragment.java @@ -32,7 +32,6 @@ import java.util.concurrent.atomic.AtomicBoolean; import icepick.State; import io.reactivex.android.schedulers.AndroidSchedulers; -import io.reactivex.functions.Consumer; import static org.schabi.newpipe.util.AnimationUtils.animateView; diff --git a/app/src/main/java/org/schabi/newpipe/fragments/BlankFragment.java b/app/src/main/java/org/schabi/newpipe/fragments/BlankFragment.java index 4ee90f083..948e9377d 100644 --- a/app/src/main/java/org/schabi/newpipe/fragments/BlankFragment.java +++ b/app/src/main/java/org/schabi/newpipe/fragments/BlankFragment.java @@ -2,7 +2,6 @@ package org.schabi.newpipe.fragments; import android.os.Bundle; import android.support.annotation.Nullable; -import android.util.Log; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; diff --git a/app/src/main/java/org/schabi/newpipe/fragments/detail/StackItem.java b/app/src/main/java/org/schabi/newpipe/fragments/detail/StackItem.java index b8957f33c..f7f8ad702 100644 --- a/app/src/main/java/org/schabi/newpipe/fragments/detail/StackItem.java +++ b/app/src/main/java/org/schabi/newpipe/fragments/detail/StackItem.java @@ -3,9 +3,9 @@ package org.schabi.newpipe.fragments.detail; import java.io.Serializable; class StackItem implements Serializable { - private int serviceId; + private final int serviceId; private String title; - private String url; + private final String url; StackItem(int serviceId, String url, String title) { this.serviceId = serviceId; diff --git a/app/src/main/java/org/schabi/newpipe/fragments/detail/VideoDetailFragment.java b/app/src/main/java/org/schabi/newpipe/fragments/detail/VideoDetailFragment.java index c726f8cee..9ab40e81c 100644 --- a/app/src/main/java/org/schabi/newpipe/fragments/detail/VideoDetailFragment.java +++ b/app/src/main/java/org/schabi/newpipe/fragments/detail/VideoDetailFragment.java @@ -33,12 +33,14 @@ import android.view.MenuItem; import android.view.MotionEvent; import android.view.View; import android.view.ViewGroup; +import android.view.ViewParent; import android.widget.AdapterView; import android.widget.FrameLayout; import android.widget.ImageButton; import android.widget.ImageView; import android.widget.LinearLayout; import android.widget.RelativeLayout; +import android.widget.ScrollView; import android.widget.Spinner; import android.widget.TextView; import android.widget.Toast; @@ -64,19 +66,17 @@ import org.schabi.newpipe.extractor.stream.StreamType; import org.schabi.newpipe.extractor.stream.VideoStream; import org.schabi.newpipe.fragments.BackPressable; import org.schabi.newpipe.fragments.BaseStateFragment; -import org.schabi.newpipe.local.history.HistoryRecordManager; -import org.schabi.newpipe.report.ErrorActivity; -import org.schabi.newpipe.util.StreamItemAdapter; -import org.schabi.newpipe.util.StreamItemAdapter.StreamSizeWrapper; -import org.schabi.newpipe.local.dialog.PlaylistAppendDialog; import org.schabi.newpipe.info_list.InfoItemBuilder; import org.schabi.newpipe.info_list.InfoItemDialog; +import org.schabi.newpipe.local.dialog.PlaylistAppendDialog; +import org.schabi.newpipe.local.history.HistoryRecordManager; import org.schabi.newpipe.player.MainVideoPlayer; import org.schabi.newpipe.player.PopupVideoPlayer; import org.schabi.newpipe.player.helper.PlayerHelper; import org.schabi.newpipe.player.old.PlayVideoActivity; import org.schabi.newpipe.player.playqueue.PlayQueue; import org.schabi.newpipe.player.playqueue.SinglePlayQueue; +import org.schabi.newpipe.report.ErrorActivity; import org.schabi.newpipe.report.UserAction; import org.schabi.newpipe.util.Constants; import org.schabi.newpipe.util.ExtractorHelper; @@ -87,6 +87,8 @@ import org.schabi.newpipe.util.Localization; import org.schabi.newpipe.util.NavigationHelper; import org.schabi.newpipe.util.OnClickGesture; import org.schabi.newpipe.util.PermissionHelper; +import org.schabi.newpipe.util.StreamItemAdapter; +import org.schabi.newpipe.util.StreamItemAdapter.StreamSizeWrapper; import org.schabi.newpipe.util.ThemeHelper; import java.io.Serializable; @@ -154,6 +156,7 @@ public class VideoDetailFragment private View videoTitleRoot; private TextView videoTitleTextView; + @Nullable private ImageView videoTitleToggleArrow; private TextView videoCountView; @@ -415,14 +418,16 @@ public class VideoDetailFragment } private void toggleTitleAndDescription() { - if (videoDescriptionRootLayout.getVisibility() == View.VISIBLE) { - videoTitleTextView.setMaxLines(1); - videoDescriptionRootLayout.setVisibility(View.GONE); - videoTitleToggleArrow.setImageResource(R.drawable.arrow_down); - } else { - videoTitleTextView.setMaxLines(10); - videoDescriptionRootLayout.setVisibility(View.VISIBLE); - videoTitleToggleArrow.setImageResource(R.drawable.arrow_up); + if (videoTitleToggleArrow != null) { //it is null for tablets + if (videoDescriptionRootLayout.getVisibility() == View.VISIBLE) { + videoTitleTextView.setMaxLines(1); + videoDescriptionRootLayout.setVisibility(View.GONE); + videoTitleToggleArrow.setImageResource(R.drawable.arrow_down); + } else { + videoTitleTextView.setMaxLines(10); + videoDescriptionRootLayout.setVisibility(View.VISIBLE); + videoTitleToggleArrow.setImageResource(R.drawable.arrow_up); + } } } @@ -622,8 +627,11 @@ public class VideoDetailFragment relatedStreamsView.addView( infoItemBuilder.buildView(relatedStreamsView, info.getNextVideo())); relatedStreamsView.addView(getSeparatorView()); - relatedStreamRootLayout.setVisibility(View.VISIBLE); - } else nextStreamTitle.setVisibility(View.GONE); + setRelatedStreamsVisibility(View.VISIBLE); + } else { + nextStreamTitle.setVisibility(View.GONE); + setRelatedStreamsVisibility(View.GONE); + } if (info.getRelatedStreams() != null && !info.getRelatedStreams().isEmpty() && showRelatedStreams) { @@ -639,13 +647,13 @@ public class VideoDetailFragment } //if (DEBUG) Log.d(TAG, "Total time " + ((System.nanoTime() - first) / 1000000L) + "ms"); - relatedStreamRootLayout.setVisibility(View.VISIBLE); + setRelatedStreamsVisibility(View.VISIBLE); relatedStreamExpandButton.setVisibility(View.VISIBLE); relatedStreamExpandButton.setImageDrawable(ContextCompat.getDrawable( activity, ThemeHelper.resolveResourceIdFromAttr(activity, R.attr.expand))); } else { - if (info.getNextVideo() == null) relatedStreamRootLayout.setVisibility(View.GONE); + if (info.getNextVideo() == null) setRelatedStreamsVisibility(View.GONE); relatedStreamExpandButton.setVisibility(View.GONE); } } @@ -760,7 +768,7 @@ public class VideoDetailFragment * Stack that contains the "navigation history".
* The peek is the current video. */ - protected LinkedList stack = new LinkedList<>(); + protected final LinkedList stack = new LinkedList<>(); public void clearHistory() { stack.clear(); @@ -1114,8 +1122,16 @@ public class VideoDetailFragment animateView(videoTitleTextView, true, 0); videoDescriptionRootLayout.setVisibility(View.GONE); - videoTitleToggleArrow.setImageResource(R.drawable.arrow_down); - videoTitleToggleArrow.setVisibility(View.GONE); + if (videoTitleToggleArrow != null) { //phone + videoTitleToggleArrow.setImageResource(R.drawable.arrow_down); + videoTitleToggleArrow.setVisibility(View.GONE); + } else { //tablet + final View related = (View) relatedStreamRootLayout.getParent(); + //don`t need to hide it if related streams are disabled + if (related.getVisibility() == View.VISIBLE) { + related.setVisibility(View.INVISIBLE); + } + } videoTitleRoot.setClickable(false); imageLoader.cancelDisplayTask(thumbnailImageView); @@ -1190,11 +1206,15 @@ public class VideoDetailFragment detailDurationView.setVisibility(View.GONE); } - videoTitleRoot.setClickable(true); - videoTitleToggleArrow.setVisibility(View.VISIBLE); - videoTitleToggleArrow.setImageResource(R.drawable.arrow_down); videoDescriptionView.setVisibility(View.GONE); - videoDescriptionRootLayout.setVisibility(View.GONE); + if (videoTitleToggleArrow != null) { + videoTitleRoot.setClickable(true); + videoTitleToggleArrow.setVisibility(View.VISIBLE); + videoTitleToggleArrow.setImageResource(R.drawable.arrow_down); + videoDescriptionRootLayout.setVisibility(View.GONE); + } else { + videoDescriptionRootLayout.setVisibility(View.VISIBLE); + } if (!TextUtils.isEmpty(info.getUploadDate())) { videoUploadDateView.setText(Localization.localizeDate(activity, info.getUploadDate())); } @@ -1242,6 +1262,11 @@ public class VideoDetailFragment // Only auto play in the first open autoPlayEnabled = false; } + + final ViewParent related = relatedStreamRootLayout.getParent(); + if (related instanceof ScrollView) { + ((ScrollView) related).scrollTo(0, 0); + } } @@ -1299,4 +1324,13 @@ public class VideoDetailFragment showError(getString(R.string.blocked_by_gema), false, R.drawable.gruese_die_gema); } + + private void setRelatedStreamsVisibility(int visibility) { + final ViewParent parent = relatedStreamRootLayout.getParent(); + if (parent instanceof ScrollView) { + ((ScrollView) parent).setVisibility(visibility); + } else { + relatedStreamRootLayout.setVisibility(visibility); + } + } } \ No newline at end of file diff --git a/app/src/main/java/org/schabi/newpipe/fragments/list/BaseListFragment.java b/app/src/main/java/org/schabi/newpipe/fragments/list/BaseListFragment.java index c70ea2b19..0816334ea 100644 --- a/app/src/main/java/org/schabi/newpipe/fragments/list/BaseListFragment.java +++ b/app/src/main/java/org/schabi/newpipe/fragments/list/BaseListFragment.java @@ -3,10 +3,15 @@ package org.schabi.newpipe.fragments.list; import android.app.Activity; import android.content.Context; import android.content.DialogInterface; +import android.content.SharedPreferences; +import android.content.res.Configuration; +import android.content.res.Resources; import android.os.Bundle; +import android.preference.PreferenceManager; import android.support.annotation.NonNull; import android.support.v7.app.ActionBar; import android.support.v7.app.AppCompatActivity; +import android.support.v7.widget.GridLayoutManager; import android.support.v7.widget.LinearLayoutManager; import android.support.v7.widget.RecyclerView; import android.util.Log; @@ -21,9 +26,9 @@ import org.schabi.newpipe.extractor.playlist.PlaylistInfoItem; import org.schabi.newpipe.extractor.stream.StreamInfoItem; import org.schabi.newpipe.fragments.BaseStateFragment; import org.schabi.newpipe.fragments.OnScrollBelowItemsListener; -import org.schabi.newpipe.local.dialog.PlaylistAppendDialog; import org.schabi.newpipe.info_list.InfoItemDialog; import org.schabi.newpipe.info_list.InfoListAdapter; +import org.schabi.newpipe.local.dialog.PlaylistAppendDialog; import org.schabi.newpipe.player.playqueue.SinglePlayQueue; import org.schabi.newpipe.report.ErrorActivity; import org.schabi.newpipe.util.NavigationHelper; @@ -36,7 +41,7 @@ import java.util.Queue; import static org.schabi.newpipe.util.AnimationUtils.animateView; -public abstract class BaseListFragment extends BaseStateFragment implements ListViewContract, StateSaver.WriteRead { +public abstract class BaseListFragment extends BaseStateFragment implements ListViewContract, StateSaver.WriteRead, SharedPreferences.OnSharedPreferenceChangeListener { /*////////////////////////////////////////////////////////////////////////// // Views @@ -44,6 +49,9 @@ public abstract class BaseListFragment extends BaseStateFragment implem protected InfoListAdapter infoListAdapter; protected RecyclerView itemsList; + private int updateFlags = 0; + + private static final int LIST_MODE_UPDATE_FLAG = 0x32; /*////////////////////////////////////////////////////////////////////////// // LifeCycle @@ -59,12 +67,31 @@ public abstract class BaseListFragment extends BaseStateFragment implem public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setHasOptionsMenu(true); + PreferenceManager.getDefaultSharedPreferences(activity) + .registerOnSharedPreferenceChangeListener(this); } @Override public void onDestroy() { super.onDestroy(); StateSaver.onDestroy(savedState); + PreferenceManager.getDefaultSharedPreferences(activity) + .unregisterOnSharedPreferenceChangeListener(this); + } + + @Override + public void onResume() { + super.onResume(); + + if (updateFlags != 0) { + if ((updateFlags & LIST_MODE_UPDATE_FLAG) != 0) { + final boolean useGrid = isGridLayout(); + itemsList.setLayoutManager(useGrid ? getGridLayoutManager() : getListLayoutManager()); + infoListAdapter.setGridItemVariants(useGrid); + infoListAdapter.notifyDataSetChanged(); + } + updateFlags = 0; + } } /*////////////////////////////////////////////////////////////////////////// @@ -119,13 +146,25 @@ public abstract class BaseListFragment extends BaseStateFragment implem return new LinearLayoutManager(activity); } + protected RecyclerView.LayoutManager getGridLayoutManager() { + final Resources resources = activity.getResources(); + int width = resources.getDimensionPixelSize(R.dimen.video_item_grid_thumbnail_image_width); + width += (24 * resources.getDisplayMetrics().density); + final int spanCount = (int) Math.floor(resources.getDisplayMetrics().widthPixels / (double)width); + final GridLayoutManager lm = new GridLayoutManager(activity, spanCount); + lm.setSpanSizeLookup(infoListAdapter.getSpanSizeLookup(spanCount)); + return lm; + } + @Override protected void initViews(View rootView, Bundle savedInstanceState) { super.initViews(rootView, savedInstanceState); + final boolean useGrid = isGridLayout(); itemsList = rootView.findViewById(R.id.items_list); - itemsList.setLayoutManager(getListLayoutManager()); + itemsList.setLayoutManager(useGrid ? getGridLayoutManager() : getListLayoutManager()); + infoListAdapter.setGridItemVariants(useGrid); infoListAdapter.setFooter(getListFooter()); infoListAdapter.setHeader(getListHeader()); @@ -308,4 +347,22 @@ public abstract class BaseListFragment extends BaseStateFragment implem public void handleNextItems(N result) { isLoading.set(false); } + + @Override + public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String key) { + if (key.equals(getString(R.string.list_view_mode_key))) { + updateFlags |= LIST_MODE_UPDATE_FLAG; + } + } + + protected boolean isGridLayout() { + final String list_mode = PreferenceManager.getDefaultSharedPreferences(activity).getString(getString(R.string.list_view_mode_key), getString(R.string.list_view_mode_value)); + if ("auto".equals(list_mode)) { + final Configuration configuration = getResources().getConfiguration(); + return configuration.orientation == Configuration.ORIENTATION_LANDSCAPE + && configuration.isLayoutSizeAtLeast(Configuration.SCREENLAYOUT_SIZE_LARGE); + } else { + return "grid".equals(list_mode); + } + } } diff --git a/app/src/main/java/org/schabi/newpipe/fragments/list/BaseListInfoFragment.java b/app/src/main/java/org/schabi/newpipe/fragments/list/BaseListInfoFragment.java index e702c602f..5d042c949 100644 --- a/app/src/main/java/org/schabi/newpipe/fragments/list/BaseListInfoFragment.java +++ b/app/src/main/java/org/schabi/newpipe/fragments/list/BaseListInfoFragment.java @@ -8,9 +8,6 @@ import android.view.View; import org.schabi.newpipe.extractor.ListExtractor; import org.schabi.newpipe.extractor.ListInfo; -import org.schabi.newpipe.extractor.NewPipe; -import org.schabi.newpipe.extractor.linkhandler.ListLinkHandler; -import org.schabi.newpipe.extractor.linkhandler.LinkHandler; import org.schabi.newpipe.util.Constants; import java.util.Queue; @@ -19,7 +16,6 @@ import icepick.State; import io.reactivex.Single; import io.reactivex.android.schedulers.AndroidSchedulers; import io.reactivex.disposables.Disposable; -import io.reactivex.functions.Consumer; import io.reactivex.schedulers.Schedulers; public abstract class BaseListInfoFragment diff --git a/app/src/main/java/org/schabi/newpipe/fragments/list/channel/ChannelFragment.java b/app/src/main/java/org/schabi/newpipe/fragments/list/channel/ChannelFragment.java index 9a52b8d12..6a3b3eb50 100644 --- a/app/src/main/java/org/schabi/newpipe/fragments/list/channel/ChannelFragment.java +++ b/app/src/main/java/org/schabi/newpipe/fragments/list/channel/ChannelFragment.java @@ -68,7 +68,7 @@ import static org.schabi.newpipe.util.AnimationUtils.animateView; public class ChannelFragment extends BaseListInfoFragment { - private CompositeDisposable disposables = new CompositeDisposable(); + private final CompositeDisposable disposables = new CompositeDisposable(); private Disposable subscribeButtonMonitor; private SubscriptionService subscriptionService; @@ -90,8 +90,6 @@ public class ChannelFragment extends BaseListInfoFragment { private MenuItem menuRssButton; - private boolean mIsVisibleToUser = false; - public static ChannelFragment getInstance(int serviceId, String url, String name) { ChannelFragment instance = new ChannelFragment(); instance.setInitialData(serviceId, url, name); @@ -105,7 +103,6 @@ public class ChannelFragment extends BaseListInfoFragment { @Override public void setUserVisibleHint(boolean isVisibleToUser) { super.setUserVisibleHint(isVisibleToUser); - mIsVisibleToUser = isVisibleToUser; if(activity != null && useAsFrontPage && isVisibleToUser) { diff --git a/app/src/main/java/org/schabi/newpipe/fragments/list/kiosk/KioskFragment.java b/app/src/main/java/org/schabi/newpipe/fragments/list/kiosk/KioskFragment.java index 833d0f55e..7d4500691 100644 --- a/app/src/main/java/org/schabi/newpipe/fragments/list/kiosk/KioskFragment.java +++ b/app/src/main/java/org/schabi/newpipe/fragments/list/kiosk/KioskFragment.java @@ -5,7 +5,6 @@ import android.preference.PreferenceManager; import android.support.annotation.NonNull; import android.support.annotation.Nullable; import android.support.v7.app.ActionBar; -import android.util.Log; import android.view.LayoutInflater; import android.view.Menu; import android.view.MenuInflater; @@ -19,8 +18,6 @@ import org.schabi.newpipe.extractor.StreamingService; import org.schabi.newpipe.extractor.exceptions.ExtractionException; import org.schabi.newpipe.extractor.kiosk.KioskInfo; import org.schabi.newpipe.extractor.linkhandler.ListLinkHandlerFactory; -import org.schabi.newpipe.extractor.linkhandler.ListLinkHandler; -import org.schabi.newpipe.extractor.linkhandler.LinkHandlerFactory; import org.schabi.newpipe.fragments.list.BaseListInfoFragment; import org.schabi.newpipe.report.UserAction; import org.schabi.newpipe.util.ExtractorHelper; @@ -131,26 +128,16 @@ public class KioskFragment extends BaseListInfoFragment { @Override public Single loadResult(boolean forceReload) { - String contentCountry = PreferenceManager - .getDefaultSharedPreferences(activity) - .getString(getString(R.string.content_country_key), - getString(R.string.default_country_value)); return ExtractorHelper.getKioskInfo(serviceId, url, - contentCountry, forceReload); } @Override public Single loadMoreItemsLogic() { - String contentCountry = PreferenceManager - .getDefaultSharedPreferences(activity) - .getString(getString(R.string.content_country_key), - getString(R.string.default_country_value)); return ExtractorHelper.getMoreKioskItems(serviceId, url, - currentNextPageUrl, - contentCountry); + currentNextPageUrl); } /*////////////////////////////////////////////////////////////////////////// diff --git a/app/src/main/java/org/schabi/newpipe/fragments/list/playlist/PlaylistFragment.java b/app/src/main/java/org/schabi/newpipe/fragments/list/playlist/PlaylistFragment.java index b7a42791c..0019a3819 100644 --- a/app/src/main/java/org/schabi/newpipe/fragments/list/playlist/PlaylistFragment.java +++ b/app/src/main/java/org/schabi/newpipe/fragments/list/playlist/PlaylistFragment.java @@ -20,7 +20,6 @@ import android.widget.TextView; import org.reactivestreams.Subscriber; import org.reactivestreams.Subscription; -import org.schabi.newpipe.App; import org.schabi.newpipe.NewPipeDatabase; import org.schabi.newpipe.R; import org.schabi.newpipe.database.playlist.model.PlaylistRemoteEntity; @@ -30,7 +29,6 @@ import org.schabi.newpipe.extractor.NewPipe; import org.schabi.newpipe.extractor.exceptions.ExtractionException; import org.schabi.newpipe.extractor.playlist.PlaylistInfo; import org.schabi.newpipe.extractor.stream.StreamInfoItem; -import org.schabi.newpipe.extractor.linkhandler.ListLinkHandler; import org.schabi.newpipe.fragments.list.BaseListInfoFragment; import org.schabi.newpipe.info_list.InfoItemDialog; import org.schabi.newpipe.local.playlist.RemotePlaylistManager; diff --git a/app/src/main/java/org/schabi/newpipe/fragments/list/search/SearchFragment.java b/app/src/main/java/org/schabi/newpipe/fragments/list/search/SearchFragment.java index a699e28bc..2833abb8d 100644 --- a/app/src/main/java/org/schabi/newpipe/fragments/list/search/SearchFragment.java +++ b/app/src/main/java/org/schabi/newpipe/fragments/list/search/SearchFragment.java @@ -122,12 +122,11 @@ public class SearchFragment private String nextPageUrl; private String contentCountry; private boolean isSuggestionsEnabled = true; - private boolean isSearchHistoryEnabled = true; - private PublishSubject suggestionPublisher = PublishSubject.create(); + private final PublishSubject suggestionPublisher = PublishSubject.create(); private Disposable searchDisposable; private Disposable suggestionDisposable; - private CompositeDisposable disposables = new CompositeDisposable(); + private final CompositeDisposable disposables = new CompositeDisposable(); private SuggestionListAdapter suggestionListAdapter; private HistoryRecordManager historyRecordManager; @@ -173,7 +172,7 @@ public class SearchFragment suggestionListAdapter = new SuggestionListAdapter(activity); SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(activity); - isSearchHistoryEnabled = preferences.getBoolean(getString(R.string.enable_search_history_key), true); + boolean isSearchHistoryEnabled = preferences.getBoolean(getString(R.string.enable_search_history_key), true); suggestionListAdapter.setShowSuggestionHistory(isSearchHistoryEnabled); historyRecordManager = new HistoryRecordManager(context); @@ -627,7 +626,7 @@ public class SearchFragment } final Observable> network = ExtractorHelper - .suggestionsFor(serviceId, query, contentCountry) + .suggestionsFor(serviceId, query) .toObservable() .map(strings -> { List result = new ArrayList<>(); @@ -727,8 +726,7 @@ public class SearchFragment searchDisposable = ExtractorHelper.searchFor(serviceId, searchString, Arrays.asList(contentFilter), - sortFilter, - contentCountry) + sortFilter) .subscribeOn(Schedulers.io()) .observeOn(AndroidSchedulers.mainThread()) .doOnEvent((searchResult, throwable) -> isLoading.set(false)) @@ -746,8 +744,7 @@ public class SearchFragment searchString, asList(contentFilter), sortFilter, - nextPageUrl, - contentCountry) + nextPageUrl) .subscribeOn(Schedulers.io()) .observeOn(AndroidSchedulers.mainThread()) .doOnEvent((nextItemsResult, throwable) -> isLoading.set(false)) diff --git a/app/src/main/java/org/schabi/newpipe/info_list/InfoItemBuilder.java b/app/src/main/java/org/schabi/newpipe/info_list/InfoItemBuilder.java index 78867c81f..f473e5d08 100644 --- a/app/src/main/java/org/schabi/newpipe/info_list/InfoItemBuilder.java +++ b/app/src/main/java/org/schabi/newpipe/info_list/InfoItemBuilder.java @@ -45,7 +45,7 @@ public class InfoItemBuilder { private static final String TAG = InfoItemBuilder.class.toString(); private final Context context; - private ImageLoader imageLoader = ImageLoader.getInstance(); + private final ImageLoader imageLoader = ImageLoader.getInstance(); private OnClickGesture onStreamSelectedListener; private OnClickGesture onChannelSelectedListener; diff --git a/app/src/main/java/org/schabi/newpipe/info_list/InfoItemDialog.java b/app/src/main/java/org/schabi/newpipe/info_list/InfoItemDialog.java index 88aa76887..fd0e9f528 100644 --- a/app/src/main/java/org/schabi/newpipe/info_list/InfoItemDialog.java +++ b/app/src/main/java/org/schabi/newpipe/info_list/InfoItemDialog.java @@ -5,7 +5,6 @@ import android.app.AlertDialog; import android.content.DialogInterface; import android.support.annotation.NonNull; import android.support.annotation.Nullable; -import android.view.LayoutInflater; import android.view.View; import android.widget.TextView; diff --git a/app/src/main/java/org/schabi/newpipe/info_list/InfoListAdapter.java b/app/src/main/java/org/schabi/newpipe/info_list/InfoListAdapter.java index cf12deb6f..15fdcad05 100644 --- a/app/src/main/java/org/schabi/newpipe/info_list/InfoListAdapter.java +++ b/app/src/main/java/org/schabi/newpipe/info_list/InfoListAdapter.java @@ -1,6 +1,7 @@ package org.schabi.newpipe.info_list; import android.app.Activity; +import android.support.v7.widget.GridLayoutManager; import android.support.v7.widget.RecyclerView; import android.util.Log; import android.view.View; @@ -12,9 +13,12 @@ import org.schabi.newpipe.extractor.playlist.PlaylistInfoItem; import org.schabi.newpipe.extractor.stream.StreamInfoItem; import org.schabi.newpipe.info_list.holder.ChannelInfoItemHolder; import org.schabi.newpipe.info_list.holder.ChannelMiniInfoItemHolder; +import org.schabi.newpipe.info_list.holder.ChannelGridInfoItemHolder; import org.schabi.newpipe.info_list.holder.InfoItemHolder; +import org.schabi.newpipe.info_list.holder.PlaylistGridInfoItemHolder; import org.schabi.newpipe.info_list.holder.PlaylistInfoItemHolder; import org.schabi.newpipe.info_list.holder.PlaylistMiniInfoItemHolder; +import org.schabi.newpipe.info_list.holder.StreamGridInfoItemHolder; import org.schabi.newpipe.info_list.holder.StreamInfoItemHolder; import org.schabi.newpipe.info_list.holder.StreamMiniInfoItemHolder; import org.schabi.newpipe.util.FallbackViewHolder; @@ -52,14 +56,18 @@ public class InfoListAdapter extends RecyclerView.Adapter infoItemList; private boolean useMiniVariant = false; + private boolean useGridVariant = false; private boolean showFooter = false; private View header = null; private View footer = null; @@ -94,6 +102,10 @@ public class InfoListAdapter extends RecyclerView.Adapter data) { if (data != null) { if (DEBUG) { @@ -206,11 +218,11 @@ public class InfoListAdapter extends RecyclerView.Adapter { + if (itemBuilder.getOnChannelSelectedListener() != null) { + itemBuilder.getOnChannelSelectedListener().held(item); + } + return true; + }); } protected String getDetailLine(final ChannelInfoItem item) { diff --git a/app/src/main/java/org/schabi/newpipe/info_list/holder/PlaylistGridInfoItemHolder.java b/app/src/main/java/org/schabi/newpipe/info_list/holder/PlaylistGridInfoItemHolder.java new file mode 100644 index 000000000..96b9c90a7 --- /dev/null +++ b/app/src/main/java/org/schabi/newpipe/info_list/holder/PlaylistGridInfoItemHolder.java @@ -0,0 +1,13 @@ +package org.schabi.newpipe.info_list.holder; + +import android.view.ViewGroup; + +import org.schabi.newpipe.R; +import org.schabi.newpipe.info_list.InfoItemBuilder; + +public class PlaylistGridInfoItemHolder extends PlaylistMiniInfoItemHolder { + + public PlaylistGridInfoItemHolder(InfoItemBuilder infoItemBuilder, ViewGroup parent) { + super(infoItemBuilder, R.layout.list_playlist_grid_item, parent); + } +} \ No newline at end of file diff --git a/app/src/main/java/org/schabi/newpipe/info_list/holder/StreamGridInfoItemHolder.java b/app/src/main/java/org/schabi/newpipe/info_list/holder/StreamGridInfoItemHolder.java new file mode 100644 index 000000000..a2e585857 --- /dev/null +++ b/app/src/main/java/org/schabi/newpipe/info_list/holder/StreamGridInfoItemHolder.java @@ -0,0 +1,13 @@ +package org.schabi.newpipe.info_list.holder; + +import android.view.ViewGroup; + +import org.schabi.newpipe.R; +import org.schabi.newpipe.info_list.InfoItemBuilder; + +public class StreamGridInfoItemHolder extends StreamMiniInfoItemHolder { + + public StreamGridInfoItemHolder(InfoItemBuilder infoItemBuilder, ViewGroup parent) { + super(infoItemBuilder, R.layout.list_stream_grid_item, parent); + } +} diff --git a/app/src/main/java/org/schabi/newpipe/local/BaseLocalListFragment.java b/app/src/main/java/org/schabi/newpipe/local/BaseLocalListFragment.java index 5192aa2ab..abdf82353 100644 --- a/app/src/main/java/org/schabi/newpipe/local/BaseLocalListFragment.java +++ b/app/src/main/java/org/schabi/newpipe/local/BaseLocalListFragment.java @@ -1,8 +1,13 @@ package org.schabi.newpipe.local; +import android.content.SharedPreferences; +import android.content.res.Configuration; +import android.content.res.Resources; import android.os.Bundle; +import android.preference.PreferenceManager; import android.support.v4.app.Fragment; import android.support.v7.app.ActionBar; +import android.support.v7.widget.GridLayoutManager; import android.support.v7.widget.LinearLayoutManager; import android.support.v7.widget.RecyclerView; import android.util.Log; @@ -25,7 +30,7 @@ import static org.schabi.newpipe.util.AnimationUtils.animateView; * called and is memory efficient when in backstack. * */ public abstract class BaseLocalListFragment extends BaseStateFragment - implements ListViewContract { + implements ListViewContract, SharedPreferences.OnSharedPreferenceChangeListener { /*////////////////////////////////////////////////////////////////////////// // Views @@ -36,6 +41,9 @@ public abstract class BaseLocalListFragment extends BaseStateFragment protected LocalItemListAdapter itemListAdapter; protected RecyclerView itemsList; + private int updateFlags = 0; + + private static final int LIST_MODE_UPDATE_FLAG = 0x32; /*////////////////////////////////////////////////////////////////////////// // Lifecycle - Creation @@ -45,6 +53,29 @@ public abstract class BaseLocalListFragment extends BaseStateFragment public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setHasOptionsMenu(true); + PreferenceManager.getDefaultSharedPreferences(activity) + .registerOnSharedPreferenceChangeListener(this); + } + + @Override + public void onDestroy() { + super.onDestroy(); + PreferenceManager.getDefaultSharedPreferences(activity) + .unregisterOnSharedPreferenceChangeListener(this); + } + + @Override + public void onResume() { + super.onResume(); + if (updateFlags != 0) { + if ((updateFlags & LIST_MODE_UPDATE_FLAG) != 0) { + final boolean useGrid = isGridLayout(); + itemsList.setLayoutManager(useGrid ? getGridLayoutManager() : getListLayoutManager()); + itemListAdapter.setGridItemVariants(useGrid); + itemListAdapter.notifyDataSetChanged(); + } + updateFlags = 0; + } } /*////////////////////////////////////////////////////////////////////////// @@ -59,6 +90,16 @@ public abstract class BaseLocalListFragment extends BaseStateFragment return activity.getLayoutInflater().inflate(R.layout.pignate_footer, itemsList, false); } + protected RecyclerView.LayoutManager getGridLayoutManager() { + final Resources resources = activity.getResources(); + int width = resources.getDimensionPixelSize(R.dimen.video_item_grid_thumbnail_image_width); + width += (24 * resources.getDisplayMetrics().density); + final int spanCount = (int) Math.floor(resources.getDisplayMetrics().widthPixels / (double)width); + final GridLayoutManager lm = new GridLayoutManager(activity, spanCount); + lm.setSpanSizeLookup(itemListAdapter.getSpanSizeLookup(spanCount)); + return lm; + } + protected RecyclerView.LayoutManager getListLayoutManager() { return new LinearLayoutManager(activity); } @@ -67,10 +108,13 @@ public abstract class BaseLocalListFragment extends BaseStateFragment protected void initViews(View rootView, Bundle savedInstanceState) { super.initViews(rootView, savedInstanceState); - itemsList = rootView.findViewById(R.id.items_list); - itemsList.setLayoutManager(getListLayoutManager()); - itemListAdapter = new LocalItemListAdapter(activity); + + final boolean useGrid = isGridLayout(); + itemsList = rootView.findViewById(R.id.items_list); + itemsList.setLayoutManager(useGrid ? getGridLayoutManager() : getListLayoutManager()); + + itemListAdapter.setGridItemVariants(useGrid); itemListAdapter.setHeader(headerRootView = getListHeader()); itemListAdapter.setFooter(footerRootView = getListFooter()); @@ -174,4 +218,22 @@ public abstract class BaseLocalListFragment extends BaseStateFragment resetFragment(); return super.onError(exception); } + + @Override + public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String key) { + if (key.equals(getString(R.string.list_view_mode_key))) { + updateFlags |= LIST_MODE_UPDATE_FLAG; + } + } + + protected boolean isGridLayout() { + final String list_mode = PreferenceManager.getDefaultSharedPreferences(activity).getString(getString(R.string.list_view_mode_key), getString(R.string.list_view_mode_value)); + if ("auto".equals(list_mode)) { + final Configuration configuration = getResources().getConfiguration(); + return configuration.orientation == Configuration.ORIENTATION_LANDSCAPE + && configuration.isLayoutSizeAtLeast(Configuration.SCREENLAYOUT_SIZE_LARGE); + } else { + return "grid".equals(list_mode); + } + } } diff --git a/app/src/main/java/org/schabi/newpipe/local/LocalItemBuilder.java b/app/src/main/java/org/schabi/newpipe/local/LocalItemBuilder.java index 148f93075..0fbab0398 100644 --- a/app/src/main/java/org/schabi/newpipe/local/LocalItemBuilder.java +++ b/app/src/main/java/org/schabi/newpipe/local/LocalItemBuilder.java @@ -33,7 +33,7 @@ public class LocalItemBuilder { private static final String TAG = LocalItemBuilder.class.toString(); private final Context context; - private ImageLoader imageLoader = ImageLoader.getInstance(); + private final ImageLoader imageLoader = ImageLoader.getInstance(); private OnClickGesture onSelectedListener; diff --git a/app/src/main/java/org/schabi/newpipe/local/LocalItemListAdapter.java b/app/src/main/java/org/schabi/newpipe/local/LocalItemListAdapter.java index 99937b58c..e298dedd3 100644 --- a/app/src/main/java/org/schabi/newpipe/local/LocalItemListAdapter.java +++ b/app/src/main/java/org/schabi/newpipe/local/LocalItemListAdapter.java @@ -1,18 +1,21 @@ package org.schabi.newpipe.local; import android.app.Activity; +import android.support.v7.widget.GridLayoutManager; import android.support.v7.widget.RecyclerView; import android.util.Log; import android.view.View; import android.view.ViewGroup; import org.schabi.newpipe.database.LocalItem; -import org.schabi.newpipe.local.HeaderFooterHolder; -import org.schabi.newpipe.local.LocalItemBuilder; import org.schabi.newpipe.local.holder.LocalItemHolder; +import org.schabi.newpipe.local.holder.LocalPlaylistGridItemHolder; import org.schabi.newpipe.local.holder.LocalPlaylistItemHolder; +import org.schabi.newpipe.local.holder.LocalPlaylistStreamGridItemHolder; import org.schabi.newpipe.local.holder.LocalPlaylistStreamItemHolder; +import org.schabi.newpipe.local.holder.LocalStatisticStreamGridItemHolder; import org.schabi.newpipe.local.holder.LocalStatisticStreamItemHolder; +import org.schabi.newpipe.local.holder.RemotePlaylistGridItemHolder; import org.schabi.newpipe.local.holder.RemotePlaylistItemHolder; import org.schabi.newpipe.util.FallbackViewHolder; import org.schabi.newpipe.util.Localization; @@ -52,14 +55,19 @@ public class LocalItemListAdapter extends RecyclerView.Adapter localItems; private final DateFormat dateFormat; private boolean showFooter = false; + private boolean useGridVariant = false; private View header = null; private View footer = null; @@ -134,6 +142,10 @@ public class LocalItemListAdapter extends RecyclerView.Adapter savedObjects) throws Exception { + public void readFrom(@NonNull Queue savedObjects) { streamEntities = (List) savedObjects.poll(); } diff --git a/app/src/main/java/org/schabi/newpipe/local/feed/FeedFragment.java b/app/src/main/java/org/schabi/newpipe/local/feed/FeedFragment.java index 634bea62b..f1bb01734 100644 --- a/app/src/main/java/org/schabi/newpipe/local/feed/FeedFragment.java +++ b/app/src/main/java/org/schabi/newpipe/local/feed/FeedFragment.java @@ -36,8 +36,6 @@ import io.reactivex.MaybeObserver; import io.reactivex.android.schedulers.AndroidSchedulers; import io.reactivex.disposables.CompositeDisposable; import io.reactivex.disposables.Disposable; -import io.reactivex.functions.Consumer; -import io.reactivex.functions.Predicate; public class FeedFragment extends BaseListFragment, Void> { diff --git a/app/src/main/java/org/schabi/newpipe/local/history/HistoryEntryAdapter.java b/app/src/main/java/org/schabi/newpipe/local/history/HistoryEntryAdapter.java index 2cb1add5d..09549346b 100644 --- a/app/src/main/java/org/schabi/newpipe/local/history/HistoryEntryAdapter.java +++ b/app/src/main/java/org/schabi/newpipe/local/history/HistoryEntryAdapter.java @@ -1,7 +1,6 @@ package org.schabi.newpipe.local.history; import android.content.Context; -import android.content.res.Resources; import android.support.annotation.NonNull; import android.support.annotation.Nullable; import android.support.v7.widget.RecyclerView; diff --git a/app/src/main/java/org/schabi/newpipe/local/history/HistoryRecordManager.java b/app/src/main/java/org/schabi/newpipe/local/history/HistoryRecordManager.java index d3d824103..56453773a 100644 --- a/app/src/main/java/org/schabi/newpipe/local/history/HistoryRecordManager.java +++ b/app/src/main/java/org/schabi/newpipe/local/history/HistoryRecordManager.java @@ -45,7 +45,6 @@ import java.util.List; import io.reactivex.Flowable; import io.reactivex.Maybe; -import io.reactivex.Scheduler; import io.reactivex.Single; import io.reactivex.schedulers.Schedulers; diff --git a/app/src/main/java/org/schabi/newpipe/local/history/StatisticsPlaylistFragment.java b/app/src/main/java/org/schabi/newpipe/local/history/StatisticsPlaylistFragment.java index 95aeb09d7..32083fd42 100644 --- a/app/src/main/java/org/schabi/newpipe/local/history/StatisticsPlaylistFragment.java +++ b/app/src/main/java/org/schabi/newpipe/local/history/StatisticsPlaylistFragment.java @@ -21,7 +21,6 @@ import org.schabi.newpipe.R; import org.schabi.newpipe.database.LocalItem; import org.schabi.newpipe.database.stream.StreamStatisticsEntry; import org.schabi.newpipe.extractor.stream.StreamInfoItem; -import org.schabi.newpipe.fragments.list.BaseListFragment; import org.schabi.newpipe.local.BaseLocalListFragment; import org.schabi.newpipe.info_list.InfoItemDialog; import org.schabi.newpipe.player.playqueue.PlayQueue; @@ -57,7 +56,7 @@ public class StatisticsPlaylistFragment /* Used for independent events */ private Subscription databaseSubscription; private HistoryRecordManager recordManager; - private CompositeDisposable disposables = new CompositeDisposable(); + private final CompositeDisposable disposables = new CompositeDisposable(); private enum StatisticSortMode { LAST_PLAYED, diff --git a/app/src/main/java/org/schabi/newpipe/local/holder/LocalPlaylistGridItemHolder.java b/app/src/main/java/org/schabi/newpipe/local/holder/LocalPlaylistGridItemHolder.java new file mode 100644 index 000000000..4276cf721 --- /dev/null +++ b/app/src/main/java/org/schabi/newpipe/local/holder/LocalPlaylistGridItemHolder.java @@ -0,0 +1,13 @@ +package org.schabi.newpipe.local.holder; + +import android.view.ViewGroup; + +import org.schabi.newpipe.R; +import org.schabi.newpipe.local.LocalItemBuilder; + +public class LocalPlaylistGridItemHolder extends LocalPlaylistItemHolder { + + public LocalPlaylistGridItemHolder(LocalItemBuilder infoItemBuilder, ViewGroup parent) { + super(infoItemBuilder, R.layout.list_playlist_grid_item, parent); + } +} diff --git a/app/src/main/java/org/schabi/newpipe/local/holder/LocalPlaylistItemHolder.java b/app/src/main/java/org/schabi/newpipe/local/holder/LocalPlaylistItemHolder.java index 1a5ec63bf..8743684ee 100644 --- a/app/src/main/java/org/schabi/newpipe/local/holder/LocalPlaylistItemHolder.java +++ b/app/src/main/java/org/schabi/newpipe/local/holder/LocalPlaylistItemHolder.java @@ -16,6 +16,10 @@ public class LocalPlaylistItemHolder extends PlaylistItemHolder { super(infoItemBuilder, parent); } + LocalPlaylistItemHolder(LocalItemBuilder infoItemBuilder, int layoutId, ViewGroup parent) { + super(infoItemBuilder, layoutId, parent); + } + @Override public void updateFromItem(final LocalItem localItem, final DateFormat dateFormat) { if (!(localItem instanceof PlaylistMetadataEntry)) return; diff --git a/app/src/main/java/org/schabi/newpipe/local/holder/LocalPlaylistStreamGridItemHolder.java b/app/src/main/java/org/schabi/newpipe/local/holder/LocalPlaylistStreamGridItemHolder.java new file mode 100644 index 000000000..6986713bb --- /dev/null +++ b/app/src/main/java/org/schabi/newpipe/local/holder/LocalPlaylistStreamGridItemHolder.java @@ -0,0 +1,13 @@ +package org.schabi.newpipe.local.holder; + +import android.view.ViewGroup; + +import org.schabi.newpipe.R; +import org.schabi.newpipe.local.LocalItemBuilder; + +public class LocalPlaylistStreamGridItemHolder extends LocalPlaylistStreamItemHolder { + + public LocalPlaylistStreamGridItemHolder(LocalItemBuilder infoItemBuilder, ViewGroup parent) { + super(infoItemBuilder, R.layout.list_stream_playlist_grid_item, parent); //TODO + } +} diff --git a/app/src/main/java/org/schabi/newpipe/local/holder/LocalStatisticStreamGridItemHolder.java b/app/src/main/java/org/schabi/newpipe/local/holder/LocalStatisticStreamGridItemHolder.java new file mode 100644 index 000000000..792ad92f0 --- /dev/null +++ b/app/src/main/java/org/schabi/newpipe/local/holder/LocalStatisticStreamGridItemHolder.java @@ -0,0 +1,13 @@ +package org.schabi.newpipe.local.holder; + +import android.view.ViewGroup; + +import org.schabi.newpipe.R; +import org.schabi.newpipe.local.LocalItemBuilder; + +public class LocalStatisticStreamGridItemHolder extends LocalStatisticStreamItemHolder { + + public LocalStatisticStreamGridItemHolder(LocalItemBuilder infoItemBuilder, ViewGroup parent) { + super(infoItemBuilder, R.layout.list_stream_grid_item, parent); + } +} diff --git a/app/src/main/java/org/schabi/newpipe/local/holder/LocalStatisticStreamItemHolder.java b/app/src/main/java/org/schabi/newpipe/local/holder/LocalStatisticStreamItemHolder.java index b2a04ca9c..57a5794e3 100644 --- a/app/src/main/java/org/schabi/newpipe/local/holder/LocalStatisticStreamItemHolder.java +++ b/app/src/main/java/org/schabi/newpipe/local/holder/LocalStatisticStreamItemHolder.java @@ -1,5 +1,6 @@ package org.schabi.newpipe.local.holder; +import android.support.annotation.Nullable; import android.support.v4.content.ContextCompat; import android.view.View; import android.view.ViewGroup; @@ -42,10 +43,15 @@ public class LocalStatisticStreamItemHolder extends LocalItemHolder { public final TextView itemVideoTitleView; public final TextView itemUploaderView; public final TextView itemDurationView; + @Nullable public final TextView itemAdditionalDetails; - public LocalStatisticStreamItemHolder(LocalItemBuilder infoItemBuilder, ViewGroup parent) { - super(infoItemBuilder, R.layout.list_stream_item, parent); + public LocalStatisticStreamItemHolder(LocalItemBuilder itemBuilder, ViewGroup parent) { + this(itemBuilder, R.layout.list_stream_item, parent); + } + + LocalStatisticStreamItemHolder(LocalItemBuilder infoItemBuilder, int layoutId, ViewGroup parent) { + super(infoItemBuilder, layoutId, parent); itemThumbnailView = itemView.findViewById(R.id.itemThumbnailView); itemVideoTitleView = itemView.findViewById(R.id.itemVideoTitleView); @@ -80,7 +86,9 @@ public class LocalStatisticStreamItemHolder extends LocalItemHolder { itemDurationView.setVisibility(View.GONE); } - itemAdditionalDetails.setText(getStreamInfoDetailLine(item, dateFormat)); + if (itemAdditionalDetails != null) { + itemAdditionalDetails.setText(getStreamInfoDetailLine(item, dateFormat)); + } // Default thumbnail is shown on error, while loading and if the url is empty itemBuilder.displayImage(item.thumbnailUrl, itemThumbnailView, diff --git a/app/src/main/java/org/schabi/newpipe/local/holder/RemotePlaylistGridItemHolder.java b/app/src/main/java/org/schabi/newpipe/local/holder/RemotePlaylistGridItemHolder.java new file mode 100644 index 000000000..5ac18fccb --- /dev/null +++ b/app/src/main/java/org/schabi/newpipe/local/holder/RemotePlaylistGridItemHolder.java @@ -0,0 +1,13 @@ +package org.schabi.newpipe.local.holder; + +import android.view.ViewGroup; + +import org.schabi.newpipe.R; +import org.schabi.newpipe.local.LocalItemBuilder; + +public class RemotePlaylistGridItemHolder extends RemotePlaylistItemHolder { + + public RemotePlaylistGridItemHolder(LocalItemBuilder infoItemBuilder, ViewGroup parent) { + super(infoItemBuilder, R.layout.list_playlist_grid_item, parent); + } +} diff --git a/app/src/main/java/org/schabi/newpipe/local/holder/RemotePlaylistItemHolder.java b/app/src/main/java/org/schabi/newpipe/local/holder/RemotePlaylistItemHolder.java index 12d3063b0..5b2a88d38 100644 --- a/app/src/main/java/org/schabi/newpipe/local/holder/RemotePlaylistItemHolder.java +++ b/app/src/main/java/org/schabi/newpipe/local/holder/RemotePlaylistItemHolder.java @@ -16,6 +16,10 @@ public class RemotePlaylistItemHolder extends PlaylistItemHolder { super(infoItemBuilder, parent); } + RemotePlaylistItemHolder(LocalItemBuilder infoItemBuilder, int layoutId, ViewGroup parent) { + super(infoItemBuilder, layoutId, parent); + } + @Override public void updateFromItem(final LocalItem localItem, final DateFormat dateFormat) { if (!(localItem instanceof PlaylistRemoteEntity)) return; diff --git a/app/src/main/java/org/schabi/newpipe/local/playlist/LocalPlaylistFragment.java b/app/src/main/java/org/schabi/newpipe/local/playlist/LocalPlaylistFragment.java index 35a1530c9..f400061e1 100644 --- a/app/src/main/java/org/schabi/newpipe/local/playlist/LocalPlaylistFragment.java +++ b/app/src/main/java/org/schabi/newpipe/local/playlist/LocalPlaylistFragment.java @@ -459,7 +459,11 @@ public class LocalPlaylistFragment extends BaseLocalListFragment> { +public class SubscriptionFragment extends BaseStateFragment> implements SharedPreferences.OnSharedPreferenceChangeListener { private static final int REQUEST_EXPORT_CODE = 666; private static final int REQUEST_IMPORT_CODE = 667; @@ -80,8 +89,10 @@ public class SubscriptionFragment extends BaseStateFragment() { - @Override + public void selected(ChannelInfoItem selectedItem) { final FragmentManager fragmentManager = getFM(); NavigationHelper.openChannelFragment(fragmentManager, @@ -328,6 +369,11 @@ public class SubscriptionFragment extends BaseStateFragment importExportOptions.switchState()); } + private void showLongTapDialog(ChannelInfoItem selectedItem) { + 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.share), + context.getResources().getString(R.string.unsubscribe) + }; + + final DialogInterface.OnClickListener actions = (dialogInterface, i) -> { + switch (i) { + case 0: + shareChannel(selectedItem); + break; + case 1: + deleteChannel(selectedItem); + break; + default: + break; + } + }; + + final View bannerView = View.inflate(activity, R.layout.dialog_title, null); + bannerView.setSelected(true); + + TextView titleView = bannerView.findViewById(R.id.itemTitleView); + titleView.setText(selectedItem.getName()); + + TextView detailsView = bannerView.findViewById(R.id.itemAdditionalDetails); + detailsView.setVisibility(View.GONE); + + new AlertDialog.Builder(activity) + .setCustomTitle(bannerView) + .setItems(commands, actions) + .create() + .show(); + + } + + private void shareChannel (ChannelInfoItem selectedItem) { + shareUrl(selectedItem.getName(), selectedItem.getUrl()); + } + + @SuppressLint("CheckResult") + private void deleteChannel (ChannelInfoItem selectedItem) { + subscriptionService.subscriptionTable() + .getSubscription(selectedItem.getServiceId(), selectedItem.getUrl()) + .toObservable() + .observeOn(Schedulers.io()) + .subscribe(getDeleteObserver()); + + Toast.makeText(activity, getString(R.string.channel_unsubscribed), Toast.LENGTH_SHORT).show(); + } + + + + private Observer> getDeleteObserver(){ + return new Observer>() { + @Override + public void onSubscribe(Disposable d) { + disposables.add(d); + } + + @Override + public void onNext(List subscriptionEntities) { + subscriptionService.subscriptionTable().delete(subscriptionEntities); + } + + @Override + public void onError(Throwable exception) { + SubscriptionFragment.this.onError(exception); + } + + @Override + public void onComplete() { } + }; + } + private void resetFragment() { if (disposables != null) disposables.clear(); if (infoListAdapter != null) infoListAdapter.clearStreamItemList(); @@ -447,4 +572,22 @@ public class SubscriptionFragment extends BaseStateFragment> subscription; + private final AppDatabase db; + private final Flowable> subscription; - private Scheduler subscriptionScheduler; + private final Scheduler subscriptionScheduler; private SubscriptionService(Context context) { db = NewPipeDatabase.getInstance(context.getApplicationContext()); @@ -116,7 +116,7 @@ public class SubscriptionService { public Completable updateChannelInfo(final ChannelInfo info) { final Function, CompletableSource> update = new Function, CompletableSource>() { @Override - public CompletableSource apply(@NonNull List subscriptionEntities) throws Exception { + public CompletableSource apply(@NonNull List subscriptionEntities) { if (DEBUG) Log.d(TAG, "updateChannelInfo() called with: subscriptionEntities = [" + subscriptionEntities + "]"); if (subscriptionEntities.size() == 1) { SubscriptionEntity subscription = subscriptionEntities.get(0); diff --git a/app/src/main/java/org/schabi/newpipe/local/subscription/services/BaseImportExportService.java b/app/src/main/java/org/schabi/newpipe/local/subscription/services/BaseImportExportService.java index 9d055b82a..e3db6e12c 100644 --- a/app/src/main/java/org/schabi/newpipe/local/subscription/services/BaseImportExportService.java +++ b/app/src/main/java/org/schabi/newpipe/local/subscription/services/BaseImportExportService.java @@ -58,8 +58,8 @@ public abstract class BaseImportExportService extends Service { protected NotificationCompat.Builder notificationBuilder; protected SubscriptionService subscriptionService; - protected CompositeDisposable disposables = new CompositeDisposable(); - protected PublishProcessor notificationUpdater = PublishProcessor.create(); + protected final CompositeDisposable disposables = new CompositeDisposable(); + protected final PublishProcessor notificationUpdater = PublishProcessor.create(); @Nullable @Override @@ -90,9 +90,9 @@ public abstract class BaseImportExportService extends Service { private static final int NOTIFICATION_SAMPLING_PERIOD = 2500; - protected AtomicInteger currentProgress = new AtomicInteger(-1); - protected AtomicInteger maxProgress = new AtomicInteger(-1); - protected ImportExportEventListener eventListener = new ImportExportEventListener() { + protected final AtomicInteger currentProgress = new AtomicInteger(-1); + protected final AtomicInteger maxProgress = new AtomicInteger(-1); + protected final ImportExportEventListener eventListener = new ImportExportEventListener() { @Override public void onSizeReceived(int size) { maxProgress.set(size); @@ -187,13 +187,13 @@ public abstract class BaseImportExportService extends Service { protected Toast toast; protected void showToast(@StringRes int message) { - showToast(getString(message), Toast.LENGTH_SHORT); + showToast(getString(message)); } - protected void showToast(String message, int duration) { + protected void showToast(String message) { if (toast != null) toast.cancel(); - toast = Toast.makeText(this, message, duration); + toast = Toast.makeText(this, message, Toast.LENGTH_SHORT); toast.show(); } diff --git a/app/src/main/java/org/schabi/newpipe/local/subscription/services/SubscriptionsImportService.java b/app/src/main/java/org/schabi/newpipe/local/subscription/services/SubscriptionsImportService.java index 3fdc91358..48410205a 100644 --- a/app/src/main/java/org/schabi/newpipe/local/subscription/services/SubscriptionsImportService.java +++ b/app/src/main/java/org/schabi/newpipe/local/subscription/services/SubscriptionsImportService.java @@ -144,12 +144,16 @@ public class SubscriptionsImportService extends BaseImportExportService { showToast(R.string.import_ongoing); Flowable> flowable = null; - if (currentMode == CHANNEL_URL_MODE) { - flowable = importFromChannelUrl(); - } else if (currentMode == INPUT_STREAM_MODE) { - flowable = importFromInputStream(); - } else if (currentMode == PREVIOUS_EXPORT_MODE) { - flowable = importFromPreviousExport(); + switch (currentMode) { + case CHANNEL_URL_MODE: + flowable = importFromChannelUrl(); + break; + case INPUT_STREAM_MODE: + flowable = importFromInputStream(); + break; + case PREVIOUS_EXPORT_MODE: + flowable = importFromPreviousExport(); + break; } if (flowable == null) { diff --git a/app/src/main/java/org/schabi/newpipe/player/BasePlayer.java b/app/src/main/java/org/schabi/newpipe/player/BasePlayer.java index 01a0614fa..0e4d07179 100644 --- a/app/src/main/java/org/schabi/newpipe/player/BasePlayer.java +++ b/app/src/main/java/org/schabi/newpipe/player/BasePlayer.java @@ -230,7 +230,8 @@ public abstract class BasePlayer implements int sizeBeforeAppend = playQueue.size(); playQueue.append(queue.getStreams()); - if (intent.getBooleanExtra(SELECT_ON_APPEND, false) && + if ((intent.getBooleanExtra(SELECT_ON_APPEND, false) || + getCurrentState() == STATE_COMPLETED) && queue.getStreams().size() > 0) { playQueue.setIndex(sizeBeforeAppend); } @@ -1112,7 +1113,9 @@ public abstract class BasePlayer implements @Player.RepeatMode public int getRepeatMode() { - return simpleExoPlayer == null ? Player.REPEAT_MODE_OFF : simpleExoPlayer.getRepeatMode(); + return simpleExoPlayer == null + ? Player.REPEAT_MODE_OFF + : simpleExoPlayer.getRepeatMode(); } public void setRepeatMode(@Player.RepeatMode final int repeatMode) { @@ -1178,4 +1181,8 @@ public abstract class BasePlayer implements if (DEBUG) Log.d(TAG, "Setting recovery, queue: " + queuePos + ", pos: " + windowPos); playQueue.setRecovery(queuePos, windowPos); } + + public boolean gotDestroyed() { + return simpleExoPlayer == null; + } } diff --git a/app/src/main/java/org/schabi/newpipe/player/MainVideoPlayer.java b/app/src/main/java/org/schabi/newpipe/player/MainVideoPlayer.java index 4e8398ff2..07a9ac71c 100644 --- a/app/src/main/java/org/schabi/newpipe/player/MainVideoPlayer.java +++ b/app/src/main/java/org/schabi/newpipe/player/MainVideoPlayer.java @@ -175,6 +175,10 @@ public final class MainVideoPlayer extends AppCompatActivity setLandscape(lastOrientationWasLandscape); } + final int lastResizeMode = defaultPreferences.getInt( + getString(R.string.last_resize_mode), AspectRatioFrameLayout.RESIZE_MODE_FIT); + playerImpl.setResizeMode(lastResizeMode); + // Upon going in or out of multiwindow mode, isInMultiWindow will always be false, // since the first onResume needs to restore the player. // Subsequent onResume calls while multiwindow mode remains the same and the player is @@ -213,10 +217,9 @@ public final class MainVideoPlayer extends AppCompatActivity if (playerImpl == null) return; playerImpl.setRecovery(); - playerState = new PlayerState(playerImpl.getPlayQueue(), playerImpl.getRepeatMode(), - playerImpl.getPlaybackSpeed(), playerImpl.getPlaybackPitch(), - playerImpl.getPlaybackQuality(), playerImpl.getPlaybackSkipSilence(), - playerImpl.isPlaying()); + if(!playerImpl.gotDestroyed()) { + playerState = createPlayerState(); + } StateSaver.tryToSave(isChangingConfigurations(), null, outState, this); } @@ -231,6 +234,7 @@ public final class MainVideoPlayer extends AppCompatActivity if (!isBackPressed) { playerImpl.minimize(); } + playerState = createPlayerState(); playerImpl.destroy(); isInMultiWindow = false; @@ -241,6 +245,13 @@ public final class MainVideoPlayer extends AppCompatActivity // State Saving //////////////////////////////////////////////////////////////////////////*/ + private PlayerState createPlayerState() { + return new PlayerState(playerImpl.getPlayQueue(), playerImpl.getRepeatMode(), + playerImpl.getPlaybackSpeed(), playerImpl.getPlaybackPitch(), + playerImpl.getPlaybackQuality(), playerImpl.getPlaybackSkipSilence(), + playerImpl.isPlaying()); + } + @Override public String generateSuffix() { return "." + UUID.randomUUID().toString() + ".player"; @@ -705,14 +716,27 @@ public final class MainVideoPlayer extends AppCompatActivity @Override protected int nextResizeMode(int currentResizeMode) { + final int newResizeMode; switch (currentResizeMode) { case AspectRatioFrameLayout.RESIZE_MODE_FIT: - return AspectRatioFrameLayout.RESIZE_MODE_FILL; + newResizeMode = AspectRatioFrameLayout.RESIZE_MODE_FILL; + break; case AspectRatioFrameLayout.RESIZE_MODE_FILL: - return AspectRatioFrameLayout.RESIZE_MODE_ZOOM; + newResizeMode = AspectRatioFrameLayout.RESIZE_MODE_ZOOM; + break; default: - return AspectRatioFrameLayout.RESIZE_MODE_FIT; + newResizeMode = AspectRatioFrameLayout.RESIZE_MODE_FIT; + break; } + + storeResizeMode(newResizeMode); + return newResizeMode; + } + + private void storeResizeMode(@AspectRatioFrameLayout.ResizeMode int resizeMode) { + defaultPreferences.edit() + .putInt(getString(R.string.last_resize_mode), resizeMode) + .apply(); } @Override @@ -989,12 +1013,14 @@ public final class MainVideoPlayer extends AppCompatActivity private static final int MOVEMENT_THRESHOLD = 40; - private final boolean isPlayerGestureEnabled = PlayerHelper.isPlayerGestureEnabled(getApplicationContext()); + private final boolean isVolumeGestureEnabled = PlayerHelper.isVolumeGestureEnabled(getApplicationContext()); + private final boolean isBrightnessGestureEnabled = PlayerHelper.isBrightnessGestureEnabled(getApplicationContext()); + private final int maxVolume = playerImpl.getAudioReactor().getMaxVolume(); @Override public boolean onScroll(MotionEvent initialEvent, MotionEvent movingEvent, float distanceX, float distanceY) { - if (!isPlayerGestureEnabled) return false; + if (!isVolumeGestureEnabled && !isBrightnessGestureEnabled) return false; //noinspection PointlessBooleanExpression if (DEBUG && false) Log.d(TAG, "MainVideoPlayer.onScroll = " + @@ -1010,7 +1036,11 @@ public final class MainVideoPlayer extends AppCompatActivity isMoving = true; - if (initialEvent.getX() > playerImpl.getRootView().getWidth() / 2) { + boolean acceptAnyArea = isVolumeGestureEnabled != isBrightnessGestureEnabled; + boolean acceptVolumeArea = acceptAnyArea || initialEvent.getX() > playerImpl.getRootView().getWidth() / 2; + boolean acceptBrightnessArea = acceptAnyArea || !acceptVolumeArea; + + if (isVolumeGestureEnabled && acceptVolumeArea) { playerImpl.getVolumeProgressBar().incrementProgressBy((int) distanceY); float currentProgressPercent = (float) playerImpl.getVolumeProgressBar().getProgress() / playerImpl.getMaxGestureLength(); @@ -1035,7 +1065,7 @@ public final class MainVideoPlayer extends AppCompatActivity if (playerImpl.getBrightnessRelativeLayout().getVisibility() == View.VISIBLE) { playerImpl.getBrightnessRelativeLayout().setVisibility(View.GONE); } - } else { + } else if (isBrightnessGestureEnabled && acceptBrightnessArea) { playerImpl.getBrightnessProgressBar().incrementProgressBy((int) distanceY); float currentProgressPercent = (float) playerImpl.getBrightnessProgressBar().getProgress() / playerImpl.getMaxGestureLength(); diff --git a/app/src/main/java/org/schabi/newpipe/player/PopupVideoPlayer.java b/app/src/main/java/org/schabi/newpipe/player/PopupVideoPlayer.java index 0e7328020..a36a0576c 100644 --- a/app/src/main/java/org/schabi/newpipe/player/PopupVideoPlayer.java +++ b/app/src/main/java/org/schabi/newpipe/player/PopupVideoPlayer.java @@ -114,7 +114,6 @@ public final class PopupVideoPlayer extends Service { private View closeOverlayView; private FloatingActionButton closeOverlayButton; - private WindowManager.LayoutParams closeOverlayLayoutParams; private int tossFlingVelocity; @@ -248,7 +247,7 @@ public final class PopupVideoPlayer extends Service { final int flags = WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE | WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE | WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM; - closeOverlayLayoutParams = new WindowManager.LayoutParams( + WindowManager.LayoutParams closeOverlayLayoutParams = new WindowManager.LayoutParams( ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT, layoutParamType, flags, diff --git a/app/src/main/java/org/schabi/newpipe/player/VideoPlayer.java b/app/src/main/java/org/schabi/newpipe/player/VideoPlayer.java index 679fc6645..d30d9b8be 100644 --- a/app/src/main/java/org/schabi/newpipe/player/VideoPlayer.java +++ b/app/src/main/java/org/schabi/newpipe/player/VideoPlayer.java @@ -137,16 +137,16 @@ public abstract class VideoPlayer extends BasePlayer private TextView captionTextView; private ValueAnimator controlViewAnimator; - private Handler controlsVisibilityHandler = new Handler(); + private final Handler controlsVisibilityHandler = new Handler(); boolean isSomePopupMenuVisible = false; - private int qualityPopupMenuGroupId = 69; + private final int qualityPopupMenuGroupId = 69; private PopupMenu qualityPopupMenu; - private int playbackSpeedPopupMenuGroupId = 79; + private final int playbackSpeedPopupMenuGroupId = 79; private PopupMenu playbackSpeedPopupMenu; - private int captionPopupMenuGroupId = 89; + private final int captionPopupMenuGroupId = 89; private PopupMenu captionPopupMenu; /////////////////////////////////////////////////////////////////////////// @@ -683,12 +683,17 @@ public abstract class VideoPlayer extends BasePlayer if (getAspectRatioFrameLayout() != null) { final int currentResizeMode = getAspectRatioFrameLayout().getResizeMode(); final int newResizeMode = nextResizeMode(currentResizeMode); - getAspectRatioFrameLayout().setResizeMode(newResizeMode); - getResizeView().setText(PlayerHelper.resizeTypeOf(context, newResizeMode)); + setResizeMode(newResizeMode); } } + protected void setResizeMode(@AspectRatioFrameLayout.ResizeMode final int resizeMode) { + getAspectRatioFrameLayout().setResizeMode(resizeMode); + getResizeView().setText(PlayerHelper.resizeTypeOf(context, resizeMode)); + } + protected abstract int nextResizeMode(@AspectRatioFrameLayout.ResizeMode final int resizeMode); + /*////////////////////////////////////////////////////////////////////////// // SeekBar Listener //////////////////////////////////////////////////////////////////////////*/ diff --git a/app/src/main/java/org/schabi/newpipe/player/helper/AudioReactor.java b/app/src/main/java/org/schabi/newpipe/player/helper/AudioReactor.java index 5b9cce947..46d20c7e1 100644 --- a/app/src/main/java/org/schabi/newpipe/player/helper/AudioReactor.java +++ b/app/src/main/java/org/schabi/newpipe/player/helper/AudioReactor.java @@ -116,7 +116,7 @@ public class AudioReactor implements AudioManager.OnAudioFocusChangeListener, private void onAudioFocusGain() { Log.d(TAG, "onAudioFocusGain() called"); player.setVolume(DUCK_AUDIO_TO); - animateAudio(DUCK_AUDIO_TO, 1f, DUCK_DURATION); + animateAudio(DUCK_AUDIO_TO, 1f); if (PlayerHelper.isResumeAfterAudioFocusGain(context)) { player.setPlayWhenReady(true); @@ -131,13 +131,13 @@ public class AudioReactor implements AudioManager.OnAudioFocusChangeListener, private void onAudioFocusLossCanDuck() { Log.d(TAG, "onAudioFocusLossCanDuck() called"); // Set the volume to 1/10 on ducking - animateAudio(player.getVolume(), DUCK_AUDIO_TO, DUCK_DURATION); + animateAudio(player.getVolume(), DUCK_AUDIO_TO); } - private void animateAudio(final float from, final float to, int duration) { + private void animateAudio(final float from, final float to) { ValueAnimator valueAnimator = new ValueAnimator(); valueAnimator.setFloatValues(from, to); - valueAnimator.setDuration(duration); + valueAnimator.setDuration(AudioReactor.DUCK_DURATION); valueAnimator.addListener(new AnimatorListenerAdapter() { @Override public void onAnimationStart(Animator animation) { diff --git a/app/src/main/java/org/schabi/newpipe/player/helper/CacheFactory.java b/app/src/main/java/org/schabi/newpipe/player/helper/CacheFactory.java index ec7813056..b8d8dc12f 100644 --- a/app/src/main/java/org/schabi/newpipe/player/helper/CacheFactory.java +++ b/app/src/main/java/org/schabi/newpipe/player/helper/CacheFactory.java @@ -4,12 +4,9 @@ import android.content.Context; import android.support.annotation.NonNull; import android.util.Log; -import com.google.android.exoplayer2.upstream.BandwidthMeter; import com.google.android.exoplayer2.upstream.DataSource; -import com.google.android.exoplayer2.upstream.DefaultBandwidthMeter; import com.google.android.exoplayer2.upstream.DefaultDataSource; import com.google.android.exoplayer2.upstream.DefaultDataSourceFactory; -import com.google.android.exoplayer2.upstream.DefaultHttpDataSource; import com.google.android.exoplayer2.upstream.FileDataSource; import com.google.android.exoplayer2.upstream.TransferListener; import com.google.android.exoplayer2.upstream.cache.CacheDataSink; @@ -17,8 +14,6 @@ import com.google.android.exoplayer2.upstream.cache.CacheDataSource; import com.google.android.exoplayer2.upstream.cache.LeastRecentlyUsedCacheEvictor; import com.google.android.exoplayer2.upstream.cache.SimpleCache; -import org.schabi.newpipe.Downloader; - import java.io.File; /* package-private */ class CacheFactory implements DataSource.Factory { diff --git a/app/src/main/java/org/schabi/newpipe/player/helper/PlaybackParameterDialog.java b/app/src/main/java/org/schabi/newpipe/player/helper/PlaybackParameterDialog.java index d6453f579..f49ca3330 100644 --- a/app/src/main/java/org/schabi/newpipe/player/helper/PlaybackParameterDialog.java +++ b/app/src/main/java/org/schabi/newpipe/player/helper/PlaybackParameterDialog.java @@ -66,25 +66,15 @@ public class PlaybackParameterDialog extends DialogFragment { private double stepSize = DEFAULT_STEP; @Nullable private SeekBar tempoSlider; - @Nullable private TextView tempoMinimumText; - @Nullable private TextView tempoMaximumText; @Nullable private TextView tempoCurrentText; @Nullable private TextView tempoStepDownText; @Nullable private TextView tempoStepUpText; @Nullable private SeekBar pitchSlider; - @Nullable private TextView pitchMinimumText; - @Nullable private TextView pitchMaximumText; @Nullable private TextView pitchCurrentText; @Nullable private TextView pitchStepDownText; @Nullable private TextView pitchStepUpText; - @Nullable private TextView stepSizeOnePercentText; - @Nullable private TextView stepSizeFivePercentText; - @Nullable private TextView stepSizeTenPercentText; - @Nullable private TextView stepSizeTwentyFivePercentText; - @Nullable private TextView stepSizeOneHundredPercentText; - @Nullable private CheckBox unhookingCheckbox; @Nullable private CheckBox skipSilenceCheckbox; @@ -181,8 +171,8 @@ public class PlaybackParameterDialog extends DialogFragment { private void setupTempoControl(@NonNull View rootView) { tempoSlider = rootView.findViewById(R.id.tempoSeekbar); - tempoMinimumText = rootView.findViewById(R.id.tempoMinimumText); - tempoMaximumText = rootView.findViewById(R.id.tempoMaximumText); + TextView tempoMinimumText = rootView.findViewById(R.id.tempoMinimumText); + TextView tempoMaximumText = rootView.findViewById(R.id.tempoMaximumText); tempoCurrentText = rootView.findViewById(R.id.tempoCurrentText); tempoStepUpText = rootView.findViewById(R.id.tempoStepUp); tempoStepDownText = rootView.findViewById(R.id.tempoStepDown); @@ -203,8 +193,8 @@ public class PlaybackParameterDialog extends DialogFragment { private void setupPitchControl(@NonNull View rootView) { pitchSlider = rootView.findViewById(R.id.pitchSeekbar); - pitchMinimumText = rootView.findViewById(R.id.pitchMinimumText); - pitchMaximumText = rootView.findViewById(R.id.pitchMaximumText); + TextView pitchMinimumText = rootView.findViewById(R.id.pitchMinimumText); + TextView pitchMaximumText = rootView.findViewById(R.id.pitchMaximumText); pitchCurrentText = rootView.findViewById(R.id.pitchCurrentText); pitchStepDownText = rootView.findViewById(R.id.pitchStepDown); pitchStepUpText = rootView.findViewById(R.id.pitchStepUp); @@ -247,11 +237,11 @@ public class PlaybackParameterDialog extends DialogFragment { } private void setupStepSizeSelector(@NonNull final View rootView) { - stepSizeOnePercentText = rootView.findViewById(R.id.stepSizeOnePercent); - stepSizeFivePercentText = rootView.findViewById(R.id.stepSizeFivePercent); - stepSizeTenPercentText = rootView.findViewById(R.id.stepSizeTenPercent); - stepSizeTwentyFivePercentText = rootView.findViewById(R.id.stepSizeTwentyFivePercent); - stepSizeOneHundredPercentText = rootView.findViewById(R.id.stepSizeOneHundredPercent); + TextView stepSizeOnePercentText = rootView.findViewById(R.id.stepSizeOnePercent); + TextView stepSizeFivePercentText = rootView.findViewById(R.id.stepSizeFivePercent); + TextView stepSizeTenPercentText = rootView.findViewById(R.id.stepSizeTenPercent); + TextView stepSizeTwentyFivePercentText = rootView.findViewById(R.id.stepSizeTwentyFivePercent); + TextView stepSizeOneHundredPercentText = rootView.findViewById(R.id.stepSizeOneHundredPercent); if (stepSizeOnePercentText != null) { stepSizeOnePercentText.setText(getPercentString(STEP_ONE_PERCENT_VALUE)); diff --git a/app/src/main/java/org/schabi/newpipe/player/helper/PlayerHelper.java b/app/src/main/java/org/schabi/newpipe/player/helper/PlayerHelper.java index ae187a834..16dffc3de 100644 --- a/app/src/main/java/org/schabi/newpipe/player/helper/PlayerHelper.java +++ b/app/src/main/java/org/schabi/newpipe/player/helper/PlayerHelper.java @@ -169,8 +169,12 @@ public class PlayerHelper { return isResumeAfterAudioFocusGain(context, false); } - public static boolean isPlayerGestureEnabled(@NonNull final Context context) { - return isPlayerGestureEnabled(context, true); + public static boolean isVolumeGestureEnabled(@NonNull final Context context) { + return isVolumeGestureEnabled(context, true); + } + + public static boolean isBrightnessGestureEnabled(@NonNull final Context context) { + return isBrightnessGestureEnabled(context, true); } public static boolean isUsingOldPlayer(@NonNull final Context context) { @@ -203,7 +207,7 @@ public class PlayerHelper { @NonNull public static SeekParameters getSeekParameters(@NonNull final Context context) { - return isUsingInexactSeek(context, false) ? + return isUsingInexactSeek(context) ? SeekParameters.CLOSEST_SYNC : SeekParameters.EXACT; } @@ -306,8 +310,12 @@ public class PlayerHelper { return getPreferences(context).getBoolean(context.getString(R.string.resume_on_audio_focus_gain_key), b); } - private static boolean isPlayerGestureEnabled(@NonNull final Context context, final boolean b) { - return getPreferences(context).getBoolean(context.getString(R.string.player_gesture_controls_key), b); + private static boolean isVolumeGestureEnabled(@NonNull final Context context, final boolean b) { + return getPreferences(context).getBoolean(context.getString(R.string.volume_gesture_control_key), b); + } + + private static boolean isBrightnessGestureEnabled(@NonNull final Context context, final boolean b) { + return getPreferences(context).getBoolean(context.getString(R.string.brightness_gesture_control_key), b); } private static boolean isUsingOldPlayer(@NonNull final Context context, final boolean b) { @@ -318,8 +326,8 @@ public class PlayerHelper { return getPreferences(context).getBoolean(context.getString(R.string.popup_remember_size_pos_key), b); } - private static boolean isUsingInexactSeek(@NonNull final Context context, final boolean b) { - return getPreferences(context).getBoolean(context.getString(R.string.use_inexact_seek_key), b); + private static boolean isUsingInexactSeek(@NonNull final Context context) { + return getPreferences(context).getBoolean(context.getString(R.string.use_inexact_seek_key), false); } private static boolean isAutoQueueEnabled(@NonNull final Context context, final boolean b) { diff --git a/app/src/main/java/org/schabi/newpipe/player/mediasession/PlayQueueNavigator.java b/app/src/main/java/org/schabi/newpipe/player/mediasession/PlayQueueNavigator.java index 429c26fd9..3d1fd171f 100644 --- a/app/src/main/java/org/schabi/newpipe/player/mediasession/PlayQueueNavigator.java +++ b/app/src/main/java/org/schabi/newpipe/player/mediasession/PlayQueueNavigator.java @@ -79,7 +79,7 @@ public class PlayQueueNavigator implements MediaSessionConnector.QueueNavigator private void publishFloatingQueueWindow() { if (callback.getQueueSize() == 0) { - mediaSession.setQueue(Collections.emptyList()); + mediaSession.setQueue(Collections.emptyList()); activeQueueItemId = MediaSessionCompat.QueueItem.UNKNOWN_ID; return; } diff --git a/app/src/main/java/org/schabi/newpipe/player/playback/BasePlayerMediaSession.java b/app/src/main/java/org/schabi/newpipe/player/playback/BasePlayerMediaSession.java index 3365828d1..00604b236 100644 --- a/app/src/main/java/org/schabi/newpipe/player/playback/BasePlayerMediaSession.java +++ b/app/src/main/java/org/schabi/newpipe/player/playback/BasePlayerMediaSession.java @@ -8,7 +8,7 @@ import org.schabi.newpipe.player.mediasession.MediaSessionCallback; import org.schabi.newpipe.player.playqueue.PlayQueueItem; public class BasePlayerMediaSession implements MediaSessionCallback { - private BasePlayer player; + private final BasePlayer player; public BasePlayerMediaSession(final BasePlayer player) { this.player = player; diff --git a/app/src/main/java/org/schabi/newpipe/player/playback/CustomTrackSelector.java b/app/src/main/java/org/schabi/newpipe/player/playback/CustomTrackSelector.java index d80ea5bae..efe6f3a58 100644 --- a/app/src/main/java/org/schabi/newpipe/player/playback/CustomTrackSelector.java +++ b/app/src/main/java/org/schabi/newpipe/player/playback/CustomTrackSelector.java @@ -4,7 +4,6 @@ import android.support.annotation.NonNull; import android.text.TextUtils; import com.google.android.exoplayer2.C; -import com.google.android.exoplayer2.ExoPlaybackException; import com.google.android.exoplayer2.Format; import com.google.android.exoplayer2.source.TrackGroup; import com.google.android.exoplayer2.source.TrackGroupArray; @@ -12,7 +11,6 @@ import com.google.android.exoplayer2.trackselection.DefaultTrackSelector; import com.google.android.exoplayer2.trackselection.FixedTrackSelection; import com.google.android.exoplayer2.trackselection.TrackSelection; import com.google.android.exoplayer2.util.Assertions; -import com.google.android.exoplayer2.util.Util; /** * This class allows irregular text language labels for use when selecting text captions and @@ -55,7 +53,7 @@ public class CustomTrackSelector extends DefaultTrackSelector { /** @see DefaultTrackSelector#selectTextTrack(TrackGroupArray, int[][], Parameters) */ @Override protected TrackSelection selectTextTrack(TrackGroupArray groups, int[][] formatSupport, - Parameters params) throws ExoPlaybackException { + Parameters params) { TrackGroup selectedGroup = null; int selectedTrackIndex = 0; int selectedTrackScore = 0; diff --git a/app/src/main/java/org/schabi/newpipe/player/playback/MediaSourceManager.java b/app/src/main/java/org/schabi/newpipe/player/playback/MediaSourceManager.java index b27dc3dd6..3c5642d51 100644 --- a/app/src/main/java/org/schabi/newpipe/player/playback/MediaSourceManager.java +++ b/app/src/main/java/org/schabi/newpipe/player/playback/MediaSourceManager.java @@ -335,7 +335,7 @@ public class MediaSourceManager { private void loadImmediate() { if (DEBUG) Log.d(TAG, "MediaSource - loadImmediate() called"); - final ItemsToLoad itemsToLoad = getItemsToLoad(playQueue, WINDOW_SIZE); + final ItemsToLoad itemsToLoad = getItemsToLoad(playQueue); if (itemsToLoad == null) return; // Evict the previous items being loaded to free up memory, before start loading new ones @@ -472,8 +472,7 @@ public class MediaSourceManager { // Manager Helpers //////////////////////////////////////////////////////////////////////////*/ @Nullable - private static ItemsToLoad getItemsToLoad(@NonNull final PlayQueue playQueue, - final int windowSize) { + private static ItemsToLoad getItemsToLoad(@NonNull final PlayQueue playQueue) { // The current item has higher priority final int currentIndex = playQueue.getIndex(); final PlayQueueItem currentItem = playQueue.getItem(currentIndex); @@ -482,8 +481,8 @@ public class MediaSourceManager { // The rest are just for seamless playback // Although timeline is not updated prior to the current index, these sources are still // loaded into the cache for faster retrieval at a potentially later time. - final int leftBound = Math.max(0, currentIndex - windowSize); - final int rightLimit = currentIndex + windowSize + 1; + final int leftBound = Math.max(0, currentIndex - MediaSourceManager.WINDOW_SIZE); + final int rightLimit = currentIndex + MediaSourceManager.WINDOW_SIZE + 1; final int rightBound = Math.min(playQueue.size(), rightLimit); final Set neighbors = new ArraySet<>( playQueue.getStreams().subList(leftBound,rightBound)); diff --git a/app/src/main/java/org/schabi/newpipe/player/playback/PlaybackListener.java b/app/src/main/java/org/schabi/newpipe/player/playback/PlaybackListener.java index 238bdfcd0..4e79c6d75 100644 --- a/app/src/main/java/org/schabi/newpipe/player/playback/PlaybackListener.java +++ b/app/src/main/java/org/schabi/newpipe/player/playback/PlaybackListener.java @@ -8,8 +8,6 @@ import com.google.android.exoplayer2.source.MediaSource; import org.schabi.newpipe.extractor.stream.StreamInfo; import org.schabi.newpipe.player.playqueue.PlayQueueItem; -import java.util.List; - public interface PlaybackListener { /** diff --git a/app/src/main/java/org/schabi/newpipe/player/playqueue/AbstractInfoPlayQueue.java b/app/src/main/java/org/schabi/newpipe/player/playqueue/AbstractInfoPlayQueue.java index 2c08f4f92..676c0ca72 100644 --- a/app/src/main/java/org/schabi/newpipe/player/playqueue/AbstractInfoPlayQueue.java +++ b/app/src/main/java/org/schabi/newpipe/player/playqueue/AbstractInfoPlayQueue.java @@ -19,14 +19,14 @@ abstract class AbstractInfoPlayQueue ext boolean isInitial; boolean isComplete; - int serviceId; - String baseUrl; + final int serviceId; + final String baseUrl; String nextUrl; transient Disposable fetchReactor; AbstractInfoPlayQueue(final U item) { - this(item.getServiceId(), item.getUrl(), null, Collections.emptyList(), 0); + this(item.getServiceId(), item.getUrl(), null, Collections.emptyList(), 0); } AbstractInfoPlayQueue(final int serviceId, diff --git a/app/src/main/java/org/schabi/newpipe/player/playqueue/PlayQueueItemBuilder.java b/app/src/main/java/org/schabi/newpipe/player/playqueue/PlayQueueItemBuilder.java index 996d3ace3..c24eff81a 100644 --- a/app/src/main/java/org/schabi/newpipe/player/playqueue/PlayQueueItemBuilder.java +++ b/app/src/main/java/org/schabi/newpipe/player/playqueue/PlayQueueItemBuilder.java @@ -5,10 +5,8 @@ import android.text.TextUtils; import android.view.MotionEvent; import android.view.View; -import com.nostra13.universalimageloader.core.DisplayImageOptions; import com.nostra13.universalimageloader.core.ImageLoader; -import org.schabi.newpipe.R; import org.schabi.newpipe.extractor.NewPipe; import org.schabi.newpipe.util.ImageDisplayConstants; import org.schabi.newpipe.util.Localization; diff --git a/app/src/main/java/org/schabi/newpipe/player/playqueue/PlayQueueItemHolder.java b/app/src/main/java/org/schabi/newpipe/player/playqueue/PlayQueueItemHolder.java index 2483e4473..effb9aae9 100644 --- a/app/src/main/java/org/schabi/newpipe/player/playqueue/PlayQueueItemHolder.java +++ b/app/src/main/java/org/schabi/newpipe/player/playqueue/PlayQueueItemHolder.java @@ -6,8 +6,6 @@ import android.widget.ImageView; import android.widget.TextView; import org.schabi.newpipe.R; -import org.schabi.newpipe.extractor.InfoItem; -import org.schabi.newpipe.info_list.holder.InfoItemHolder; /** * Created by Christian Schabesberger on 01.08.16. diff --git a/app/src/main/java/org/schabi/newpipe/report/AcraReportSender.java b/app/src/main/java/org/schabi/newpipe/report/AcraReportSender.java index 2d3226ab6..a6a81474f 100644 --- a/app/src/main/java/org/schabi/newpipe/report/AcraReportSender.java +++ b/app/src/main/java/org/schabi/newpipe/report/AcraReportSender.java @@ -5,7 +5,6 @@ import android.support.annotation.NonNull; import org.acra.collector.CrashReportData; import org.acra.sender.ReportSender; -import org.acra.sender.ReportSenderException; import org.schabi.newpipe.R; /* @@ -31,7 +30,7 @@ import org.schabi.newpipe.R; public class AcraReportSender implements ReportSender { @Override - public void send(@NonNull Context context, @NonNull CrashReportData report) throws ReportSenderException { + public void send(@NonNull Context context, @NonNull CrashReportData report) { ErrorActivity.reportError(context, report, ErrorActivity.ErrorInfo.make(UserAction.UI_ERROR,"none", "App crash, UI failure", R.string.app_ui_crash)); diff --git a/app/src/main/java/org/schabi/newpipe/report/ErrorActivity.java b/app/src/main/java/org/schabi/newpipe/report/ErrorActivity.java index 3ad08c3ec..f852e0134 100644 --- a/app/src/main/java/org/schabi/newpipe/report/ErrorActivity.java +++ b/app/src/main/java/org/schabi/newpipe/report/ErrorActivity.java @@ -3,7 +3,6 @@ package org.schabi.newpipe.report; import android.app.Activity; import android.app.AlertDialog; import android.content.Context; -import android.content.DialogInterface; import android.content.Intent; import android.graphics.Color; import android.net.Uri; @@ -46,7 +45,6 @@ import java.util.Date; import java.util.List; import java.util.TimeZone; import java.util.Vector; -import java.util.concurrent.atomic.AtomicBoolean; /* * Created by Christian Schabesberger on 24.10.15. @@ -81,12 +79,7 @@ public class ErrorActivity extends AppCompatActivity { private ErrorInfo errorInfo; private Class returnActivity; private String currentTimeStamp; - // views - private TextView errorView; private EditText userCommentBox; - private Button reportButton; - private TextView infoView; - private TextView errorMessageView; public static void reportUiError(final AppCompatActivity activity, final Throwable el) { reportError(activity, el, activity.getClass(), null, @@ -194,11 +187,11 @@ public class ErrorActivity extends AppCompatActivity { actionBar.setDisplayShowTitleEnabled(true); } - reportButton = findViewById(R.id.errorReportButton); + Button reportButton = findViewById(R.id.errorReportButton); userCommentBox = findViewById(R.id.errorCommentBox); - errorView = findViewById(R.id.errorView); - infoView = findViewById(R.id.errorInfosView); - errorMessageView = findViewById(R.id.errorMessageView); + TextView errorView = findViewById(R.id.errorView); + TextView infoView = findViewById(R.id.errorInfosView); + TextView errorMessageView = findViewById(R.id.errorMessageView); ActivityCommunicator ac = ActivityCommunicator.getCommunicator(); returnActivity = ac.returnActivity; @@ -281,15 +274,14 @@ public class ErrorActivity extends AppCompatActivity { } private String formErrorText(String[] el) { - String text = ""; + StringBuilder text = new StringBuilder(); if (el != null) { for (String e : el) { - text += "-------------------------------------\n" - + e; + text.append("-------------------------------------\n").append(e); } } - text += "-------------------------------------"; - return text; + text.append("-------------------------------------"); + return text.toString(); } /** diff --git a/app/src/main/java/org/schabi/newpipe/settings/AppearanceSettingsFragment.java b/app/src/main/java/org/schabi/newpipe/settings/AppearanceSettingsFragment.java index 806b30a5b..821636ee5 100644 --- a/app/src/main/java/org/schabi/newpipe/settings/AppearanceSettingsFragment.java +++ b/app/src/main/java/org/schabi/newpipe/settings/AppearanceSettingsFragment.java @@ -6,7 +6,6 @@ import android.os.Bundle; import android.provider.Settings; import android.support.annotation.Nullable; import android.support.v7.preference.Preference; -import android.util.Log; import org.schabi.newpipe.R; import org.schabi.newpipe.util.Constants; @@ -49,7 +48,7 @@ public class AppearanceSettingsFragment extends BasePreferenceFragment { return super.onPreferenceTreeClick(preference); } - private Preference.OnPreferenceChangeListener themePreferenceChange = new Preference.OnPreferenceChangeListener() { + private final Preference.OnPreferenceChangeListener themePreferenceChange = new Preference.OnPreferenceChangeListener() { @Override public boolean onPreferenceChange(Preference preference, Object newValue) { defaultPreferences.edit().putBoolean(Constants.KEY_THEME_CHANGE, true).apply(); diff --git a/app/src/main/java/org/schabi/newpipe/settings/BasePreferenceFragment.java b/app/src/main/java/org/schabi/newpipe/settings/BasePreferenceFragment.java index e3c52cdad..e4fae3e1f 100644 --- a/app/src/main/java/org/schabi/newpipe/settings/BasePreferenceFragment.java +++ b/app/src/main/java/org/schabi/newpipe/settings/BasePreferenceFragment.java @@ -13,7 +13,7 @@ import org.schabi.newpipe.MainActivity; public abstract class BasePreferenceFragment extends PreferenceFragmentCompat { protected final String TAG = getClass().getSimpleName() + "@" + Integer.toHexString(hashCode()); - protected boolean DEBUG = MainActivity.DEBUG; + protected final boolean DEBUG = MainActivity.DEBUG; protected SharedPreferences defaultPreferences; diff --git a/app/src/main/java/org/schabi/newpipe/settings/ContentSettingsFragment.java b/app/src/main/java/org/schabi/newpipe/settings/ContentSettingsFragment.java index 0ca78b34a..82604f7da 100644 --- a/app/src/main/java/org/schabi/newpipe/settings/ContentSettingsFragment.java +++ b/app/src/main/java/org/schabi/newpipe/settings/ContentSettingsFragment.java @@ -9,8 +9,6 @@ import android.os.Bundle; import android.preference.PreferenceManager; import android.support.annotation.NonNull; import android.support.annotation.Nullable; -import android.support.v4.app.Fragment; -import android.support.v7.preference.ListPreference; import android.support.v7.preference.Preference; import android.util.Log; import android.widget.Toast; @@ -20,11 +18,10 @@ import com.nostra13.universalimageloader.core.ImageLoader; import org.schabi.newpipe.R; import org.schabi.newpipe.extractor.NewPipe; -import org.schabi.newpipe.extractor.StreamingService; +import org.schabi.newpipe.extractor.utils.Localization; import org.schabi.newpipe.report.ErrorActivity; import org.schabi.newpipe.report.UserAction; import org.schabi.newpipe.util.FilePickerActivityHelper; -import org.schabi.newpipe.util.KioskTranslator; import org.schabi.newpipe.util.ZipHelper; import java.io.BufferedOutputStream; @@ -47,7 +44,6 @@ public class ContentSettingsFragment extends BasePreferenceFragment { private static final int REQUEST_IMPORT_PATH = 8945; private static final int REQUEST_EXPORT_PATH = 30945; - private String homeDir; private File databasesDir; private File newpipe_db; private File newpipe_db_journal; @@ -81,7 +77,7 @@ public class ContentSettingsFragment extends BasePreferenceFragment { @Override public void onCreatePreferences(Bundle savedInstanceState, String rootKey) { - homeDir = getActivity().getApplicationInfo().dataDir; + String homeDir = getActivity().getApplicationInfo().dataDir; databasesDir = new File(homeDir + "/databases"); newpipe_db = new File(homeDir + "/databases/newpipe.db"); newpipe_db_journal = new File(homeDir + "/databases/newpipe.db-journal"); @@ -112,6 +108,20 @@ public class ContentSettingsFragment extends BasePreferenceFragment { startActivityForResult(i, REQUEST_EXPORT_PATH); return true; }); + + Preference setPreferredLanguage = findPreference(getString(R.string.content_language_key)); + setPreferredLanguage.setOnPreferenceChangeListener((Preference p, Object newLanguage) -> { + Localization oldLocal = org.schabi.newpipe.util.Localization.getPreferredExtractorLocal(getActivity()); + NewPipe.setLocalization(new Localization(oldLocal.getCountry(), (String) newLanguage)); + return true; + }); + + Preference setPreferredCountry = findPreference(getString(R.string.content_country_key)); + setPreferredCountry.setOnPreferenceChangeListener((Preference p, Object newCountry) -> { + Localization oldLocal = org.schabi.newpipe.util.Localization.getPreferredExtractorLocal(getActivity()); + NewPipe.setLocalization(new Localization((String) newCountry, oldLocal.getLanguage())); + return true; + }); } @Override @@ -193,7 +203,7 @@ public class ContentSettingsFragment extends BasePreferenceFragment { } finally { try { zipFile.close(); - } catch (Exception e){} + } catch (Exception ignored){} } try { @@ -254,17 +264,17 @@ public class ContentSettingsFragment extends BasePreferenceFragment { String key = entry.getKey(); if (v instanceof Boolean) - prefEdit.putBoolean(key, ((Boolean) v).booleanValue()); + prefEdit.putBoolean(key, (Boolean) v); else if (v instanceof Float) - prefEdit.putFloat(key, ((Float) v).floatValue()); + prefEdit.putFloat(key, (Float) v); else if (v instanceof Integer) - prefEdit.putInt(key, ((Integer) v).intValue()); + prefEdit.putInt(key, (Integer) v); else if (v instanceof Long) - prefEdit.putLong(key, ((Long) v).longValue()); + prefEdit.putLong(key, (Long) v); else if (v instanceof String) prefEdit.putString(key, ((String) v)); } - prefEdit.commit(); + prefEdit.apply(); } catch (FileNotFoundException e) { e.printStackTrace(); } catch (IOException e) { @@ -286,13 +296,12 @@ public class ContentSettingsFragment extends BasePreferenceFragment { // Error //////////////////////////////////////////////////////////////////////////*/ - protected boolean onError(Throwable e) { + protected void onError(Throwable e) { final Activity activity = getActivity(); ErrorActivity.reportError(activity, e, activity.getClass(), null, ErrorActivity.ErrorInfo.make(UserAction.UI_ERROR, "none", "", R.string.app_ui_crash)); - return true; } } diff --git a/app/src/main/java/org/schabi/newpipe/settings/HistorySettingsFragment.java b/app/src/main/java/org/schabi/newpipe/settings/HistorySettingsFragment.java index cc1f408b7..d28c3179c 100644 --- a/app/src/main/java/org/schabi/newpipe/settings/HistorySettingsFragment.java +++ b/app/src/main/java/org/schabi/newpipe/settings/HistorySettingsFragment.java @@ -1,29 +1,20 @@ package org.schabi.newpipe.settings; -import android.content.DialogInterface; import android.os.Bundle; import android.support.annotation.Nullable; -import android.support.design.widget.Snackbar; import android.support.v7.app.AlertDialog; import android.support.v7.preference.Preference; -import android.util.Log; import android.widget.Toast; -import org.schabi.newpipe.MainActivity; import org.schabi.newpipe.R; import org.schabi.newpipe.local.history.HistoryRecordManager; import org.schabi.newpipe.report.ErrorActivity; import org.schabi.newpipe.report.UserAction; import org.schabi.newpipe.util.InfoCache; -import java.util.ArrayList; -import java.util.Collection; - -import io.reactivex.Single; import io.reactivex.android.schedulers.AndroidSchedulers; import io.reactivex.disposables.CompositeDisposable; import io.reactivex.disposables.Disposable; -import io.reactivex.disposables.Disposables; public class HistorySettingsFragment extends BasePreferenceFragment { private String cacheWipeKey; diff --git a/app/src/main/java/org/schabi/newpipe/settings/SelectChannelFragment.java b/app/src/main/java/org/schabi/newpipe/settings/SelectChannelFragment.java index 0ebdbefe0..61bd4077e 100644 --- a/app/src/main/java/org/schabi/newpipe/settings/SelectChannelFragment.java +++ b/app/src/main/java/org/schabi/newpipe/settings/SelectChannelFragment.java @@ -51,9 +51,7 @@ import io.reactivex.schedulers.Schedulers; */ public class SelectChannelFragment extends DialogFragment { - private SelectChannelAdapter channelAdapter; - private SubscriptionService subscriptionService; - private ImageLoader imageLoader = ImageLoader.getInstance(); + private final ImageLoader imageLoader = ImageLoader.getInstance(); private ProgressBar progressBar; private TextView emptyView; @@ -89,9 +87,9 @@ public class SelectChannelFragment extends DialogFragment { @Override public View onCreateView(@NonNull LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { View v = inflater.inflate(R.layout.select_channel_fragment, container, false); - recyclerView = (RecyclerView) v.findViewById(R.id.items_list); + recyclerView = v.findViewById(R.id.items_list); recyclerView.setLayoutManager(new LinearLayoutManager(getContext())); - channelAdapter = new SelectChannelAdapter(); + SelectChannelAdapter channelAdapter = new SelectChannelAdapter(); recyclerView.setAdapter(channelAdapter); progressBar = v.findViewById(R.id.progressBar); @@ -101,7 +99,7 @@ public class SelectChannelFragment extends DialogFragment { emptyView.setVisibility(View.GONE); - subscriptionService = SubscriptionService.getInstance(getContext()); + SubscriptionService subscriptionService = SubscriptionService.getInstance(getContext()); subscriptionService.getSubscription().toObservable() .subscribeOn(Schedulers.io()) .observeOn(AndroidSchedulers.mainThread()) @@ -203,9 +201,9 @@ public class SelectChannelFragment extends DialogFragment { thumbnailView = v.findViewById(R.id.itemThumbnailView); titleView = v.findViewById(R.id.itemTitleView); } - public View view; - public CircleImageView thumbnailView; - public TextView titleView; + public final View view; + public final CircleImageView thumbnailView; + public final TextView titleView; } } @@ -213,14 +211,13 @@ public class SelectChannelFragment extends DialogFragment { // Error //////////////////////////////////////////////////////////////////////////*/ - protected boolean onError(Throwable e) { + protected void onError(Throwable e) { final Activity activity = getActivity(); ErrorActivity.reportError(activity, e, activity.getClass(), null, ErrorActivity.ErrorInfo.make(UserAction.UI_ERROR, "none", "", R.string.app_ui_crash)); - return true; } diff --git a/app/src/main/java/org/schabi/newpipe/settings/SelectKioskFragment.java b/app/src/main/java/org/schabi/newpipe/settings/SelectKioskFragment.java index 44cb16682..8c3bd56e7 100644 --- a/app/src/main/java/org/schabi/newpipe/settings/SelectKioskFragment.java +++ b/app/src/main/java/org/schabi/newpipe/settings/SelectKioskFragment.java @@ -75,7 +75,7 @@ public class SelectKioskFragment extends DialogFragment { @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { View v = inflater.inflate(R.layout.select_kiosk_fragment, container, false); - recyclerView = (RecyclerView) v.findViewById(R.id.items_list); + recyclerView = v.findViewById(R.id.items_list); recyclerView.setLayoutManager(new LinearLayoutManager(getContext())); try { selectKioskAdapter = new SelectKioskAdapter(); @@ -112,13 +112,13 @@ public class SelectKioskFragment extends DialogFragment { public Entry (int i, int si, String ki, String kn){ icon = i; serviceId=si; kioskId=ki; kioskName = kn; } - int icon; - int serviceId; - String kioskId; - String kioskName; + final int icon; + final int serviceId; + final String kioskId; + final String kioskName; } - private List kioskList = new Vector<>(); + private final List kioskList = new Vector<>(); public SelectKioskAdapter() throws Exception { @@ -157,9 +157,9 @@ public class SelectKioskFragment extends DialogFragment { thumbnailView = v.findViewById(R.id.itemThumbnailView); titleView = v.findViewById(R.id.itemTitleView); } - public View view; - public ImageView thumbnailView; - public TextView titleView; + public final View view; + public final ImageView thumbnailView; + public final TextView titleView; } public void onBindViewHolder(SelectKioskItemHolder holder, final int position) { @@ -179,13 +179,12 @@ public class SelectKioskFragment extends DialogFragment { // Error //////////////////////////////////////////////////////////////////////////*/ - protected boolean onError(Throwable e) { + protected void onError(Throwable e) { final Activity activity = getActivity(); ErrorActivity.reportError(activity, e, activity.getClass(), null, ErrorActivity.ErrorInfo.make(UserAction.UI_ERROR, "none", "", R.string.app_ui_crash)); - return true; } } diff --git a/app/src/main/java/org/schabi/newpipe/util/ExtractorHelper.java b/app/src/main/java/org/schabi/newpipe/util/ExtractorHelper.java index e445233c3..e04c1e8d0 100644 --- a/app/src/main/java/org/schabi/newpipe/util/ExtractorHelper.java +++ b/app/src/main/java/org/schabi/newpipe/util/ExtractorHelper.java @@ -32,6 +32,7 @@ import org.schabi.newpipe.extractor.Info; import org.schabi.newpipe.extractor.ListExtractor.InfoItemsPage; import org.schabi.newpipe.extractor.NewPipe; import org.schabi.newpipe.extractor.channel.ChannelInfo; +import org.schabi.newpipe.extractor.channel.ChannelInfoItem; import org.schabi.newpipe.extractor.exceptions.ContentNotAvailableException; import org.schabi.newpipe.extractor.exceptions.ParsingException; import org.schabi.newpipe.extractor.exceptions.ReCaptchaException; @@ -67,42 +68,37 @@ public final class ExtractorHelper { public static Single searchFor(final int serviceId, final String searchString, final List contentFilter, - final String sortFilter, - final String contentCountry) { + final String sortFilter) { checkServiceId(serviceId); return Single.fromCallable(() -> SearchInfo.getInfo(NewPipe.getService(serviceId), NewPipe.getService(serviceId) .getSearchQHFactory() - .fromQuery(searchString, contentFilter, sortFilter), - contentCountry)); + .fromQuery(searchString, contentFilter, sortFilter))); } public static Single getMoreSearchItems(final int serviceId, final String searchString, final List contentFilter, final String sortFilter, - final String pageUrl, - final String contentCountry) { + final String pageUrl) { checkServiceId(serviceId); return Single.fromCallable(() -> SearchInfo.getMoreItems(NewPipe.getService(serviceId), NewPipe.getService(serviceId) .getSearchQHFactory() .fromQuery(searchString, contentFilter, sortFilter), - contentCountry, pageUrl)); } public static Single> suggestionsFor(final int serviceId, - final String query, - final String contentCountry) { + final String query) { checkServiceId(serviceId); return Single.fromCallable(() -> NewPipe.getService(serviceId) .getSuggestionExtractor() - .suggestionList(query, contentCountry)); + .suggestionList(query)); } public static Single getStreamInfo(final int serviceId, @@ -147,19 +143,17 @@ public final class ExtractorHelper { public static Single getKioskInfo(final int serviceId, final String url, - final String contentCountry, boolean forceLoad) { return checkCache(forceLoad, serviceId, url, Single.fromCallable(() -> - KioskInfo.getInfo(NewPipe.getService(serviceId), url, contentCountry))); + KioskInfo.getInfo(NewPipe.getService(serviceId), url))); } public static Single getMoreKioskItems(final int serviceId, final String url, - final String nextStreamsUrl, - final String contentCountry) { + final String nextStreamsUrl) { return Single.fromCallable(() -> KioskInfo.getMoreItems(NewPipe.getService(serviceId), - url, nextStreamsUrl, contentCountry)); + url, nextStreamsUrl)); } /*////////////////////////////////////////////////////////////////////////// @@ -183,7 +177,7 @@ public final class ExtractorHelper { cache.removeInfo(serviceId, url); load = loadFromNetwork; } else { - load = Maybe.concat(ExtractorHelper.loadFromCache(serviceId, url), + load = Maybe.concat(ExtractorHelper.loadFromCache(serviceId, url), loadFromNetwork.toMaybe()) .firstElement() //Take the first valid .toSingle(); diff --git a/app/src/main/java/org/schabi/newpipe/util/InfoCache.java b/app/src/main/java/org/schabi/newpipe/util/InfoCache.java index ecc66bb40..318db37a1 100644 --- a/app/src/main/java/org/schabi/newpipe/util/InfoCache.java +++ b/app/src/main/java/org/schabi/newpipe/util/InfoCache.java @@ -28,9 +28,6 @@ import org.schabi.newpipe.MainActivity; import org.schabi.newpipe.extractor.Info; import java.util.Map; -import java.util.concurrent.TimeUnit; - -import static org.schabi.newpipe.extractor.ServiceList.SoundCloud; public final class InfoCache { @@ -58,7 +55,7 @@ public final class InfoCache { public Info getFromKey(int serviceId, @NonNull String url) { if (DEBUG) Log.d(TAG, "getFromKey() called with: serviceId = [" + serviceId + "], url = [" + url + "]"); synchronized (lruCache) { - return getInfo(lruCache, keyOf(serviceId, url)); + return getInfo(keyOf(serviceId, url)); } } @@ -89,7 +86,7 @@ public final class InfoCache { public void trimCache() { if (DEBUG) Log.d(TAG, "trimCache() called"); synchronized (lruCache) { - removeStaleCache(lruCache); + removeStaleCache(); lruCache.trimToSize(TRIM_CACHE_TO); } } @@ -105,23 +102,22 @@ public final class InfoCache { return serviceId + url; } - private static void removeStaleCache(@NonNull final LruCache cache) { - for (Map.Entry entry : cache.snapshot().entrySet()) { + private static void removeStaleCache() { + for (Map.Entry entry : InfoCache.lruCache.snapshot().entrySet()) { final CacheData data = entry.getValue(); if (data != null && data.isExpired()) { - cache.remove(entry.getKey()); + InfoCache.lruCache.remove(entry.getKey()); } } } @Nullable - private static Info getInfo(@NonNull final LruCache cache, - @NonNull final String key) { - final CacheData data = cache.get(key); + private static Info getInfo(@NonNull final String key) { + final CacheData data = InfoCache.lruCache.get(key); if (data == null) return null; if (data.isExpired()) { - cache.remove(key); + InfoCache.lruCache.remove(key); return null; } diff --git a/app/src/main/java/org/schabi/newpipe/util/ListHelper.java b/app/src/main/java/org/schabi/newpipe/util/ListHelper.java index 1a5bf14f7..871d0578f 100644 --- a/app/src/main/java/org/schabi/newpipe/util/ListHelper.java +++ b/app/src/main/java/org/schabi/newpipe/util/ListHelper.java @@ -204,7 +204,7 @@ public final class ListHelper { */ private static void sortStreamList(List videoStreams, final boolean ascendingOrder) { Collections.sort(videoStreams, (o1, o2) -> { - int result = compareVideoStreamResolution(o1, o2, VIDEO_FORMAT_QUALITY_RANKING); + int result = compareVideoStreamResolution(o1, o2); return result == 0 ? 0 : (ascendingOrder ? result : -result); }); } @@ -399,8 +399,7 @@ public final class ListHelper { } // Compares the quality of two video streams. - private static int compareVideoStreamResolution(VideoStream streamA, VideoStream streamB, - List formatRanking) { + private static int compareVideoStreamResolution(VideoStream streamA, VideoStream streamB) { if (streamA == null) { return -1; } @@ -414,7 +413,7 @@ public final class ListHelper { } // Same bitrate and format - return formatRanking.indexOf(streamA.getFormat()) - formatRanking.indexOf(streamB.getFormat()); + return ListHelper.VIDEO_FORMAT_QUALITY_RANKING.indexOf(streamA.getFormat()) - ListHelper.VIDEO_FORMAT_QUALITY_RANKING.indexOf(streamB.getFormat()); } diff --git a/app/src/main/java/org/schabi/newpipe/util/Localization.java b/app/src/main/java/org/schabi/newpipe/util/Localization.java index c1e5c9ed4..eed1a8ae2 100644 --- a/app/src/main/java/org/schabi/newpipe/util/Localization.java +++ b/app/src/main/java/org/schabi/newpipe/util/Localization.java @@ -69,10 +69,23 @@ public class Localization { return stringBuilder.toString(); } + public static org.schabi.newpipe.extractor.utils.Localization getPreferredExtractorLocal(Context context) { + SharedPreferences sp = PreferenceManager.getDefaultSharedPreferences(context); + + String languageCode = sp.getString(context.getString(R.string.content_language_key), + context.getString(R.string.default_language_value)); + + String countryCode = sp.getString(context.getString(R.string.content_country_key), + context.getString(R.string.default_country_value)); + + return new org.schabi.newpipe.extractor.utils.Localization(countryCode, languageCode); + } + public static Locale getPreferredLocale(Context context) { SharedPreferences sp = PreferenceManager.getDefaultSharedPreferences(context); - String languageCode = sp.getString(context.getString(R.string.search_language_key), context.getString(R.string.default_language_value)); + String languageCode = sp.getString(context.getString(R.string.content_language_key), + context.getString(R.string.default_language_value)); try { if (languageCode.length() == 2) { diff --git a/app/src/main/java/org/schabi/newpipe/util/NavigationHelper.java b/app/src/main/java/org/schabi/newpipe/util/NavigationHelper.java index 13767125d..5b953697d 100644 --- a/app/src/main/java/org/schabi/newpipe/util/NavigationHelper.java +++ b/app/src/main/java/org/schabi/newpipe/util/NavigationHelper.java @@ -26,7 +26,6 @@ import org.schabi.newpipe.download.DownloadActivity; import org.schabi.newpipe.extractor.NewPipe; import org.schabi.newpipe.extractor.StreamingService; import org.schabi.newpipe.extractor.exceptions.ExtractionException; -import org.schabi.newpipe.extractor.search.SearchExtractor; import org.schabi.newpipe.extractor.stream.AudioStream; import org.schabi.newpipe.extractor.stream.Stream; import org.schabi.newpipe.extractor.stream.StreamInfo; diff --git a/app/src/main/java/org/schabi/newpipe/util/StateSaver.java b/app/src/main/java/org/schabi/newpipe/util/StateSaver.java index 51dceddf3..3115862e0 100644 --- a/app/src/main/java/org/schabi/newpipe/util/StateSaver.java +++ b/app/src/main/java/org/schabi/newpipe/util/StateSaver.java @@ -21,7 +21,6 @@ package org.schabi.newpipe.util; import android.content.Context; -import android.os.Build; import android.os.Bundle; import android.os.Parcel; import android.os.Parcelable; diff --git a/app/src/main/java/org/schabi/newpipe/util/StreamItemAdapter.java b/app/src/main/java/org/schabi/newpipe/util/StreamItemAdapter.java index e3fe4a679..e100a447b 100644 --- a/app/src/main/java/org/schabi/newpipe/util/StreamItemAdapter.java +++ b/app/src/main/java/org/schabi/newpipe/util/StreamItemAdapter.java @@ -31,7 +31,7 @@ import us.shandian.giga.util.Utility; public class StreamItemAdapter extends BaseAdapter { private final Context context; - private StreamSizeWrapper streamsWrapper; + private final StreamSizeWrapper streamsWrapper; private final boolean showIconNoAudio; public StreamItemAdapter(Context context, StreamSizeWrapper streamsWrapper, boolean showIconNoAudio) { @@ -124,7 +124,7 @@ public class StreamItemAdapter extends BaseAdapter { public static class StreamSizeWrapper implements Serializable { private static final StreamSizeWrapper EMPTY = new StreamSizeWrapper<>(Collections.emptyList()); private final List streamsList; - private long[] streamSizes; + private final long[] streamSizes; public StreamSizeWrapper(List streamsList) { this.streamsList = streamsList; diff --git a/app/src/main/java/org/schabi/newpipe/util/ZipHelper.java b/app/src/main/java/org/schabi/newpipe/util/ZipHelper.java index 3578f34ac..3142ad8dc 100644 --- a/app/src/main/java/org/schabi/newpipe/util/ZipHelper.java +++ b/app/src/main/java/org/schabi/newpipe/util/ZipHelper.java @@ -56,7 +56,6 @@ public class ZipHelper { /** * This will extract data from Zipfiles. * Caution this will override the original file. - * @param inZip The ZipOutputStream where the data is stored in * @param file The path of the file on the disk where the data should be extracted to. * @param name The path of the file inside the zip. * @return will return true if the file was found within the zip file diff --git a/app/src/main/java/org/schabi/newpipe/views/CollapsibleView.java b/app/src/main/java/org/schabi/newpipe/views/CollapsibleView.java index adef7e76f..88d525625 100644 --- a/app/src/main/java/org/schabi/newpipe/views/CollapsibleView.java +++ b/app/src/main/java/org/schabi/newpipe/views/CollapsibleView.java @@ -81,7 +81,7 @@ public class CollapsibleView extends LinearLayout { private int targetHeight = -1; private ValueAnimator currentAnimator; - private List listeners = new ArrayList<>(); + private final List listeners = new ArrayList<>(); /** * This method recalculates the height of this view so it must be called when diff --git a/app/src/main/java/us/shandian/giga/get/DownloadManagerImpl.java b/app/src/main/java/us/shandian/giga/get/DownloadManagerImpl.java index 3294f5164..a377d861c 100755 --- a/app/src/main/java/us/shandian/giga/get/DownloadManagerImpl.java +++ b/app/src/main/java/us/shandian/giga/get/DownloadManagerImpl.java @@ -123,7 +123,7 @@ public class DownloadManagerImpl implements DownloadManager { Collections.sort(missions, new Comparator() { @Override public int compare(DownloadMission o1, DownloadMission o2) { - return Long.valueOf(o1.timestamp).compareTo(o2.timestamp); + return Long.compare(o1.timestamp, o2.timestamp); } }); } diff --git a/app/src/main/java/us/shandian/giga/get/DownloadMission.java b/app/src/main/java/us/shandian/giga/get/DownloadMission.java index f02eaae28..79c4baf05 100644 --- a/app/src/main/java/us/shandian/giga/get/DownloadMission.java +++ b/app/src/main/java/us/shandian/giga/get/DownloadMission.java @@ -67,8 +67,8 @@ public class DownloadMission implements Serializable { public long done; public int threadCount = 3; public int finishCount; - private List threadPositions = new ArrayList(); - public final Map blockState = new HashMap(); + private final List threadPositions = new ArrayList<>(); + public final Map blockState = new HashMap<>(); public boolean running; public boolean finished; public boolean fallback; @@ -77,7 +77,7 @@ public class DownloadMission implements Serializable { public transient boolean recovered; - private transient ArrayList> mListeners = new ArrayList>(); + private transient ArrayList> mListeners = new ArrayList<>(); private transient boolean mWritingToFile; private static final int NO_IDENTIFIER = -1; @@ -232,7 +232,7 @@ public class DownloadMission implements Serializable { public synchronized void addListener(MissionListener listener) { Handler handler = new Handler(Looper.getMainLooper()); MissionListener.handlerStore.put(listener, handler); - mListeners.add(new WeakReference(listener)); + mListeners.add(new WeakReference<>(listener)); } public synchronized void removeListener(MissionListener listener) { diff --git a/app/src/main/java/us/shandian/giga/get/DownloadRunnable.java b/app/src/main/java/us/shandian/giga/get/DownloadRunnable.java index b53f8aea9..6ad8626c3 100644 --- a/app/src/main/java/us/shandian/giga/get/DownloadRunnable.java +++ b/app/src/main/java/us/shandian/giga/get/DownloadRunnable.java @@ -92,7 +92,7 @@ public class DownloadRunnable implements Runnable { // A server may be ignoring the range request if (conn.getResponseCode() != 206) { mMission.errCode = DownloadMission.ERROR_SERVER_UNSUPPORTED; - notifyError(DownloadMission.ERROR_SERVER_UNSUPPORTED); + notifyError(); if (DEBUG) { Log.e(TAG, mId + ":Unsupported " + conn.getResponseCode()); @@ -161,9 +161,9 @@ public class DownloadRunnable implements Runnable { } } - private void notifyError(final int err) { + private void notifyError() { synchronized (mMission) { - mMission.notifyError(err); + mMission.notifyError(DownloadMission.ERROR_SERVER_UNSUPPORTED); mMission.pause(); } } diff --git a/app/src/main/java/us/shandian/giga/service/DownloadManagerService.java b/app/src/main/java/us/shandian/giga/service/DownloadManagerService.java index 59f5e2225..ff410a79a 100755 --- a/app/src/main/java/us/shandian/giga/service/DownloadManagerService.java +++ b/app/src/main/java/us/shandian/giga/service/DownloadManagerService.java @@ -56,7 +56,7 @@ public class DownloadManagerService extends Service { private DownloadDataSource mDataSource; - private MissionListener missionListener = new MissionListener(); + private final MissionListener missionListener = new MissionListener(); private void notifyMediaScanner(DownloadMission mission) { diff --git a/app/src/main/java/us/shandian/giga/ui/adapter/MissionAdapter.java b/app/src/main/java/us/shandian/giga/ui/adapter/MissionAdapter.java index 8127c3467..d5555c2be 100644 --- a/app/src/main/java/us/shandian/giga/ui/adapter/MissionAdapter.java +++ b/app/src/main/java/us/shandian/giga/ui/adapter/MissionAdapter.java @@ -306,12 +306,12 @@ public class MissionAdapter extends RecyclerView.Adapter { ProgressDialog prog; - WeakReference weakReference; + final WeakReference weakReference; ChecksumTask(@NonNull Activity activity) { weakReference = new WeakReference<>(activity); diff --git a/app/src/main/java/us/shandian/giga/ui/common/ProgressDrawable.java b/app/src/main/java/us/shandian/giga/ui/common/ProgressDrawable.java index 6a0e35cff..955ce4c65 100644 --- a/app/src/main/java/us/shandian/giga/ui/common/ProgressDrawable.java +++ b/app/src/main/java/us/shandian/giga/ui/common/ProgressDrawable.java @@ -12,7 +12,8 @@ import android.support.v4.content.ContextCompat; public class ProgressDrawable extends Drawable { private float mProgress; - private int mBackgroundColor, mForegroundColor; + private final int mBackgroundColor; + private final int mForegroundColor; public ProgressDrawable(Context context, @ColorRes int background, @ColorRes int foreground) { this(ContextCompat.getColor(context, background), ContextCompat.getColor(context, foreground)); diff --git a/app/src/main/java/us/shandian/giga/ui/fragment/MissionsFragment.java b/app/src/main/java/us/shandian/giga/ui/fragment/MissionsFragment.java index 14439f6c8..5241415b2 100644 --- a/app/src/main/java/us/shandian/giga/ui/fragment/MissionsFragment.java +++ b/app/src/main/java/us/shandian/giga/ui/fragment/MissionsFragment.java @@ -16,6 +16,8 @@ import android.support.v7.widget.GridLayoutManager; import android.support.v7.widget.LinearLayoutManager; import android.support.v7.widget.RecyclerView; import android.view.LayoutInflater; +import android.view.Menu; +import android.view.MenuInflater; import android.view.MenuItem; import android.view.View; import android.view.ViewGroup; @@ -44,7 +46,7 @@ public abstract class MissionsFragment extends Fragment { private DeleteDownloadManager mDeleteDownloadManager; private Disposable mDeleteDisposable; - private ServiceConnection mConnection = new ServiceConnection() { + private final ServiceConnection mConnection = new ServiceConnection() { @Override public void onServiceConnected(ComponentName name, IBinder binder) { @@ -144,17 +146,21 @@ public abstract class MissionsFragment extends Fragment { } @Override - public boolean onOptionsItemSelected(MenuItem item) { - return super.onOptionsItemSelected(item); + public void onPrepareOptionsMenu(Menu menu) { + mSwitch = menu.findItem(R.id.switch_mode); + super.onPrepareOptionsMenu(menu); + } - /*switch (item.getItemId()) { + @Override + public boolean onOptionsItemSelected(MenuItem item) { + switch (item.getItemId()) { case R.id.switch_mode: mLinear = !mLinear; updateList(); return true; default: return super.onOptionsItemSelected(item); - }*/ + } } public void notifyChange() { diff --git a/app/src/main/java/us/shandian/giga/util/Utility.java b/app/src/main/java/us/shandian/giga/util/Utility.java index de9a16a1b..163ac2b14 100644 --- a/app/src/main/java/us/shandian/giga/util/Utility.java +++ b/app/src/main/java/us/shandian/giga/util/Utility.java @@ -11,9 +11,7 @@ import android.widget.Toast; import org.schabi.newpipe.R; -import java.io.BufferedInputStream; import java.io.BufferedOutputStream; -import java.io.File; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.FileOutputStream; @@ -198,7 +196,7 @@ public class Utility { while ((len = i.read(buf)) != -1) { md.update(buf, 0, len); } - } catch (IOException e) { + } catch (IOException ignored) { } diff --git a/app/src/main/res/layout-large-land/activity_main_player.xml b/app/src/main/res/layout-large-land/activity_main_player.xml new file mode 100644 index 000000000..7d7e1230e --- /dev/null +++ b/app/src/main/res/layout-large-land/activity_main_player.xml @@ -0,0 +1,581 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/app/src/main/res/layout-large-land/fragment_video_detail.xml b/app/src/main/res/layout-large-land/fragment_video_detail.xml new file mode 100644 index 000000000..73939d60a --- /dev/null +++ b/app/src/main/res/layout-large-land/fragment_video_detail.xml @@ -0,0 +1,491 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/app/src/main/res/layout-v21/drawer_header.xml b/app/src/main/res/layout-v21/drawer_header.xml index 4cdc2b30e..4474ee4ed 100644 --- a/app/src/main/res/layout-v21/drawer_header.xml +++ b/app/src/main/res/layout-v21/drawer_header.xml @@ -16,7 +16,8 @@ android:layout_height="match_parent" android:background="?attr/colorPrimary" android:scaleType="centerCrop" - android:src="@drawable/background_header" /> + android:src="@drawable/background_header" + android:contentDescription="TODO" /> + android:src="@drawable/np_logo_nude_shadow" + android:contentDescription="TODO" /> @@ -50,7 +52,7 @@ android:layout_alignStart="@id/drawer_header_np_text_view" android:layout_below="@id/drawer_header_np_text_view" android:text="YouTube" - android:textSize="18dp" + android:textSize="18sp" android:textColor="@color/drawer_header_font_color" android:textStyle="italic" /> @@ -66,6 +68,7 @@ android:paddingBottom="20dp" android:paddingEnd="20dp" android:paddingRight="20dp" - android:src="@drawable/ic_arrow_down_white" /> + android:src="@drawable/ic_arrow_down_white" + android:contentDescription="TODO" /> \ No newline at end of file diff --git a/app/src/main/res/layout/activity_error.xml b/app/src/main/res/layout/activity_error.xml index 7752dc7cb..c47077c73 100644 --- a/app/src/main/res/layout/activity_error.xml +++ b/app/src/main/res/layout/activity_error.xml @@ -114,7 +114,8 @@ + android:layout_height="wrap_content" + android:inputType="" />