diff --git a/app/build.gradle b/app/build.gradle index ef034f98d..13f422afa 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -8,8 +8,8 @@ android { applicationId "org.schabi.newpipe" minSdkVersion 15 targetSdkVersion 27 - versionCode 45 - versionName "0.11.4" + versionCode 46 + versionName "0.11.5" testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner" vectorDrawables.useSupportLibrary = true @@ -55,7 +55,7 @@ dependencies { exclude module: 'support-annotations' } - implementation 'com.github.TeamNewPipe:NewPipeExtractor:9de63f8c0a170a066' + implementation 'com.github.TeamNewPipe:NewPipeExtractor:1c97da8b51b3610' testImplementation 'junit:junit:4.12' testImplementation 'org.mockito:mockito-core:1.10.19' diff --git a/app/src/main/java/org/schabi/newpipe/MainActivity.java b/app/src/main/java/org/schabi/newpipe/MainActivity.java index 056db3500..f5a43fa63 100644 --- a/app/src/main/java/org/schabi/newpipe/MainActivity.java +++ b/app/src/main/java/org/schabi/newpipe/MainActivity.java @@ -28,8 +28,13 @@ import android.os.Looper; import android.preference.PreferenceManager; import android.support.annotation.NonNull; import android.support.annotation.Nullable; +import android.support.design.widget.NavigationView; import android.support.v4.app.Fragment; +import android.support.v4.app.FragmentManager; +import android.support.v4.view.GravityCompat; +import android.support.v4.widget.DrawerLayout; import android.support.v7.app.ActionBar; +import android.support.v7.app.ActionBarDrawerToggle; import android.support.v7.app.AppCompatActivity; import android.support.v7.widget.Toolbar; import android.util.Log; @@ -45,6 +50,7 @@ import org.schabi.newpipe.database.history.dao.WatchHistoryDAO; import org.schabi.newpipe.database.history.model.HistoryEntry; import org.schabi.newpipe.database.history.model.SearchHistoryEntry; import org.schabi.newpipe.database.history.model.WatchHistoryEntry; +import org.schabi.newpipe.extractor.NewPipe; import org.schabi.newpipe.extractor.StreamingService; import org.schabi.newpipe.extractor.stream.AudioStream; import org.schabi.newpipe.extractor.stream.StreamInfo; @@ -69,6 +75,7 @@ public class MainActivity extends AppCompatActivity implements HistoryListener { private static final String TAG = "MainActivity"; public static final boolean DEBUG = false; private SharedPreferences sharedPreferences; + private ActionBarDrawerToggle toggle = null; /*////////////////////////////////////////////////////////////////////////// // Activity's LifeCycle @@ -76,7 +83,8 @@ public class MainActivity extends AppCompatActivity implements HistoryListener { @Override protected void onCreate(Bundle savedInstanceState) { - if (DEBUG) Log.d(TAG, "onCreate() called with: savedInstanceState = [" + savedInstanceState + "]"); + if (DEBUG) + Log.d(TAG, "onCreate() called with: savedInstanceState = [" + savedInstanceState + "]"); ThemeHelper.setTheme(this); super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); @@ -85,8 +93,59 @@ public class MainActivity extends AppCompatActivity implements HistoryListener { initFragments(); } - Toolbar toolbar = findViewById(R.id.toolbar); + final Toolbar toolbar = findViewById(R.id.toolbar); + final DrawerLayout drawer = findViewById(R.id.drawer_layout); + final NavigationView drawerItems = findViewById(R.id.navigation); setSupportActionBar(toolbar); + + drawerItems.getMenu().getItem(NewPipe.getIdOfService(PreferenceManager.getDefaultSharedPreferences(getApplicationContext()).getString("service", "YouTube"))).setChecked(true); + + if (!BuildConfig.BUILD_TYPE.equals("release")) { + toggle = new ActionBarDrawerToggle(this, drawer, toolbar, R.string.drawer_open, R.string.drawer_close); + toggle.syncState(); + drawer.addDrawerListener(toggle); + + drawerItems.setNavigationItemSelectedListener(new NavigationView.OnNavigationItemSelectedListener() { + public boolean onNavigationItemSelected(@NonNull MenuItem item) { + drawerItems.getMenu().getItem(NewPipe.getIdOfService(PreferenceManager.getDefaultSharedPreferences(getApplicationContext()).getString("service", "YouTube"))).setChecked(false); + SharedPreferences.Editor editor = PreferenceManager.getDefaultSharedPreferences(getApplicationContext()).edit(); + editor.putString("service", item.getTitle().toString()); + editor.apply(); + drawer.closeDrawers(); + drawerItems.getMenu().getItem(NewPipe.getIdOfService(PreferenceManager.getDefaultSharedPreferences(getApplicationContext()).getString("service", "YouTube"))).setChecked(true); + return true; + } + }); + } else { + drawer.setDrawerLockMode(DrawerLayout.LOCK_MODE_LOCKED_CLOSED); + } + + getSupportFragmentManager().addOnBackStackChangedListener(new FragmentManager.OnBackStackChangedListener() { + @Override + public void onBackStackChanged() { + if (getSupportFragmentManager().getBackStackEntryCount() > 1) { + getSupportActionBar().setDisplayHomeAsUpEnabled(true); + toolbar.setNavigationOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + onBackPressed(); + } + }); + } else { + getSupportActionBar().setDisplayHomeAsUpEnabled(false); + if (toggle != null) { + toggle.syncState(); + toolbar.setNavigationOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + drawer.openDrawer(GravityCompat.START); + } + }); + } + } + } + }); + sharedPreferences = PreferenceManager.getDefaultSharedPreferences(this); initHistory(); diff --git a/app/src/main/java/org/schabi/newpipe/fragments/MainFragment.java b/app/src/main/java/org/schabi/newpipe/fragments/MainFragment.java index e220654a4..be3422706 100644 --- a/app/src/main/java/org/schabi/newpipe/fragments/MainFragment.java +++ b/app/src/main/java/org/schabi/newpipe/fragments/MainFragment.java @@ -138,7 +138,7 @@ public class MainFragment extends BaseFragment implements TabLayout.OnTabSelecte public boolean onOptionsItemSelected(MenuItem item) { switch (item.getItemId()) { case R.id.action_search: - NavigationHelper.openSearchFragment(getFragmentManager(), 0, ""); + NavigationHelper.openSearchFragment(getFragmentManager(), NewPipe.getIdOfService(PreferenceManager.getDefaultSharedPreferences(getActivity()).getString("service", "YouTube")), ""); return true; } return super.onOptionsItemSelected(item); 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 802389a95..665a8f7f9 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 @@ -342,7 +342,11 @@ public class VideoDetailFragment extends BaseStateFragment implement } break; case R.id.detail_thumbnail_root_layout: - openVideoPlayer(); + if (currentInfo.video_streams.isEmpty() && currentInfo.video_only_streams.isEmpty()) { + openBackgroundPlayer(false); + } else { + openVideoPlayer(); + } break; case R.id.detail_title_root_layout: toggleTitleAndDescription(); @@ -1158,6 +1162,13 @@ public class VideoDetailFragment extends BaseStateFragment implement showSnackBarError(info.getErrors(), UserAction.REQUESTED_STREAM, NewPipe.getNameOfService(info.getServiceId()), info.getUrl(), 0); } + if (info.video_streams.isEmpty() && info.video_only_streams.isEmpty()) { + detailControlsBackground.setVisibility(View.GONE); + detailControlsPopup.setVisibility(View.GONE); + spinnerToolbar.setVisibility(View.GONE); + thumbnailPlayButton.setImageResource(R.drawable.ic_headset_white_24dp); + } + if (autoPlayEnabled) { openVideoPlayer(); // Only auto play in the first open @@ -1201,4 +1212,4 @@ public class VideoDetailFragment extends BaseStateFragment implement showError(getString(R.string.blocked_by_gema), false, R.drawable.gruese_die_gema); } -} \ No newline at end of file +} 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 41561af66..57e77d97a 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 @@ -124,20 +124,12 @@ public abstract class BaseListInfoFragment extends BaseListF currentWorker = loadResult(forceLoad) .subscribeOn(Schedulers.io()) .observeOn(AndroidSchedulers.mainThread()) - .subscribe(new Consumer() { - @Override - public void accept(@NonNull I result) throws Exception { - isLoading.set(false); - currentInfo = result; - currentNextItemsUrl = result.next_streams_url; - handleResult(result); - } - }, new Consumer() { - @Override - public void accept(@NonNull Throwable throwable) throws Exception { - onError(throwable); - } - }); + .subscribe((@NonNull I result) -> { + isLoading.set(false); + currentInfo = result; + currentNextItemsUrl = result.next_streams_url; + handleResult(result); + }, (@NonNull Throwable throwable) -> onError(throwable)); } /** @@ -153,18 +145,12 @@ public abstract class BaseListInfoFragment extends BaseListF currentWorker = loadMoreItemsLogic() .subscribeOn(Schedulers.io()) .observeOn(AndroidSchedulers.mainThread()) - .subscribe(new Consumer() { - @Override - public void accept(@io.reactivex.annotations.NonNull ListExtractor.NextItemsResult nextItemsResult) throws Exception { - isLoading.set(false); - handleNextItems(nextItemsResult); - } - }, new Consumer() { - @Override - public void accept(@io.reactivex.annotations.NonNull Throwable throwable) throws Exception { - isLoading.set(false); - onError(throwable); - } + .subscribe((@io.reactivex.annotations.NonNull ListExtractor.NextItemsResult nextItemsResult) -> { + isLoading.set(false); + handleNextItems(nextItemsResult); + }, (@io.reactivex.annotations.NonNull Throwable throwable) -> { + isLoading.set(false); + onError(throwable); }); } 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 98dd99c3c..2ec0dc14f 100644 --- a/app/src/main/java/org/schabi/newpipe/player/MainVideoPlayer.java +++ b/app/src/main/java/org/schabi/newpipe/player/MainVideoPlayer.java @@ -25,6 +25,7 @@ import android.content.Intent; import android.content.SharedPreferences; import android.content.pm.ActivityInfo; import android.content.res.Configuration; +import android.content.res.Resources; import android.graphics.Color; import android.media.AudioManager; import android.os.Build; @@ -37,7 +38,6 @@ import android.support.v7.widget.RecyclerView; import android.support.v7.widget.helper.ItemTouchHelper; import android.util.Log; import android.view.GestureDetector; -import android.view.MenuItem; import android.view.MotionEvent; import android.view.View; import android.view.WindowManager; @@ -62,6 +62,7 @@ import org.schabi.newpipe.util.AnimationUtils; import org.schabi.newpipe.util.ListHelper; import org.schabi.newpipe.util.NavigationHelper; import org.schabi.newpipe.util.PermissionHelper; +import org.schabi.newpipe.util.PopupMenuIconHacker; import org.schabi.newpipe.util.ThemeHelper; import java.lang.reflect.Field; @@ -326,7 +327,7 @@ public final class MainVideoPlayer extends Activity { this.playNextButton = rootView.findViewById(R.id.playNextButton); this.moreOptionsButton = rootView.findViewById(R.id.moreOptionsButton); this.moreOptionsPopupMenu = new PopupMenu(context, moreOptionsButton); - this.moreOptionsPopupMenu.getMenuInflater().inflate(R.menu.menu_videooptions, moreOptionsPopupMenu.getMenu()); + buildMoreOptionsMenu(); titleTextView.setSelected(true); channelTextView.setSelected(true); @@ -379,7 +380,7 @@ public final class MainVideoPlayer extends Activity { titleTextView.setText(getVideoTitle()); channelTextView.setText(getUploaderName()); - playPauseButton.setImageResource(R.drawable.ic_pause_white); + //playPauseButton.setImageResource(R.drawable.ic_pause_white); } @Override @@ -499,25 +500,7 @@ public final class MainVideoPlayer extends Activity { private void onMoreOptionsClicked() { if (DEBUG) Log.d(TAG, "onMoreOptionsClicked() called"); - buildMoreOptionsMenu(); - try { - Field[] fields = moreOptionsPopupMenu.getClass().getDeclaredFields(); - for (Field field : fields) { - if ("mPopup".equals(field.getName())) { - field.setAccessible(true); - Object menuPopupHelper = field.get(moreOptionsPopupMenu); - Class classPopupHelper = Class.forName(menuPopupHelper - .getClass().getName()); - Method setForceIcons = classPopupHelper.getMethod( - "setForceShowIcon", boolean.class); - setForceIcons.invoke(menuPopupHelper, true); - break; - } - } - } catch (Exception e) { - e.printStackTrace(); - } moreOptionsPopupMenu.show(); isSomePopupMenuVisible = true; showControls(300); @@ -659,7 +642,9 @@ public final class MainVideoPlayer extends Activity { } private void buildMoreOptionsMenu() { - if (moreOptionsPopupMenu == null) return; + this.moreOptionsPopupMenu.getMenuInflater().inflate(R.menu.menu_videooptions, + moreOptionsPopupMenu.getMenu()); + moreOptionsPopupMenu.setOnMenuItemClickListener(menuItem -> { switch (menuItem.getItemId()) { case R.id.toggleOrientation: @@ -674,6 +659,22 @@ public final class MainVideoPlayer extends Activity { } return false; }); + + try { + PopupMenuIconHacker.setShowPopupIcon(moreOptionsPopupMenu); + } catch (Exception e) { + e.printStackTrace(); + } + + // fix icon theme + if(ThemeHelper.isLightThemeSelected(MainVideoPlayer.this)) { + moreOptionsPopupMenu.getMenu() + .findItem(R.id.toggleOrientation) + .setIcon(R.drawable.ic_screen_rotation_black_24dp); + moreOptionsPopupMenu.getMenu() + .findItem(R.id.switchPopup) + .setIcon(R.drawable.ic_fullscreen_exit_black_24dp); + } } private void buildQueue() { 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 f31ee0131..0f1c568e7 100644 --- a/app/src/main/java/org/schabi/newpipe/util/ExtractorHelper.java +++ b/app/src/main/java/org/schabi/newpipe/util/ExtractorHelper.java @@ -57,105 +57,96 @@ public final class ExtractorHelper { } } - public static Single searchFor(final int serviceId, final String query, final int pageNumber, final String contentCountry, final SearchEngine.Filter filter) { + public static Single searchFor(final int serviceId, + final String query, + final int pageNumber, + final String contentCountry, + final SearchEngine.Filter filter) { checkServiceId(serviceId); - return Single.fromCallable(new Callable() { - @Override - public SearchResult call() throws Exception { - return SearchResult.getSearchResult(NewPipe.getService(serviceId).getSearchEngine(), - query, pageNumber, contentCountry, filter); - } - }); + return Single.fromCallable(() -> + SearchResult.getSearchResult(NewPipe.getService(serviceId).getSearchEngine(), + query, pageNumber, contentCountry, filter) + ); } - public static Single getMoreSearchItems(final int serviceId, final String query, final int nextPageNumber, final String searchLanguage, final SearchEngine.Filter filter) { + public static Single getMoreSearchItems(final int serviceId, + final String query, + final int nextPageNumber, + final String searchLanguage, + final SearchEngine.Filter filter) { checkServiceId(serviceId); return searchFor(serviceId, query, nextPageNumber, searchLanguage, filter) - .map(new Function() { - @Override - public NextItemsResult apply(@NonNull SearchResult searchResult) throws Exception { - return new NextItemsResult(searchResult.resultList, nextPageNumber + "", searchResult.errors); - } - }); + .map((@NonNull SearchResult searchResult) -> + new NextItemsResult(searchResult.resultList, + nextPageNumber + "", + searchResult.errors)); } - public static Single> suggestionsFor(final int serviceId, final String query, final String contentCountry) { + public static Single> suggestionsFor(final int serviceId, + final String query, + final String contentCountry) { checkServiceId(serviceId); - return Single.fromCallable(new Callable>() { - @Override - public List call() throws Exception { - return NewPipe.getService(serviceId).getSuggestionExtractor().suggestionList(query, contentCountry); - } - }); + return Single.fromCallable(() -> + NewPipe.getService(serviceId) + .getSuggestionExtractor() + .suggestionList(query, contentCountry)); } - public static Single getStreamInfo(final int serviceId, final String url, boolean forceLoad) { + public static Single getStreamInfo(final int serviceId, + final String url, + boolean forceLoad) { checkServiceId(serviceId); - return checkCache(forceLoad, serviceId, url, Single.fromCallable(new Callable() { - @Override - public StreamInfo call() throws Exception { - return StreamInfo.getInfo(NewPipe.getService(serviceId), url); - } - })); + return checkCache(forceLoad, serviceId, url, Single.fromCallable(() -> + StreamInfo.getInfo(NewPipe.getService(serviceId), url))); } - public static Single getChannelInfo(final int serviceId, final String url, boolean forceLoad) { + public static Single getChannelInfo(final int serviceId, + final String url, + boolean forceLoad) { checkServiceId(serviceId); - return checkCache(forceLoad, serviceId, url, Single.fromCallable(new Callable() { - @Override - public ChannelInfo call() throws Exception { - return ChannelInfo.getInfo(NewPipe.getService(serviceId), url); - } - })); + return checkCache(forceLoad, serviceId, url, Single.fromCallable(() -> + ChannelInfo.getInfo(NewPipe.getService(serviceId), url))); } - public static Single getMoreChannelItems(final int serviceId, final String url, final String nextStreamsUrl) { + public static Single getMoreChannelItems(final int serviceId, + final String url, + final String nextStreamsUrl) { checkServiceId(serviceId); - return Single.fromCallable(new Callable() { - @Override - public NextItemsResult call() throws Exception { - return ChannelInfo.getMoreItems(NewPipe.getService(serviceId), url, nextStreamsUrl); - } - }); + return Single.fromCallable(() -> + ChannelInfo.getMoreItems(NewPipe.getService(serviceId), url, nextStreamsUrl)); } - public static Single getPlaylistInfo(final int serviceId, final String url, boolean forceLoad) { + public static Single getPlaylistInfo(final int serviceId, + final String url, + boolean forceLoad) { checkServiceId(serviceId); - return checkCache(forceLoad, serviceId, url, Single.fromCallable(new Callable() { - @Override - public PlaylistInfo call() throws Exception { - return PlaylistInfo.getInfo(NewPipe.getService(serviceId), url); - } - })); + return checkCache(forceLoad, serviceId, url, Single.fromCallable(() -> + PlaylistInfo.getInfo(NewPipe.getService(serviceId), url))); } - public static Single getMorePlaylistItems(final int serviceId, final String url, final String nextStreamsUrl) { + public static Single getMorePlaylistItems(final int serviceId, + final String url, + final String nextStreamsUrl) { checkServiceId(serviceId); - return Single.fromCallable(new Callable() { - @Override - public NextItemsResult call() throws Exception { - return PlaylistInfo.getMoreItems(NewPipe.getService(serviceId), url, nextStreamsUrl); - } - }); + return Single.fromCallable(() -> + PlaylistInfo.getMoreItems(NewPipe.getService(serviceId), url, nextStreamsUrl)); } - public static Single getKioskInfo(final int serviceId, final String url, final String contentCountry, boolean forceLoad) { - return checkCache(forceLoad, serviceId, url, Single.fromCallable(new Callable() { - @Override - public KioskInfo call() throws Exception { - Log.e("---------", contentCountry); - return KioskInfo.getInfo(NewPipe.getService(serviceId), url, contentCountry); - } - })); + 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))); } - public static Single getMoreKioskItems(final int serviceId, final String url, final String nextStreamsUrl, final String contentCountry) { - return Single.fromCallable(new Callable() { - @Override - public NextItemsResult call() throws Exception { - return KioskInfo.getMoreItems(NewPipe.getService(serviceId), url, nextStreamsUrl, contentCountry); - } - }); + public static Single getMoreKioskItems(final int serviceId, + final String url, + final String nextStreamsUrl, + final String contentCountry) { + return Single.fromCallable(() -> + KioskInfo.getMoreItems(NewPipe.getService(serviceId), + url, nextStreamsUrl, contentCountry)); } /*////////////////////////////////////////////////////////////////////////// @@ -163,24 +154,24 @@ public final class ExtractorHelper { //////////////////////////////////////////////////////////////////////////*/ /** - * Check if we can load it from the cache (forceLoad parameter), if we can't, load from the network (Single loadFromNetwork) + * Check if we can load it from the cache (forceLoad parameter), if we can't, + * load from the network (Single loadFromNetwork) * and put the results in the cache. */ - private static Single checkCache(boolean forceLoad, int serviceId, String url, Single loadFromNetwork) { + private static Single checkCache(boolean forceLoad, + int serviceId, + String url, + Single loadFromNetwork) { checkServiceId(serviceId); - loadFromNetwork = loadFromNetwork.doOnSuccess(new Consumer() { - @Override - public void accept(@NonNull I i) throws Exception { - cache.putInfo(i); - } - }); + loadFromNetwork = loadFromNetwork.doOnSuccess((@NonNull I i) -> cache.putInfo(i)); Single load; if (forceLoad) { cache.removeInfo(serviceId, url); load = loadFromNetwork; } else { - load = Maybe.concat(ExtractorHelper.loadFromCache(serviceId, url), loadFromNetwork.toMaybe()) + load = Maybe.concat(ExtractorHelper.loadFromCache(serviceId, url), + loadFromNetwork.toMaybe()) .firstElement() //Take the first valid .toSingle(); } @@ -193,9 +184,7 @@ public final class ExtractorHelper { */ public static Maybe loadFromCache(final int serviceId, final String url) { checkServiceId(serviceId); - return Maybe.defer(new Callable>() { - @Override - public MaybeSource call() throws Exception { + return Maybe.defer(() -> { //noinspection unchecked I info = (I) cache.getFromKey(serviceId, url); if (MainActivity.DEBUG) Log.d(TAG, "loadFromCache() called, info > " + info); @@ -206,8 +195,7 @@ public final class ExtractorHelper { } return Maybe.empty(); - } - }); + }); } /** @@ -215,7 +203,8 @@ public final class ExtractorHelper { * * @see Class#isAssignableFrom(Class) */ - public static boolean hasAssignableCauseThrowable(Throwable throwable, Class... causesToCheck) { + public static boolean hasAssignableCauseThrowable(Throwable throwable, + Class... causesToCheck) { // Check if getCause is not the same as cause (the getCause is already the root), // as it will cause a infinite loop if it is Throwable cause, getCause = throwable; @@ -270,7 +259,9 @@ public final class ExtractorHelper { * Check if throwable have Interrupted* exception as one of its causes. */ public static boolean isInterruptedCaused(Throwable throwable) { - return ExtractorHelper.hasExactCauseThrowable(throwable, InterruptedIOException.class, InterruptedException.class); + return ExtractorHelper.hasExactCauseThrowable(throwable, + InterruptedIOException.class, + InterruptedException.class); } public static String toUpperCase(String value) { 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 0f082cc11..46c08b01b 100644 --- a/app/src/main/java/org/schabi/newpipe/util/InfoCache.java +++ b/app/src/main/java/org/schabi/newpipe/util/InfoCache.java @@ -1,4 +1,4 @@ -/* +/** * Copyright 2017 Mauricio Colli * InfoCache.java is part of NewPipe * diff --git a/app/src/main/java/org/schabi/newpipe/util/PopupMenuIconHacker.java b/app/src/main/java/org/schabi/newpipe/util/PopupMenuIconHacker.java new file mode 100644 index 000000000..70affb900 --- /dev/null +++ b/app/src/main/java/org/schabi/newpipe/util/PopupMenuIconHacker.java @@ -0,0 +1,48 @@ +package org.schabi.newpipe.util; + +import android.widget.PopupMenu; + +import java.lang.reflect.Field; +import java.lang.reflect.Method; + +/** + * Created by Christian Schabesberger on 20.01.18. + * Copyright 2018 Christian Schabesberger + * PopupMenuIconHacker.java is part of NewPipe + * + * License: GPL-3.0+ + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +public class PopupMenuIconHacker { + public static void setShowPopupIcon(PopupMenu menu) throws Exception { + try { + Field[] fields = menu.getClass().getDeclaredFields(); + for (Field field : fields) { + if ("mPopup".equals(field.getName())) { + field.setAccessible(true); + Object menuPopupHelper = field.get(menu); + Class classPopupHelper = Class.forName(menuPopupHelper + .getClass().getName()); + Method setForceIcons = classPopupHelper.getMethod( + "setForceShowIcon", boolean.class); + setForceIcons.invoke(menuPopupHelper, true); + break; + } + } + } catch (Exception e) { + throw new Exception("Could not make Popup menu show Icons", e); + } + } +} diff --git a/app/src/main/res/drawable-hdpi/ic_fullscreen_exit_black_24dp.png b/app/src/main/res/drawable-hdpi/ic_fullscreen_exit_black_24dp.png new file mode 100644 index 000000000..8328e2efe Binary files /dev/null and b/app/src/main/res/drawable-hdpi/ic_fullscreen_exit_black_24dp.png differ diff --git a/app/src/main/res/drawable-hdpi/ic_screen_rotation_black_24dp.png b/app/src/main/res/drawable-hdpi/ic_screen_rotation_black_24dp.png new file mode 100644 index 000000000..9a55a65b7 Binary files /dev/null and b/app/src/main/res/drawable-hdpi/ic_screen_rotation_black_24dp.png differ diff --git a/app/src/main/res/drawable-mdpi/ic_fullscreen_exit_black_24dp.png b/app/src/main/res/drawable-mdpi/ic_fullscreen_exit_black_24dp.png new file mode 100644 index 000000000..c8394487c Binary files /dev/null and b/app/src/main/res/drawable-mdpi/ic_fullscreen_exit_black_24dp.png differ diff --git a/app/src/main/res/drawable-mdpi/ic_screen_rotation_black_24dp.png b/app/src/main/res/drawable-mdpi/ic_screen_rotation_black_24dp.png new file mode 100644 index 000000000..012a32d4f Binary files /dev/null and b/app/src/main/res/drawable-mdpi/ic_screen_rotation_black_24dp.png differ diff --git a/app/src/main/res/drawable-xhdpi/ic_fullscreen_exit_black_24dp.png b/app/src/main/res/drawable-xhdpi/ic_fullscreen_exit_black_24dp.png new file mode 100644 index 000000000..5fc3166ac Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/ic_fullscreen_exit_black_24dp.png differ diff --git a/app/src/main/res/drawable-xhdpi/ic_screen_rotation_black_24dp.png b/app/src/main/res/drawable-xhdpi/ic_screen_rotation_black_24dp.png new file mode 100644 index 000000000..ae2be1fa8 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/ic_screen_rotation_black_24dp.png differ diff --git a/app/src/main/res/drawable-xxhdpi/ic_fullscreen_exit_black_24dp.png b/app/src/main/res/drawable-xxhdpi/ic_fullscreen_exit_black_24dp.png new file mode 100644 index 000000000..5691b5541 Binary files /dev/null and b/app/src/main/res/drawable-xxhdpi/ic_fullscreen_exit_black_24dp.png differ diff --git a/app/src/main/res/drawable-xxhdpi/ic_screen_rotation_black_24dp.png b/app/src/main/res/drawable-xxhdpi/ic_screen_rotation_black_24dp.png new file mode 100644 index 000000000..bfd31c55a Binary files /dev/null and b/app/src/main/res/drawable-xxhdpi/ic_screen_rotation_black_24dp.png differ diff --git a/app/src/main/res/drawable-xxxhdpi/ic_fullscreen_exit_black_24dp.png b/app/src/main/res/drawable-xxxhdpi/ic_fullscreen_exit_black_24dp.png new file mode 100644 index 000000000..2221235df Binary files /dev/null and b/app/src/main/res/drawable-xxxhdpi/ic_fullscreen_exit_black_24dp.png differ diff --git a/app/src/main/res/drawable-xxxhdpi/ic_screen_rotation_black_24dp.png b/app/src/main/res/drawable-xxxhdpi/ic_screen_rotation_black_24dp.png new file mode 100644 index 000000000..29fef9a47 Binary files /dev/null and b/app/src/main/res/drawable-xxxhdpi/ic_screen_rotation_black_24dp.png differ diff --git a/app/src/main/res/layout/activity_main.xml b/app/src/main/res/layout/activity_main.xml index 88a015e81..7eafc6c69 100644 --- a/app/src/main/res/layout/activity_main.xml +++ b/app/src/main/res/layout/activity_main.xml @@ -1,18 +1,30 @@ - + android:layout_height="match_parent"> + android:orientation="vertical" + tools:context="org.schabi.newpipe.MainActivity"> + - + + - + + \ No newline at end of file diff --git a/app/src/main/res/layout/activity_main_player.xml b/app/src/main/res/layout/activity_main_player.xml index 6086dd5cb..36222f5bc 100644 --- a/app/src/main/res/layout/activity_main_player.xml +++ b/app/src/main/res/layout/activity_main_player.xml @@ -244,7 +244,7 @@ android:clickable="true" android:focusable="true" android:scaleType="fitXY" - android:src="?attr/options" + android:src="@drawable/ic_more_vert_white_24dp" tools:ignore="ContentDescription,RtlHardcoded"/> diff --git a/app/src/main/res/layout/fragment_video_detail.xml b/app/src/main/res/layout/fragment_video_detail.xml index 86e8d6ad9..8c445adcd 100644 --- a/app/src/main/res/layout/fragment_video_detail.xml +++ b/app/src/main/res/layout/fragment_video_detail.xml @@ -273,7 +273,7 @@ android:paddingBottom="6dp" android:paddingTop="6dp" android:text="@string/controls_background_title" - android:textSize="12sp"/> + android:textSize="12sp" /> diff --git a/app/src/main/res/menu/drawer_items.xml b/app/src/main/res/menu/drawer_items.xml new file mode 100644 index 000000000..2f82327c3 --- /dev/null +++ b/app/src/main/res/menu/drawer_items.xml @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/app/src/main/res/menu/menu_videooptions.xml b/app/src/main/res/menu/menu_videooptions.xml index 1887ec1dd..ce69ba9c1 100644 --- a/app/src/main/res/menu/menu_videooptions.xml +++ b/app/src/main/res/menu/menu_videooptions.xml @@ -4,17 +4,18 @@ xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto"> - diff --git a/app/src/main/res/values/settings_keys.xml b/app/src/main/res/values/settings_keys.xml index d5c78d4ed..f0c496aa2 100644 --- a/app/src/main/res/values/settings_keys.xml +++ b/app/src/main/res/values/settings_keys.xml @@ -46,6 +46,13 @@ 144p + + @string/youtube + @string/soundcloud + + service + @string/youtube + video_mp4 video_webm video_3gp diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 16bfcbb1a..6a6014a29 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -84,6 +84,7 @@ Show tip when background or popup button is pressed on video details page URL not supported Default content country + Service Default content language Player Behavior @@ -329,4 +330,10 @@ Start Playing Here Start Here on Background Start Here on Popup + + + Open Drawer + Close Drawer + YouTube + SoundCloud diff --git a/app/src/main/res/xml/content_settings.xml b/app/src/main/res/xml/content_settings.xml index 15088494d..22269eef6 100644 --- a/app/src/main/res/xml/content_settings.xml +++ b/app/src/main/res/xml/content_settings.xml @@ -2,7 +2,6 @@ - -