diff --git a/app/src/main/java/org/schabi/newpipe/MainActivity.java b/app/src/main/java/org/schabi/newpipe/MainActivity.java
index 681711d22..1bb0858ee 100644
--- a/app/src/main/java/org/schabi/newpipe/MainActivity.java
+++ b/app/src/main/java/org/schabi/newpipe/MainActivity.java
@@ -21,19 +21,23 @@
package org.schabi.newpipe;
import android.content.Intent;
-import android.media.AudioManager;
import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentManager;
+import android.support.v7.app.ActionBar;
import android.support.v7.app.AppCompatActivity;
+import android.support.v7.widget.Toolbar;
+import android.util.Log;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
+import android.view.View;
import com.nostra13.universalimageloader.core.ImageLoader;
import org.schabi.newpipe.download.DownloadActivity;
import org.schabi.newpipe.extractor.StreamingService;
+import org.schabi.newpipe.fragments.MainFragment;
import org.schabi.newpipe.fragments.OnItemSelectedListener;
import org.schabi.newpipe.fragments.channel.ChannelFragment;
import org.schabi.newpipe.fragments.detail.VideoDetailFragment;
@@ -45,7 +49,8 @@ import org.schabi.newpipe.util.PermissionHelper;
import org.schabi.newpipe.util.ThemeHelper;
public class MainActivity extends AppCompatActivity implements OnItemSelectedListener {
- //private static final String TAG = "MainActivity";
+ private static final String TAG = "MainActivity";
+ public static final boolean DEBUG = false;
/*//////////////////////////////////////////////////////////////////////////
// Activity's LifeCycle
@@ -53,18 +58,22 @@ public class MainActivity extends AppCompatActivity implements OnItemSelectedLis
@Override
protected void onCreate(Bundle savedInstanceState) {
- ThemeHelper.setTheme(this, true);
+ if (DEBUG) Log.d(TAG, "onCreate() called with: savedInstanceState = [" + savedInstanceState + "]");
+ ThemeHelper.setTheme(this);
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
- setVolumeControlStream(AudioManager.STREAM_MUSIC);
if (getSupportFragmentManager() != null && getSupportFragmentManager().getBackStackEntryCount() == 0) {
initFragments();
}
+
+ Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
+ setSupportActionBar(toolbar);
}
@Override
protected void onNewIntent(Intent intent) {
+ if (DEBUG) Log.d(TAG, "onNewIntent() called with: intent = [" + intent + "]");
if (intent != null) {
// Return if launched from a launcher (e.g. Nova Launcher, Pixel Launcher ...)
// to not destroy the already created backstack
@@ -79,22 +88,11 @@ public class MainActivity extends AppCompatActivity implements OnItemSelectedLis
@Override
public void onBackPressed() {
+ if (DEBUG) Log.d(TAG, "onBackPressed() called");
Fragment fragment = getSupportFragmentManager().findFragmentById(R.id.fragment_holder);
if (fragment instanceof VideoDetailFragment) if (((VideoDetailFragment) fragment).onActivityBackPressed()) return;
- if (getSupportFragmentManager().getBackStackEntryCount() >= 2) {
- getSupportFragmentManager().popBackStackImmediate();
- } else {
- if (fragment instanceof SearchFragment) {
- SearchFragment searchFragment = (SearchFragment) fragment;
- if (!searchFragment.isMainBgVisible()) {
- getSupportFragmentManager().beginTransaction().remove(fragment).commitNow();
- NavigationHelper.openMainActivity(this);
- return;
- }
- }
- finish();
- }
+ super.onBackPressed();
}
/*//////////////////////////////////////////////////////////////////////////
@@ -103,14 +101,32 @@ public class MainActivity extends AppCompatActivity implements OnItemSelectedLis
@Override
public boolean onCreateOptionsMenu(Menu menu) {
+ if (DEBUG) Log.d(TAG, "onCreateOptionsMenu() called with: menu = [" + menu + "]");
super.onCreateOptionsMenu(menu);
- MenuInflater inflater = getMenuInflater();
- inflater.inflate(R.menu.main_menu, menu);
+
+ Fragment fragment = getSupportFragmentManager().findFragmentById(R.id.fragment_holder);
+ if (!(fragment instanceof VideoDetailFragment)) {
+ findViewById(R.id.toolbar).findViewById(R.id.toolbar_spinner).setVisibility(View.GONE);
+ }
+
+ if (!(fragment instanceof SearchFragment)) {
+ findViewById(R.id.toolbar).findViewById(R.id.toolbar_search_container).setVisibility(View.GONE);
+
+ MenuInflater inflater = getMenuInflater();
+ inflater.inflate(R.menu.main_menu, menu);
+ }
+
+ ActionBar actionBar = getSupportActionBar();
+ if (actionBar != null) {
+ actionBar.setDisplayShowTitleEnabled(false);
+ actionBar.setDisplayHomeAsUpEnabled(false);
+ }
return true;
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
+ if (DEBUG) Log.d(TAG, "onOptionsItemSelected() called with: item = [" + item + "]");
int id = item.getItemId();
switch (id) {
@@ -144,9 +160,10 @@ public class MainActivity extends AppCompatActivity implements OnItemSelectedLis
//////////////////////////////////////////////////////////////////////////*/
private void initFragments() {
+ openMainFragment();
if (getIntent() != null && getIntent().hasExtra(Constants.KEY_URL)) {
handleIntent(getIntent());
- } else openSearchFragment();
+ }
}
/*//////////////////////////////////////////////////////////////////////////
@@ -170,6 +187,13 @@ public class MainActivity extends AppCompatActivity implements OnItemSelectedLis
//////////////////////////////////////////////////////////////////////////*/
private void handleIntent(Intent intent) {
+ if (intent.hasExtra(Constants.KEY_THEME_CHANGE) && intent.getBooleanExtra(Constants.KEY_THEME_CHANGE, false)) {
+ this.recreate();
+ Intent setI = new Intent(this, SettingsActivity.class);
+ startActivity(setI);
+ return;
+ }
+
if (intent.hasExtra(Constants.KEY_LINK_TYPE)) {
String url = intent.getStringExtra(Constants.KEY_URL);
int serviceId = intent.getIntExtra(Constants.KEY_SERVICE_ID, 0);
@@ -187,24 +211,34 @@ public class MainActivity extends AppCompatActivity implements OnItemSelectedLis
} catch (Exception e) {
e.printStackTrace();
}
+ } else if (intent.hasExtra(Constants.KEY_OPEN_SEARCH)) {
+ String searchQuery = intent.getStringExtra(Constants.KEY_QUERY);
+ if (searchQuery == null) searchQuery = "";
+ int serviceId = intent.getIntExtra(Constants.KEY_SERVICE_ID, 0);
+ openSearchFragment(serviceId, searchQuery);
} else {
getSupportFragmentManager().popBackStackImmediate(null, FragmentManager.POP_BACK_STACK_INCLUSIVE);
- openSearchFragment();
+ openMainFragment();//openSearchFragment();
}
}
- private void openSearchFragment() {
+ private void openMainFragment() {
ImageLoader.getInstance().clearMemoryCache();
getSupportFragmentManager().beginTransaction()
.setCustomAnimations(android.R.anim.fade_in, android.R.anim.fade_out, android.R.anim.fade_in, android.R.anim.fade_out)
- .replace(R.id.fragment_holder, new SearchFragment())
+ .replace(R.id.fragment_holder, new MainFragment())
+ .commit();
+ }
+
+ private void openSearchFragment(int serviceId, String query) {
+ getSupportFragmentManager().beginTransaction()
+ .setCustomAnimations(android.R.anim.fade_in, android.R.anim.fade_out, android.R.anim.fade_in, android.R.anim.fade_out)
+ .replace(R.id.fragment_holder, SearchFragment.getInstance(serviceId, query))
.addToBackStack(null)
.commit();
}
private void openVideoDetailFragment(int serviceId, String url, String title, boolean autoPlay) {
- ImageLoader.getInstance().clearMemoryCache();
-
Fragment fragment = getSupportFragmentManager().findFragmentById(R.id.fragment_holder);
if (title == null) title = "";
@@ -226,11 +260,10 @@ public class MainActivity extends AppCompatActivity implements OnItemSelectedLis
}
private void openChannelFragment(int serviceId, String url, String name) {
- ImageLoader.getInstance().clearMemoryCache();
if (name == null) name = "";
getSupportFragmentManager().beginTransaction()
.setCustomAnimations(android.R.anim.fade_in, android.R.anim.fade_out, android.R.anim.fade_in, android.R.anim.fade_out)
- .replace(R.id.fragment_holder, ChannelFragment.newInstance(serviceId, url, name))
+ .replace(R.id.fragment_holder, ChannelFragment.getInstance(serviceId, url, name))
.addToBackStack(null)
.commit();
}
diff --git a/app/src/main/java/org/schabi/newpipe/download/DownloadActivity.java b/app/src/main/java/org/schabi/newpipe/download/DownloadActivity.java
index 61e0a12b7..aef3d3bce 100644
--- a/app/src/main/java/org/schabi/newpipe/download/DownloadActivity.java
+++ b/app/src/main/java/org/schabi/newpipe/download/DownloadActivity.java
@@ -8,7 +8,6 @@ import android.content.Intent;
import android.content.SharedPreferences;
import android.os.Bundle;
import android.preference.PreferenceManager;
-import android.support.v4.app.NavUtils;
import android.support.v7.app.ActionBar;
import android.support.v7.app.AppCompatActivity;
import android.support.v7.widget.Toolbar;
@@ -26,13 +25,11 @@ import android.widget.TextView;
import android.widget.Toast;
import org.schabi.newpipe.R;
-import org.schabi.newpipe.report.ErrorActivity;
import org.schabi.newpipe.settings.NewPipeSettings;
import org.schabi.newpipe.settings.SettingsActivity;
import org.schabi.newpipe.util.ThemeHelper;
import java.io.File;
-import java.util.Vector;
import us.shandian.giga.service.DownloadManagerService;
import us.shandian.giga.ui.fragment.AllMissionsFragment;
@@ -64,17 +61,19 @@ public class DownloadActivity extends AppCompatActivity implements AdapterView.O
i.setClass(this, DownloadManagerService.class);
startService(i);
+ ThemeHelper.setTheme(this);
super.onCreate(savedInstanceState);
- ThemeHelper.setTheme(this, true);
setContentView(R.layout.activity_downloader);
- //noinspection ConstantConditions
+ Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
+ setSupportActionBar(toolbar);
- // its ok if this fails, we will catch that error later, and send it as report
ActionBar actionBar = getSupportActionBar();
- actionBar.setDisplayHomeAsUpEnabled(true);
- actionBar.setTitle(R.string.downloads_title);
- actionBar.setDisplayShowTitleEnabled(true);
+ if (actionBar != null) {
+ actionBar.setDisplayHomeAsUpEnabled(true);
+ actionBar.setTitle(R.string.downloads_title);
+ actionBar.setDisplayShowTitleEnabled(true);
+ }
mPrefs = PreferenceManager.getDefaultSharedPreferences(this);
@@ -159,7 +158,7 @@ public class DownloadActivity extends AppCompatActivity implements AdapterView.O
name.setText(getIntent().getStringExtra("fileName"));
toolbar.setTitle(R.string.add);
- toolbar.setNavigationIcon(R.drawable.ic_arrow_back_black_24dp);
+ toolbar.setNavigationIcon(ThemeHelper.isLightThemeSelected(this) ? R.drawable.ic_arrow_back_black_24dp : R.drawable.ic_arrow_back_white_24dp);
toolbar.inflateMenu(R.menu.dialog_url);
// Show the dialog
@@ -183,7 +182,7 @@ public class DownloadActivity extends AppCompatActivity implements AdapterView.O
if (item.getItemId() == R.id.okay) {
String location;
- if(audioButton.isChecked()) {
+ if (audioButton.isChecked()) {
location = NewPipeSettings.getAudioDownloadPath(DownloadActivity.this);
} else {
location = NewPipeSettings.getVideoDownloadPath(DownloadActivity.this);
@@ -201,7 +200,7 @@ public class DownloadActivity extends AppCompatActivity implements AdapterView.O
audioButton.isChecked(), threads.getProgress() + 1);
mFragment.notifyChange();
- mPrefs.edit().putInt(THREADS, threads.getProgress() + 1).commit();
+ mPrefs.edit().putInt(THREADS, threads.getProgress() + 1).apply();
mPendingUrl = null;
dialog.dismiss();
}
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 22911fc19..4902b63f2 100644
--- a/app/src/main/java/org/schabi/newpipe/download/DownloadDialog.java
+++ b/app/src/main/java/org/schabi/newpipe/download/DownloadDialog.java
@@ -1,14 +1,11 @@
package org.schabi.newpipe.download;
import android.Manifest;
-import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
-import android.content.ServiceConnection;
import android.content.pm.PackageManager;
import android.net.Uri;
import android.os.Bundle;
-import android.os.IBinder;
import android.support.annotation.Nullable;
import android.support.v4.app.ActivityCompat;
import android.support.v4.app.DialogFragment;
@@ -26,34 +23,32 @@ import android.widget.TextView;
import org.schabi.newpipe.App;
import org.schabi.newpipe.R;
-import org.schabi.newpipe.extractor.NewPipe;
import org.schabi.newpipe.settings.NewPipeSettings;
+import org.schabi.newpipe.util.ThemeHelper;
import java.io.File;
import java.util.ArrayList;
import java.util.List;
-import us.shandian.giga.get.DownloadManager;
-import us.shandian.giga.get.DownloadMission;
import us.shandian.giga.service.DownloadManagerService;
/**
* Created by Christian Schabesberger on 21.09.15.
- *
+ *
* Copyright (C) Christian Schabesberger 2015
* DownloadDialog.java is part of NewPipe.
- *
+ *
* NewPipe 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.
- *
+ *
* NewPipe 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 NewPipe. If not, see .
*/
@@ -71,8 +66,7 @@ public class DownloadDialog extends DialogFragment {
}
- public static DownloadDialog newInstance(Bundle args)
- {
+ public static DownloadDialog newInstance(Bundle args) {
DownloadDialog dialog = new DownloadDialog();
dialog.setArguments(args);
dialog.setStyle(DialogFragment.STYLE_NO_TITLE, 0);
@@ -100,7 +94,7 @@ public class DownloadDialog extends DialogFragment {
final SeekBar threads = (SeekBar) view.findViewById(R.id.threads);
toolbar.setTitle(R.string.download_dialog_title);
- toolbar.setNavigationIcon(R.drawable.ic_arrow_back_black_24dp);
+ toolbar.setNavigationIcon(ThemeHelper.isLightThemeSelected(getActivity()) ? R.drawable.ic_arrow_back_black_24dp : R.drawable.ic_arrow_back_white_24dp);
toolbar.inflateMenu(R.menu.dialog_url);
toolbar.setNavigationOnClickListener(new View.OnClickListener() {
@Override
@@ -151,16 +145,16 @@ public class DownloadDialog extends DialogFragment {
}
- protected void checkDownloadOptions(){
+ protected void checkDownloadOptions() {
View view = getView();
Bundle arguments = getArguments();
RadioButton audioButton = (RadioButton) view.findViewById(R.id.audio_button);
RadioButton videoButton = (RadioButton) view.findViewById(R.id.video_button);
- if(arguments.getString(AUDIO_URL) == null) {
+ if (arguments.getString(AUDIO_URL) == null) {
audioButton.setVisibility(View.GONE);
videoButton.setChecked(true);
- } else if(arguments.getString(VIDEO_URL) == null) {
+ } else if (arguments.getString(VIDEO_URL) == null) {
videoButton.setVisibility(View.GONE);
audioButton.setChecked(true);
}
@@ -169,11 +163,11 @@ public class DownloadDialog extends DialogFragment {
/**
* #143 #44 #42 #22: make shure that the filename does not contain illegal chars.
* This should fix some of the "cannot download" problems.
- * */
+ */
private String createFileName(String fName) {
// from http://eng-przemelek.blogspot.de/2009/07/how-to-create-valid-file-name.html
- List forbiddenCharsPatterns = new ArrayList<> ();
+ List forbiddenCharsPatterns = new ArrayList<>();
forbiddenCharsPatterns.add("[:]+"); // Mac OS, but it looks that also Windows XP
forbiddenCharsPatterns.add("[\\*\"/\\\\\\[\\]\\:\\;\\|\\=\\,]+"); // Windows
forbiddenCharsPatterns.add("[^\\w\\d\\.]+"); // last chance... only latin letters and digits
@@ -186,8 +180,7 @@ public class DownloadDialog extends DialogFragment {
//download audio, video or both?
- private void download()
- {
+ private void download() {
View view = getView();
Bundle arguments = getArguments();
final EditText name = (EditText) view.findViewById(R.id.file_name);
@@ -199,7 +192,7 @@ public class DownloadDialog extends DialogFragment {
boolean isAudio = audioButton.isChecked();
String url, location, filename;
- if(isAudio) {
+ if (isAudio) {
url = arguments.getString(AUDIO_URL);
location = NewPipeSettings.getAudioDownloadPath(getContext());
filename = fName + arguments.getString(FILE_SUFFIX_AUDIO);
@@ -218,11 +211,11 @@ public class DownloadDialog extends DialogFragment {
private void download(String url, String title,
String fileSuffix, File downloadDir, Context context) {
- File saveFilePath = new File(downloadDir,createFileName(title) + fileSuffix);
+ File saveFilePath = new File(downloadDir, createFileName(title) + fileSuffix);
long id = 0;
- Log.i(TAG,"Started downloading '" + url +
+ Log.i(TAG, "Started downloading '" + url +
"' => '" + saveFilePath + "' #" + id);
if (App.isUsingTor()) {
diff --git a/app/src/main/java/org/schabi/newpipe/fragments/BaseFragment.java b/app/src/main/java/org/schabi/newpipe/fragments/BaseFragment.java
new file mode 100644
index 000000000..d51267104
--- /dev/null
+++ b/app/src/main/java/org/schabi/newpipe/fragments/BaseFragment.java
@@ -0,0 +1,243 @@
+package org.schabi.newpipe.fragments;
+
+import android.animation.Animator;
+import android.animation.AnimatorListenerAdapter;
+import android.content.Context;
+import android.content.res.TypedArray;
+import android.graphics.Rect;
+import android.os.Bundle;
+import android.support.annotation.AttrRes;
+import android.support.v4.app.Fragment;
+import android.support.v4.view.ViewCompat;
+import android.support.v7.app.AppCompatActivity;
+import android.support.v7.widget.Toolbar;
+import android.util.Log;
+import android.view.Gravity;
+import android.view.View;
+import android.widget.Button;
+import android.widget.ProgressBar;
+import android.widget.TextView;
+import android.widget.Toast;
+
+import com.nostra13.universalimageloader.core.DisplayImageOptions;
+import com.nostra13.universalimageloader.core.ImageLoader;
+import com.nostra13.universalimageloader.core.display.FadeInBitmapDisplayer;
+
+import org.schabi.newpipe.MainActivity;
+import org.schabi.newpipe.R;
+
+import java.util.concurrent.atomic.AtomicBoolean;
+
+public abstract class BaseFragment extends Fragment {
+ protected final String TAG = "BaseFragment@" + Integer.toHexString(hashCode());
+ protected static final boolean DEBUG = MainActivity.DEBUG;
+
+ protected AppCompatActivity activity;
+ protected OnItemSelectedListener onItemSelectedListener;
+
+ protected AtomicBoolean isLoading = new AtomicBoolean(false);
+ protected AtomicBoolean wasLoading = new AtomicBoolean(false);
+
+ protected static final ImageLoader imageLoader = ImageLoader.getInstance();
+ protected static final DisplayImageOptions displayImageOptions =
+ new DisplayImageOptions.Builder().displayer(new FadeInBitmapDisplayer(400)).cacheInMemory(false).build();
+
+ /*//////////////////////////////////////////////////////////////////////////
+ // Views
+ //////////////////////////////////////////////////////////////////////////*/
+
+ protected Toolbar toolbar;
+
+ protected View errorPanel;
+ protected Button errorButtonRetry;
+ protected TextView errorTextView;
+ protected ProgressBar loadingProgressBar;
+ //protected SwipeRefreshLayout swipeRefreshLayout;
+
+ /*//////////////////////////////////////////////////////////////////////////
+ // Fragment's Lifecycle
+ //////////////////////////////////////////////////////////////////////////*/
+
+ @Override
+ public void onAttach(Context context) {
+ super.onAttach(context);
+ if (DEBUG) Log.d(TAG, "onAttach() called with: context = [" + context + "]");
+
+ activity = (AppCompatActivity) context;
+ onItemSelectedListener = (OnItemSelectedListener) context;
+ }
+
+ @Override
+ public void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ if (DEBUG) Log.d(TAG, "onCreate() called with: savedInstanceState = [" + savedInstanceState + "]");
+
+ isLoading.set(false);
+ setHasOptionsMenu(true);
+ }
+
+ @Override
+ public void onViewCreated(View rootView, Bundle savedInstanceState) {
+ if (DEBUG) Log.d(TAG, "onViewCreated() called with: rootView = [" + rootView + "], savedInstanceState = [" + savedInstanceState + "]");
+ initViews(rootView, savedInstanceState);
+ initListeners();
+ wasLoading.set(false);
+ }
+
+ @Override
+ public void onDestroyView() {
+ super.onDestroyView();
+ if (DEBUG) Log.d(TAG, "onDestroyView() called");
+ toolbar = null;
+
+ errorPanel = null;
+ errorButtonRetry = null;
+ errorTextView = null;
+ }
+
+ /*//////////////////////////////////////////////////////////////////////////
+ // Init
+ //////////////////////////////////////////////////////////////////////////*/
+
+ protected void initViews(View rootView, Bundle savedInstanceState) {
+ toolbar = (Toolbar) activity.findViewById(R.id.toolbar);
+
+ loadingProgressBar = (ProgressBar) rootView.findViewById(R.id.loading_progress_bar);
+ //swipeRefreshLayout = (SwipeRefreshLayout) rootView.findViewById(R.id.swipe_refresh);
+
+ errorPanel = rootView.findViewById(R.id.error_panel);
+ errorButtonRetry = (Button) rootView.findViewById(R.id.error_button_retry);
+ errorTextView = (TextView) rootView.findViewById(R.id.error_message_view);
+ }
+
+ protected void initListeners() {
+ errorButtonRetry.setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View v) {
+ onRetryButtonClicked();
+ }
+ });
+ }
+
+ protected abstract void reloadContent();
+
+ protected void onRetryButtonClicked() {
+ if (DEBUG) Log.d(TAG, "onRetryButtonClicked() called");
+ reloadContent();
+ }
+
+ /*//////////////////////////////////////////////////////////////////////////
+ // Utils
+ //////////////////////////////////////////////////////////////////////////*/
+
+ public void animateView(final View view, final boolean enterOrExit, long duration) {
+ animateView(view, enterOrExit, duration, 0, null);
+ }
+
+ public void animateView(final View view, final boolean enterOrExit, long duration, final Runnable execOnEnd) {
+ animateView(view, enterOrExit, duration, 0, execOnEnd);
+ }
+
+ public void animateView(final View view, final boolean enterOrExit, long duration, long delay) {
+ animateView(view, enterOrExit, duration, delay, null);
+ }
+
+ /**
+ * Animate the view
+ *
+ * @param view view that will be animated
+ * @param enterOrExit true to enter, false to exit
+ * @param duration how long the animation will take, in milliseconds
+ * @param delay how long the animation will take to start, in milliseconds
+ * @param execOnEnd runnable that will be executed when the animation ends
+ */
+ public void animateView(final View view, final boolean enterOrExit, long duration, long delay, final Runnable execOnEnd) {
+ if (DEBUG) Log.d(TAG, "animateView() called with: view = [" + view + "], enterOrExit = [" + enterOrExit + "], duration = [" + duration + "], execOnEnd = [" + execOnEnd + "]");
+ if (view == null) return;
+
+ if (view.getVisibility() == View.VISIBLE && enterOrExit) {
+ view.animate().setListener(null).cancel();
+ view.setVisibility(View.VISIBLE);
+ view.setAlpha(1f);
+ if (execOnEnd != null) execOnEnd.run();
+ return;
+ } else if ((view.getVisibility() == View.GONE || view.getVisibility() == View.INVISIBLE) && !enterOrExit) {
+ view.animate().setListener(null).cancel();
+ view.setVisibility(View.GONE);
+ view.setAlpha(0f);
+ if (execOnEnd != null) execOnEnd.run();
+ return;
+ }
+
+ view.animate().setListener(null).cancel();
+ view.setVisibility(View.VISIBLE);
+
+ if (enterOrExit) {
+ view.animate().alpha(1f).setDuration(duration).setStartDelay(delay)
+ .setListener(new AnimatorListenerAdapter() {
+ @Override
+ public void onAnimationEnd(Animator animation) {
+ if (execOnEnd != null) execOnEnd.run();
+ }
+ }).start();
+ } else {
+ view.animate().alpha(0f)
+ .setDuration(duration).setStartDelay(delay)
+ .setListener(new AnimatorListenerAdapter() {
+ @Override
+ public void onAnimationEnd(Animator animation) {
+ view.setVisibility(View.GONE);
+ if (execOnEnd != null) execOnEnd.run();
+ }
+ })
+ .start();
+ }
+ }
+
+ protected void setErrorMessage(String message, boolean showRetryButton) {
+ if (errorTextView == null || activity == null) return;
+
+ errorTextView.setText(message);
+ if (showRetryButton) animateView(errorButtonRetry, true, 300);
+ else animateView(errorButtonRetry, false, 0);
+
+ animateView(errorPanel, true, 300);
+ isLoading.set(false);
+
+ animateView(loadingProgressBar, false, 200);
+ }
+
+ protected int getResourceIdFromAttr(@AttrRes int attr) {
+ TypedArray a = activity.getTheme().obtainStyledAttributes(new int[]{attr});
+ int attributeResourceId = a.getResourceId(0, 0);
+ a.recycle();
+ return attributeResourceId;
+ }
+
+ public static void showMenuTooltip(View v, String message) {
+ final int[] screenPos = new int[2];
+ final Rect displayFrame = new Rect();
+ v.getLocationOnScreen(screenPos);
+ v.getWindowVisibleDisplayFrame(displayFrame);
+
+ final Context context = v.getContext();
+ final int width = v.getWidth();
+ final int height = v.getHeight();
+ final int midy = screenPos[1] + height / 2;
+ int referenceX = screenPos[0] + width / 2;
+ if (ViewCompat.getLayoutDirection(v) == View.LAYOUT_DIRECTION_LTR) {
+ final int screenWidth = context.getResources().getDisplayMetrics().widthPixels;
+ referenceX = screenWidth - referenceX; // mirror
+ }
+ Toast cheatSheet = Toast.makeText(context, message, Toast.LENGTH_SHORT);
+ if (midy < displayFrame.height()) {
+ // Show along the top; follow action buttons
+ cheatSheet.setGravity(Gravity.TOP | Gravity.END, referenceX,
+ screenPos[1] + height - displayFrame.top);
+ } else {
+ // Show along the bottom center
+ cheatSheet.setGravity(Gravity.BOTTOM | Gravity.CENTER_HORIZONTAL, 0, height);
+ }
+ cheatSheet.show();
+ }
+}
diff --git a/app/src/main/java/org/schabi/newpipe/fragments/MainFragment.java b/app/src/main/java/org/schabi/newpipe/fragments/MainFragment.java
new file mode 100644
index 000000000..97563e15e
--- /dev/null
+++ b/app/src/main/java/org/schabi/newpipe/fragments/MainFragment.java
@@ -0,0 +1,76 @@
+package org.schabi.newpipe.fragments;
+
+import android.content.Context;
+import android.os.Bundle;
+import android.support.annotation.Nullable;
+import android.support.v4.app.Fragment;
+import android.support.v7.app.ActionBar;
+import android.support.v7.app.AppCompatActivity;
+import android.util.Log;
+import android.view.LayoutInflater;
+import android.view.Menu;
+import android.view.MenuInflater;
+import android.view.MenuItem;
+import android.view.View;
+import android.view.ViewGroup;
+
+import org.schabi.newpipe.MainActivity;
+import org.schabi.newpipe.R;
+import org.schabi.newpipe.util.NavigationHelper;
+
+public class MainFragment extends Fragment {
+ private final String TAG = "MainFragment@" + Integer.toHexString(hashCode());
+ private static final boolean DEBUG = MainActivity.DEBUG;
+
+ private AppCompatActivity activity;
+
+ /*//////////////////////////////////////////////////////////////////////////
+ // Fragment's LifeCycle
+ //////////////////////////////////////////////////////////////////////////*/
+
+ @Override
+ public void onAttach(Context context) {
+ super.onAttach(context);
+ if (DEBUG) Log.d(TAG, "onAttach() called with: context = [" + context + "]");
+ activity = ((AppCompatActivity) context);
+ }
+
+ @Override
+ public void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ if (DEBUG) Log.d(TAG, "onCreate() called with: savedInstanceState = [" + savedInstanceState + "]");
+ setHasOptionsMenu(true);
+ }
+
+ @Override
+ public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
+ if (DEBUG) Log.d(TAG, "onCreateView() called with: inflater = [" + inflater + "], container = [" + container + "], savedInstanceState = [" + savedInstanceState + "]");
+ return inflater.inflate(R.layout.fragment_main, container, false);
+ }
+
+ /*//////////////////////////////////////////////////////////////////////////
+ // Menu
+ //////////////////////////////////////////////////////////////////////////*/
+ @Override
+ public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
+ super.onCreateOptionsMenu(menu, inflater);
+ if (DEBUG) Log.d(TAG, "onCreateOptionsMenu() called with: menu = [" + menu + "], inflater = [" + inflater + "]");
+ inflater.inflate(R.menu.main_fragment_menu, menu);
+
+ ActionBar supportActionBar = activity.getSupportActionBar();
+ if (supportActionBar != null) {
+ supportActionBar.setDisplayShowTitleEnabled(false);
+ supportActionBar.setDisplayHomeAsUpEnabled(false);
+ }
+ }
+
+ @Override
+ public boolean onOptionsItemSelected(MenuItem item) {
+ switch (item.getItemId()) {
+ case R.id.action_search:
+ NavigationHelper.openSearch(activity, 0, "");
+ return true;
+ }
+ return super.onOptionsItemSelected(item);
+ }
+}
diff --git a/app/src/main/java/org/schabi/newpipe/fragments/channel/ChannelFragment.java b/app/src/main/java/org/schabi/newpipe/fragments/channel/ChannelFragment.java
index 52f42cf84..fa02dbfdb 100644
--- a/app/src/main/java/org/schabi/newpipe/fragments/channel/ChannelFragment.java
+++ b/app/src/main/java/org/schabi/newpipe/fragments/channel/ChannelFragment.java
@@ -1,6 +1,5 @@
package org.schabi.newpipe.fragments.channel;
-import android.content.Context;
import android.content.Intent;
import android.net.Uri;
import android.os.Bundle;
@@ -8,9 +7,9 @@ import android.support.annotation.Nullable;
import android.support.v4.app.Fragment;
import android.support.v4.content.ContextCompat;
import android.support.v7.app.ActionBar;
-import android.support.v7.app.AppCompatActivity;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;
+import android.text.TextUtils;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.Menu;
@@ -20,222 +19,144 @@ import android.view.View;
import android.view.ViewGroup;
import android.widget.Button;
import android.widget.ImageView;
-import android.widget.ProgressBar;
import android.widget.TextView;
-import android.widget.Toast;
-
-import com.nostra13.universalimageloader.core.ImageLoader;
import org.schabi.newpipe.ImageErrorLoadingListener;
import org.schabi.newpipe.R;
-import org.schabi.newpipe.extractor.NewPipe;
+import org.schabi.newpipe.extractor.InfoItem;
import org.schabi.newpipe.extractor.channel.ChannelInfo;
-import org.schabi.newpipe.fragments.OnItemSelectedListener;
+import org.schabi.newpipe.fragments.BaseFragment;
import org.schabi.newpipe.info_list.InfoItemBuilder;
import org.schabi.newpipe.info_list.InfoListAdapter;
-import org.schabi.newpipe.report.ErrorActivity;
import org.schabi.newpipe.util.Constants;
import org.schabi.newpipe.util.NavigationHelper;
import org.schabi.newpipe.workers.ChannelExtractorWorker;
+import java.io.Serializable;
import java.text.NumberFormat;
+import java.util.ArrayList;
-import static android.os.Build.VERSION.SDK_INT;
+public class ChannelFragment extends BaseFragment implements ChannelExtractorWorker.OnChannelInfoReceive {
+ private final String TAG = "ChannelFragment@" + Integer.toHexString(hashCode());
+ private static final String INFO_LIST_KEY = "info_list_key";
+ private static final String CHANNEL_INFO_KEY = "channel_info_key";
+ private static final String PAGE_NUMBER_KEY = "page_number_key";
-/**
- * Copyright (C) Christian Schabesberger 2016
- * ChannelFragment.java is part of NewPipe.
- *
- * NewPipe 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.
- *
- * NewPipe 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 NewPipe. If not, see .
- */
-
-public class ChannelFragment extends Fragment implements ChannelExtractorWorker.OnChannelInfoReceive {
- private static final String TAG = "ChannelFragment";
-
- private AppCompatActivity activity;
- private OnItemSelectedListener onItemSelectedListener;
private InfoListAdapter infoListAdapter;
- private ChannelExtractorWorker currentExtractorWorker;
+ private ChannelExtractorWorker currentChannelWorker;
private ChannelInfo currentChannelInfo;
private int serviceId = -1;
private String channelName = "";
private String channelUrl = "";
-
- private boolean isLoading = false;
private int pageNumber = 0;
private boolean hasNextPage = true;
- private ImageLoader imageLoader = ImageLoader.getInstance();
-
/*//////////////////////////////////////////////////////////////////////////
// Views
//////////////////////////////////////////////////////////////////////////*/
- private View rootView = null;
-
private RecyclerView channelVideosList;
- private LinearLayoutManager layoutManager;
- private ProgressBar loadingProgressBar;
private View headerRootLayout;
private ImageView headerChannelBanner;
private ImageView headerAvatarView;
private TextView headerTitleView;
- private TextView headerSubscriberView;
- private Button headerSubscriberButton;
- private View headerSubscriberLayout;
+ private TextView headerSubscribersTextView;
+ private Button headerRssButton;
/*////////////////////////////////////////////////////////////////////////*/
public ChannelFragment() {
}
- public static ChannelFragment newInstance(int serviceId, String url, String name) {
- ChannelFragment instance = newInstance();
-
- Bundle bundle = new Bundle();
- bundle.putString(Constants.KEY_URL, url);
- bundle.putString(Constants.KEY_TITLE, name);
- bundle.putInt(Constants.KEY_SERVICE_ID, serviceId);
-
- instance.setArguments(bundle);
+ public static Fragment getInstance(int serviceId, String channelUrl, String name) {
+ ChannelFragment instance = new ChannelFragment();
+ instance.setChannel(serviceId, channelUrl, name);
return instance;
}
- public static ChannelFragment newInstance() {
- return new ChannelFragment();
- }
-
/*//////////////////////////////////////////////////////////////////////////
// Fragment's LifeCycle
//////////////////////////////////////////////////////////////////////////*/
- @Override
- public void onAttach(Context context) {
- super.onAttach(context);
- activity = ((AppCompatActivity) context);
- onItemSelectedListener = ((OnItemSelectedListener) context);
- }
-
@Override
public void onCreate(Bundle savedInstanceState) {
+ if (DEBUG) Log.d(TAG, "onCreate() called with: savedInstanceState = [" + savedInstanceState + "]");
super.onCreate(savedInstanceState);
setHasOptionsMenu(true);
- isLoading = false;
if (savedInstanceState != null) {
channelUrl = savedInstanceState.getString(Constants.KEY_URL);
channelName = savedInstanceState.getString(Constants.KEY_TITLE);
serviceId = savedInstanceState.getInt(Constants.KEY_SERVICE_ID, -1);
- } else {
- try {
- Bundle args = getArguments();
- if (args != null) {
- channelUrl = args.getString(Constants.KEY_URL);
- channelName = args.getString(Constants.KEY_TITLE);
- serviceId = args.getInt(Constants.KEY_SERVICE_ID, 0);
- }
- } catch (Exception e) {
- e.printStackTrace();
- ErrorActivity.reportError(getActivity(), e, null,
- getActivity().findViewById(android.R.id.content),
- ErrorActivity.ErrorInfo.make(ErrorActivity.SEARCHED,
- NewPipe.getNameOfService(serviceId),
- "", R.string.general_error));
- }
+
+ pageNumber = savedInstanceState.getInt(PAGE_NUMBER_KEY, 0);
+ Serializable serializable = savedInstanceState.getSerializable(CHANNEL_INFO_KEY);
+ if (serializable instanceof ChannelInfo) currentChannelInfo = (ChannelInfo) serializable;
}
}
@Override
public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
- rootView = inflater.inflate(R.layout.fragment_channel, container, false);
- return rootView;
+ if (DEBUG) Log.d(TAG, "onCreateView() called with: inflater = [" + inflater + "], container = [" + container + "], savedInstanceState = [" + savedInstanceState + "]");
+ return inflater.inflate(R.layout.fragment_channel, container, false);
}
@Override
public void onViewCreated(View view, @Nullable Bundle savedInstanceState) {
- loadingProgressBar = (ProgressBar) view.findViewById(R.id.loading_progress_bar);
- channelVideosList = (RecyclerView) view.findViewById(R.id.channel_streams_view);
+ super.onViewCreated(view, savedInstanceState);
- infoListAdapter = new InfoListAdapter(activity, rootView);
- layoutManager = new LinearLayoutManager(activity);
- channelVideosList.setLayoutManager(layoutManager);
-
- headerRootLayout = activity.getLayoutInflater().inflate(R.layout.channel_header, channelVideosList, false);
- infoListAdapter.setHeader(headerRootLayout);
- infoListAdapter.setFooter(activity.getLayoutInflater().inflate(R.layout.pignate_footer, channelVideosList, false));
- channelVideosList.setAdapter(infoListAdapter);
-
- headerChannelBanner = (ImageView) headerRootLayout.findViewById(R.id.channel_banner_image);
- headerAvatarView = (ImageView) headerRootLayout.findViewById(R.id.channel_avatar_view);
- headerTitleView = (TextView) headerRootLayout.findViewById(R.id.channel_title_view);
- headerSubscriberView = (TextView) headerRootLayout.findViewById(R.id.channel_subscriber_view);
- headerSubscriberButton = (Button) headerRootLayout.findViewById(R.id.channel_subscribe_button);
- headerSubscriberLayout = headerRootLayout.findViewById(R.id.channel_subscriber_layout);
-
- initListeners();
-
- isLoading = true;
+ if (currentChannelInfo == null) loadPage(0);
+ else handleChannelInfo(currentChannelInfo, false, false);
}
@Override
public void onDestroyView() {
- super.onDestroyView();
+ if (DEBUG) Log.d(TAG, "onDestroyView() called");
headerAvatarView.setImageBitmap(null);
headerChannelBanner.setImageBitmap(null);
channelVideosList.removeAllViews();
- rootView = null;
channelVideosList = null;
- layoutManager = null;
- loadingProgressBar = null;
headerRootLayout = null;
headerChannelBanner = null;
headerAvatarView = null;
headerTitleView = null;
- headerSubscriberView = null;
- headerSubscriberButton = null;
- headerSubscriberLayout = null;
+ headerSubscribersTextView = null;
+ headerRssButton = null;
+
+ super.onDestroyView();
}
@Override
public void onResume() {
+ if (DEBUG) Log.d(TAG, "onResume() called");
super.onResume();
- if (isLoading) {
- requestData(false);
+ if (wasLoading.getAndSet(false) && (currentChannelWorker == null || !currentChannelWorker.isRunning())) {
+ loadPage(pageNumber);
}
}
@Override
public void onStop() {
+ if (DEBUG) Log.d(TAG, "onStop() called");
super.onStop();
- if (currentExtractorWorker != null) currentExtractorWorker.cancel();
- }
-
- @Override
- public void onDestroy() {
- super.onDestroy();
- imageLoader.clearMemoryCache();
+ wasLoading.set(currentChannelWorker != null && currentChannelWorker.isRunning());
+ if (currentChannelWorker != null && currentChannelWorker.isRunning()) currentChannelWorker.cancel();
}
@Override
public void onSaveInstanceState(Bundle outState) {
+ if (DEBUG) Log.d(TAG, "onSaveInstanceState() called with: outState = [" + outState + "]");
super.onSaveInstanceState(outState);
outState.putString(Constants.KEY_URL, channelUrl);
outState.putString(Constants.KEY_TITLE, channelName);
outState.putInt(Constants.KEY_SERVICE_ID, serviceId);
+
+ outState.putSerializable(INFO_LIST_KEY, ((ArrayList) infoListAdapter.getItemsList()));
+ outState.putSerializable(CHANNEL_INFO_KEY, currentChannelInfo);
+ outState.putInt(PAGE_NUMBER_KEY, pageNumber);
}
/*//////////////////////////////////////////////////////////////////////////
@@ -243,6 +164,7 @@ public class ChannelFragment extends Fragment implements ChannelExtractorWorker.
//////////////////////////////////////////////////////////////////////////*/
@Override
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
+ if (DEBUG) Log.d(TAG, "onCreateOptionsMenu() called with: menu = [" + menu + "], inflater = [" + inflater + "]");
super.onCreateOptionsMenu(menu, inflater);
inflater.inflate(R.menu.menu_channel, menu);
@@ -250,20 +172,18 @@ public class ChannelFragment extends Fragment implements ChannelExtractorWorker.
if (supportActionBar != null) {
supportActionBar.setDisplayShowTitleEnabled(true);
supportActionBar.setDisplayHomeAsUpEnabled(true);
- //noinspection deprecation
- supportActionBar.setNavigationMode(0);
}
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
+ if (DEBUG) Log.d(TAG, "onOptionsItemSelected() called with: item = [" + item + "]");
super.onOptionsItemSelected(item);
switch (item.getItemId()) {
case R.id.menu_item_openInBrowser: {
Intent intent = new Intent();
intent.setAction(Intent.ACTION_VIEW);
intent.setData(Uri.parse(channelUrl));
-
startActivity(Intent.createChooser(intent, getString(R.string.choose_browser)));
return true;
}
@@ -283,79 +203,185 @@ public class ChannelFragment extends Fragment implements ChannelExtractorWorker.
// Init's
//////////////////////////////////////////////////////////////////////////*/
- private void initListeners() {
+ @Override
+ protected void initViews(View rootView, Bundle savedInstanceState) {
+ super.initViews(rootView, savedInstanceState);
+
+ channelVideosList = (RecyclerView) rootView.findViewById(R.id.channel_streams_view);
+
+ channelVideosList.setLayoutManager(new LinearLayoutManager(activity));
+ if (infoListAdapter == null) {
+ infoListAdapter = new InfoListAdapter(activity, rootView);
+ if (savedInstanceState != null) {
+ //noinspection unchecked
+ ArrayList serializable = (ArrayList) savedInstanceState.getSerializable(INFO_LIST_KEY);
+ infoListAdapter.addInfoItemList(serializable);
+ }
+ }
+
+ channelVideosList.setAdapter(infoListAdapter);
+ headerRootLayout = activity.getLayoutInflater().inflate(R.layout.channel_header, channelVideosList, false);
+ infoListAdapter.setHeader(headerRootLayout);
+ infoListAdapter.setFooter(activity.getLayoutInflater().inflate(R.layout.pignate_footer, channelVideosList, false));
+
+ headerChannelBanner = (ImageView) headerRootLayout.findViewById(R.id.channel_banner_image);
+ headerAvatarView = (ImageView) headerRootLayout.findViewById(R.id.channel_avatar_view);
+ headerTitleView = (TextView) headerRootLayout.findViewById(R.id.channel_title_view);
+ headerSubscribersTextView = (TextView) headerRootLayout.findViewById(R.id.channel_subscriber_view);
+ headerRssButton = (Button) headerRootLayout.findViewById(R.id.channel_rss_button);
+ }
+
+ protected void initListeners() {
+ super.initListeners();
+
infoListAdapter.setOnStreamInfoItemSelectedListener(new InfoItemBuilder.OnInfoItemSelectedListener() {
@Override
public void selected(int serviceId, String url, String title) {
+ if (DEBUG) Log.d(TAG, "selected() called with: serviceId = [" + serviceId + "], url = [" + url + "], title = [" + title + "]");
NavigationHelper.openVideoDetail(onItemSelectedListener, serviceId, url, title);
}
});
- // detect if list has ben scrolled to the bottom
- channelVideosList.setOnScrollListener(new RecyclerView.OnScrollListener() {
+ channelVideosList.clearOnScrollListeners();
+ channelVideosList.addOnScrollListener(new RecyclerView.OnScrollListener() {
@Override
public void onScrolled(RecyclerView recyclerView, int dx, int dy) {
int pastVisiblesItems, visibleItemCount, totalItemCount;
super.onScrolled(recyclerView, dx, dy);
//check for scroll down
if (dy > 0) {
+ LinearLayoutManager layoutManager = (LinearLayoutManager) channelVideosList.getLayoutManager();
+
visibleItemCount = layoutManager.getChildCount();
totalItemCount = layoutManager.getItemCount();
pastVisiblesItems = layoutManager.findFirstVisibleItemPosition();
- if ((visibleItemCount + pastVisiblesItems) >= totalItemCount && !currentExtractorWorker.isRunning() && hasNextPage) {
+ if ((visibleItemCount + pastVisiblesItems) >= totalItemCount && (currentChannelWorker == null || !currentChannelWorker.isRunning()) && hasNextPage && !isLoading.get()) {
pageNumber++;
- requestData(true);
+ loadMoreVideos();
}
}
}
});
- headerSubscriberButton.setOnClickListener(new View.OnClickListener() {
+ headerRssButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
- Log.d(TAG, currentChannelInfo.feed_url);
+ if (DEBUG) Log.d(TAG, "onClick() called with: view = [" + view + "] feed url > " + currentChannelInfo.feed_url);
Intent i = new Intent(Intent.ACTION_VIEW, Uri.parse(currentChannelInfo.feed_url));
startActivity(i);
}
});
}
+ @Override
+ protected void reloadContent() {
+ if (DEBUG) Log.d(TAG, "reloadContent() called");
+ currentChannelInfo = null;
+ infoListAdapter.clearStreamItemList();
+ loadPage(0);
+ }
+
/*//////////////////////////////////////////////////////////////////////////
// Utils
//////////////////////////////////////////////////////////////////////////*/
+
private String buildSubscriberString(long count) {
String out = NumberFormat.getNumberInstance().format(count);
out += " " + getString(count > 1 ? R.string.subscriber_plural : R.string.subscriber);
return out;
}
- private void requestData(boolean onlyVideos) {
- if (currentExtractorWorker != null && currentExtractorWorker.isRunning()) currentExtractorWorker.cancel();
+ private void loadPage(int page) {
+ if (DEBUG) Log.d(TAG, "loadPage() called with: page = [" + page + "]");
+ if (currentChannelWorker != null && currentChannelWorker.isRunning()) currentChannelWorker.cancel();
+ isLoading.set(true);
+ pageNumber = page;
+ infoListAdapter.showFooter(false);
- isLoading = true;
- if (!onlyVideos) {
- //delete already displayed content
- loadingProgressBar.setVisibility(View.VISIBLE);
- infoListAdapter.clearSteamItemList();
- pageNumber = 0;
- headerSubscriberLayout.setVisibility(View.GONE);
- headerTitleView.setText(channelName != null ? channelName : "");
- if (activity.getSupportActionBar() != null) activity.getSupportActionBar().setTitle(channelName != null ? channelName : "");
- if (SDK_INT >= 21) {
- headerChannelBanner.setImageDrawable(ContextCompat.getDrawable(activity, R.drawable.channel_banner));
- headerAvatarView.setImageDrawable(ContextCompat.getDrawable(activity, R.drawable.buddy));
- }
- infoListAdapter.showFooter(false);
- }
+ animateView(loadingProgressBar, true, 200);
+ animateView(errorPanel, false, 200);
- currentExtractorWorker = new ChannelExtractorWorker(activity, serviceId, channelUrl, pageNumber, this);
- currentExtractorWorker.setOnlyVideos(onlyVideos);
- currentExtractorWorker.start();
+ imageLoader.cancelDisplayTask(headerChannelBanner);
+ imageLoader.cancelDisplayTask(headerAvatarView);
+
+ headerRssButton.setVisibility(View.GONE);
+ headerSubscribersTextView.setVisibility(View.GONE);
+
+ headerTitleView.setText(channelName != null ? channelName : "");
+ headerChannelBanner.setImageDrawable(ContextCompat.getDrawable(activity, R.drawable.channel_banner));
+ headerAvatarView.setImageDrawable(ContextCompat.getDrawable(activity, R.drawable.buddy));
+ if (activity.getSupportActionBar() != null) activity.getSupportActionBar().setTitle(channelName != null ? channelName : "");
+
+ currentChannelWorker = new ChannelExtractorWorker(activity, serviceId, channelUrl, page, false, this);
+ currentChannelWorker.start();
}
- private void addVideos(ChannelInfo info) {
- infoListAdapter.addInfoItemList(info.related_streams);
+ private void loadMoreVideos() {
+ if (DEBUG) Log.d(TAG, "loadMoreVideos() called");
+ if (currentChannelWorker != null && currentChannelWorker.isRunning()) currentChannelWorker.cancel();
+ isLoading.set(true);
+ currentChannelWorker = new ChannelExtractorWorker(activity, serviceId, channelUrl, pageNumber, true, this);
+ currentChannelWorker.start();
+ }
+
+ private void setChannel(int serviceId, String channelUrl, String name) {
+ this.serviceId = serviceId;
+ this.channelUrl = channelUrl;
+ this.channelName = name;
+ }
+
+ private void handleChannelInfo(ChannelInfo info, boolean onlyVideos, boolean addVideos) {
+ currentChannelInfo = info;
+
+ animateView(errorPanel, false, 300);
+ animateView(channelVideosList, true, 200);
+ animateView(loadingProgressBar, false, 200);
+
+ if (!onlyVideos) {
+ headerRootLayout.setVisibility(View.VISIBLE);
+ //animateView(loadingProgressBar, false, 200, null);
+
+ if (!TextUtils.isEmpty(info.channel_name)) {
+ if (activity.getSupportActionBar() != null) activity.getSupportActionBar().setTitle(info.channel_name);
+ headerTitleView.setText(info.channel_name);
+ channelName = info.channel_name;
+ } else channelName = "";
+
+ if (!TextUtils.isEmpty(info.banner_url)) {
+ imageLoader.displayImage(info.banner_url, headerChannelBanner, displayImageOptions, new ImageErrorLoadingListener(activity, getView(), info.service_id));
+ }
+
+ if (!TextUtils.isEmpty(info.avatar_url)) {
+ headerAvatarView.setVisibility(View.VISIBLE);
+ imageLoader.displayImage(info.avatar_url, headerAvatarView, displayImageOptions, new ImageErrorLoadingListener(activity, getView(), info.service_id));
+ }
+
+ if (info.subscriberCount != -1) {
+ headerSubscribersTextView.setText(buildSubscriberString(info.subscriberCount));
+ headerSubscribersTextView.setVisibility(View.VISIBLE);
+ } else headerSubscribersTextView.setVisibility(View.GONE);
+
+ if (!TextUtils.isEmpty(info.feed_url)) headerRssButton.setVisibility(View.VISIBLE);
+ else headerRssButton.setVisibility(View.INVISIBLE);
+
+ infoListAdapter.showFooter(true);
+ }
+
+ hasNextPage = info.hasNextPage;
+ if (!hasNextPage) infoListAdapter.showFooter(false);
+
+ //if (!listRestored) {
+ if (addVideos) infoListAdapter.addInfoItemList(info.related_streams);
+ //}
+ }
+
+ @Override
+ protected void setErrorMessage(String message, boolean showRetryButton) {
+ super.setErrorMessage(message, showRetryButton);
+
+ animateView(channelVideosList, false, 200);
+ currentChannelInfo = null;
}
/*//////////////////////////////////////////////////////////////////////////
@@ -363,59 +389,23 @@ public class ChannelFragment extends Fragment implements ChannelExtractorWorker.
//////////////////////////////////////////////////////////////////////////*/
@Override
- public void onReceive(ChannelInfo info) {
+ public void onReceive(ChannelInfo info, boolean onlyVideos) {
+ if (DEBUG) Log.d(TAG, "onReceive() called with: info = [" + info + "]");
if (info == null || isRemoving() || !isVisible()) return;
- currentChannelInfo = info;
-
- if (!currentExtractorWorker.isOnlyVideos()) {
- headerRootLayout.setVisibility(View.VISIBLE);
- loadingProgressBar.setVisibility(View.GONE);
-
- if (info.channel_name != null && !info.channel_name.isEmpty()) {
- if (activity.getSupportActionBar() != null) activity.getSupportActionBar().setTitle(info.channel_name);
- headerTitleView.setText(info.channel_name);
- channelName = info.channel_name;
- } else channelName = "";
-
- if (info.banner_url != null && !info.banner_url.isEmpty()) {
- imageLoader.displayImage(info.banner_url, headerChannelBanner,
- new ImageErrorLoadingListener(activity, rootView, info.service_id));
- }
-
- if (info.avatar_url != null && !info.avatar_url.isEmpty()) {
- headerAvatarView.setVisibility(View.VISIBLE);
- imageLoader.displayImage(info.avatar_url, headerAvatarView,
- new ImageErrorLoadingListener(activity, rootView, info.service_id));
- }
-
- if (info.subscriberCount != -1) {
- headerSubscriberView.setText(buildSubscriberString(info.subscriberCount));
- }
-
- if ((info.feed_url != null && !info.feed_url.isEmpty()) || (info.subscriberCount != -1)) {
- headerSubscriberLayout.setVisibility(View.VISIBLE);
- }
-
- if (info.feed_url == null || info.feed_url.isEmpty()) {
- headerSubscriberButton.setVisibility(View.INVISIBLE);
- }
-
- infoListAdapter.showFooter(true);
- }
- hasNextPage = info.hasNextPage;
- if (!hasNextPage) infoListAdapter.showFooter(false);
- addVideos(info);
- isLoading = false;
+ handleChannelInfo(info, onlyVideos, true);
+ isLoading.set(false);
}
@Override
public void onError(int messageId) {
- Toast.makeText(activity, messageId, Toast.LENGTH_LONG).show();
+ if (DEBUG) Log.d(TAG, "onError() called with: messageId = [" + messageId + "]");
+ setErrorMessage(getString(messageId), true);
}
@Override
public void onUnrecoverableError(Exception exception) {
+ if (DEBUG) Log.d(TAG, "onUnrecoverableError() called with: exception = [" + exception + "]");
activity.finish();
}
}
diff --git a/app/src/main/java/org/schabi/newpipe/fragments/detail/ActionBarHandler.java b/app/src/main/java/org/schabi/newpipe/fragments/detail/ActionBarHandler.java
index 007cb0082..3805c30e7 100644
--- a/app/src/main/java/org/schabi/newpipe/fragments/detail/ActionBarHandler.java
+++ b/app/src/main/java/org/schabi/newpipe/fragments/detail/ActionBarHandler.java
@@ -2,13 +2,15 @@ package org.schabi.newpipe.fragments.detail;
import android.content.SharedPreferences;
import android.preference.PreferenceManager;
-import android.support.v7.app.ActionBar;
import android.support.v7.app.AppCompatActivity;
import android.util.Log;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
+import android.view.View;
+import android.widget.AdapterView;
import android.widget.ArrayAdapter;
+import android.widget.Spinner;
import org.schabi.newpipe.R;
import org.schabi.newpipe.extractor.MediaFormat;
@@ -19,27 +21,27 @@ import java.util.List;
/**
* Created by Christian Schabesberger on 18.08.15.
- *
+ *
* Copyright (C) Christian Schabesberger 2015
* DetailsMenuHandler.java is part of NewPipe.
- *
+ *
* NewPipe 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.
- *
+ *
* NewPipe 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 NewPipe. If not, see .
*/
class ActionBarHandler {
- private static final String TAG = ActionBarHandler.class.toString();
+ private static final String TAG = "ActionBarHandler";
private AppCompatActivity activity;
private int selectedVideoStream = -1;
@@ -52,11 +54,8 @@ class ActionBarHandler {
// those are edited directly. Typically VideoDetailFragment will implement those callbacks.
private OnActionListener onShareListener;
private OnActionListener onOpenInBrowserListener;
- private OnActionListener onOpenInPopupListener;
private OnActionListener onDownloadListener;
private OnActionListener onPlayWithKodiListener;
- private OnActionListener onPlayAudioListener;
-
// Triggered when a stream related action is triggered.
public interface OnActionListener {
@@ -67,46 +66,32 @@ class ActionBarHandler {
this.activity = activity;
}
- @SuppressWarnings({"deprecation", "ConstantConditions"})
- public void setupNavMenu(AppCompatActivity activity) {
- this.activity = activity;
- try {
- activity.getSupportActionBar().setNavigationMode(ActionBar.NAVIGATION_MODE_LIST);
- } catch (NullPointerException e) {
- e.printStackTrace();
+ public void setupStreamList(final List videoStreams, Spinner toolbarSpinner) {
+ if (activity == null) return;
+ selectedVideoStream = 0;
+
+ // this array will be shown in the dropdown menu for selecting the stream/resolution.
+ String[] itemArray = new String[videoStreams.size()];
+ for (int i = 0; i < videoStreams.size(); i++) {
+ VideoStream item = videoStreams.get(i);
+ itemArray[i] = MediaFormat.getNameById(item.format) + " " + item.resolution;
}
- }
- public void setupStreamList(final List videoStreams) {
- if (activity != null) {
- selectedVideoStream = 0;
-
-
- // this array will be shown in the dropdown menu for selecting the stream/resolution.
- String[] itemArray = new String[videoStreams.size()];
- for (int i = 0; i < videoStreams.size(); i++) {
- VideoStream item = videoStreams.get(i);
- itemArray[i] = MediaFormat.getNameById(item.format) + " " + item.resolution;
+ int defaultResolutionIndex = Utils.getDefaultResolution(activity, videoStreams);
+ ArrayAdapter itemAdapter = new ArrayAdapter<>(activity.getBaseContext(), android.R.layout.simple_spinner_dropdown_item, itemArray);
+ toolbarSpinner.setAdapter(itemAdapter);
+ toolbarSpinner.setSelection(defaultResolutionIndex);
+ toolbarSpinner.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
+ @Override
+ public void onItemSelected(AdapterView> parent, View view, int position, long id) {
+ selectedVideoStream = position;
}
- int defaultResolution = Utils.getDefaultResolution(activity, videoStreams);
- ArrayAdapter itemAdapter = new ArrayAdapter<>(activity.getBaseContext(),
- android.R.layout.simple_spinner_dropdown_item, itemArray);
+ @Override
+ public void onNothingSelected(AdapterView> parent) {
+ }
+ });
- ActionBar ab = activity.getSupportActionBar();
- //todo: make this throwsable
- assert ab != null : "Could not get actionbar";
- ab.setListNavigationCallbacks(itemAdapter
- , new ActionBar.OnNavigationListener() {
- @Override
- public boolean onNavigationItemSelected(int itemPosition, long itemId) {
- selectedVideoStream = (int) itemId;
- return true;
- }
- });
-
- ab.setSelectedNavigationItem(defaultResolution);
- }
}
public void setupMenu(Menu menu, MenuInflater inflater) {
@@ -116,55 +101,36 @@ class ActionBarHandler {
// appcompat itemsinflater.inflate(R.menu.videoitem_detail, menu);
defaultPreferences = PreferenceManager.getDefaultSharedPreferences(activity);
- inflater.inflate(R.menu.videoitem_detail, menu);
+ inflater.inflate(R.menu.video_detail_menu, menu);
- showPlayWithKodiAction(defaultPreferences
- .getBoolean(activity.getString(R.string.show_play_with_kodi_key), false));
+ showPlayWithKodiAction(defaultPreferences.getBoolean(activity.getString(R.string.show_play_with_kodi_key), false));
}
public boolean onItemSelected(MenuItem item) {
int id = item.getItemId();
switch (id) {
case R.id.menu_item_share: {
- /*
- Intent intent = new Intent();
- intent.setAction(Intent.ACTION_SEND);
- intent.putExtra(Intent.EXTRA_TEXT, websiteUrl);
- intent.setType("text/plain");
- activity.startActivity(Intent.createChooser(intent, activity.getString(R.string.share_dialog_title)));
- */
- if(onShareListener != null) {
+ if (onShareListener != null) {
onShareListener.onActionSelected(selectedVideoStream);
}
return true;
}
case R.id.menu_item_openInBrowser: {
- if(onOpenInBrowserListener != null) {
+ if (onOpenInBrowserListener != null) {
onOpenInBrowserListener.onActionSelected(selectedVideoStream);
}
+ return true;
}
- return true;
case R.id.menu_item_download:
- if(onDownloadListener != null) {
+ if (onDownloadListener != null) {
onDownloadListener.onActionSelected(selectedVideoStream);
}
return true;
case R.id.action_play_with_kodi:
- if(onPlayWithKodiListener != null) {
+ if (onPlayWithKodiListener != null) {
onPlayWithKodiListener.onActionSelected(selectedVideoStream);
}
return true;
- case R.id.menu_item_play_audio:
- if(onPlayAudioListener != null) {
- onPlayAudioListener.onActionSelected(selectedVideoStream);
- }
- return true;
- case R.id.menu_item_popup: {
- if(onOpenInPopupListener != null) {
- onOpenInPopupListener.onActionSelected(selectedVideoStream);
- }
- return true;
- }
default:
Log.e(TAG, "Menu Item not known");
}
@@ -183,10 +149,6 @@ class ActionBarHandler {
onOpenInBrowserListener = listener;
}
- public void setOnOpenInPopupListener(OnActionListener listener) {
- onOpenInPopupListener = listener;
- }
-
public void setOnDownloadListener(OnActionListener listener) {
onDownloadListener = listener;
}
@@ -195,14 +157,6 @@ class ActionBarHandler {
onPlayWithKodiListener = listener;
}
- public void setOnPlayAudioListener(OnActionListener listener) {
- onPlayAudioListener = listener;
- }
-
- public void showAudioAction(boolean visible) {
- menu.findItem(R.id.menu_item_play_audio).setVisible(visible);
- }
-
public void showDownloadAction(boolean visible) {
menu.findItem(R.id.menu_item_download).setVisible(visible);
}
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 e335be1e3..647637fec 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
@@ -1,11 +1,14 @@
package org.schabi.newpipe.fragments.detail;
+import org.schabi.newpipe.extractor.stream_info.StreamInfo;
+
import java.io.Serializable;
@SuppressWarnings("WeakerAccess")
public class StackItem implements Serializable {
private String title, url;
+ private StreamInfo info;
public StackItem(String url, String title) {
this.title = title;
@@ -24,6 +27,14 @@ public class StackItem implements Serializable {
return url;
}
+ public void setInfo(StreamInfo info) {
+ this.info = info;
+ }
+
+ public StreamInfo getInfo() {
+ return info;
+ }
+
@Override
public String toString() {
return getUrl() + " > " + getTitle();
diff --git a/app/src/main/java/org/schabi/newpipe/fragments/detail/StreamInfoCache.java b/app/src/main/java/org/schabi/newpipe/fragments/detail/StreamInfoCache.java
new file mode 100644
index 000000000..c7bf80245
--- /dev/null
+++ b/app/src/main/java/org/schabi/newpipe/fragments/detail/StreamInfoCache.java
@@ -0,0 +1,85 @@
+package org.schabi.newpipe.fragments.detail;
+
+import android.support.annotation.NonNull;
+import android.text.TextUtils;
+import android.util.Log;
+
+import org.schabi.newpipe.MainActivity;
+import org.schabi.newpipe.extractor.stream_info.StreamInfo;
+
+import java.util.Iterator;
+import java.util.LinkedHashMap;
+
+
+@SuppressWarnings("WeakerAccess")
+public class StreamInfoCache {
+ private static String TAG = "StreamInfoCache@";
+ private static final boolean DEBUG = MainActivity.DEBUG;
+ private static final StreamInfoCache instance = new StreamInfoCache();
+ private static final int MAX_ITEMS_ON_CACHE = 20;
+
+ private final LinkedHashMap myCache = new LinkedHashMap<>();
+
+ private StreamInfoCache() {
+ TAG += "" + Integer.toHexString(hashCode());
+ }
+
+ public static StreamInfoCache getInstance() {
+ if (DEBUG) Log.d(TAG, "getInstance() called");
+ return instance;
+ }
+
+ public boolean hasKey(@NonNull String url) {
+ if (DEBUG) Log.d(TAG, "hasKey() called with: url = [" + url + "]");
+ return !TextUtils.isEmpty(url) && myCache.containsKey(url) && myCache.get(url) != null;
+ }
+
+ public StreamInfo getFromKey(@NonNull String url) {
+ if (DEBUG) Log.d(TAG, "getFromKey() called with: url = [" + url + "]");
+ return myCache.get(url);
+ }
+
+ public void putInfo(@NonNull StreamInfo info) {
+ if (DEBUG) Log.d(TAG, "putInfo() called with: info = [" + info + "]");
+ putInfo(info.webpage_url, info);
+ }
+
+ public void putInfo(@NonNull String url, @NonNull StreamInfo info) {
+ if (DEBUG) Log.d(TAG, "putInfo() called with: url = [" + url + "], info = [" + info + "]");
+ myCache.put(url, info);
+ }
+
+ public void removeInfo(@NonNull StreamInfo info) {
+ if (DEBUG) Log.d(TAG, "removeInfo() called with: info = [" + info + "]");
+ myCache.remove(info.webpage_url);
+ }
+
+ public void removeInfo(@NonNull String url) {
+ if (DEBUG) Log.d(TAG, "removeInfo() called with: url = [" + url + "]");
+ myCache.remove(url);
+ }
+
+ @SuppressWarnings("unused")
+ public void clearCache() {
+ if (DEBUG) Log.d(TAG, "clearCache() called");
+ myCache.clear();
+ }
+
+ public void removeOldEntries() {
+ if (DEBUG) Log.d(TAG, "removeOldEntries() called , size = " + getSize());
+ if (getSize() > MAX_ITEMS_ON_CACHE) {
+ Iterator iterator = myCache.keySet().iterator();
+ while (iterator.hasNext()) {
+ iterator.next();
+ iterator.remove();
+ if (DEBUG) Log.d(TAG, "getSize() = " + getSize());
+ if (getSize() <= MAX_ITEMS_ON_CACHE) break;
+ }
+ }
+ }
+
+ public int getSize() {
+ return myCache.size();
+ }
+
+}
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 611b90d28..f7469e8fd 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
@@ -1,23 +1,19 @@
package org.schabi.newpipe.fragments.detail;
-import android.animation.Animator;
-import android.animation.AnimatorListenerAdapter;
import android.app.Activity;
-import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.SharedPreferences;
-import android.media.AudioManager;
import android.net.Uri;
import android.os.Build;
import android.os.Bundle;
import android.preference.PreferenceManager;
-import android.support.v4.app.Fragment;
+import android.support.annotation.NonNull;
import android.support.v4.content.ContextCompat;
import android.support.v7.app.ActionBar;
import android.support.v7.app.AlertDialog;
-import android.support.v7.app.AppCompatActivity;
import android.text.Html;
+import android.text.TextUtils;
import android.text.method.LinkMovementMethod;
import android.util.Log;
import android.util.TypedValue;
@@ -28,18 +24,16 @@ import android.view.MenuItem;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Button;
+import android.widget.ImageButton;
import android.widget.ImageView;
import android.widget.LinearLayout;
-import android.widget.ProgressBar;
import android.widget.RelativeLayout;
+import android.widget.Spinner;
import android.widget.TextView;
import android.widget.Toast;
import com.nirhart.parallaxscroll.views.ParallaxScrollView;
-import com.nostra13.universalimageloader.core.DisplayImageOptions;
-import com.nostra13.universalimageloader.core.ImageLoader;
import com.nostra13.universalimageloader.core.assist.FailReason;
-import com.nostra13.universalimageloader.core.display.FadeInBitmapDisplayer;
import com.nostra13.universalimageloader.core.listener.SimpleImageLoadingListener;
import org.schabi.newpipe.ImageErrorLoadingListener;
@@ -53,7 +47,7 @@ import org.schabi.newpipe.extractor.NewPipe;
import org.schabi.newpipe.extractor.stream_info.AudioStream;
import org.schabi.newpipe.extractor.stream_info.StreamInfo;
import org.schabi.newpipe.extractor.stream_info.VideoStream;
-import org.schabi.newpipe.fragments.OnItemSelectedListener;
+import org.schabi.newpipe.fragments.BaseFragment;
import org.schabi.newpipe.info_list.InfoItemBuilder;
import org.schabi.newpipe.player.MainVideoPlayer;
import org.schabi.newpipe.player.PlayVideoActivity;
@@ -67,23 +61,27 @@ import org.schabi.newpipe.workers.StreamExtractorWorker;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.Stack;
-import java.util.concurrent.atomic.AtomicBoolean;
-
-@SuppressWarnings("FieldCanBeLocal")
-public class VideoDetailFragment extends Fragment implements StreamExtractorWorker.OnStreamInfoReceivedListener, SharedPreferences.OnSharedPreferenceChangeListener {
+public class VideoDetailFragment extends BaseFragment implements StreamExtractorWorker.OnStreamInfoReceivedListener, SharedPreferences.OnSharedPreferenceChangeListener, View.OnClickListener {
private final String TAG = "VideoDetailFragment@" + Integer.toHexString(hashCode());
+ // Amount of videos to show on start
+ private static final int INITIAL_RELATED_VIDEOS = 8;
+
private static final String KORE_PACKET = "org.xbmc.kore";
private static final String SERVICE_ID_KEY = "service_id_key";
private static final String VIDEO_URL_KEY = "video_url_key";
private static final String VIDEO_TITLE_KEY = "video_title_key";
private static final String STACK_KEY = "stack_key";
+ private static final String INFO_KEY = "info_key";
+ private static final String WAS_RELATED_EXPANDED_KEY = "was_related_expanded_key";
public static final String AUTO_PLAY = "auto_play";
- private AppCompatActivity activity;
- private OnItemSelectedListener onItemSelectedListener;
+ private String thousand;
+ private String million;
+ private String billion;
+
private ArrayList sortedStreamVideosList;
private ActionBarHandler actionBarHandler;
@@ -95,27 +93,22 @@ public class VideoDetailFragment extends Fragment implements StreamExtractorWork
private String videoUrl;
private int serviceId = -1;
- private AtomicBoolean wasLoading = new AtomicBoolean(false);
- private AtomicBoolean isLoading = new AtomicBoolean(false);
private static final int RELATED_STREAMS_UPDATE_FLAG = 0x1;
private static final int RESOLUTIONS_MENU_UPDATE_FLAG = 0x2;
private int updateFlags = 0;
private boolean autoPlayEnabled;
private boolean showRelatedStreams;
-
- private static final ImageLoader imageLoader = ImageLoader.getInstance();
- private static final DisplayImageOptions displayImageOptions =
- new DisplayImageOptions.Builder().displayer(new FadeInBitmapDisplayer(400)).cacheInMemory(false).build();
+ private boolean wasRelatedStreamsExpanded = false;
/*//////////////////////////////////////////////////////////////////////////
// Views
//////////////////////////////////////////////////////////////////////////*/
- private ProgressBar loadingProgressBar;
+ private Spinner spinnerToolbar;
private ParallaxScrollView parallaxScrollRootView;
- private RelativeLayout contentRootLayout;
+ private RelativeLayout contentRootLayoutHiding;
private Button thumbnailBackgroundButton;
private ImageView thumbnailImageView;
@@ -126,6 +119,9 @@ public class VideoDetailFragment extends Fragment implements StreamExtractorWork
private ImageView videoTitleToggleArrow;
private TextView videoCountView;
+ private TextView detailControlsBackground;
+ private TextView detailControlsPopup;
+
private RelativeLayout videoDescriptionRootLayout;
private TextView videoUploadDateView;
private TextView videoDescriptionView;
@@ -143,6 +139,7 @@ public class VideoDetailFragment extends Fragment implements StreamExtractorWork
private TextView nextStreamTitle;
private RelativeLayout relatedStreamRootLayout;
private LinearLayout relatedStreamsView;
+ private ImageButton relatedStreamExpandButton;
/*////////////////////////////////////////////////////////////////////////*/
@@ -159,24 +156,21 @@ public class VideoDetailFragment extends Fragment implements StreamExtractorWork
public static VideoDetailFragment getInstance() {
return new VideoDetailFragment();
}
+
/*//////////////////////////////////////////////////////////////////////////
// Fragment's Lifecycle
//////////////////////////////////////////////////////////////////////////*/
- @Override
- public void onAttach(Context context) {
- super.onAttach(context);
- activity = (AppCompatActivity) context;
- onItemSelectedListener = (OnItemSelectedListener) context;
- }
-
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
+ if (DEBUG) Log.d(TAG, "onCreate() called with: savedInstanceState = [" + savedInstanceState + "]");
+
if (savedInstanceState != null) {
videoTitle = savedInstanceState.getString(VIDEO_TITLE_KEY);
videoUrl = savedInstanceState.getString(VIDEO_URL_KEY);
- serviceId = savedInstanceState.getInt(SERVICE_ID_KEY);
+ serviceId = savedInstanceState.getInt(SERVICE_ID_KEY, 0);
+ wasRelatedStreamsExpanded = savedInstanceState.getBoolean(WAS_RELATED_EXPANDED_KEY, false);
Serializable serializable = savedInstanceState.getSerializable(STACK_KEY);
if (serializable instanceof Stack) {
//noinspection unchecked
@@ -184,65 +178,30 @@ public class VideoDetailFragment extends Fragment implements StreamExtractorWork
stack.clear();
stack.addAll(list);
}
+
+ Serializable serial = savedInstanceState.getSerializable(INFO_KEY);
+ if (serial instanceof StreamInfo) currentStreamInfo = (StreamInfo) serial;
}
showRelatedStreams = PreferenceManager.getDefaultSharedPreferences(activity).getBoolean(getString(R.string.show_next_video_key), true);
PreferenceManager.getDefaultSharedPreferences(activity).registerOnSharedPreferenceChangeListener(this);
- activity.setVolumeControlStream(AudioManager.STREAM_MUSIC);
- isLoading.set(false);
- setHasOptionsMenu(true);
+
+ thousand = getString(R.string.short_thousand);
+ million = getString(R.string.short_million);
+ billion = getString(R.string.short_billion);
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
+ if (DEBUG) Log.d(TAG, "onCreateView() called with: inflater = [" + inflater + "], container = [" + container + "], savedInstanceState = [" + savedInstanceState + "]");
return inflater.inflate(R.layout.fragment_video_detail, container, false);
}
@Override
public void onViewCreated(View rootView, Bundle savedInstanceState) {
- initViews(rootView);
- initListeners();
- selectAndLoadVideo(serviceId, videoUrl, videoTitle);
- wasLoading.set(false);
- }
-
- @Override
- public void onDestroyView() {
- super.onDestroyView();
- thumbnailImageView.setImageBitmap(null);
- relatedStreamsView.removeAllViews();
-
- loadingProgressBar = null;
-
- parallaxScrollRootView = null;
- contentRootLayout = null;
-
- thumbnailBackgroundButton = null;
- thumbnailImageView = null;
- thumbnailPlayButton = null;
-
- videoTitleRoot = null;
- videoTitleTextView = null;
- videoTitleToggleArrow = null;
- videoCountView = null;
-
- videoDescriptionRootLayout = null;
- videoUploadDateView = null;
- videoDescriptionView = null;
-
- uploaderButton = null;
- uploaderTextView = null;
- uploaderThumb = null;
-
- thumbsUpTextView = null;
- thumbsUpImageView = null;
- thumbsDownTextView = null;
- thumbsDownImageView = null;
- thumbsDisabledTextView = null;
-
- nextStreamTitle = null;
- relatedStreamRootLayout = null;
- relatedStreamsView = null;
+ super.onViewCreated(rootView, savedInstanceState);
+ if (currentStreamInfo == null) selectAndLoadVideo(serviceId, videoUrl, videoTitle);
+ else prepareAndLoad(currentStreamInfo);
}
@Override
@@ -267,23 +226,79 @@ public class VideoDetailFragment extends Fragment implements StreamExtractorWork
@Override
public void onStop() {
super.onStop();
- wasLoading.set(curExtractorWorker.isRunning());
+ wasLoading.set(curExtractorWorker != null && curExtractorWorker.isRunning());
if (curExtractorWorker != null && curExtractorWorker.isRunning()) curExtractorWorker.cancel();
+ StreamInfoCache.getInstance().removeOldEntries();
}
@Override
public void onDestroy() {
super.onDestroy();
PreferenceManager.getDefaultSharedPreferences(activity).unregisterOnSharedPreferenceChangeListener(this);
- imageLoader.clearMemoryCache();
+ }
+
+ @Override
+ public void onDestroyView() {
+ if (DEBUG) Log.d(TAG, "onDestroyView() called");
+ thumbnailImageView.setImageBitmap(null);
+ relatedStreamsView.removeAllViews();
+ spinnerToolbar.setOnItemSelectedListener(null);
+
+ spinnerToolbar = null;
+
+ parallaxScrollRootView = null;
+ contentRootLayoutHiding = null;
+
+ thumbnailBackgroundButton = null;
+ thumbnailImageView = null;
+ thumbnailPlayButton = null;
+
+ videoTitleRoot = null;
+ videoTitleTextView = null;
+ videoTitleToggleArrow = null;
+ videoCountView = null;
+
+ detailControlsBackground = null;
+ detailControlsPopup = null;
+
+ videoDescriptionRootLayout = null;
+ videoUploadDateView = null;
+ videoDescriptionView = null;
+
+ uploaderButton = null;
+ uploaderTextView = null;
+ uploaderThumb = null;
+
+ thumbsUpTextView = null;
+ thumbsUpImageView = null;
+ thumbsDownTextView = null;
+ thumbsDownImageView = null;
+ thumbsDisabledTextView = null;
+
+ nextStreamTitle = null;
+ relatedStreamRootLayout = null;
+ relatedStreamsView = null;
+ relatedStreamExpandButton = null;
+
+ super.onDestroyView();
}
@Override
public void onSaveInstanceState(Bundle outState) {
+ if (DEBUG) Log.d(TAG, "onSaveInstanceState() called with: outState = [" + outState + "]");
outState.putString(VIDEO_URL_KEY, videoUrl);
outState.putString(VIDEO_TITLE_KEY, videoTitle);
outState.putInt(SERVICE_ID_KEY, serviceId);
outState.putSerializable(STACK_KEY, stack);
+
+ int nextCount = currentStreamInfo != null && currentStreamInfo.next_video != null ? 2 : 0;
+ if (relatedStreamsView != null && relatedStreamsView.getChildCount() > INITIAL_RELATED_VIDEOS + nextCount) {
+ outState.putSerializable(WAS_RELATED_EXPANDED_KEY, true);
+ }
+
+ if (!isLoading.get() && (curExtractorWorker == null || !curExtractorWorker.isRunning())) {
+ outState.putSerializable(INFO_KEY, currentStreamInfo);
+ }
}
@Override
@@ -313,27 +328,164 @@ public class VideoDetailFragment extends Fragment implements StreamExtractorWork
}
}
+ /*//////////////////////////////////////////////////////////////////////////
+ // OnClick
+ //////////////////////////////////////////////////////////////////////////*/
+
+ @Override
+ public void onClick(View v) {
+ if (isLoading.get() || currentStreamInfo == null) return;
+
+ switch (v.getId()) {
+ case R.id.detail_controls_background:
+ openInBackground();
+ break;
+ case R.id.detail_controls_popup:
+ openInPopup();
+ break;
+ case R.id.detail_uploader_button:
+ NavigationHelper.openChannel(onItemSelectedListener, currentStreamInfo.service_id, currentStreamInfo.channel_url, currentStreamInfo.uploader);
+ break;
+ case R.id.detail_thumbnail_background_button:
+ playVideo(currentStreamInfo);
+ break;
+ case R.id.detail_title_root_layout:
+ toggleTitleAndDescription();
+ break;
+ case R.id.detail_related_streams_expand:
+ toggleExpandRelatedVideos(currentStreamInfo);
+ break;
+ }
+ }
+
+ @Override
+ protected void reloadContent() {
+ if (DEBUG) Log.d(TAG, "reloadContent() called");
+ if (currentStreamInfo != null) StreamInfoCache.getInstance().removeInfo(currentStreamInfo);
+ currentStreamInfo = null;
+ for (StackItem stackItem : stack) if (stackItem.getUrl().equals(videoUrl)) stackItem.setInfo(null);
+ prepareAndLoad(null);
+ }
+
+ private void openInBackground() {
+ if (isLoading.get()) return;
+
+ boolean useExternalAudioPlayer = PreferenceManager.getDefaultSharedPreferences(activity)
+ .getBoolean(activity.getString(R.string.use_external_audio_player_key), false);
+ Intent intent;
+ AudioStream audioStream = currentStreamInfo.audio_streams.get(Utils.getPreferredAudioFormat(activity, currentStreamInfo.audio_streams));
+ if (!useExternalAudioPlayer && android.os.Build.VERSION.SDK_INT >= 16) {
+ activity.startService(NavigationHelper.getOpenBackgroundPlayerIntent(activity, currentStreamInfo, audioStream));
+ Toast.makeText(activity, R.string.background_player_playing_toast, Toast.LENGTH_SHORT).show();
+ } else {
+ intent = new Intent();
+ try {
+ intent.setAction(Intent.ACTION_VIEW);
+ intent.setDataAndType(Uri.parse(audioStream.url),
+ MediaFormat.getMimeById(audioStream.format));
+ intent.putExtra(Intent.EXTRA_TITLE, currentStreamInfo.title);
+ intent.putExtra("title", currentStreamInfo.title);
+ // HERE !!!
+ activity.startActivity(intent);
+ } catch (Exception e) {
+ e.printStackTrace();
+ AlertDialog.Builder builder = new AlertDialog.Builder(activity);
+ builder.setMessage(R.string.no_player_found)
+ .setPositiveButton(R.string.install, new DialogInterface.OnClickListener() {
+ @Override
+ public void onClick(DialogInterface dialog, int which) {
+ Intent intent = new Intent();
+ intent.setAction(Intent.ACTION_VIEW);
+ intent.setData(Uri.parse(activity.getString(R.string.fdroid_vlc_url)));
+ activity.startActivity(intent);
+ }
+ })
+ .setNegativeButton(R.string.cancel, new DialogInterface.OnClickListener() {
+ @Override
+ public void onClick(DialogInterface dialog, int which) {
+ Log.i(TAG, "You unlocked a secret unicorn.");
+ }
+ });
+ builder.create().show();
+ Log.e(TAG, "Either no Streaming player for audio was installed, or something important crashed:");
+ e.printStackTrace();
+ }
+ }
+ }
+
+ private void openInPopup() {
+ if (isLoading.get()) return;
+
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M && !PermissionHelper.checkSystemAlertWindowPermission(activity)) {
+ Toast.makeText(activity, R.string.msg_popup_permission, Toast.LENGTH_LONG).show();
+ return;
+ }
+
+ Toast.makeText(activity, R.string.popup_playing_toast, Toast.LENGTH_SHORT).show();
+ Intent mIntent = NavigationHelper.getOpenVideoPlayerIntent(activity, PopupVideoPlayer.class, currentStreamInfo, actionBarHandler.getSelectedVideoStream());
+ activity.startService(mIntent);
+ }
+
+ 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);
+ }
+ }
+
+ private void toggleExpandRelatedVideos(StreamInfo info) {
+ if (DEBUG) Log.d(TAG, "toggleExpandRelatedVideos() called with: info = [" + info + "]");
+ if (!showRelatedStreams) return;
+
+ int nextCount = info.next_video != null ? 2 : 0;
+ int initialCount = INITIAL_RELATED_VIDEOS + nextCount;
+
+ if (relatedStreamsView.getChildCount() > initialCount) {
+ relatedStreamsView.removeViews(initialCount, relatedStreamsView.getChildCount() - (initialCount));
+ relatedStreamExpandButton.setImageDrawable(ContextCompat.getDrawable(activity, getResourceIdFromAttr(R.attr.expand)));
+ return;
+ }
+
+ //Log.d(TAG, "toggleExpandRelatedVideos() called with: info = [" + info + "], from = [" + INITIAL_RELATED_VIDEOS + "]");
+ for (int i = INITIAL_RELATED_VIDEOS; i < info.related_streams.size(); i++) {
+ InfoItem item = info.related_streams.get(i);
+ //Log.d(TAG, "i = " + i);
+ relatedStreamsView.addView(infoItemBuilder.buildView(relatedStreamsView, item));
+ }
+ relatedStreamExpandButton.setImageDrawable(ContextCompat.getDrawable(activity, getResourceIdFromAttr(R.attr.collapse)));
+ }
+
/*//////////////////////////////////////////////////////////////////////////
// Init
//////////////////////////////////////////////////////////////////////////*/
- private void initViews(View rootView) {
- loadingProgressBar = (ProgressBar) rootView.findViewById(R.id.detail_loading_progress_bar);
+ protected void initViews(View rootView, Bundle savedInstanceState) {
+ super.initViews(rootView, savedInstanceState);
+
+ spinnerToolbar = (Spinner) toolbar.findViewById(R.id.toolbar_spinner);
parallaxScrollRootView = (ParallaxScrollView) rootView.findViewById(R.id.detail_main_content);
//thumbnailRootLayout = (RelativeLayout) rootView.findViewById(R.id.detail_thumbnail_root_layout);
- thumbnailBackgroundButton = (Button) rootView.findViewById(R.id.detail_stream_thumbnail_background_button);
+ thumbnailBackgroundButton = (Button) rootView.findViewById(R.id.detail_thumbnail_background_button);
thumbnailImageView = (ImageView) rootView.findViewById(R.id.detail_thumbnail_image_view);
thumbnailPlayButton = (ImageView) rootView.findViewById(R.id.detail_thumbnail_play_button);
- contentRootLayout = (RelativeLayout) rootView.findViewById(R.id.detail_content_root_layout);
+ contentRootLayoutHiding = (RelativeLayout) rootView.findViewById(R.id.detail_content_root_hiding);
videoTitleRoot = rootView.findViewById(R.id.detail_title_root_layout);
videoTitleTextView = (TextView) rootView.findViewById(R.id.detail_video_title_view);
videoTitleToggleArrow = (ImageView) rootView.findViewById(R.id.detail_toggle_description_view);
videoCountView = (TextView) rootView.findViewById(R.id.detail_view_count_view);
+ detailControlsBackground = (TextView) rootView.findViewById(R.id.detail_controls_background);
+ detailControlsPopup = (TextView) rootView.findViewById(R.id.detail_controls_popup);
+
videoDescriptionRootLayout = (RelativeLayout) rootView.findViewById(R.id.detail_description_root_layout);
videoUploadDateView = (TextView) rootView.findViewById(R.id.detail_upload_date_view);
videoDescriptionView = (TextView) rootView.findViewById(R.id.detail_description_view);
@@ -353,6 +505,7 @@ public class VideoDetailFragment extends Fragment implements StreamExtractorWork
relatedStreamRootLayout = (RelativeLayout) rootView.findViewById(R.id.detail_related_streams_root_layout);
nextStreamTitle = (TextView) rootView.findViewById(R.id.detail_next_stream_title);
relatedStreamsView = (LinearLayout) rootView.findViewById(R.id.detail_related_streams_view);
+ relatedStreamExpandButton = ((ImageButton) rootView.findViewById(R.id.detail_related_streams_expand));
actionBarHandler = new ActionBarHandler(activity);
videoDescriptionView.setMovementMethod(LinkMovementMethod.getInstance());
@@ -362,28 +515,8 @@ public class VideoDetailFragment extends Fragment implements StreamExtractorWork
setHeightThumbnail();
}
- private void initListeners() {
- videoTitleRoot.setOnClickListener(new View.OnClickListener() {
- @Override
- public void onClick(View v) {
- 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);
- }
- }
- });
- thumbnailBackgroundButton.setOnClickListener(new View.OnClickListener() {
- @Override
- public void onClick(View v) {
- if (!isLoading.get() && currentStreamInfo != null) playVideo(currentStreamInfo);
- }
- });
-
+ protected void initListeners() {
+ super.initListeners();
infoItemBuilder.setOnStreamInfoItemSelectedListener(new InfoItemBuilder.OnInfoItemSelectedListener() {
@Override
public void selected(int serviceId, String url, String title) {
@@ -392,33 +525,26 @@ public class VideoDetailFragment extends Fragment implements StreamExtractorWork
}
});
- uploaderButton.setOnClickListener(new View.OnClickListener() {
- @Override
- public void onClick(View view) {
- NavigationHelper.openChannel(onItemSelectedListener, currentStreamInfo.service_id, currentStreamInfo.channel_url, currentStreamInfo.uploader);
- }
- });
+ videoTitleRoot.setOnClickListener(this);
+ uploaderButton.setOnClickListener(this);
+ thumbnailBackgroundButton.setOnClickListener(this);
+ detailControlsBackground.setOnClickListener(this);
+ detailControlsPopup.setOnClickListener(this);
+ relatedStreamExpandButton.setOnClickListener(this);
}
private void initThumbnailViews(StreamInfo info) {
if (info.thumbnail_url != null && !info.thumbnail_url.isEmpty()) {
- imageLoader.displayImage(info.thumbnail_url, thumbnailImageView,
- displayImageOptions, new SimpleImageLoadingListener() {
- @Override
- public void onLoadingFailed(String imageUri, View view, FailReason failReason) {
- ErrorActivity.reportError(activity,
- failReason.getCause(), null, activity.findViewById(android.R.id.content),
- ErrorActivity.ErrorInfo.make(ErrorActivity.LOAD_IMAGE,
- NewPipe.getNameOfService(currentStreamInfo.service_id), imageUri,
- R.string.could_not_load_thumbnails));
- }
-
- });
+ imageLoader.displayImage(info.thumbnail_url, thumbnailImageView, displayImageOptions, new SimpleImageLoadingListener() {
+ @Override
+ public void onLoadingFailed(String imageUri, View view, FailReason failReason) {
+ ErrorActivity.reportError(activity, failReason.getCause(), null, activity.findViewById(android.R.id.content), ErrorActivity.ErrorInfo.make(ErrorActivity.LOAD_IMAGE, NewPipe.getNameOfService(currentStreamInfo.service_id), imageUri, R.string.could_not_load_thumbnails));
+ }
+ });
} else thumbnailImageView.setImageResource(R.drawable.dummy_thumbnail_dark);
if (info.uploader_thumbnail_url != null && !info.uploader_thumbnail_url.isEmpty()) {
- imageLoader.displayImage(info.uploader_thumbnail_url,
- uploaderThumb, displayImageOptions,
+ imageLoader.displayImage(info.uploader_thumbnail_url, uploaderThumb, displayImageOptions,
new ImageErrorLoadingListener(activity, activity.findViewById(android.R.id.content), info.service_id));
}
}
@@ -434,11 +560,24 @@ public class VideoDetailFragment extends Fragment implements StreamExtractorWork
} else nextStreamTitle.setVisibility(View.GONE);
if (info.related_streams != null && !info.related_streams.isEmpty() && showRelatedStreams) {
- for (InfoItem item : info.related_streams) {
+ //long first = System.nanoTime(), each;
+ int to = info.related_streams.size() >= INITIAL_RELATED_VIDEOS ? INITIAL_RELATED_VIDEOS : info.related_streams.size();
+ for (int i = 0; i < to; i++) {
+ InfoItem item = info.related_streams.get(i);
+ //each = System.nanoTime();
relatedStreamsView.addView(infoItemBuilder.buildView(relatedStreamsView, item));
+ //if (DEBUG) Log.d(TAG, "each took " + ((System.nanoTime() - each) / 1000000L) + "ms");
}
+ //if (DEBUG) Log.d(TAG, "Total time " + ((System.nanoTime() - first) / 1000000L) + "ms");
+
relatedStreamRootLayout.setVisibility(View.VISIBLE);
- } else if (info.next_video == null) relatedStreamRootLayout.setVisibility(View.GONE);
+ relatedStreamExpandButton.setVisibility(View.VISIBLE);
+
+ relatedStreamExpandButton.setImageDrawable(ContextCompat.getDrawable(activity, getResourceIdFromAttr(R.attr.expand)));
+ } else {
+ if (info.next_video == null) relatedStreamRootLayout.setVisibility(View.GONE);
+ relatedStreamExpandButton.setVisibility(View.GONE);
+ }
}
/*//////////////////////////////////////////////////////////////////////////
@@ -448,13 +587,10 @@ public class VideoDetailFragment extends Fragment implements StreamExtractorWork
@Override
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
actionBarHandler.setupMenu(menu, inflater);
- actionBarHandler.setupNavMenu(activity);
ActionBar supportActionBar = activity.getSupportActionBar();
if (supportActionBar != null) {
supportActionBar.setDisplayHomeAsUpEnabled(true);
supportActionBar.setDisplayShowTitleEnabled(false);
- //noinspection deprecation
- supportActionBar.setNavigationMode(0);
}
}
@@ -464,13 +600,8 @@ public class VideoDetailFragment extends Fragment implements StreamExtractorWork
}
private void setupActionBarHandler(final StreamInfo info) {
- if (activity.getSupportActionBar() != null) {
- //noinspection deprecation
- activity.getSupportActionBar().setNavigationMode(ActionBar.NAVIGATION_MODE_LIST);
- }
-
sortedStreamVideosList = Utils.getSortedStreamVideosList(activity, info.video_streams, info.video_only_streams, false);
- actionBarHandler.setupStreamList(sortedStreamVideosList);
+ actionBarHandler.setupStreamList(sortedStreamVideosList, spinnerToolbar);
actionBarHandler.setOnShareListener(new ActionBarHandler.OnActionListener() {
@Override
public void onActionSelected(int selectedStreamId) {
@@ -496,22 +627,6 @@ public class VideoDetailFragment extends Fragment implements StreamExtractorWork
}
});
- actionBarHandler.setOnOpenInPopupListener(new ActionBarHandler.OnActionListener() {
- @Override
- public void onActionSelected(int selectedStreamId) {
- if (isLoading.get()) return;
-
- if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M && !PermissionHelper.checkSystemAlertWindowPermission(activity)) {
- Toast.makeText(activity, R.string.msg_popup_permission, Toast.LENGTH_LONG).show();
- return;
- }
-
- Toast.makeText(activity, R.string.popup_playing_toast, Toast.LENGTH_SHORT).show();
- Intent mIntent = NavigationHelper.getOpenVideoPlayerIntent(activity, PopupVideoPlayer.class, info, selectedStreamId);
- activity.startService(mIntent);
- }
- });
-
actionBarHandler.setOnPlayWithKodiListener(new ActionBarHandler.OnActionListener() {
@Override
public void onActionSelected(int selectedStreamId) {
@@ -586,59 +701,6 @@ public class VideoDetailFragment extends Fragment implements StreamExtractorWork
}
}
});
-
- if (info.audio_streams == null) {
- actionBarHandler.showAudioAction(false);
- } else {
- actionBarHandler.setOnPlayAudioListener(new ActionBarHandler.OnActionListener() {
- @Override
- public void onActionSelected(int selectedStreamId) {
- if (isLoading.get()) return;
-
- boolean useExternalAudioPlayer = PreferenceManager.getDefaultSharedPreferences(activity)
- .getBoolean(activity.getString(R.string.use_external_audio_player_key), false);
- Intent intent;
- AudioStream audioStream = info.audio_streams.get(Utils.getPreferredAudioFormat(activity, info.audio_streams));
- if (!useExternalAudioPlayer && android.os.Build.VERSION.SDK_INT >= 16) {
- activity.startService(NavigationHelper.getOpenBackgroundPlayerIntent(activity, info, audioStream));
- Toast.makeText(activity, R.string.background_player_playing_toast, Toast.LENGTH_SHORT).show();
- } else {
- intent = new Intent();
- try {
- intent.setAction(Intent.ACTION_VIEW);
- intent.setDataAndType(Uri.parse(audioStream.url),
- MediaFormat.getMimeById(audioStream.format));
- intent.putExtra(Intent.EXTRA_TITLE, info.title);
- intent.putExtra("title", info.title);
- // HERE !!!
- activity.startActivity(intent);
- } catch (Exception e) {
- e.printStackTrace();
- AlertDialog.Builder builder = new AlertDialog.Builder(activity);
- builder.setMessage(R.string.no_player_found)
- .setPositiveButton(R.string.install, new DialogInterface.OnClickListener() {
- @Override
- public void onClick(DialogInterface dialog, int which) {
- Intent intent = new Intent();
- intent.setAction(Intent.ACTION_VIEW);
- intent.setData(Uri.parse(activity.getString(R.string.fdroid_vlc_url)));
- activity.startActivity(intent);
- }
- })
- .setNegativeButton(R.string.cancel, new DialogInterface.OnClickListener() {
- @Override
- public void onClick(DialogInterface dialog, int which) {
- Log.i(TAG, "You unlocked a secret unicorn.");
- }
- });
- builder.create().show();
- Log.e(TAG, "Either no Streaming player for audio was installed, or something important crashed:");
- e.printStackTrace();
- }
- }
- }
- });
- }
}
/*//////////////////////////////////////////////////////////////////////////
@@ -656,10 +718,9 @@ public class VideoDetailFragment extends Fragment implements StreamExtractorWork
}
public void pushToStack(String videoUrl, String videoTitle) {
-
+ if (DEBUG) Log.d(TAG, "pushToStack() called with: videoUrl = [" + videoUrl + "], videoTitle = [" + videoTitle + "]");
if (stack.size() > 0 && stack.peek().getUrl().equals(videoUrl)) return;
stack.push(new StackItem(videoUrl, videoTitle));
-
}
public void setTitleToUrl(String videoUrl, String videoTitle) {
@@ -670,7 +731,16 @@ public class VideoDetailFragment extends Fragment implements StreamExtractorWork
}
}
+ public void setStreamInfoToUrl(String videoUrl, StreamInfo info) {
+ if (info != null) {
+ for (StackItem stackItem : stack) {
+ if (stackItem.getUrl().equals(videoUrl)) stackItem.setInfo(info);
+ }
+ }
+ }
+
public boolean onActivityBackPressed() {
+ if (DEBUG) Log.d(TAG, "onActivityBackPressed() called");
// That means that we are on the start of the stack,
// return false to let the MainActivity handle the onBack
if (stack.size() == 1) return false;
@@ -678,18 +748,16 @@ public class VideoDetailFragment extends Fragment implements StreamExtractorWork
stack.pop();
// Get url from the new top
StackItem peek = stack.peek();
- selectAndLoadVideo(0, peek.getUrl(),
- peek.getTitle() != null && !peek.getTitle().isEmpty() ? peek.getTitle() : ""
- );
+
+ if (peek.getInfo() != null) selectAndHandleInfo(peek.getInfo());
+ else selectAndLoadVideo(0, peek.getUrl(), !TextUtils.isEmpty(peek.getTitle()) ? peek.getTitle() : "");
return true;
}
-
/*//////////////////////////////////////////////////////////////////////////
// Utils
//////////////////////////////////////////////////////////////////////////*/
-
public void setAutoplay(boolean autoplay) {
this.autoPlayEnabled = autoplay;
}
@@ -700,52 +768,145 @@ public class VideoDetailFragment extends Fragment implements StreamExtractorWork
this.serviceId = serviceId;
}
- public void selectAndLoadVideo(int serviceId, String videoUrl, String videoTitle) {
- selectVideo(serviceId, videoUrl, videoTitle);
- loadSelectedVideo();
+ public void selectAndHandleInfo(StreamInfo info) {
+ if (DEBUG) Log.d(TAG, "selectAndHandleInfo() called with: info = [" + info + "]");
+ selectVideo(info.service_id, info.webpage_url, info.title);
+ prepareAndLoad(info);
}
- public void loadSelectedVideo() {
+ public void selectAndLoadVideo(int serviceId, String videoUrl, String videoTitle) {
+ if (DEBUG) Log.d(TAG, "selectAndLoadVideo() called with: serviceId = [" + serviceId + "], videoUrl = [" + videoUrl + "], videoTitle = [" + videoTitle + "]");
+ selectVideo(serviceId, videoUrl, videoTitle);
+ prepareAndLoad(null);
+ }
+
+ /**
+ * Prepare the UI for loading the info.
+ * If the argument info is not null, it'll be passed in {@link #handleStreamInfo(StreamInfo, boolean)}.
+ * If it is, check if the cache contains the info already.
+ * If the cache doesn't have the info, load from the network.
+ *
+ * @param info info to prepare and load, can be null
+ */
+ public void prepareAndLoad(StreamInfo info) {
+ if (DEBUG) Log.d(TAG, "prepareAndLoad() called with: info = [" + info + "]");
isLoading.set(true);
+
+ // Only try to get from the cache if the passed info IS null
+ if (info == null && StreamInfoCache.getInstance().hasKey(videoUrl)) {
+ info = StreamInfoCache.getInstance().getFromKey(videoUrl);
+ }
+
+ if (info != null) selectVideo(info.service_id, info.webpage_url, info.title);
pushToStack(videoUrl, videoTitle);
if (curExtractorWorker != null && curExtractorWorker.isRunning()) curExtractorWorker.cancel();
-
- if (activity.getSupportActionBar() != null) {
- //noinspection deprecation
- activity.getSupportActionBar().setNavigationMode(0);
- }
-
- animateView(contentRootLayout, false, 50, null);
-
- videoTitleTextView.setMaxLines(1);
- int scrollY = parallaxScrollRootView.getScrollY();
- if (scrollY < 30) animateView(videoTitleTextView, false, 200, new Runnable() {
+ animateView(spinnerToolbar, false, 200);
+ animateView(errorPanel, false, 200);
+ animateView(videoTitleTextView, false, 100, new Runnable() {
@Override
public void run() {
if (videoTitleTextView == null) return;
videoTitleTextView.setText(videoTitle != null ? videoTitle : "");
- animateView(videoTitleTextView, true, 400, null);
+ videoTitleTextView.setMaxLines(1);
+ animateView(videoTitleTextView, true, 100);
}
});
- else videoTitleTextView.setText(videoTitle != null ? videoTitle : "");
- //videoTitleTextView.setText(videoTitle != null ? videoTitle : "");
videoDescriptionRootLayout.setVisibility(View.GONE);
videoTitleToggleArrow.setImageResource(R.drawable.arrow_down);
videoTitleToggleArrow.setVisibility(View.GONE);
videoTitleRoot.setClickable(false);
- //thumbnailPlayButton.setVisibility(View.GONE);
- animateView(thumbnailPlayButton, false, 50, null);
- loadingProgressBar.setVisibility(View.VISIBLE);
-
+ animateView(thumbnailPlayButton, false, 50);
imageLoader.cancelDisplayTask(thumbnailImageView);
imageLoader.cancelDisplayTask(uploaderThumb);
thumbnailImageView.setImageBitmap(null);
uploaderThumb.setImageBitmap(null);
- curExtractorWorker = new StreamExtractorWorker(activity, serviceId, videoUrl, this);
- curExtractorWorker.start();
+ if (info != null) {
+ final StreamInfo infoFinal = info;
+ animateView(contentRootLayoutHiding, false, 300, new Runnable() {
+ @Override
+ public void run() {
+ if (contentRootLayoutHiding == null) return;
+ handleStreamInfo(infoFinal, false);
+ isLoading.set(false);
+ animateView(contentRootLayoutHiding, true, 400, 200);
+ }
+ });
+ } else {
+ curExtractorWorker = new StreamExtractorWorker(activity, serviceId, videoUrl, this);
+ curExtractorWorker.start();
+ animateView(loadingProgressBar, true, 200);
+ animateView(contentRootLayoutHiding, false, 200);
+ }
+ }
+
+ private void handleStreamInfo(@NonNull StreamInfo info, boolean fromNetwork) {
+ if (DEBUG) Log.d(TAG, "handleStreamInfo() called with: info = [" + info + "]");
+ currentStreamInfo = info;
+ selectVideo(info.service_id, info.webpage_url, info.title);
+
+ loadingProgressBar.setVisibility(View.GONE);
+ animateView(thumbnailPlayButton, true, 200);
+ parallaxScrollRootView.scrollTo(0, 0);
+
+
+ // Since newpipe is designed to work even if certain information is not available,
+ // the UI has to react on missing information.
+ if (fromNetwork) videoTitleTextView.setText(info.title);
+
+ if (!TextUtils.isEmpty(info.uploader)) uploaderTextView.setText(info.uploader);
+ uploaderTextView.setVisibility(!TextUtils.isEmpty(info.uploader) ? View.VISIBLE : View.GONE);
+ uploaderButton.setVisibility(!TextUtils.isEmpty(info.channel_url) ? View.VISIBLE : View.GONE);
+ uploaderThumb.setImageDrawable(ContextCompat.getDrawable(activity, R.drawable.buddy));
+
+ if (info.view_count >= 0) videoCountView.setText(Localization.localizeViewCount(info.view_count, activity));
+ videoCountView.setVisibility(info.view_count >= 0 ? View.VISIBLE : View.GONE);
+
+ if (info.dislike_count == -1 && info.like_count == -1) {
+ thumbsDownImageView.setVisibility(View.VISIBLE);
+ thumbsUpImageView.setVisibility(View.VISIBLE);
+ thumbsUpTextView.setVisibility(View.GONE);
+ thumbsDownTextView.setVisibility(View.GONE);
+
+ thumbsDisabledTextView.setVisibility(View.VISIBLE);
+ } else {
+ thumbsDisabledTextView.setVisibility(View.GONE);
+
+ if (info.dislike_count >= 0) thumbsDownTextView.setText(getShortCount((long) info.dislike_count));
+ thumbsDownTextView.setVisibility(info.dislike_count >= 0 ? View.VISIBLE : View.GONE);
+ thumbsDownImageView.setVisibility(info.dislike_count >= 0 ? View.VISIBLE : View.GONE);
+
+ if (info.like_count >= 0) thumbsUpTextView.setText(getShortCount((long) info.like_count));
+ thumbsUpTextView.setVisibility(info.like_count >= 0 ? View.VISIBLE : View.GONE);
+ thumbsUpImageView.setVisibility(info.like_count >= 0 ? View.VISIBLE : View.GONE);
+ }
+
+ if (!TextUtils.isEmpty(info.upload_date)) videoUploadDateView.setText(Localization.localizeDate(info.upload_date, activity));
+ videoUploadDateView.setVisibility(!TextUtils.isEmpty(info.upload_date) ? View.VISIBLE : View.GONE);
+
+ if (!TextUtils.isEmpty(info.description)) { //noinspection deprecation
+ videoDescriptionView.setText(Build.VERSION.SDK_INT >= 24 ? Html.fromHtml(info.description, 0) : Html.fromHtml(info.description));
+ }
+ videoDescriptionView.setVisibility(!TextUtils.isEmpty(info.description) ? View.VISIBLE : View.GONE);
+
+ videoDescriptionRootLayout.setVisibility(View.GONE);
+ videoTitleToggleArrow.setImageResource(R.drawable.arrow_down);
+ videoTitleToggleArrow.setVisibility(View.VISIBLE);
+ videoTitleRoot.setClickable(true);
+
+ animateView(spinnerToolbar, true, 500);
+ setupActionBarHandler(info);
+ initThumbnailViews(info);
+ initRelatedVideos(info);
+ if (wasRelatedStreamsExpanded) {
+ toggleExpandRelatedVideos(currentStreamInfo);
+ wasRelatedStreamsExpanded = false;
+ }
+
+ setTitleToUrl(info.webpage_url, info.title);
+ setStreamInfoToUrl(info.webpage_url, info);
}
public void playVideo(StreamInfo info) {
@@ -813,6 +974,7 @@ public class VideoDetailFragment extends Fragment implements StreamExtractorWork
TypedValue typedValue = new TypedValue();
activity.getTheme().resolveAttribute(R.attr.separatorColor, typedValue, true);
separator.setBackgroundColor(typedValue.data);
+
return separator;
}
@@ -827,51 +989,15 @@ public class VideoDetailFragment extends Fragment implements StreamExtractorWork
thumbnailBackgroundButton.setMinimumHeight(height);
}
- /**
- * Animate the view
- *
- * @param view view that will be animated
- * @param enterOrExit true to enter, false to exit
- * @param duration how long the animation will take, in milliseconds
- * @param execOnEnd runnable that will be executed when the animation ends
- */
- public void animateView(final View view, final boolean enterOrExit, long duration, final Runnable execOnEnd) {
- if (view.getVisibility() == View.VISIBLE && enterOrExit) {
- view.animate().setListener(null).cancel();
- view.setVisibility(View.VISIBLE);
- view.setAlpha(1f);
- if (execOnEnd != null) execOnEnd.run();
- return;
- } else if ((view.getVisibility() == View.GONE || view.getVisibility() == View.INVISIBLE) && !enterOrExit) {
- view.animate().setListener(null).cancel();
- view.setVisibility(View.GONE);
- view.setAlpha(0f);
- if (execOnEnd != null) execOnEnd.run();
- return;
- }
-
- view.animate().setListener(null).cancel();
- view.setVisibility(View.VISIBLE);
-
- if (enterOrExit) {
- view.animate().alpha(1f).setDuration(duration)
- .setListener(new AnimatorListenerAdapter() {
- @Override
- public void onAnimationEnd(Animator animation) {
- if (execOnEnd != null) execOnEnd.run();
- }
- }).start();
+ public String getShortCount(Long viewCount) {
+ if (viewCount >= 1000000000) {
+ return Long.toString(viewCount / 1000000000) + billion;
+ } else if (viewCount >= 1000000) {
+ return Long.toString(viewCount / 1000000) + million;
+ } else if (viewCount >= 1000) {
+ return Long.toString(viewCount / 1000) + thousand;
} else {
- view.animate().alpha(0f)
- .setDuration(duration)
- .setListener(new AnimatorListenerAdapter() {
- @Override
- public void onAnimationEnd(Animator animation) {
- view.setVisibility(View.GONE);
- if (execOnEnd != null) execOnEnd.run();
- }
- })
- .start();
+ return Long.toString(viewCount);
}
}
@@ -879,66 +1005,33 @@ public class VideoDetailFragment extends Fragment implements StreamExtractorWork
// OnStreamInfoReceivedListener callbacks
//////////////////////////////////////////////////////////////////////////*/
+ private void setErrorImage(final int imageResource) {
+ if (thumbnailImageView == null || activity == null) return;
+ thumbnailImageView.setImageDrawable(ContextCompat.getDrawable(activity, imageResource));
+ animateView(thumbnailImageView, false, 0, new Runnable() {
+ @Override
+ public void run() {
+ animateView(thumbnailImageView, true, 500);
+ }
+ });
+ }
+
+ @Override
+ protected void setErrorMessage(String message, boolean showRetryButton) {
+ super.setErrorMessage(message, showRetryButton);
+
+ if (!TextUtils.isEmpty(videoUrl)) StreamInfoCache.getInstance().removeInfo(videoUrl);
+ currentStreamInfo = null;
+ }
+
@Override
public void onReceive(StreamInfo info) {
+ if (DEBUG) Log.d(TAG, "onReceive() called with: info = [" + info + "]");
if (info == null || isRemoving() || !isVisible()) return;
- currentStreamInfo = info;
- loadingProgressBar.setVisibility(View.GONE);
- animateView(thumbnailPlayButton, true, 200, null);
- parallaxScrollRootView.scrollTo(0, 0);
-
- // Since newpipe is designed to work even if certain information is not available,
- // the UI has to react on missing information.
- videoTitle = info.title;
- videoTitleTextView.setText(info.title);
- if (!info.uploader.isEmpty()) uploaderTextView.setText(info.uploader);
- uploaderTextView.setVisibility(!info.uploader.isEmpty() ? View.VISIBLE : View.GONE);
- uploaderButton.setVisibility(!info.channel_url.isEmpty() ? View.VISIBLE : View.GONE);
- uploaderThumb.setImageDrawable(ContextCompat.getDrawable(activity, R.drawable.buddy));
-
- if (info.view_count >= 0) videoCountView.setText(Localization.localizeViewCount(info.view_count, activity));
- videoCountView.setVisibility(info.view_count >= 0 ? View.VISIBLE : View.GONE);
-
- if (info.dislike_count == -1 && info.like_count == -1) {
- thumbsDownImageView.setVisibility(View.VISIBLE);
- thumbsUpImageView.setVisibility(View.VISIBLE);
- thumbsUpTextView.setVisibility(View.GONE);
- thumbsDownTextView.setVisibility(View.GONE);
-
- thumbsDisabledTextView.setVisibility(View.VISIBLE);
- } else {
- thumbsDisabledTextView.setVisibility(View.GONE);
-
- if (info.dislike_count >= 0) thumbsDownTextView.setText(Localization.localizeNumber(info.dislike_count, activity));
- thumbsDownTextView.setVisibility(info.dislike_count >= 0 ? View.VISIBLE : View.GONE);
- thumbsDownImageView.setVisibility(info.dislike_count >= 0 ? View.VISIBLE : View.GONE);
-
- if (info.like_count >= 0) thumbsUpTextView.setText(Localization.localizeNumber(info.like_count, activity));
- thumbsUpTextView.setVisibility(info.like_count >= 0 ? View.VISIBLE : View.GONE);
- thumbsUpImageView.setVisibility(info.like_count >= 0 ? View.VISIBLE : View.GONE);
- }
-
- if (!info.upload_date.isEmpty()) videoUploadDateView.setText(Localization.localizeDate(info.upload_date, activity));
- videoUploadDateView.setVisibility(!info.upload_date.isEmpty() ? View.VISIBLE : View.GONE);
-
- if (!info.description.isEmpty()) { //noinspection deprecation
- videoDescriptionView.setText(Build.VERSION.SDK_INT >= 24 ? Html.fromHtml(info.description, 0) : Html.fromHtml(info.description));
- }
- videoDescriptionView.setVisibility(!info.description.isEmpty() ? View.VISIBLE : View.GONE);
-
- videoDescriptionRootLayout.setVisibility(View.GONE);
- videoTitleToggleArrow.setImageResource(R.drawable.arrow_down);
- videoTitleToggleArrow.setVisibility(View.VISIBLE);
- videoTitleRoot.setClickable(true);
-
- setupActionBarHandler(info);
- initRelatedVideos(info);
- initThumbnailViews(info);
-
- setTitleToUrl(info.webpage_url, info.title);
-
- animateView(contentRootLayout, true, 200, null);
+ handleStreamInfo(info, true);
+ animateView(contentRootLayoutHiding, true, 400);
+ animateView(loadingProgressBar, false, 200);
if (autoPlayEnabled) {
playVideo(info);
@@ -946,15 +1039,17 @@ public class VideoDetailFragment extends Fragment implements StreamExtractorWork
autoPlayEnabled = false;
}
+ StreamInfoCache.getInstance().putInfo(info);
isLoading.set(false);
+
}
@Override
public void onError(int messageId) {
- Toast.makeText(activity, messageId, Toast.LENGTH_LONG).show();
- loadingProgressBar.setVisibility(View.GONE);
- videoTitleTextView.setText(getString(messageId));
- thumbnailImageView.setImageDrawable(ContextCompat.getDrawable(activity, R.drawable.not_available_monkey));
+ if (DEBUG) Log.d(TAG, "onError() called with: messageId = [" + messageId + "]");
+ //Toast.makeText(activity, messageId, Toast.LENGTH_LONG).show();
+ setErrorImage(R.drawable.not_available_monkey);
+ setErrorMessage(getString(messageId), true);
}
@Override
@@ -962,12 +1057,13 @@ public class VideoDetailFragment extends Fragment implements StreamExtractorWork
Toast.makeText(activity, R.string.recaptcha_request_toast, Toast.LENGTH_LONG).show();
// Starting ReCaptcha Challenge Activity
startActivityForResult(new Intent(activity, ReCaptchaActivity.class), ReCaptchaActivity.RECAPTCHA_REQUEST);
+
+ setErrorMessage(getString(R.string.recaptcha_request_toast), false);
}
@Override
public void onBlockedByGemaError() {
- loadingProgressBar.setVisibility(View.GONE);
- thumbnailImageView.setImageDrawable(ContextCompat.getDrawable(activity, R.drawable.gruese_die_gema));
+
thumbnailBackgroundButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
@@ -978,21 +1074,20 @@ public class VideoDetailFragment extends Fragment implements StreamExtractorWork
}
});
- Toast.makeText(activity, R.string.blocked_by_gema, Toast.LENGTH_LONG).show();
+ setErrorImage(R.drawable.gruese_die_gema);
+ setErrorMessage(getString(R.string.blocked_by_gema), false);
}
@Override
public void onContentErrorWithMessage(int messageId) {
- loadingProgressBar.setVisibility(View.GONE);
- thumbnailImageView.setImageDrawable(ContextCompat.getDrawable(activity, R.drawable.not_available_monkey));
- Toast.makeText(activity, messageId, Toast.LENGTH_LONG).show();
+ setErrorImage(R.drawable.not_available_monkey);
+ setErrorMessage(getString(messageId), false);
}
@Override
public void onContentError() {
- loadingProgressBar.setVisibility(View.GONE);
- thumbnailImageView.setImageDrawable(ContextCompat.getDrawable(activity, R.drawable.not_available_monkey));
- Toast.makeText(activity, R.string.content_not_available, Toast.LENGTH_LONG).show();
+ setErrorImage(R.drawable.not_available_monkey);
+ setErrorMessage(getString(R.string.content_not_available), false);
}
@Override
diff --git a/app/src/main/java/org/schabi/newpipe/fragments/search/SearchFragment.java b/app/src/main/java/org/schabi/newpipe/fragments/search/SearchFragment.java
index e95473b2b..8071f4a36 100644
--- a/app/src/main/java/org/schabi/newpipe/fragments/search/SearchFragment.java
+++ b/app/src/main/java/org/schabi/newpipe/fragments/search/SearchFragment.java
@@ -3,245 +3,189 @@ package org.schabi.newpipe.fragments.search;
import android.app.Activity;
import android.content.Context;
import android.content.Intent;
+import android.os.Build;
import android.os.Bundle;
+import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
-import android.support.v4.app.Fragment;
import android.support.v7.app.ActionBar;
-import android.support.v7.app.AppCompatActivity;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;
-import android.support.v7.widget.SearchView;
+import android.text.Editable;
+import android.text.TextUtils;
+import android.text.TextWatcher;
import android.util.Log;
+import android.view.KeyEvent;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.View;
import android.view.ViewGroup;
+import android.view.animation.DecelerateInterpolator;
+import android.view.inputmethod.EditorInfo;
import android.view.inputmethod.InputMethodManager;
-import android.widget.ProgressBar;
+import android.widget.AdapterView;
+import android.widget.AutoCompleteTextView;
+import android.widget.TextView;
import android.widget.Toast;
import org.schabi.newpipe.R;
import org.schabi.newpipe.ReCaptchaActivity;
-import org.schabi.newpipe.extractor.NewPipe;
+import org.schabi.newpipe.extractor.InfoItem;
import org.schabi.newpipe.extractor.search.SearchEngine;
import org.schabi.newpipe.extractor.search.SearchResult;
-import org.schabi.newpipe.fragments.OnItemSelectedListener;
+import org.schabi.newpipe.fragments.BaseFragment;
import org.schabi.newpipe.info_list.InfoItemBuilder;
import org.schabi.newpipe.info_list.InfoListAdapter;
-import org.schabi.newpipe.report.ErrorActivity;
import org.schabi.newpipe.util.NavigationHelper;
+import org.schabi.newpipe.workers.SearchWorker;
+import org.schabi.newpipe.workers.SuggestionWorker;
+import java.util.ArrayList;
import java.util.EnumSet;
+import java.util.List;
-import static android.app.Activity.RESULT_OK;
-import static org.schabi.newpipe.ReCaptchaActivity.RECAPTCHA_REQUEST;
-
-/**
- * Created by Christian Schabesberger on 02.08.16.
- *
- * Copyright (C) Christian Schabesberger 2016
- * SearchFragment.java is part of NewPipe.
- *
- * NewPipe 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.
- *
- * NewPipe 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 NewPipe. If not, see .
- */
-
-public class SearchFragment extends Fragment implements SearchView.OnQueryTextListener, SearchWorker.SearchWorkerResultListener {
-
- private static final String TAG = SearchFragment.class.toString();
-
+public class SearchFragment extends BaseFragment implements SuggestionWorker.OnSuggestionResult, SearchWorker.OnSearchResult {
+ private final String TAG = "SearchFragment@" + Integer.toHexString(hashCode());
// savedInstanceBundle arguments
- private static final String QUERY = "query";
- private static final String STREAMING_SERVICE = "streaming_service";
+ private static final String QUERY_KEY = "query_key";
+ private static final String PAGE_NUMBER_KEY = "page_number_key";
+ private static final String SERVICE_KEY = "service_key";
+ private static final String INFO_LIST_KEY = "info_list_key";
+ private static final String WAS_LOADING_KEY = "was_loading_key";
+ private static final String ERROR_KEY = "error_key";
+ private static final String FILTER_CHECKED_ID_KEY = "filter_checked_id_key";
- private int streamingServiceId = -1;
+ /*//////////////////////////////////////////////////////////////////////////
+ // Search
+ //////////////////////////////////////////////////////////////////////////*/
+
+ private int filterItemCheckedId = -1;
+ private EnumSet filter = EnumSet.of(SearchEngine.Filter.CHANNEL, SearchEngine.Filter.STREAM);
+
+ private int serviceId = -1;
private String searchQuery = "";
- private boolean isLoading = false;
-
- @SuppressWarnings("FieldCanBeLocal")
- private SearchView searchView;
- private RecyclerView recyclerView;
- private ProgressBar loadingIndicator;
private int pageNumber = 0;
+
+ private SearchWorker curSearchWorker;
+ private SuggestionWorker curSuggestionWorker;
private SuggestionListAdapter suggestionListAdapter;
private InfoListAdapter infoListAdapter;
- private LinearLayoutManager streamInfoListLayoutManager;
- private EnumSet filter = EnumSet.of(SearchEngine.Filter.CHANNEL, SearchEngine.Filter.STREAM);
- private OnItemSelectedListener onItemSelectedListener;
+ /*//////////////////////////////////////////////////////////////////////////
+ // Views
+ //////////////////////////////////////////////////////////////////////////*/
- /**
- * Mandatory empty constructor for the fragment manager to instantiate the
- * fragment (e.g. upon screen orientation changes).
- */
- public SearchFragment() {
- }
+ private View searchToolbarContainer;
+ private AutoCompleteTextView searchEditText;
+ private View searchClear;
- @SuppressWarnings("unused")
- public static SearchFragment newInstance(int streamingServiceId, String searchQuery) {
- Bundle args = new Bundle();
- args.putInt(STREAMING_SERVICE, streamingServiceId);
- args.putString(QUERY, searchQuery);
- SearchFragment fragment = new SearchFragment();
- fragment.setArguments(args);
- return fragment;
+ private RecyclerView resultRecyclerView;
+
+ /*////////////////////////////////////////////////////////////////////////*/
+
+ public static SearchFragment getInstance(int serviceId, String query) {
+ SearchFragment searchFragment = new SearchFragment();
+ searchFragment.setQuery(serviceId, query);
+ return searchFragment;
}
/*//////////////////////////////////////////////////////////////////////////
// Fragment's LifeCycle
//////////////////////////////////////////////////////////////////////////*/
- @Override
- public void onAttach(Context context) {
- super.onAttach(context);
- onItemSelectedListener = ((OnItemSelectedListener) context);
- }
-
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
- searchQuery = "";
- isLoading = false;
- if (savedInstanceState != null) {
- searchQuery = savedInstanceState.getString(QUERY);
- streamingServiceId = savedInstanceState.getInt(STREAMING_SERVICE);
- } else {
- try {
- Bundle args = getArguments();
- if (args != null) {
- searchQuery = args.getString(QUERY);
- streamingServiceId = args.getInt(STREAMING_SERVICE);
- } else {
- streamingServiceId = NewPipe.getIdOfService("Youtube");
- }
- } catch (Exception e) {
- e.printStackTrace();
- ErrorActivity.reportError(getActivity(), e, null,
- getActivity().findViewById(android.R.id.content),
- ErrorActivity.ErrorInfo.make(ErrorActivity.SEARCHED,
- NewPipe.getNameOfService(streamingServiceId),
- "", R.string.general_error));
- }
- }
-
+ if (DEBUG) Log.d(TAG, "onCreate() called with: savedInstanceState = [" + savedInstanceState + "]");
setHasOptionsMenu(true);
-
- SearchWorker sw = SearchWorker.getInstance();
- sw.setSearchWorkerResultListener(this);
- }
-
- @Override
- public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
- View view = inflater.inflate(R.layout.fragment_search, container, false);
-
- Context context = view.getContext();
- loadingIndicator = (ProgressBar) view.findViewById(R.id.loading_progress_bar);
- recyclerView = (RecyclerView) view.findViewById(R.id.list);
- streamInfoListLayoutManager = new LinearLayoutManager(context);
- recyclerView.setLayoutManager(streamInfoListLayoutManager);
-
- infoListAdapter = new InfoListAdapter(getActivity(),
- getActivity().findViewById(android.R.id.content));
- infoListAdapter.setFooter(inflater.inflate(R.layout.pignate_footer, recyclerView, false));
- infoListAdapter.showFooter(false);
- infoListAdapter.setOnStreamInfoItemSelectedListener(new InfoItemBuilder.OnInfoItemSelectedListener() {
- @Override
- public void selected(int serviceId, String url, String title) {
- NavigationHelper.openVideoDetail(onItemSelectedListener, serviceId, url, title);
- }
- });
- infoListAdapter.setOnChannelInfoItemSelectedListener(new InfoItemBuilder.OnInfoItemSelectedListener() {
- @Override
- public void selected(int serviceId, String url, String title) {
- NavigationHelper.openChannel(onItemSelectedListener, serviceId, url, title);
- }
- });
- recyclerView.setAdapter(infoListAdapter);
- recyclerView.clearOnScrollListeners();
- recyclerView.addOnScrollListener(new RecyclerView.OnScrollListener() {
- @Override
- public void onScrolled(RecyclerView recyclerView, int dx, int dy) {
- int pastVisiblesItems, visibleItemCount, totalItemCount;
- super.onScrolled(recyclerView, dx, dy);
- if (dy > 0) //check for scroll down
- {
- visibleItemCount = streamInfoListLayoutManager.getChildCount();
- totalItemCount = streamInfoListLayoutManager.getItemCount();
- pastVisiblesItems = streamInfoListLayoutManager.findFirstVisibleItemPosition();
-
- if ((visibleItemCount + pastVisiblesItems) >= totalItemCount && !isLoading) {
- pageNumber++;
- recyclerView.post(new Runnable() {
- @Override
- public void run() {
- infoListAdapter.showFooter(true);
-
- }
- });
- search(searchQuery, pageNumber);
- }
- }
- }
- });
-
- return view;
- }
-
- @Override
- public void onViewCreated(View view, @Nullable Bundle savedInstanceState) {
- super.onViewCreated(view, savedInstanceState);
- if (!searchQuery.isEmpty()) {
- search(searchQuery);
+ if (savedInstanceState != null) {
+ searchQuery = savedInstanceState.getString(QUERY_KEY);
+ serviceId = savedInstanceState.getInt(SERVICE_KEY, 0);
+ pageNumber = savedInstanceState.getInt(PAGE_NUMBER_KEY, 0);
+ wasLoading.set(savedInstanceState.getBoolean(WAS_LOADING_KEY, false));
+ filterItemCheckedId = savedInstanceState.getInt(FILTER_CHECKED_ID_KEY, 0);
}
}
@Override
- public void onDestroyView() {
- super.onDestroyView();
- recyclerView.removeAllViews();
- infoListAdapter.clearSteamItemList();
- recyclerView = null;
+ public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
+ if (DEBUG) Log.d(TAG, "onCreateView() called with: inflater = [" + inflater + "], container = [" + container + "], savedInstanceState = [" + savedInstanceState + "]");
+ return inflater.inflate(R.layout.fragment_search, container, false);
+ }
+
+ @Override
+ public void onViewCreated(View rootView, @Nullable Bundle savedInstanceState) {
+ super.onViewCreated(rootView, savedInstanceState);
+ if (DEBUG) Log.d(TAG, "onViewCreated() called with: rootView = [" + rootView + "], savedInstanceState = [" + savedInstanceState + "]");
+
+ if (savedInstanceState != null && savedInstanceState.getBoolean(ERROR_KEY, false)) {
+ search(searchQuery, 0, true);
+ }
+
}
@Override
public void onResume() {
super.onResume();
- if (isLoading && !searchQuery.isEmpty()) {
- search(searchQuery);
+ if (DEBUG) Log.d(TAG, "onResume() called");
+ if (wasLoading.getAndSet(false) && !TextUtils.isEmpty(searchQuery)) {
+ if (pageNumber > 0) search(searchQuery, pageNumber);
+ else search(searchQuery, 0, true);
}
}
@Override
public void onStop() {
super.onStop();
- SearchWorker.getInstance().terminate();
+ if (DEBUG) Log.d(TAG, "onStop() called");
+
+ hideSoftKeyboard(searchEditText);
+
+ wasLoading.set(curSearchWorker != null && curSearchWorker.isRunning());
+ if (curSearchWorker != null && curSearchWorker.isRunning()) curSearchWorker.cancel();
+ if (curSuggestionWorker != null && curSuggestionWorker.isRunning()) curSuggestionWorker.cancel();
+ }
+
+ @Override
+ public void onDestroyView() {
+ if (DEBUG) Log.d(TAG, "onDestroyView() called");
+ unsetSearchListeners();
+
+ resultRecyclerView.removeAllViews();
+
+ searchToolbarContainer = null;
+ searchEditText = null;
+ searchClear = null;
+
+ resultRecyclerView = null;
+
+ super.onDestroyView();
}
@Override
public void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
- outState.putString(QUERY, searchQuery);
- outState.putInt(STREAMING_SERVICE, streamingServiceId);
+ if (DEBUG) Log.d(TAG, "onSaveInstanceState() called with: outState = [" + outState + "]");
+
+ String query = searchEditText != null && !TextUtils.isEmpty(searchEditText.getText().toString())
+ ? searchEditText.getText().toString() : searchQuery;
+ outState.putString(QUERY_KEY, query);
+ outState.putInt(SERVICE_KEY, serviceId);
+ outState.putInt(PAGE_NUMBER_KEY, pageNumber);
+ outState.putSerializable(INFO_LIST_KEY, ((ArrayList) infoListAdapter.getItemsList()));
+ outState.putBoolean(WAS_LOADING_KEY, curSearchWorker != null && curSearchWorker.isRunning());
+
+ if (errorPanel != null && errorPanel.getVisibility() == View.VISIBLE) outState.putBoolean(ERROR_KEY, true);
+ if (filterItemCheckedId != -1) outState.putInt(FILTER_CHECKED_ID_KEY, filterItemCheckedId);
}
@Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
switch (requestCode) {
- case RECAPTCHA_REQUEST:
- if (resultCode == RESULT_OK && searchQuery.length() != 0) {
- search(searchQuery);
+ case ReCaptchaActivity.RECAPTCHA_REQUEST:
+ if (resultCode == Activity.RESULT_OK && searchQuery.length() != 0) {
+ search(searchQuery, pageNumber, true);
} else Log.e(TAG, "ReCaptcha failed");
break;
@@ -251,6 +195,88 @@ public class SearchFragment extends Fragment implements SearchView.OnQueryTextLi
}
}
+ /*//////////////////////////////////////////////////////////////////////////
+ // Init's
+ //////////////////////////////////////////////////////////////////////////*/
+
+ @Override
+ protected void initViews(View rootView, Bundle savedInstanceState) {
+ super.initViews(rootView, savedInstanceState);
+ resultRecyclerView = ((RecyclerView) rootView.findViewById(R.id.result_list_view));
+ resultRecyclerView.setLayoutManager(new LinearLayoutManager(activity));
+
+ if (infoListAdapter == null) {
+ infoListAdapter = new InfoListAdapter(getActivity(), getActivity().findViewById(android.R.id.content));
+ if (savedInstanceState != null) {
+ //noinspection unchecked
+ ArrayList serializable = (ArrayList) savedInstanceState.getSerializable(INFO_LIST_KEY);
+ infoListAdapter.addInfoItemList(serializable);
+ }
+
+ infoListAdapter.setFooter(activity.getLayoutInflater().inflate(R.layout.pignate_footer, resultRecyclerView, false));
+ infoListAdapter.showFooter(false);
+ infoListAdapter.setOnStreamInfoItemSelectedListener(new InfoItemBuilder.OnInfoItemSelectedListener() {
+ @Override
+ public void selected(int serviceId, String url, String title) {
+ NavigationHelper.openVideoDetail(onItemSelectedListener, serviceId, url, title);
+ }
+ });
+ infoListAdapter.setOnChannelInfoItemSelectedListener(new InfoItemBuilder.OnInfoItemSelectedListener() {
+ @Override
+ public void selected(int serviceId, String url, String title) {
+ NavigationHelper.openChannel(onItemSelectedListener, serviceId, url, title);
+ }
+ });
+ }
+
+ resultRecyclerView.setAdapter(infoListAdapter);
+ }
+
+ @Override
+ protected void initListeners() {
+ super.initListeners();
+ resultRecyclerView.clearOnScrollListeners();
+ resultRecyclerView.addOnScrollListener(new RecyclerView.OnScrollListener() {
+ @Override
+ public void onScrolled(RecyclerView recyclerView, int dx, int dy) {
+ int pastVisiblesItems, visibleItemCount, totalItemCount;
+ super.onScrolled(recyclerView, dx, dy);
+ //check for scroll down
+ if (dy > 0) {
+ LinearLayoutManager layoutManager = (LinearLayoutManager) resultRecyclerView.getLayoutManager();
+ visibleItemCount = resultRecyclerView.getLayoutManager().getChildCount();
+ totalItemCount = resultRecyclerView.getLayoutManager().getItemCount();
+ pastVisiblesItems = layoutManager.findFirstVisibleItemPosition();
+
+ if ((visibleItemCount + pastVisiblesItems) >= totalItemCount && !isLoading.get()) {
+ pageNumber++;
+ recyclerView.post(new Runnable() {
+ @Override
+ public void run() {
+ infoListAdapter.showFooter(true);
+ }
+ });
+ search(searchQuery, pageNumber);
+ }
+ }
+ }
+ });
+ }
+
+ @Override
+ protected void reloadContent() {
+ if (DEBUG) Log.d(TAG, "reloadContent() called");
+ if (!TextUtils.isEmpty(searchQuery) || (searchEditText != null && !TextUtils.isEmpty(searchEditText.getText()))) {
+ search(!TextUtils.isEmpty(searchQuery) ? searchQuery : searchEditText.getText().toString(), 0, true);
+ } else {
+ if (searchEditText != null) {
+ searchEditText.setText("");
+ showSoftKeyboard(searchEditText);
+ }
+ animateView(errorPanel, false, 200);
+ }
+ }
+
/*//////////////////////////////////////////////////////////////////////////
// Menu
//////////////////////////////////////////////////////////////////////////*/
@@ -258,22 +284,47 @@ public class SearchFragment extends Fragment implements SearchView.OnQueryTextLi
@Override
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
super.onCreateOptionsMenu(menu, inflater);
- ActionBar supportActionBar = ((AppCompatActivity) getActivity()).getSupportActionBar();
- if (supportActionBar != null) {
- supportActionBar.setDisplayHomeAsUpEnabled(false);
- supportActionBar.setDisplayShowTitleEnabled(false);
- //noinspection deprecation
- supportActionBar.setNavigationMode(0);
- }
+ if (DEBUG) Log.d(TAG, "onCreateOptionsMenu() called with: menu = [" + menu + "], inflater = [" + inflater + "]");
inflater.inflate(R.menu.search_menu, menu);
- MenuItem searchItem = menu.findItem(R.id.action_search);
- searchView = (SearchView) searchItem.getActionView();
- setupSearchView(searchView);
+ ActionBar supportActionBar = activity.getSupportActionBar();
+ if (supportActionBar != null) {
+ supportActionBar.setDisplayShowTitleEnabled(false);
+ supportActionBar.setDisplayHomeAsUpEnabled(true);
+ }
+
+ searchToolbarContainer = activity.findViewById(R.id.toolbar_search_container);
+ searchEditText = (AutoCompleteTextView) searchToolbarContainer.findViewById(R.id.toolbar_search_edit_text);
+ searchClear = searchToolbarContainer.findViewById(R.id.toolbar_search_clear);
+ setupSearchView();
+
+ restoreFilterChecked(menu, filterItemCheckedId);
+ }
+
+ private void restoreFilterChecked(Menu menu, int itemId) {
+ if (itemId != -1) {
+ MenuItem item = menu.findItem(itemId);
+ if (item == null) return;
+
+ item.setChecked(true);
+ switch (itemId) {
+ case R.id.menu_filter_all:
+ filter = EnumSet.of(SearchEngine.Filter.STREAM, SearchEngine.Filter.CHANNEL);
+ break;
+ case R.id.menu_filter_video:
+ filter = EnumSet.of(SearchEngine.Filter.STREAM);
+ break;
+ case R.id.menu_filter_channel:
+ filter = EnumSet.of(SearchEngine.Filter.CHANNEL);
+ break;
+ }
+ }
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
+ if (DEBUG) Log.d(TAG, "onOptionsItemSelected() called with: item = [" + item + "]");
+
switch (item.getItemId()) {
case R.id.menu_filter_all:
changeFilter(item, EnumSet.of(SearchEngine.Filter.STREAM, SearchEngine.Filter.CHANNEL));
@@ -289,119 +340,238 @@ public class SearchFragment extends Fragment implements SearchView.OnQueryTextLi
}
}
+ /*//////////////////////////////////////////////////////////////////////////
+ // Search
+ //////////////////////////////////////////////////////////////////////////*/
+
+ private TextWatcher textWatcher;
+
+ private void setupSearchView() {
+ searchEditText.setText(searchQuery != null ? searchQuery : "");
+ searchEditText.setHint(getString(R.string.search) + "...");
+ ////searchEditText.setCursorVisible(true);
+
+ suggestionListAdapter = new SuggestionListAdapter(activity);
+ searchEditText.setAdapter(suggestionListAdapter);
+
+
+ if (TextUtils.isEmpty(searchQuery) || TextUtils.isEmpty(searchEditText.getText())) {
+ searchToolbarContainer.setTranslationX(100);
+ searchToolbarContainer.setAlpha(0f);
+ searchToolbarContainer.setVisibility(View.VISIBLE);
+ searchToolbarContainer.animate().translationX(0).alpha(1f).setDuration(400).setInterpolator(new DecelerateInterpolator()).start();
+ } else {
+ searchToolbarContainer.setTranslationX(0);
+ searchToolbarContainer.setAlpha(1f);
+ searchToolbarContainer.setVisibility(View.VISIBLE);
+ }
+
+ //
+ initSearchListeners();
+
+ if (TextUtils.isEmpty(searchQuery)) showSoftKeyboard(searchEditText);
+ else hideSoftKeyboard(searchEditText);
+
+ if (!TextUtils.isEmpty(searchQuery) && searchQuery.length() > 2 && suggestionListAdapter != null && suggestionListAdapter.isEmpty()) {
+ searchSuggestions(searchQuery);
+ }
+ }
+
+ private void initSearchListeners() {
+ searchClear.setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View v) {
+ if (DEBUG) Log.d(TAG, "onClick() called with: v = [" + v + "]");
+ if (TextUtils.isEmpty(searchEditText.getText())) {
+ NavigationHelper.openMainActivity(activity);
+ return;
+ }
+
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) {
+ searchEditText.setText("", false);
+ } else searchEditText.setText("");
+ suggestionListAdapter.updateAdapter(new ArrayList());
+ showSoftKeyboard(searchEditText);
+ }
+ });
+
+ searchClear.setOnLongClickListener(new View.OnLongClickListener() {
+ @Override
+ public boolean onLongClick(View v) {
+ if (DEBUG) Log.d(TAG, "onLongClick() called with: v = [" + v + "]");
+ showMenuTooltip(v, getString(R.string.clear));
+ return true;
+ }
+ });
+
+ searchEditText.setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View v) {
+ searchEditText.showDropDown();
+ }
+ });
+
+ searchEditText.setOnFocusChangeListener(new View.OnFocusChangeListener() {
+ @Override
+ public void onFocusChange(View v, boolean hasFocus) {
+ if (hasFocus) searchEditText.showDropDown();
+ }
+ });
+
+ searchEditText.setOnItemClickListener(new AdapterView.OnItemClickListener() {
+ @Override
+ public void onItemClick(AdapterView> parent, View view, int position, long id) {
+ if (DEBUG) Log.d(TAG, "onItemClick() called with: parent = [" + parent + "], view = [" + view + "], position = [" + position + "], id = [" + id + "]");
+ String s = suggestionListAdapter.getSuggestion(position);
+ if (DEBUG) Log.d(TAG, "onItemClick text = " + s);
+ submitQuery(s);
+ }
+ });
+
+
+ if (textWatcher != null) searchEditText.removeTextChangedListener(textWatcher);
+ textWatcher = new TextWatcher() {
+ @Override
+ public void beforeTextChanged(CharSequence s, int start, int count, int after) {
+ }
+
+ @Override
+ public void onTextChanged(CharSequence s, int start, int before, int count) {
+ }
+
+ @Override
+ public void afterTextChanged(Editable s) {
+ String newText = searchEditText.getText().toString();
+ if (!TextUtils.isEmpty(newText) && newText.length() > 1) onQueryTextChange(newText);
+ }
+ };
+ searchEditText.addTextChangedListener(textWatcher);
+
+ searchEditText.setOnEditorActionListener(new TextView.OnEditorActionListener() {
+ @Override
+ public boolean onEditorAction(TextView v, int actionId, KeyEvent event) {
+ if (DEBUG) Log.d(TAG, "onEditorAction() called with: v = [" + v + "], actionId = [" + actionId + "], event = [" + event + "]");
+ if (event != null && (event.getKeyCode() == KeyEvent.KEYCODE_ENTER || event.getAction() == EditorInfo.IME_ACTION_SEARCH)) {
+ submitQuery(searchEditText.getText().toString());
+ return true;
+ }
+ return false;
+ }
+ });
+ }
+
+ private void unsetSearchListeners() {
+ searchClear.setOnClickListener(null);
+ searchClear.setOnLongClickListener(null);
+ if (textWatcher != null) searchEditText.removeTextChangedListener(textWatcher);
+ searchEditText.setOnClickListener(null);
+ searchEditText.setOnItemClickListener(null);
+ searchEditText.setOnFocusChangeListener(null);
+ searchEditText.setOnEditorActionListener(null);
+
+ textWatcher = null;
+ }
+
+ public void showSoftKeyboard(View view) {
+ if (DEBUG) Log.d(TAG, "showSoftKeyboard() called with: view = [" + view + "]");
+ if (view == null) return;
+
+ if (view.requestFocus()) {
+ InputMethodManager imm = (InputMethodManager) activity.getSystemService(Context.INPUT_METHOD_SERVICE);
+ imm.showSoftInput(view, InputMethodManager.SHOW_IMPLICIT);
+ }
+ }
+
+ public void hideSoftKeyboard(View view) {
+ if (DEBUG) Log.d(TAG, "hideSoftKeyboard() called with: view = [" + view + "]");
+ if (view == null) return;
+
+ InputMethodManager imm = (InputMethodManager) activity.getSystemService(Context.INPUT_METHOD_SERVICE);
+ imm.hideSoftInputFromWindow(view.getWindowToken(), InputMethodManager.HIDE_NOT_ALWAYS);
+
+ view.clearFocus();
+ }
+
/*//////////////////////////////////////////////////////////////////////////
// Utils
//////////////////////////////////////////////////////////////////////////*/
private void changeFilter(MenuItem item, EnumSet filter) {
this.filter = filter;
+ this.filterItemCheckedId = item.getItemId();
item.setChecked(true);
- if (searchQuery != null && !searchQuery.isEmpty()) {
- Log.e(TAG, "Fuck+ " + searchQuery);
- search(searchQuery);
- }
+ if (searchQuery != null && !searchQuery.isEmpty()) search(searchQuery, 0, true);
}
- private void setupSearchView(SearchView searchView) {
- suggestionListAdapter = new SuggestionListAdapter(getActivity());
- searchView.setSuggestionsAdapter(suggestionListAdapter);
- searchView.setOnSuggestionListener(new SearchSuggestionListener(searchView, suggestionListAdapter));
- searchView.setOnQueryTextListener(this);
- if (searchQuery != null && !searchQuery.isEmpty()) {
- searchView.setQuery(searchQuery, false);
- searchView.setIconifiedByDefault(false);
- }
- }
-
- private void search(String query) {
- infoListAdapter.clearSteamItemList();
- infoListAdapter.showFooter(false);
- pageNumber = 0;
+ public void submitQuery(String query) {
+ if (DEBUG) Log.d(TAG, "submitQuery() called with: query = [" + query + "]");
+ if (query.isEmpty()) return;
+ search(query, 0, true);
searchQuery = query;
- search(query, pageNumber);
- hideBackground();
- loadingIndicator.setVisibility(View.VISIBLE);
}
- private void search(String query, int page) {
- isLoading = true;
- SearchWorker sw = SearchWorker.getInstance();
- sw.search(streamingServiceId,
- query,
- page,
- getActivity(),
- filter);
+ public void onQueryTextChange(String newText) {
+ if (DEBUG) Log.d(TAG, "onQueryTextChange() called with: newText = [" + newText + "]");
+ if (!newText.isEmpty()) searchSuggestions(newText);
}
- private void setDoneLoading() {
- isLoading = false;
- loadingIndicator.setVisibility(View.GONE);
- infoListAdapter.showFooter(false);
- }
-
- /**
- * Hides the "dummy" background when no results are shown
- */
- private void hideBackground() {
- View view = getView();
- if (view == null) return;
- view.findViewById(R.id.mainBG).setVisibility(View.GONE);
+ private void setQuery(int serviceId, String searchQuery) {
+ this.serviceId = serviceId;
+ this.searchQuery = searchQuery;
}
private void searchSuggestions(String query) {
- SuggestionSearchRunnable suggestionSearchRunnable =
- new SuggestionSearchRunnable(streamingServiceId, query, getActivity(), suggestionListAdapter);
- Thread suggestionThread = new Thread(suggestionSearchRunnable);
- suggestionThread.start();
+ if (DEBUG) Log.d(TAG, "searchSuggestions() called with: query = [" + query + "]");
+ if (curSuggestionWorker != null && curSuggestionWorker.isRunning()) curSuggestionWorker.cancel();
+ curSuggestionWorker = SuggestionWorker.startForQuery(activity, serviceId, query, this);
}
- public boolean isMainBgVisible() {
- return getActivity().findViewById(R.id.mainBG).getVisibility() == View.VISIBLE;
+ private void search(String query, int pageNumber) {
+ if (DEBUG) Log.d(TAG, "search() called with: query = [" + query + "], pageNumber = [" + pageNumber + "]");
+ search(query, pageNumber, false);
+ }
+
+ private void search(String query, int pageNumber, boolean clearList) {
+ if (DEBUG) Log.d(TAG, "search() called with: query = [" + query + "], pageNumber = [" + pageNumber + "], clearList = [" + clearList + "]");
+ isLoading.set(true);
+ hideSoftKeyboard(searchEditText);
+
+ searchQuery = query;
+ this.pageNumber = pageNumber;
+
+ if (clearList) {
+ animateView(resultRecyclerView, false, 50);
+ infoListAdapter.clearStreamItemList();
+ infoListAdapter.showFooter(false);
+ animateView(loadingProgressBar, true, 200);
+ }
+ animateView(errorPanel, false, 200);
+
+ if (curSearchWorker != null && curSearchWorker.isRunning()) curSearchWorker.cancel();
+ curSearchWorker = SearchWorker.startForQuery(activity, serviceId, query, pageNumber, filter, this);
+ }
+
+ protected void setErrorMessage(String message, boolean showRetryButton) {
+ super.setErrorMessage(message, showRetryButton);
+
+ animateView(resultRecyclerView, false, 400);
+ hideSoftKeyboard(searchEditText);
}
/*//////////////////////////////////////////////////////////////////////////
- // OnQueryTextListener
+ // OnSuggestionResult
//////////////////////////////////////////////////////////////////////////*/
@Override
- public boolean onQueryTextSubmit(String query) {
- Activity a = getActivity();
- try {
- search(query);
-
- // hide virtual keyboard
- InputMethodManager inputManager =
- (InputMethodManager) a.getSystemService(Context.INPUT_METHOD_SERVICE);
- try {
- //noinspection ConstantConditions
- inputManager.hideSoftInputFromWindow(
- a.getCurrentFocus().getWindowToken(), InputMethodManager.HIDE_NOT_ALWAYS);
- } catch (NullPointerException e) {
- e.printStackTrace();
- ErrorActivity.reportError(a, e, null,
- a.findViewById(android.R.id.content),
- ErrorActivity.ErrorInfo.make(ErrorActivity.SEARCHED,
- NewPipe.getNameOfService(streamingServiceId),
- "Could not get widget with focus", R.string.general_error));
- }
- // clear focus
- // 1. to not open up the keyboard after switching back to this
- // 2. It's a workaround to a seeming bug by the Android OS it self, causing
- // onQueryTextSubmit to trigger twice when focus is not cleared.
- // See: http://stackoverflow.com/questions/17874951/searchview-onquerytextsubmit-runs-twice-while-i-pressed-once
- a.getCurrentFocus().clearFocus();
- } catch (Exception e) {
- e.printStackTrace();
- }
- return true;
+ public void onSuggestionResult(@NonNull List suggestions) {
+ if (DEBUG) Log.d(TAG, "onSuggestionResult() called with: suggestions = [" + suggestions + "]");
+ suggestionListAdapter.updateAdapter(suggestions);
}
@Override
- public boolean onQueryTextChange(String newText) {
- if (!newText.isEmpty()) {
- searchSuggestions(newText);
- }
- return true;
+ public void onSuggestionError(int messageId) {
+ if (DEBUG) Log.d(TAG, "onSuggestionError() called with: messageId = [" + messageId + "]");
+ setErrorMessage(getString(messageId), true);
}
/*//////////////////////////////////////////////////////////////////////////
@@ -409,32 +579,35 @@ public class SearchFragment extends Fragment implements SearchView.OnQueryTextLi
//////////////////////////////////////////////////////////////////////////*/
@Override
- public void onResult(SearchResult result) {
+ public void onSearchResult(SearchResult result) {
+ if (DEBUG) Log.d(TAG, "onSearchResult() called with: result = [" + result + "]");
infoListAdapter.addInfoItemList(result.resultList);
- setDoneLoading();
+ animateView(resultRecyclerView, true, 400);
+ animateView(loadingProgressBar, false, 200);
+ isLoading.set(false);
}
@Override
- public void onNothingFound(int stringResource) {
- //setListShown(true);
- Toast.makeText(getActivity(), getString(stringResource), Toast.LENGTH_SHORT).show();
- setDoneLoading();
+ public void onNothingFound(String message) {
+ if (DEBUG) Log.d(TAG, "onNothingFound() called with: messageId = [" + message + "]");
+ setErrorMessage(message, false);
}
@Override
- public void onError(String message) {
- //setListShown(true);
- Toast.makeText(getActivity(), message, Toast.LENGTH_LONG).show();
- setDoneLoading();
+ public void onSearchError(int messageId) {
+ if (DEBUG) Log.d(TAG, "onSearchError() called with: messageId = [" + messageId + "]");
+ //Toast.makeText(getActivity(), messageId, Toast.LENGTH_LONG).show();
+ setErrorMessage(getString(messageId), true);
}
@Override
public void onReCaptchaChallenge() {
- Toast.makeText(getActivity(), "ReCaptcha Challenge requested",
- Toast.LENGTH_LONG).show();
+ if (DEBUG) Log.d(TAG, "onReCaptchaChallenge() called");
+ Toast.makeText(getActivity(), R.string.recaptcha_request_toast, Toast.LENGTH_LONG).show();
+ setErrorMessage(getString(R.string.recaptcha_request_toast), false);
// Starting ReCaptcha Challenge Activity
- startActivityForResult(new Intent(getActivity(), ReCaptchaActivity.class), RECAPTCHA_REQUEST);
+ startActivityForResult(new Intent(getActivity(), ReCaptchaActivity.class), ReCaptchaActivity.RECAPTCHA_REQUEST);
}
}
diff --git a/app/src/main/java/org/schabi/newpipe/fragments/search/SuggestionListAdapter.java b/app/src/main/java/org/schabi/newpipe/fragments/search/SuggestionListAdapter.java
index b8ecaad1d..dda698a78 100644
--- a/app/src/main/java/org/schabi/newpipe/fragments/search/SuggestionListAdapter.java
+++ b/app/src/main/java/org/schabi/newpipe/fragments/search/SuggestionListAdapter.java
@@ -75,6 +75,11 @@ public class SuggestionListAdapter extends ResourceCursorAdapter {
return ((Cursor) getItem(position)).getString(INDEX_TITLE);
}
+ @Override
+ public CharSequence convertToString(Cursor cursor) {
+ return cursor.getString(INDEX_TITLE);
+ }
+
private class ViewHolder {
private final TextView suggestionTitle;
private ViewHolder(View view) {
diff --git a/app/src/main/java/org/schabi/newpipe/info_list/ChannelInfoItemHolder.java b/app/src/main/java/org/schabi/newpipe/info_list/ChannelInfoItemHolder.java
index d47c63cdb..29eaafcd9 100644
--- a/app/src/main/java/org/schabi/newpipe/info_list/ChannelInfoItemHolder.java
+++ b/app/src/main/java/org/schabi/newpipe/info_list/ChannelInfoItemHolder.java
@@ -1,7 +1,6 @@
package org.schabi.newpipe.info_list;
import android.view.View;
-import android.widget.Button;
import android.widget.TextView;
import org.schabi.newpipe.R;
@@ -35,16 +34,17 @@ public class ChannelInfoItemHolder extends InfoItemHolder {
public final TextView itemSubscriberCountView;
public final TextView itemVideoCountView;
public final TextView itemChannelDescriptionView;
- public final Button itemButton;
+
+ public final View itemRoot;
ChannelInfoItemHolder(View v) {
super(v);
+ itemRoot = v.findViewById(R.id.itemRoot);
itemThumbnailView = (CircleImageView) v.findViewById(R.id.itemThumbnailView);
itemChannelTitleView = (TextView) v.findViewById(R.id.itemChannelTitleView);
itemSubscriberCountView = (TextView) v.findViewById(R.id.itemSubscriberCountView);
itemVideoCountView = (TextView) v.findViewById(R.id.itemVideoCountView);
itemChannelDescriptionView = (TextView) v.findViewById(R.id.itemChannelDescriptionView);
- itemButton = (Button) v.findViewById(R.id.item_button);
}
@Override
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 20dda18a2..f83d954a2 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
@@ -1,6 +1,7 @@
package org.schabi.newpipe.info_list;
import android.content.Context;
+import android.text.TextUtils;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
@@ -18,20 +19,20 @@ import org.schabi.newpipe.extractor.stream_info.StreamInfoItem;
/**
* Created by Christian Schabesberger on 26.09.16.
- *
+ *
* Copyright (C) Christian Schabesberger 2016
* InfoItemBuilder.java is part of NewPipe.
- *
+ *
* NewPipe 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.
- *
+ *
* NewPipe 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 NewPipe. If not, see .
*/
@@ -48,11 +49,13 @@ public class InfoItemBuilder {
private final String billion;
private static final String TAG = InfoItemBuilder.class.toString();
+
public interface OnInfoItemSelectedListener {
void selected(int serviceId, String url, String title);
}
private Context mContext = null;
+ private LayoutInflater inflater;
private View rootView = null;
private ImageLoader imageLoader = ImageLoader.getInstance();
private DisplayImageOptions displayImageOptions =
@@ -70,6 +73,7 @@ public class InfoItemBuilder {
thousand = context.getString(R.string.short_thousand);
million = context.getString(R.string.short_million);
billion = context.getString(R.string.short_billion);
+ inflater = LayoutInflater.from(context);
}
public void setOnStreamInfoItemSelectedListener(
@@ -83,9 +87,9 @@ public class InfoItemBuilder {
}
public void buildByHolder(InfoItemHolder holder, final InfoItem i) {
- if(i.infoType() != holder.infoType())
+ if (i.infoType() != holder.infoType())
return;
- switch(i.infoType()) {
+ switch (i.infoType()) {
case STREAM:
buildStreamInfoItem((StreamInfoItemHolder) holder, (StreamInfoItem) i);
break;
@@ -103,15 +107,15 @@ public class InfoItemBuilder {
public View buildView(ViewGroup parent, final InfoItem info) {
View itemView = null;
InfoItemHolder holder = null;
- switch(info.infoType()) {
+ switch (info.infoType()) {
case STREAM:
- itemView = LayoutInflater.from(parent.getContext())
- .inflate(R.layout.stream_item, parent, false);
+ //long start = System.nanoTime();
+ itemView = inflater.inflate(R.layout.stream_item, parent, false);
+ //Log.d(TAG, "time to inflate: " + ((System.nanoTime() - start) / 1000000L) + "ms");
holder = new StreamInfoItemHolder(itemView);
break;
case CHANNEL:
- itemView = LayoutInflater.from(parent.getContext())
- .inflate(R.layout.channel_item, parent, false);
+ itemView = inflater.inflate(R.layout.channel_item, parent, false);
holder = new ChannelInfoItemHolder(itemView);
break;
case PLAYLIST:
@@ -124,43 +128,39 @@ public class InfoItemBuilder {
}
private void buildStreamInfoItem(StreamInfoItemHolder holder, final StreamInfoItem info) {
- if(info.infoType() != InfoItem.InfoType.STREAM) {
+ if (info.infoType() != InfoItem.InfoType.STREAM) {
Log.e("InfoItemBuilder", "Info type not yet supported");
}
// fill holder with information
- holder.itemVideoTitleView.setText(info.title);
- if(info.uploader != null && !info.uploader.isEmpty()) {
- holder.itemUploaderView.setText(info.uploader);
- } else {
- holder.itemUploaderView.setVisibility(View.INVISIBLE);
- }
- if(info.duration > 0) {
+ if (!TextUtils.isEmpty(info.title)) holder.itemVideoTitleView.setText(info.title);
+
+ if (!TextUtils.isEmpty(info.uploader)) holder.itemUploaderView.setText(info.uploader);
+ else holder.itemUploaderView.setVisibility(View.INVISIBLE);
+
+ if (info.duration > 0) {
holder.itemDurationView.setText(getDurationString(info.duration));
} else {
- if(info.stream_type == AbstractStreamInfo.StreamType.LIVE_STREAM) {
+ if (info.stream_type == AbstractStreamInfo.StreamType.LIVE_STREAM) {
holder.itemDurationView.setText(R.string.duration_live);
} else {
holder.itemDurationView.setVisibility(View.GONE);
}
}
- if(info.view_count >= 0) {
+ if (info.view_count >= 0) {
holder.itemViewCountView.setText(shortViewCount(info.view_count));
} else {
holder.itemViewCountView.setVisibility(View.GONE);
}
- if(info.upload_date != null && !info.upload_date.isEmpty()) {
- holder.itemUploadDateView.setText(info.upload_date + " • ");
- }
+ if (!TextUtils.isEmpty(info.upload_date)) holder.itemUploadDateView.setText(info.upload_date + " • ");
holder.itemThumbnailView.setImageResource(R.drawable.dummy_thumbnail);
- if(info.thumbnail_url != null && !info.thumbnail_url.isEmpty()) {
+ if (!TextUtils.isEmpty(info.thumbnail_url)) {
imageLoader.displayImage(info.thumbnail_url,
- holder.itemThumbnailView,
- displayImageOptions,
+ holder.itemThumbnailView, displayImageOptions,
new ImageErrorLoadingListener(mContext, rootView, info.service_id));
}
- holder.itemButton.setOnClickListener(new View.OnClickListener() {
+ holder.itemRoot.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
onStreamInfoItemSelectedListener.selected(info.service_id, info.webpage_url, info.getTitle());
@@ -169,20 +169,20 @@ public class InfoItemBuilder {
}
private void buildChannelInfoItem(ChannelInfoItemHolder holder, final ChannelInfoItem info) {
- holder.itemChannelTitleView.setText(info.getTitle());
+ if (!TextUtils.isEmpty(info.getTitle())) holder.itemChannelTitleView.setText(info.getTitle());
holder.itemSubscriberCountView.setText(shortSubscriber(info.subscriberCount) + " • ");
holder.itemVideoCountView.setText(info.videoAmount + " " + videosS);
- holder.itemChannelDescriptionView.setText(info.description);
+ if (!TextUtils.isEmpty(info.description)) holder.itemChannelDescriptionView.setText(info.description);
holder.itemThumbnailView.setImageResource(R.drawable.buddy_channel_item);
- if(info.thumbnailUrl != null && !info.thumbnailUrl.isEmpty()) {
+ if (!TextUtils.isEmpty(info.thumbnailUrl)) {
imageLoader.displayImage(info.thumbnailUrl,
holder.itemThumbnailView,
displayImageOptions,
new ImageErrorLoadingListener(mContext, rootView, info.serviceId));
}
- holder.itemButton.setOnClickListener(new View.OnClickListener() {
+ holder.itemRoot.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
onChannelInfoItemSelectedListener.selected(info.serviceId, info.getLink(), info.channelName);
@@ -191,15 +191,15 @@ public class InfoItemBuilder {
}
- public String shortViewCount(Long viewCount){
- if(viewCount >= 1000000000){
- return Long.toString(viewCount/1000000000)+ billion + " " + viewsS;
- }else if(viewCount>=1000000){
- return Long.toString(viewCount/1000000)+ million + " " + viewsS;
- }else if(viewCount>=1000){
- return Long.toString(viewCount/1000)+ thousand + " " + viewsS;
- }else {
- return Long.toString(viewCount)+ " " + viewsS;
+ public String shortViewCount(Long viewCount) {
+ if (viewCount >= 1000000000) {
+ return Long.toString(viewCount / 1000000000) + billion + " " + viewsS;
+ } else if (viewCount >= 1000000) {
+ return Long.toString(viewCount / 1000000) + million + " " + viewsS;
+ } else if (viewCount >= 1000) {
+ return Long.toString(viewCount / 1000) + thousand + " " + viewsS;
+ } else {
+ return Long.toString(viewCount) + " " + viewsS;
}
}
@@ -227,13 +227,13 @@ public class InfoItemBuilder {
int seconds = duration % 60;
//handle days
- if(days > 0) {
+ if (days > 0) {
output = Integer.toString(days) + ":";
}
// handle hours
- if(hours > 0 || !output.isEmpty()) {
- if(hours > 0) {
- if(hours >= 10 || output.isEmpty()) {
+ if (hours > 0 || !output.isEmpty()) {
+ if (hours > 0) {
+ if (hours >= 10 || output.isEmpty()) {
output += Integer.toString(hours);
} else {
output += "0" + Integer.toString(hours);
@@ -244,9 +244,9 @@ public class InfoItemBuilder {
output += ":";
}
//handle minutes
- if(minutes > 0 || !output.isEmpty()) {
- if(minutes > 0) {
- if(minutes >= 10 || output.isEmpty()) {
+ if (minutes > 0 || !output.isEmpty()) {
+ if (minutes > 0) {
+ if (minutes >= 10 || output.isEmpty()) {
output += Integer.toString(minutes);
} else {
output += "0" + Integer.toString(minutes);
@@ -258,11 +258,11 @@ public class InfoItemBuilder {
}
//handle seconds
- if(output.isEmpty()) {
+ if (output.isEmpty()) {
output += "0:";
}
- if(seconds >= 10) {
+ if (seconds >= 10) {
output += Integer.toString(seconds);
} else {
output += "0" + Integer.toString(seconds);
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 d6f173350..e17e2aaac 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
@@ -10,8 +10,8 @@ import android.view.ViewGroup;
import org.schabi.newpipe.R;
import org.schabi.newpipe.extractor.InfoItem;
+import java.util.ArrayList;
import java.util.List;
-import java.util.Vector;
/**
* Created by Christian Schabesberger on 01.08.16.
@@ -57,7 +57,7 @@ public class InfoListAdapter extends RecyclerView.Adapter();
+ infoItemList = new ArrayList<>();
}
public void setOnStreamInfoItemSelectedListener
@@ -77,7 +77,7 @@ public class InfoListAdapter extends RecyclerView.Adapter getItemsList() {
+ return infoItemList;
+ }
+
@Override
public int getItemCount() {
- int cound = infoItemList.size();
- if(header != null) cound++;
- if(footer != null && showFooter) cound++;
- return cound;
+ int count = infoItemList.size();
+ if(header != null) count++;
+ if(footer != null && showFooter) count++;
+ return count;
}
// don't ask why we have to do that this way... it's android accept it -.-
diff --git a/app/src/main/java/org/schabi/newpipe/info_list/StreamInfoItemHolder.java b/app/src/main/java/org/schabi/newpipe/info_list/StreamInfoItemHolder.java
index 81981fd82..a527cd300 100644
--- a/app/src/main/java/org/schabi/newpipe/info_list/StreamInfoItemHolder.java
+++ b/app/src/main/java/org/schabi/newpipe/info_list/StreamInfoItemHolder.java
@@ -1,9 +1,6 @@
package org.schabi.newpipe.info_list;
-import android.icu.text.IDNA;
-import android.support.v7.widget.RecyclerView;
import android.view.View;
-import android.widget.Button;
import android.widget.ImageView;
import android.widget.TextView;
@@ -12,20 +9,20 @@ import org.schabi.newpipe.extractor.InfoItem;
/**
* Created by Christian Schabesberger on 01.08.16.
- *
+ *
* Copyright (C) Christian Schabesberger 2016
* StreamInfoItemHolder.java is part of NewPipe.
- *
+ *
* NewPipe 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.
- *
+ *
* NewPipe 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 NewPipe. If not, see .
*/
@@ -38,17 +35,17 @@ public class StreamInfoItemHolder extends InfoItemHolder {
itemDurationView,
itemUploadDateView,
itemViewCountView;
- public final Button itemButton;
+ public final View itemRoot;
public StreamInfoItemHolder(View v) {
super(v);
+ itemRoot = v.findViewById(R.id.itemRoot);
itemThumbnailView = (ImageView) v.findViewById(R.id.itemThumbnailView);
itemVideoTitleView = (TextView) v.findViewById(R.id.itemVideoTitleView);
itemUploaderView = (TextView) v.findViewById(R.id.itemUploaderView);
itemDurationView = (TextView) v.findViewById(R.id.itemDurationView);
itemUploadDateView = (TextView) v.findViewById(R.id.itemUploadDateView);
itemViewCountView = (TextView) v.findViewById(R.id.itemViewCountView);
- itemButton = (Button) v.findViewById(R.id.item_button);
}
@Override
diff --git a/app/src/main/java/org/schabi/newpipe/settings/SettingsActivity.java b/app/src/main/java/org/schabi/newpipe/settings/SettingsActivity.java
index 1ad2747a7..a1e8fb49b 100644
--- a/app/src/main/java/org/schabi/newpipe/settings/SettingsActivity.java
+++ b/app/src/main/java/org/schabi/newpipe/settings/SettingsActivity.java
@@ -1,18 +1,11 @@
package org.schabi.newpipe.settings;
import android.content.Context;
-import android.content.Intent;
-import android.content.res.Configuration;
import android.os.Bundle;
-import android.preference.PreferenceActivity;
-import android.support.annotation.LayoutRes;
-import android.support.annotation.NonNull;
import android.support.v7.app.ActionBar;
-import android.support.v7.app.AppCompatDelegate;
-import android.view.MenuInflater;
+import android.support.v7.app.AppCompatActivity;
+import android.support.v7.widget.Toolbar;
import android.view.MenuItem;
-import android.view.View;
-import android.view.ViewGroup;
import org.schabi.newpipe.R;
import org.schabi.newpipe.util.ThemeHelper;
@@ -38,9 +31,7 @@ import org.schabi.newpipe.util.ThemeHelper;
* along with NewPipe. If not, see .
*/
-public class SettingsActivity extends PreferenceActivity {
- SettingsFragment f = new SettingsFragment();
- private AppCompatDelegate mDelegate = null;
+public class SettingsActivity extends AppCompatActivity {
public static void initSettings(Context context) {
NewPipeSettings.initSettings(context);
@@ -48,104 +39,25 @@ public class SettingsActivity extends PreferenceActivity {
@Override
protected void onCreate(Bundle savedInstanceBundle) {
- ThemeHelper.setTheme(this, true);
- getDelegate().installViewFactory();
- getDelegate().onCreate(savedInstanceBundle);
+ ThemeHelper.setTheme(this);
super.onCreate(savedInstanceBundle);
+ setContentView(R.layout.settings_layout);
+
+ Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
+ setSupportActionBar(toolbar);
ActionBar actionBar = getSupportActionBar();
- actionBar.setDisplayHomeAsUpEnabled(true);
- actionBar.setTitle(R.string.settings_title);
- actionBar.setDisplayShowTitleEnabled(true);
+ if (actionBar != null) {
+ actionBar.setDisplayHomeAsUpEnabled(true);
+ actionBar.setTitle(R.string.settings_title);
+ actionBar.setDisplayShowTitleEnabled(true);
+ }
getFragmentManager().beginTransaction()
- .replace(android.R.id.content, f)
+ .replace(R.id.fragment_holder, new SettingsFragment())
.commit();
}
- @Override
- protected void onActivityResult(int requestCode, int resultCode, Intent data) {
- super.onActivityResult(requestCode, resultCode, data);
- f.onActivityResult(requestCode, resultCode, data);
- }
-
- @Override
- protected void onPostCreate(Bundle savedInstanceState) {
- super.onPostCreate(savedInstanceState);
- getDelegate().onPostCreate(savedInstanceState);
- }
-
- private ActionBar getSupportActionBar() {
- return getDelegate().getSupportActionBar();
- }
-
- @NonNull
- @Override
- public MenuInflater getMenuInflater() {
- return getDelegate().getMenuInflater();
- }
-
- @Override
- public void setContentView(@LayoutRes int layoutResID) {
- getDelegate().setContentView(layoutResID);
- }
-
- @Override
- public void setContentView(View view) {
- getDelegate().setContentView(view);
- }
-
- @Override
- public void setContentView(View view, ViewGroup.LayoutParams params) {
- getDelegate().setContentView(view, params);
- }
-
- @Override
- public void addContentView(View view, ViewGroup.LayoutParams params) {
- getDelegate().addContentView(view, params);
- }
-
- @Override
- protected void onPostResume() {
- super.onPostResume();
- getDelegate().onPostResume();
- }
-
- @Override
- protected void onTitleChanged(CharSequence title, int color) {
- super.onTitleChanged(title, color);
- getDelegate().setTitle(title);
- }
-
- @Override
- public void onConfigurationChanged(Configuration newConfig) {
- super.onConfigurationChanged(newConfig);
- getDelegate().onConfigurationChanged(newConfig);
- }
-
- @Override
- protected void onStop() {
- super.onStop();
- getDelegate().onStop();
- }
-
- @Override
- protected void onDestroy() {
- super.onDestroy();
- getDelegate().onDestroy();
- }
-
- public void invalidateOptionsMenu() {
- getDelegate().invalidateOptionsMenu();
- }
-
- private AppCompatDelegate getDelegate() {
- if (mDelegate == null) {
- mDelegate = AppCompatDelegate.create(this, null);
- }
- return mDelegate;
- }
-
@Override
public boolean onOptionsItemSelected(MenuItem item) {
int id = item.getItemId();
diff --git a/app/src/main/java/org/schabi/newpipe/settings/SettingsFragment.java b/app/src/main/java/org/schabi/newpipe/settings/SettingsFragment.java
index 5ca2fb180..8ac9b0b41 100644
--- a/app/src/main/java/org/schabi/newpipe/settings/SettingsFragment.java
+++ b/app/src/main/java/org/schabi/newpipe/settings/SettingsFragment.java
@@ -1,205 +1,84 @@
package org.schabi.newpipe.settings;
import android.app.Activity;
-import android.content.ClipData;
-import android.content.DialogInterface;
import android.content.Intent;
import android.content.SharedPreferences;
-import android.net.Uri;
-import android.os.Build;
import android.os.Bundle;
-import android.preference.ListPreference;
import android.preference.Preference;
import android.preference.PreferenceFragment;
import android.preference.PreferenceManager;
import android.preference.PreferenceScreen;
-import android.support.v7.app.AlertDialog;
+import android.text.TextUtils;
+import android.util.Log;
import com.nononsenseapps.filepicker.FilePickerActivity;
import org.schabi.newpipe.App;
import org.schabi.newpipe.MainActivity;
import org.schabi.newpipe.R;
-
-import java.util.ArrayList;
+import org.schabi.newpipe.util.Constants;
import info.guardianproject.netcipher.proxy.OrbotHelper;
-/**
- * Created by david on 15/06/16.
- *
- * Copyright (C) Christian Schabesberger 2016
- * SettingsFragment.java is part of NewPipe.
- *
- * NewPipe 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.
- *
- * NewPipe 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 NewPipe. If not, see .
- */
+public class SettingsFragment extends PreferenceFragment implements SharedPreferences.OnSharedPreferenceChangeListener {
+ private static final int REQUEST_INSTALL_ORBOT = 0x1234;
+ private static final int REQUEST_DOWNLOAD_PATH = 0x1235;
+ private static final int REQUEST_DOWNLOAD_AUDIO_PATH = 0x1236;
-public class SettingsFragment extends PreferenceFragment
- implements SharedPreferences.OnSharedPreferenceChangeListener
-{
- public static final int REQUEST_INSTALL_ORBOT = 0x1234;
- SharedPreferences.OnSharedPreferenceChangeListener prefListener;
- // get keys
- String DEFAULT_RESOLUTION_PREFERENCE;
- String DEFAULT_POPUP_RESOLUTION_PREFERENCE;
- String PREFERRED_VIDEO_FORMAT_PREFERENCE;
- String DEFAULT_AUDIO_FORMAT_PREFERENCE;
- String SEARCH_LANGUAGE_PREFERENCE;
- String DOWNLOAD_PATH_PREFERENCE;
- String DOWNLOAD_PATH_AUDIO_PREFERENCE;
- String USE_TOR_KEY;
- String THEME;
- private ListPreference defaultResolutionPreference;
- private ListPreference defaultPopupResolutionPreference;
- private ListPreference preferredVideoFormatPreference;
- private ListPreference defaultAudioFormatPreference;
- private ListPreference searchLanguagePreference;
- private Preference downloadPathPreference;
- private Preference downloadPathAudioPreference;
- private Preference themePreference;
+ private String DOWNLOAD_PATH_PREFERENCE;
+ private String DOWNLOAD_PATH_AUDIO_PREFERENCE;
+ private String USE_TOR_KEY;
+ private String THEME;
+
+ private String currentTheme;
private SharedPreferences defaultPreferences;
+ private Activity activity;
+
@Override
public void onCreate(final Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
+ activity = getActivity();
addPreferencesFromResource(R.xml.settings);
- final Activity activity = getActivity();
-
defaultPreferences = PreferenceManager.getDefaultSharedPreferences(activity);
+ initKeys();
+ updatePreferencesSummary();
- // get keys
- DEFAULT_RESOLUTION_PREFERENCE = getString(R.string.default_resolution_key);
- DEFAULT_POPUP_RESOLUTION_PREFERENCE = getString(R.string.default_popup_resolution_key);
- PREFERRED_VIDEO_FORMAT_PREFERENCE = getString(R.string.preferred_video_format_key);
- DEFAULT_AUDIO_FORMAT_PREFERENCE = getString(R.string.default_audio_format_key);
- SEARCH_LANGUAGE_PREFERENCE = getString(R.string.search_language_key);
+ currentTheme = defaultPreferences.getString(THEME, getString(R.string.default_theme_value));
+ }
+
+ @Override
+ public void onResume() {
+ super.onResume();
+ defaultPreferences.registerOnSharedPreferenceChangeListener(this);
+ }
+
+ @Override
+ public void onStop() {
+ super.onStop();
+ defaultPreferences.unregisterOnSharedPreferenceChangeListener(this);
+ }
+
+ private void initKeys() {
DOWNLOAD_PATH_PREFERENCE = getString(R.string.download_path_key);
DOWNLOAD_PATH_AUDIO_PREFERENCE = getString(R.string.download_path_audio_key);
THEME = getString(R.string.theme_key);
USE_TOR_KEY = getString(R.string.use_tor_key);
-
- // get pref objects
- defaultResolutionPreference =
- (ListPreference) findPreference(DEFAULT_RESOLUTION_PREFERENCE);
- defaultPopupResolutionPreference =
- (ListPreference) findPreference(DEFAULT_POPUP_RESOLUTION_PREFERENCE);
- preferredVideoFormatPreference =
- (ListPreference) findPreference(PREFERRED_VIDEO_FORMAT_PREFERENCE);
- defaultAudioFormatPreference =
- (ListPreference) findPreference(DEFAULT_AUDIO_FORMAT_PREFERENCE);
- searchLanguagePreference =
- (ListPreference) findPreference(SEARCH_LANGUAGE_PREFERENCE);
- downloadPathPreference = findPreference(DOWNLOAD_PATH_PREFERENCE);
- downloadPathAudioPreference = findPreference(DOWNLOAD_PATH_AUDIO_PREFERENCE);
- themePreference = findPreference(THEME);
-
- final String currentTheme = defaultPreferences.getString(THEME, "Light");
-
- // TODO: Clean this, as the class is already implementing the class
- // and those double equals...
-
- prefListener = new SharedPreferences.OnSharedPreferenceChangeListener() {
- @Override
- public void onSharedPreferenceChanged(SharedPreferences sharedPreferences,
- String key) {
- Activity a = getActivity();
- if(a == null)
- {
- return;
- }
- if (key == USE_TOR_KEY)
- {
- if (defaultPreferences.getBoolean(USE_TOR_KEY, false)) {
- if (OrbotHelper.isOrbotInstalled(a)) {
- App.configureTor(true);
- OrbotHelper.requestStartTor(a);
- } else {
- Intent intent = OrbotHelper.getOrbotInstallIntent(a);
- a.startActivityForResult(intent, REQUEST_INSTALL_ORBOT);
- }
- } else {
- App.configureTor(false);
- }
- }
- else if (key == DOWNLOAD_PATH_PREFERENCE)
- {
- String downloadPath = sharedPreferences
- .getString(DOWNLOAD_PATH_PREFERENCE,
- getString(R.string.download_path_summary));
- downloadPathPreference
- .setSummary(downloadPath);
- }
- else if (key == DOWNLOAD_PATH_AUDIO_PREFERENCE)
- {
- String downloadPath = sharedPreferences
- .getString(DOWNLOAD_PATH_AUDIO_PREFERENCE,
- getString(R.string.download_path_audio_summary));
- downloadPathAudioPreference
- .setSummary(downloadPath);
- }
- else if (key == THEME)
- {
- String selectedTheme = sharedPreferences.getString(THEME, "Light");
- themePreference.setSummary(selectedTheme);
-
- if(!selectedTheme.equals(currentTheme)) { // If it's not the current theme
- new AlertDialog.Builder(activity)
- .setTitle(R.string.restart_title)
- .setMessage(R.string.msg_restart)
- .setPositiveButton(R.string.yes, new DialogInterface.OnClickListener() {
- @Override
- public void onClick(DialogInterface dialog, int which) {
- Intent intentToMain = new Intent(activity, MainActivity.class);
- intentToMain.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK);
- activity.startActivity(intentToMain);
-
- activity.finish();
- Runtime.getRuntime().exit(0);
- }
- })
- .setNegativeButton(R.string.later, null)
- .create().show();
- }
- }
- updateSummary();
- }
- };
- defaultPreferences.registerOnSharedPreferenceChangeListener(prefListener);
-
- updateSummary();
}
@Override
public boolean onPreferenceTreeClick(PreferenceScreen preferenceScreen, Preference preference) {
-
- if(preference.getKey().equals(downloadPathPreference.getKey()) ||
- preference.getKey().equals(downloadPathAudioPreference.getKey()))
- {
- Activity activity = getActivity();
- Intent i = new Intent(activity, FilePickerActivity.class);
-
- i.putExtra(FilePickerActivity.EXTRA_ALLOW_MULTIPLE, false);
- i.putExtra(FilePickerActivity.EXTRA_ALLOW_CREATE_DIR, true);
- i.putExtra(FilePickerActivity.EXTRA_MODE, FilePickerActivity.MODE_DIR);
- if(preference.getKey().equals(downloadPathPreference.getKey()))
- {
- activity.startActivityForResult(i, R.string.download_path_key);
- }
- else if (preference.getKey().equals(downloadPathAudioPreference.getKey()))
- {
- activity.startActivityForResult(i, R.string.download_path_audio_key);
+ Log.d("TAG", "onPreferenceTreeClick() called with: preferenceScreen = [" + preferenceScreen + "], preference = [" + preference + "]");
+ if (preference.getKey().equals(DOWNLOAD_PATH_PREFERENCE) || preference.getKey().equals(DOWNLOAD_PATH_AUDIO_PREFERENCE)) {
+ Intent i = new Intent(activity, FilePickerActivity.class)
+ .putExtra(FilePickerActivity.EXTRA_ALLOW_MULTIPLE, false)
+ .putExtra(FilePickerActivity.EXTRA_ALLOW_CREATE_DIR, true)
+ .putExtra(FilePickerActivity.EXTRA_MODE, FilePickerActivity.MODE_DIR);
+ if (preference.getKey().equals(DOWNLOAD_PATH_PREFERENCE)) {
+ startActivityForResult(i, REQUEST_DOWNLOAD_PATH);
+ } else if (preference.getKey().equals(DOWNLOAD_PATH_AUDIO_PREFERENCE)) {
+ startActivityForResult(i, REQUEST_DOWNLOAD_AUDIO_PATH);
}
}
return super.onPreferenceTreeClick(preferenceScreen, preference);
@@ -208,90 +87,56 @@ public class SettingsFragment extends PreferenceFragment
@Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
- Activity a = getActivity();
+ Log.d("TAG", "onActivityResult() called with: requestCode = [" + requestCode + "], resultCode = [" + resultCode + "], data = [" + data + "]");
- if ((requestCode == R.string.download_path_audio_key
- || requestCode == R.string.download_path_key)
- && resultCode == Activity.RESULT_OK) {
-
- Uri uri = null;
- if (data.getBooleanExtra(FilePickerActivity.EXTRA_ALLOW_MULTIPLE, false)) {
- // For JellyBean and above
- if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) {
- ClipData clip = data.getClipData();
-
- if (clip != null) {
- for (int i = 0; i < clip.getItemCount(); i++) {
- uri = clip.getItemAt(i).getUri();
- }
- }
- // For Ice Cream Sandwich
- } else {
- ArrayList paths = data.getStringArrayListExtra
- (FilePickerActivity.EXTRA_PATHS);
-
- if (paths != null) {
- for (String path: paths) {
- uri = Uri.parse(path);
- }
- }
- }
- } else {
- uri = data.getData();
- }
- SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(a);
-
- //requestCode is equal to R.string.download_path_key or
- //R.string.download_path_audio_key
- String key = getString(requestCode);
+ if ((requestCode == REQUEST_DOWNLOAD_PATH || requestCode == REQUEST_DOWNLOAD_AUDIO_PATH) && resultCode == Activity.RESULT_OK) {
+ String key = getString(requestCode == REQUEST_DOWNLOAD_PATH ? R.string.download_path_key : R.string.download_path_audio_key);
String path = data.getData().toString().substring(7);
- prefs.edit()
- .putString(key, path)
- .apply();
-
- }
- else if(requestCode == REQUEST_INSTALL_ORBOT)
- {
+ defaultPreferences.edit().putString(key, path).apply();
+ updatePreferencesSummary();
+ } else if (requestCode == REQUEST_INSTALL_ORBOT) {
// try to start tor regardless of resultCode since clicking back after
// installing the app does not necessarily return RESULT_OK
- App.configureTor(requestCode == REQUEST_INSTALL_ORBOT
- && OrbotHelper.requestStartTor(a));
+ App.configureTor(OrbotHelper.requestStartTor(activity));
}
-
- updateSummary();
- super.onActivityResult(requestCode, resultCode, data);
}
- // This is used to show the status of some preference in the description
- private void updateSummary() {
- defaultResolutionPreference.setSummary(
- defaultPreferences.getString(DEFAULT_RESOLUTION_PREFERENCE,
- getString(R.string.default_resolution_value)));
- defaultPopupResolutionPreference.setSummary(
- defaultPreferences.getString(DEFAULT_POPUP_RESOLUTION_PREFERENCE,
- getString(R.string.default_popup_resolution_value)));
- preferredVideoFormatPreference.setSummary(
- defaultPreferences.getString(PREFERRED_VIDEO_FORMAT_PREFERENCE,
- getString(R.string.preferred_video_format_default)));
- defaultAudioFormatPreference.setSummary(
- defaultPreferences.getString(DEFAULT_AUDIO_FORMAT_PREFERENCE,
- getString(R.string.default_audio_format_value)));
- searchLanguagePreference.setSummary(
- defaultPreferences.getString(SEARCH_LANGUAGE_PREFERENCE,
- getString(R.string.default_language_value)));
- downloadPathPreference.setSummary(
- defaultPreferences.getString(DOWNLOAD_PATH_PREFERENCE,
- getString(R.string.download_path_summary)));
- downloadPathAudioPreference.setSummary(
- defaultPreferences.getString(DOWNLOAD_PATH_AUDIO_PREFERENCE,
- getString(R.string.download_path_audio_summary)));
- themePreference.setSummary(
- defaultPreferences.getString(THEME,
- getString(R.string.light_theme_title)));
+ /**
+ * Update ONLY the summary of some preferences that don't fire in the onSharedPreferenceChanged or CAN'T be update via xml (%s)
+ *
+ * For example, the download_path use the startActivityForResult, firing the onStop of this fragment,
+ * unregistering the listener (unregisterOnSharedPreferenceChangeListener)
+ */
+ private void updatePreferencesSummary() {
+ findPreference(DOWNLOAD_PATH_PREFERENCE).setSummary(defaultPreferences.getString(DOWNLOAD_PATH_PREFERENCE, getString(R.string.download_path_summary)));
+ findPreference(DOWNLOAD_PATH_AUDIO_PREFERENCE).setSummary(defaultPreferences.getString(DOWNLOAD_PATH_AUDIO_PREFERENCE, getString(R.string.download_path_audio_summary)));
}
@Override
public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String key) {
+ Log.d("TAG", "onSharedPreferenceChanged() called with: sharedPreferences = [" + sharedPreferences + "], key = [" + key + "]");
+ String summary = null;
+ if (key.equals(USE_TOR_KEY)) {
+ if (defaultPreferences.getBoolean(USE_TOR_KEY, false)) {
+ if (OrbotHelper.isOrbotInstalled(activity)) {
+ App.configureTor(true);
+ OrbotHelper.requestStartTor(activity);
+ } else {
+ Intent intent = OrbotHelper.getOrbotInstallIntent(activity);
+ startActivityForResult(intent, REQUEST_INSTALL_ORBOT);
+ }
+ } else App.configureTor(false);
+ return;
+ } else if (key.equals(THEME)) {
+ summary = sharedPreferences.getString(THEME, getString(R.string.default_theme_value));
+ if (!summary.equals(currentTheme)) { // If it's not the current theme
+ Intent intentToMain = new Intent(activity, MainActivity.class);
+ intentToMain.putExtra(Constants.KEY_THEME_CHANGE, true);
+ startActivity(intentToMain);
+ }
+ }
+
+ if (!TextUtils.isEmpty(summary)) findPreference(key).setSummary(summary);
}
}