Merge pull request #4814 from Isira-Seneviratne/Use_view_binding_in_fragments
Use view binding in fragments.
This commit is contained in:
commit
94b086de20
|
@ -7,13 +7,14 @@ import android.view.MenuInflater;
|
|||
import android.view.MenuItem;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.TextView;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.fragment.app.Fragment;
|
||||
|
||||
import org.schabi.newpipe.R;
|
||||
import org.schabi.newpipe.databinding.FragmentLicensesBinding;
|
||||
import org.schabi.newpipe.databinding.ItemSoftwareComponentBinding;
|
||||
import org.schabi.newpipe.util.ShareUtils;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
@ -67,43 +68,42 @@ public class LicenseFragment extends Fragment {
|
|||
|
||||
@Nullable
|
||||
@Override
|
||||
public View onCreateView(final LayoutInflater inflater, @Nullable final ViewGroup container,
|
||||
public View onCreateView(@NonNull final LayoutInflater inflater,
|
||||
@Nullable final ViewGroup container,
|
||||
@Nullable final Bundle savedInstanceState) {
|
||||
final View rootView = inflater.inflate(R.layout.fragment_licenses, container, false);
|
||||
final ViewGroup softwareComponentsView = rootView.findViewById(R.id.software_components);
|
||||
final FragmentLicensesBinding binding = FragmentLicensesBinding
|
||||
.inflate(inflater, container, false);
|
||||
|
||||
final View licenseLink = rootView.findViewById(R.id.app_read_license);
|
||||
licenseLink.setOnClickListener(v -> {
|
||||
binding.appReadLicense.setOnClickListener(v -> {
|
||||
activeLicense = StandardLicenses.GPL3;
|
||||
compositeDisposable.add(LicenseFragmentHelper.showLicense(getActivity(),
|
||||
StandardLicenses.GPL3));
|
||||
});
|
||||
|
||||
for (final SoftwareComponent component : softwareComponents) {
|
||||
final View componentView = inflater
|
||||
.inflate(R.layout.item_software_component, container, false);
|
||||
final TextView softwareName = componentView.findViewById(R.id.name);
|
||||
final TextView copyright = componentView.findViewById(R.id.copyright);
|
||||
softwareName.setText(component.getName());
|
||||
copyright.setText(getString(R.string.copyright,
|
||||
final ItemSoftwareComponentBinding componentBinding = ItemSoftwareComponentBinding
|
||||
.inflate(inflater, container, false);
|
||||
componentBinding.name.setText(component.getName());
|
||||
componentBinding.copyright.setText(getString(R.string.copyright,
|
||||
component.getYears(),
|
||||
component.getCopyrightOwner(),
|
||||
component.getLicense().getAbbreviation()));
|
||||
|
||||
componentView.setTag(component);
|
||||
componentView.setOnClickListener(v -> {
|
||||
final View root = componentBinding.getRoot();
|
||||
root.setTag(component);
|
||||
root.setOnClickListener(v -> {
|
||||
activeLicense = component.getLicense();
|
||||
compositeDisposable.add(LicenseFragmentHelper.showLicense(getActivity(),
|
||||
component.getLicense()));
|
||||
});
|
||||
softwareComponentsView.addView(componentView);
|
||||
registerForContextMenu(componentView);
|
||||
binding.softwareComponents.addView(root);
|
||||
registerForContextMenu(root);
|
||||
}
|
||||
if (activeLicense != null) {
|
||||
compositeDisposable.add(LicenseFragmentHelper.showLicense(getActivity(),
|
||||
activeLicense));
|
||||
}
|
||||
return rootView;
|
||||
return binding.getRoot();
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -16,12 +16,8 @@ import android.view.LayoutInflater;
|
|||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.AdapterView;
|
||||
import android.widget.EditText;
|
||||
import android.widget.RadioButton;
|
||||
import android.widget.RadioGroup;
|
||||
import android.widget.SeekBar;
|
||||
import android.widget.Spinner;
|
||||
import android.widget.TextView;
|
||||
import android.widget.Toast;
|
||||
|
||||
import androidx.annotation.IdRes;
|
||||
|
@ -40,6 +36,7 @@ import com.nononsenseapps.filepicker.Utils;
|
|||
import org.schabi.newpipe.MainActivity;
|
||||
import org.schabi.newpipe.R;
|
||||
import org.schabi.newpipe.RouterActivity;
|
||||
import org.schabi.newpipe.databinding.DownloadDialogBinding;
|
||||
import org.schabi.newpipe.extractor.MediaFormat;
|
||||
import org.schabi.newpipe.extractor.NewPipe;
|
||||
import org.schabi.newpipe.extractor.localization.Localization;
|
||||
|
@ -116,11 +113,7 @@ public class DownloadDialog extends DialogFragment
|
|||
|
||||
private final CompositeDisposable disposables = new CompositeDisposable();
|
||||
|
||||
private EditText nameEditText;
|
||||
private Spinner streamsSpinner;
|
||||
private RadioGroup radioStreamsGroup;
|
||||
private TextView threadsCountTextView;
|
||||
private SeekBar threadsSeekBar;
|
||||
private DownloadDialogBinding dialogBinding;
|
||||
|
||||
private SharedPreferences prefs;
|
||||
|
||||
|
@ -277,38 +270,35 @@ public class DownloadDialog extends DialogFragment
|
|||
@Override
|
||||
public void onViewCreated(@NonNull final View view, @Nullable final Bundle savedInstanceState) {
|
||||
super.onViewCreated(view, savedInstanceState);
|
||||
nameEditText = view.findViewById(R.id.file_name);
|
||||
nameEditText.setText(FilenameUtils.createFilename(getContext(), currentInfo.getName()));
|
||||
dialogBinding = DownloadDialogBinding.bind(view);
|
||||
|
||||
dialogBinding.fileName.setText(FilenameUtils.createFilename(getContext(),
|
||||
currentInfo.getName()));
|
||||
selectedAudioIndex = ListHelper
|
||||
.getDefaultAudioFormat(getContext(), currentInfo.getAudioStreams());
|
||||
|
||||
selectedSubtitleIndex = getSubtitleIndexBy(subtitleStreamsAdapter.getAll());
|
||||
|
||||
streamsSpinner = view.findViewById(R.id.quality_spinner);
|
||||
streamsSpinner.setOnItemSelectedListener(this);
|
||||
dialogBinding.qualitySpinner.setOnItemSelectedListener(this);
|
||||
|
||||
threadsCountTextView = view.findViewById(R.id.threads_count);
|
||||
threadsSeekBar = view.findViewById(R.id.threads);
|
||||
dialogBinding.videoAudioGroup.setOnCheckedChangeListener(this);
|
||||
|
||||
radioStreamsGroup = view.findViewById(R.id.video_audio_group);
|
||||
radioStreamsGroup.setOnCheckedChangeListener(this);
|
||||
|
||||
initToolbar(view.findViewById(R.id.toolbar));
|
||||
initToolbar(dialogBinding.toolbarLayout.toolbar);
|
||||
setupDownloadOptions();
|
||||
|
||||
prefs = PreferenceManager.getDefaultSharedPreferences(requireContext());
|
||||
|
||||
final int threads = prefs.getInt(getString(R.string.default_download_threads), 3);
|
||||
threadsCountTextView.setText(String.valueOf(threads));
|
||||
threadsSeekBar.setProgress(threads - 1);
|
||||
threadsSeekBar.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() {
|
||||
dialogBinding.threadsCount.setText(String.valueOf(threads));
|
||||
dialogBinding.threads.setProgress(threads - 1);
|
||||
dialogBinding.threads.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() {
|
||||
@Override
|
||||
public void onProgressChanged(final SeekBar seekbar, final int progress,
|
||||
final boolean fromUser) {
|
||||
final int newProgress = progress + 1;
|
||||
prefs.edit().putInt(getString(R.string.default_download_threads), newProgress)
|
||||
.apply();
|
||||
threadsCountTextView.setText(String.valueOf(newProgress));
|
||||
dialogBinding.threadsCount.setText(String.valueOf(newProgress));
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -326,19 +316,19 @@ public class DownloadDialog extends DialogFragment
|
|||
|
||||
disposables.add(StreamSizeWrapper.fetchSizeForWrapper(wrappedVideoStreams)
|
||||
.subscribe(result -> {
|
||||
if (radioStreamsGroup.getCheckedRadioButtonId() == R.id.video_button) {
|
||||
if (dialogBinding.videoAudioGroup.getCheckedRadioButtonId() == R.id.video_button) {
|
||||
setupVideoSpinner();
|
||||
}
|
||||
}));
|
||||
disposables.add(StreamSizeWrapper.fetchSizeForWrapper(wrappedAudioStreams)
|
||||
.subscribe(result -> {
|
||||
if (radioStreamsGroup.getCheckedRadioButtonId() == R.id.audio_button) {
|
||||
if (dialogBinding.videoAudioGroup.getCheckedRadioButtonId() == R.id.audio_button) {
|
||||
setupAudioSpinner();
|
||||
}
|
||||
}));
|
||||
disposables.add(StreamSizeWrapper.fetchSizeForWrapper(wrappedSubtitleStreams)
|
||||
.subscribe(result -> {
|
||||
if (radioStreamsGroup.getCheckedRadioButtonId() == R.id.subtitle_button) {
|
||||
if (dialogBinding.videoAudioGroup.getCheckedRadioButtonId() == R.id.subtitle_button) {
|
||||
setupSubtitleSpinner();
|
||||
}
|
||||
}));
|
||||
|
@ -350,6 +340,12 @@ public class DownloadDialog extends DialogFragment
|
|||
disposables.clear();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDestroyView() {
|
||||
dialogBinding = null;
|
||||
super.onDestroyView();
|
||||
}
|
||||
|
||||
/*//////////////////////////////////////////////////////////////////////////
|
||||
// Radio group Video&Audio options - Listener
|
||||
//////////////////////////////////////////////////////////////////////////*/
|
||||
|
@ -429,8 +425,8 @@ public class DownloadDialog extends DialogFragment
|
|||
return;
|
||||
}
|
||||
|
||||
streamsSpinner.setAdapter(audioStreamsAdapter);
|
||||
streamsSpinner.setSelection(selectedAudioIndex);
|
||||
dialogBinding.qualitySpinner.setAdapter(audioStreamsAdapter);
|
||||
dialogBinding.qualitySpinner.setSelection(selectedAudioIndex);
|
||||
setRadioButtonsState(true);
|
||||
}
|
||||
|
||||
|
@ -439,8 +435,8 @@ public class DownloadDialog extends DialogFragment
|
|||
return;
|
||||
}
|
||||
|
||||
streamsSpinner.setAdapter(videoStreamsAdapter);
|
||||
streamsSpinner.setSelection(selectedVideoIndex);
|
||||
dialogBinding.qualitySpinner.setAdapter(videoStreamsAdapter);
|
||||
dialogBinding.qualitySpinner.setSelection(selectedVideoIndex);
|
||||
setRadioButtonsState(true);
|
||||
}
|
||||
|
||||
|
@ -449,8 +445,8 @@ public class DownloadDialog extends DialogFragment
|
|||
return;
|
||||
}
|
||||
|
||||
streamsSpinner.setAdapter(subtitleStreamsAdapter);
|
||||
streamsSpinner.setSelection(selectedSubtitleIndex);
|
||||
dialogBinding.qualitySpinner.setAdapter(subtitleStreamsAdapter);
|
||||
dialogBinding.qualitySpinner.setSelection(selectedSubtitleIndex);
|
||||
setRadioButtonsState(true);
|
||||
}
|
||||
|
||||
|
@ -475,7 +471,7 @@ public class DownloadDialog extends DialogFragment
|
|||
break;
|
||||
}
|
||||
|
||||
threadsSeekBar.setEnabled(flag);
|
||||
dialogBinding.threads.setEnabled(flag);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -486,7 +482,7 @@ public class DownloadDialog extends DialogFragment
|
|||
+ "parent = [" + parent + "], view = [" + view + "], "
|
||||
+ "position = [" + position + "], id = [" + id + "]");
|
||||
}
|
||||
switch (radioStreamsGroup.getCheckedRadioButtonId()) {
|
||||
switch (dialogBinding.videoAudioGroup.getCheckedRadioButtonId()) {
|
||||
case R.id.audio_button:
|
||||
selectedAudioIndex = position;
|
||||
break;
|
||||
|
@ -506,16 +502,14 @@ public class DownloadDialog extends DialogFragment
|
|||
protected void setupDownloadOptions() {
|
||||
setRadioButtonsState(false);
|
||||
|
||||
final RadioButton audioButton = radioStreamsGroup.findViewById(R.id.audio_button);
|
||||
final RadioButton videoButton = radioStreamsGroup.findViewById(R.id.video_button);
|
||||
final RadioButton subtitleButton = radioStreamsGroup.findViewById(R.id.subtitle_button);
|
||||
final boolean isVideoStreamsAvailable = videoStreamsAdapter.getCount() > 0;
|
||||
final boolean isAudioStreamsAvailable = audioStreamsAdapter.getCount() > 0;
|
||||
final boolean isSubtitleStreamsAvailable = subtitleStreamsAdapter.getCount() > 0;
|
||||
|
||||
audioButton.setVisibility(isAudioStreamsAvailable ? View.VISIBLE : View.GONE);
|
||||
videoButton.setVisibility(isVideoStreamsAvailable ? View.VISIBLE : View.GONE);
|
||||
subtitleButton.setVisibility(isSubtitleStreamsAvailable ? View.VISIBLE : View.GONE);
|
||||
dialogBinding.audioButton.setVisibility(isAudioStreamsAvailable ? View.VISIBLE : View.GONE);
|
||||
dialogBinding.videoButton.setVisibility(isVideoStreamsAvailable ? View.VISIBLE : View.GONE);
|
||||
dialogBinding.subtitleButton.setVisibility(isSubtitleStreamsAvailable
|
||||
? View.VISIBLE : View.GONE);
|
||||
|
||||
prefs = PreferenceManager.getDefaultSharedPreferences(getContext());
|
||||
final String defaultMedia = prefs.getString(getString(R.string.last_used_download_type),
|
||||
|
@ -523,24 +517,24 @@ public class DownloadDialog extends DialogFragment
|
|||
|
||||
if (isVideoStreamsAvailable
|
||||
&& (defaultMedia.equals(getString(R.string.last_download_type_video_key)))) {
|
||||
videoButton.setChecked(true);
|
||||
dialogBinding.videoButton.setChecked(true);
|
||||
setupVideoSpinner();
|
||||
} else if (isAudioStreamsAvailable
|
||||
&& (defaultMedia.equals(getString(R.string.last_download_type_audio_key)))) {
|
||||
audioButton.setChecked(true);
|
||||
dialogBinding.audioButton.setChecked(true);
|
||||
setupAudioSpinner();
|
||||
} else if (isSubtitleStreamsAvailable
|
||||
&& (defaultMedia.equals(getString(R.string.last_download_type_subtitle_key)))) {
|
||||
subtitleButton.setChecked(true);
|
||||
dialogBinding.subtitleButton.setChecked(true);
|
||||
setupSubtitleSpinner();
|
||||
} else if (isVideoStreamsAvailable) {
|
||||
videoButton.setChecked(true);
|
||||
dialogBinding.videoButton.setChecked(true);
|
||||
setupVideoSpinner();
|
||||
} else if (isAudioStreamsAvailable) {
|
||||
audioButton.setChecked(true);
|
||||
dialogBinding.audioButton.setChecked(true);
|
||||
setupAudioSpinner();
|
||||
} else if (isSubtitleStreamsAvailable) {
|
||||
subtitleButton.setChecked(true);
|
||||
dialogBinding.subtitleButton.setChecked(true);
|
||||
setupSubtitleSpinner();
|
||||
} else {
|
||||
Toast.makeText(getContext(), R.string.no_streams_available_download,
|
||||
|
@ -550,9 +544,9 @@ public class DownloadDialog extends DialogFragment
|
|||
}
|
||||
|
||||
private void setRadioButtonsState(final boolean enabled) {
|
||||
radioStreamsGroup.findViewById(R.id.audio_button).setEnabled(enabled);
|
||||
radioStreamsGroup.findViewById(R.id.video_button).setEnabled(enabled);
|
||||
radioStreamsGroup.findViewById(R.id.subtitle_button).setEnabled(enabled);
|
||||
dialogBinding.audioButton.setEnabled(enabled);
|
||||
dialogBinding.videoButton.setEnabled(enabled);
|
||||
dialogBinding.subtitleButton.setEnabled(enabled);
|
||||
}
|
||||
|
||||
private int getSubtitleIndexBy(final List<SubtitlesStream> streams) {
|
||||
|
@ -582,7 +576,7 @@ public class DownloadDialog extends DialogFragment
|
|||
}
|
||||
|
||||
private String getNameEditText() {
|
||||
final String str = nameEditText.getText().toString().trim();
|
||||
final String str = dialogBinding.fileName.getText().toString().trim();
|
||||
|
||||
return FilenameUtils.createFilename(context, str.isEmpty() ? currentInfo.getName() : str);
|
||||
}
|
||||
|
@ -619,7 +613,7 @@ public class DownloadDialog extends DialogFragment
|
|||
|
||||
String filename = getNameEditText().concat(".");
|
||||
|
||||
switch (radioStreamsGroup.getCheckedRadioButtonId()) {
|
||||
switch (dialogBinding.videoAudioGroup.getCheckedRadioButtonId()) {
|
||||
case R.id.audio_button:
|
||||
selectedMediaType = getString(R.string.last_download_type_audio_key);
|
||||
mainStorage = mainStorageAudio;
|
||||
|
@ -669,7 +663,7 @@ public class DownloadDialog extends DialogFragment
|
|||
filename, mime);
|
||||
} else {
|
||||
File initialSavePath;
|
||||
if (radioStreamsGroup.getCheckedRadioButtonId() == R.id.audio_button) {
|
||||
if (dialogBinding.videoAudioGroup.getCheckedRadioButtonId() == R.id.audio_button) {
|
||||
initialSavePath = NewPipeSettings.getDir(Environment.DIRECTORY_MUSIC);
|
||||
} else {
|
||||
initialSavePath = NewPipeSettings.getDir(Environment.DIRECTORY_MOVIES);
|
||||
|
@ -862,7 +856,7 @@ public class DownloadDialog extends DialogFragment
|
|||
final Stream selectedStream;
|
||||
Stream secondaryStream = null;
|
||||
final char kind;
|
||||
int threads = threadsSeekBar.getProgress() + 1;
|
||||
int threads = dialogBinding.threads.getProgress() + 1;
|
||||
final String[] urls;
|
||||
final MissionRecoveryInfo[] recoveryInfo;
|
||||
String psName = null;
|
||||
|
@ -870,7 +864,7 @@ public class DownloadDialog extends DialogFragment
|
|||
long nearLength = 0;
|
||||
|
||||
// more download logic: select muxer, subtitle converter, etc.
|
||||
switch (radioStreamsGroup.getCheckedRadioButtonId()) {
|
||||
switch (dialogBinding.videoAudioGroup.getCheckedRadioButtonId()) {
|
||||
case R.id.audio_button:
|
||||
kind = 'a';
|
||||
selectedStream = audioStreamsAdapter.getItem(selectedAudioIndex);
|
||||
|
|
|
@ -19,12 +19,12 @@ import androidx.fragment.app.Fragment;
|
|||
import androidx.fragment.app.FragmentManager;
|
||||
import androidx.fragment.app.FragmentStatePagerAdapterMenuWorkaround;
|
||||
import androidx.preference.PreferenceManager;
|
||||
import androidx.viewpager.widget.ViewPager;
|
||||
|
||||
import com.google.android.material.tabs.TabLayout;
|
||||
|
||||
import org.schabi.newpipe.BaseFragment;
|
||||
import org.schabi.newpipe.R;
|
||||
import org.schabi.newpipe.databinding.FragmentMainBinding;
|
||||
import org.schabi.newpipe.extractor.exceptions.ExtractionException;
|
||||
import org.schabi.newpipe.report.ErrorActivity;
|
||||
import org.schabi.newpipe.report.ErrorInfo;
|
||||
|
@ -34,15 +34,13 @@ import org.schabi.newpipe.settings.tabs.TabsManager;
|
|||
import org.schabi.newpipe.util.NavigationHelper;
|
||||
import org.schabi.newpipe.util.ServiceHelper;
|
||||
import org.schabi.newpipe.util.ThemeHelper;
|
||||
import org.schabi.newpipe.views.ScrollableTabLayout;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
public class MainFragment extends BaseFragment implements TabLayout.OnTabSelectedListener {
|
||||
private ViewPager viewPager;
|
||||
private FragmentMainBinding binding;
|
||||
private SelectedTabsPagerAdapter pagerAdapter;
|
||||
private ScrollableTabLayout tabLayout;
|
||||
|
||||
private final List<Tab> tabsList = new ArrayList<>();
|
||||
private TabsManager tabsManager;
|
||||
|
@ -90,13 +88,12 @@ public class MainFragment extends BaseFragment implements TabLayout.OnTabSelecte
|
|||
protected void initViews(final View rootView, final Bundle savedInstanceState) {
|
||||
super.initViews(rootView, savedInstanceState);
|
||||
|
||||
tabLayout = rootView.findViewById(R.id.main_tab_layout);
|
||||
viewPager = rootView.findViewById(R.id.pager);
|
||||
binding = FragmentMainBinding.bind(rootView);
|
||||
|
||||
tabLayout.setTabIconTint(ColorStateList.valueOf(
|
||||
binding.mainTabLayout.setTabIconTint(ColorStateList.valueOf(
|
||||
ThemeHelper.resolveColorFromAttr(requireContext(), R.attr.colorAccent)));
|
||||
tabLayout.setupWithViewPager(viewPager);
|
||||
tabLayout.addOnTabSelectedListener(this);
|
||||
binding.mainTabLayout.setupWithViewPager(binding.pager);
|
||||
binding.mainTabLayout.addOnTabSelectedListener(this);
|
||||
|
||||
setupTabs();
|
||||
}
|
||||
|
@ -120,8 +117,14 @@ public class MainFragment extends BaseFragment implements TabLayout.OnTabSelecte
|
|||
public void onDestroy() {
|
||||
super.onDestroy();
|
||||
tabsManager.unsetSavedTabsListener();
|
||||
if (viewPager != null) {
|
||||
viewPager.setAdapter(null);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDestroyView() {
|
||||
super.onDestroyView();
|
||||
if (binding != null) {
|
||||
binding.pager.setAdapter(null);
|
||||
binding = null;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -172,19 +175,19 @@ public class MainFragment extends BaseFragment implements TabLayout.OnTabSelecte
|
|||
getChildFragmentManager(), tabsList);
|
||||
}
|
||||
|
||||
viewPager.setAdapter(null);
|
||||
viewPager.setOffscreenPageLimit(tabsList.size());
|
||||
viewPager.setAdapter(pagerAdapter);
|
||||
binding.pager.setAdapter(null);
|
||||
binding.pager.setOffscreenPageLimit(tabsList.size());
|
||||
binding.pager.setAdapter(pagerAdapter);
|
||||
|
||||
updateTabsIconAndDescription();
|
||||
updateTitleForTab(viewPager.getCurrentItem());
|
||||
updateTitleForTab(binding.pager.getCurrentItem());
|
||||
|
||||
hasTabsChanged = false;
|
||||
}
|
||||
|
||||
private void updateTabsIconAndDescription() {
|
||||
for (int i = 0; i < tabsList.size(); i++) {
|
||||
final TabLayout.Tab tabToSet = tabLayout.getTabAt(i);
|
||||
final TabLayout.Tab tabToSet = binding.mainTabLayout.getTabAt(i);
|
||||
if (tabToSet != null) {
|
||||
final Tab tab = tabsList.get(i);
|
||||
tabToSet.setIcon(tab.getTabIconRes(requireContext()));
|
||||
|
|
|
@ -12,13 +12,16 @@ import android.view.MenuInflater;
|
|||
import android.view.View;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.appcompat.app.ActionBar;
|
||||
import androidx.appcompat.app.AppCompatActivity;
|
||||
import androidx.preference.PreferenceManager;
|
||||
import androidx.recyclerview.widget.GridLayoutManager;
|
||||
import androidx.recyclerview.widget.RecyclerView;
|
||||
import androidx.viewbinding.ViewBinding;
|
||||
|
||||
import org.schabi.newpipe.R;
|
||||
import org.schabi.newpipe.databinding.PignateFooterBinding;
|
||||
import org.schabi.newpipe.extractor.InfoItem;
|
||||
import org.schabi.newpipe.extractor.channel.ChannelInfoItem;
|
||||
import org.schabi.newpipe.extractor.comments.CommentsInfoItem;
|
||||
|
@ -215,12 +218,13 @@ public abstract class BaseListFragment<I, N> extends BaseStateFragment<I>
|
|||
// Init
|
||||
//////////////////////////////////////////////////////////////////////////*/
|
||||
|
||||
protected View getListHeader() {
|
||||
@Nullable
|
||||
protected ViewBinding getListHeader() {
|
||||
return null;
|
||||
}
|
||||
|
||||
protected View getListFooter() {
|
||||
return activity.getLayoutInflater().inflate(R.layout.pignate_footer, itemsList, false);
|
||||
protected ViewBinding getListFooter() {
|
||||
return PignateFooterBinding.inflate(activity.getLayoutInflater(), itemsList, false);
|
||||
}
|
||||
|
||||
protected RecyclerView.LayoutManager getListLayoutManager() {
|
||||
|
@ -247,8 +251,12 @@ public abstract class BaseListFragment<I, N> extends BaseStateFragment<I>
|
|||
itemsList.setLayoutManager(useGrid ? getGridLayoutManager() : getListLayoutManager());
|
||||
|
||||
infoListAdapter.setUseGridVariant(useGrid);
|
||||
infoListAdapter.setFooter(getListFooter());
|
||||
infoListAdapter.setHeader(getListHeader());
|
||||
infoListAdapter.setFooter(getListFooter().getRoot());
|
||||
|
||||
final ViewBinding listHeader = getListHeader();
|
||||
if (listHeader != null) {
|
||||
infoListAdapter.setHeader(listHeader.getRoot());
|
||||
}
|
||||
|
||||
itemsList.setAdapter(infoListAdapter);
|
||||
}
|
||||
|
|
|
@ -14,20 +14,21 @@ import android.view.MenuItem;
|
|||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.Button;
|
||||
import android.widget.ImageView;
|
||||
import android.widget.LinearLayout;
|
||||
import android.widget.TextView;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.appcompat.app.ActionBar;
|
||||
import androidx.appcompat.app.AppCompatActivity;
|
||||
import androidx.core.content.ContextCompat;
|
||||
import androidx.viewbinding.ViewBinding;
|
||||
|
||||
import com.jakewharton.rxbinding4.view.RxView;
|
||||
|
||||
import org.schabi.newpipe.R;
|
||||
import org.schabi.newpipe.database.subscription.SubscriptionEntity;
|
||||
import org.schabi.newpipe.databinding.ChannelHeaderBinding;
|
||||
import org.schabi.newpipe.databinding.FragmentChannelBinding;
|
||||
import org.schabi.newpipe.databinding.PlaylistControlBinding;
|
||||
import org.schabi.newpipe.extractor.InfoItem;
|
||||
import org.schabi.newpipe.extractor.ListExtractor;
|
||||
import org.schabi.newpipe.extractor.NewPipe;
|
||||
|
@ -78,22 +79,12 @@ public class ChannelFragment extends BaseListInfoFragment<ChannelInfo>
|
|||
//////////////////////////////////////////////////////////////////////////*/
|
||||
|
||||
private SubscriptionManager subscriptionManager;
|
||||
private View headerRootLayout;
|
||||
private ImageView headerChannelBanner;
|
||||
private ImageView headerAvatarView;
|
||||
private TextView headerTitleView;
|
||||
private ImageView headerSubChannelAvatarView;
|
||||
private TextView headerSubChannelTitleView;
|
||||
private TextView headerSubscribersTextView;
|
||||
private Button headerSubscribeButton;
|
||||
private View playlistCtrl;
|
||||
private LinearLayout headerPlayAllButton;
|
||||
private LinearLayout headerPopupButton;
|
||||
private LinearLayout headerBackgroundButton;
|
||||
|
||||
private FragmentChannelBinding channelBinding;
|
||||
private ChannelHeaderBinding headerBinding;
|
||||
private PlaylistControlBinding playlistControlBinding;
|
||||
|
||||
private MenuItem menuRssButton;
|
||||
private TextView contentNotSupportedTextView;
|
||||
private TextView kaomojiTextView;
|
||||
private TextView noVideosTextView;
|
||||
|
||||
public static ChannelFragment getInstance(final int serviceId, final String url,
|
||||
final String name) {
|
||||
|
@ -132,53 +123,45 @@ public class ChannelFragment extends BaseListInfoFragment<ChannelInfo>
|
|||
@Override
|
||||
public void onViewCreated(final View rootView, final Bundle savedInstanceState) {
|
||||
super.onViewCreated(rootView, savedInstanceState);
|
||||
contentNotSupportedTextView = rootView.findViewById(R.id.error_content_not_supported);
|
||||
kaomojiTextView = rootView.findViewById(R.id.channel_kaomoji);
|
||||
noVideosTextView = rootView.findViewById(R.id.channel_no_videos);
|
||||
channelBinding = FragmentChannelBinding.bind(rootView);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDestroy() {
|
||||
super.onDestroy();
|
||||
if (disposables != null) {
|
||||
disposables.clear();
|
||||
}
|
||||
disposables.clear();
|
||||
if (subscribeButtonMonitor != null) {
|
||||
subscribeButtonMonitor.dispose();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDestroyView() {
|
||||
channelBinding = null;
|
||||
headerBinding = null;
|
||||
playlistControlBinding = null;
|
||||
super.onDestroyView();
|
||||
}
|
||||
|
||||
/*//////////////////////////////////////////////////////////////////////////
|
||||
// Init
|
||||
//////////////////////////////////////////////////////////////////////////*/
|
||||
|
||||
protected View getListHeader() {
|
||||
headerRootLayout = activity.getLayoutInflater()
|
||||
.inflate(R.layout.channel_header, itemsList, false);
|
||||
headerChannelBanner = headerRootLayout.findViewById(R.id.channel_banner_image);
|
||||
headerAvatarView = headerRootLayout.findViewById(R.id.channel_avatar_view);
|
||||
headerTitleView = headerRootLayout.findViewById(R.id.channel_title_view);
|
||||
headerSubscribersTextView = headerRootLayout.findViewById(R.id.channel_subscriber_view);
|
||||
headerSubscribeButton = headerRootLayout.findViewById(R.id.channel_subscribe_button);
|
||||
playlistCtrl = headerRootLayout.findViewById(R.id.playlist_control);
|
||||
headerSubChannelAvatarView =
|
||||
headerRootLayout.findViewById(R.id.sub_channel_avatar_view);
|
||||
headerSubChannelTitleView =
|
||||
headerRootLayout.findViewById(R.id.sub_channel_title_view);
|
||||
@Override
|
||||
protected ViewBinding getListHeader() {
|
||||
headerBinding = ChannelHeaderBinding
|
||||
.inflate(activity.getLayoutInflater(), itemsList, false);
|
||||
playlistControlBinding = headerBinding.playlistControl;
|
||||
|
||||
headerPlayAllButton = headerRootLayout.findViewById(R.id.playlist_ctrl_play_all_button);
|
||||
headerPopupButton = headerRootLayout.findViewById(R.id.playlist_ctrl_play_popup_button);
|
||||
headerBackgroundButton = headerRootLayout.findViewById(R.id.playlist_ctrl_play_bg_button);
|
||||
|
||||
return headerRootLayout;
|
||||
return headerBinding;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void initListeners() {
|
||||
super.initListeners();
|
||||
|
||||
headerSubChannelTitleView.setOnClickListener(this);
|
||||
headerSubChannelAvatarView.setOnClickListener(this);
|
||||
headerBinding.subChannelTitleView.setOnClickListener(this);
|
||||
headerBinding.subChannelAvatarView.setOnClickListener(this);
|
||||
}
|
||||
|
||||
/*//////////////////////////////////////////////////////////////////////////
|
||||
|
@ -241,7 +224,7 @@ public class ChannelFragment extends BaseListInfoFragment<ChannelInfo>
|
|||
|
||||
private void monitorSubscription(final ChannelInfo info) {
|
||||
final Consumer<Throwable> onError = (Throwable throwable) -> {
|
||||
animateView(headerSubscribeButton, false, 100);
|
||||
animateView(headerBinding.channelSubscribeButton, false, 100);
|
||||
showSnackBarError(throwable, UserAction.SUBSCRIPTION,
|
||||
NewPipe.getNameOfService(currentInfo.getServiceId()),
|
||||
"Get subscription status", 0);
|
||||
|
@ -351,15 +334,15 @@ public class ChannelFragment extends BaseListInfoFragment<ChannelInfo>
|
|||
info.getAvatarUrl(),
|
||||
info.getDescription(),
|
||||
info.getSubscriberCount());
|
||||
subscribeButtonMonitor = monitorSubscribeButton(headerSubscribeButton,
|
||||
mapOnSubscribe(channel, info));
|
||||
subscribeButtonMonitor = monitorSubscribeButton(
|
||||
headerBinding.channelSubscribeButton, mapOnSubscribe(channel, info));
|
||||
} else {
|
||||
if (DEBUG) {
|
||||
Log.d(TAG, "Found subscription to this channel!");
|
||||
}
|
||||
final SubscriptionEntity subscription = subscriptionEntities.get(0);
|
||||
subscribeButtonMonitor = monitorSubscribeButton(headerSubscribeButton,
|
||||
mapOnUnsubscribe(subscription));
|
||||
subscribeButtonMonitor = monitorSubscribeButton(
|
||||
headerBinding.channelSubscribeButton, mapOnUnsubscribe(subscription));
|
||||
}
|
||||
};
|
||||
}
|
||||
|
@ -370,7 +353,8 @@ public class ChannelFragment extends BaseListInfoFragment<ChannelInfo>
|
|||
+ "isSubscribed = [" + isSubscribed + "]");
|
||||
}
|
||||
|
||||
final boolean isButtonVisible = headerSubscribeButton.getVisibility() == View.VISIBLE;
|
||||
final boolean isButtonVisible = headerBinding.channelSubscribeButton.getVisibility()
|
||||
== View.VISIBLE;
|
||||
final int backgroundDuration = isButtonVisible ? 300 : 0;
|
||||
final int textDuration = isButtonVisible ? 200 : 0;
|
||||
|
||||
|
@ -382,18 +366,21 @@ public class ChannelFragment extends BaseListInfoFragment<ChannelInfo>
|
|||
final int subscribedText = ContextCompat.getColor(activity, R.color.subscribed_text_color);
|
||||
|
||||
if (!isSubscribed) {
|
||||
headerSubscribeButton.setText(R.string.subscribe_button_title);
|
||||
animateBackgroundColor(headerSubscribeButton, backgroundDuration, subscribedBackground,
|
||||
subscribeBackground);
|
||||
animateTextColor(headerSubscribeButton, textDuration, subscribedText, subscribeText);
|
||||
headerBinding.channelSubscribeButton.setText(R.string.subscribe_button_title);
|
||||
animateBackgroundColor(headerBinding.channelSubscribeButton, backgroundDuration,
|
||||
subscribedBackground, subscribeBackground);
|
||||
animateTextColor(headerBinding.channelSubscribeButton, textDuration, subscribedText,
|
||||
subscribeText);
|
||||
} else {
|
||||
headerSubscribeButton.setText(R.string.subscribed_button_title);
|
||||
animateBackgroundColor(headerSubscribeButton, backgroundDuration, subscribeBackground,
|
||||
subscribedBackground);
|
||||
animateTextColor(headerSubscribeButton, textDuration, subscribeText, subscribedText);
|
||||
headerBinding.channelSubscribeButton.setText(R.string.subscribed_button_title);
|
||||
animateBackgroundColor(headerBinding.channelSubscribeButton, backgroundDuration,
|
||||
subscribeBackground, subscribedBackground);
|
||||
animateTextColor(headerBinding.channelSubscribeButton, textDuration, subscribeText,
|
||||
subscribedText);
|
||||
}
|
||||
|
||||
animateView(headerSubscribeButton, AnimationUtils.Type.LIGHT_SCALE_AND_ALPHA, true, 100);
|
||||
animateView(headerBinding.channelSubscribeButton, AnimationUtils.Type.LIGHT_SCALE_AND_ALPHA,
|
||||
true, 100);
|
||||
}
|
||||
|
||||
/*//////////////////////////////////////////////////////////////////////////
|
||||
|
@ -446,48 +433,49 @@ public class ChannelFragment extends BaseListInfoFragment<ChannelInfo>
|
|||
public void showLoading() {
|
||||
super.showLoading();
|
||||
|
||||
IMAGE_LOADER.cancelDisplayTask(headerChannelBanner);
|
||||
IMAGE_LOADER.cancelDisplayTask(headerAvatarView);
|
||||
IMAGE_LOADER.cancelDisplayTask(headerSubChannelAvatarView);
|
||||
animateView(headerSubscribeButton, false, 100);
|
||||
IMAGE_LOADER.cancelDisplayTask(headerBinding.channelBannerImage);
|
||||
IMAGE_LOADER.cancelDisplayTask(headerBinding.channelAvatarView);
|
||||
IMAGE_LOADER.cancelDisplayTask(headerBinding.subChannelAvatarView);
|
||||
animateView(headerBinding.channelSubscribeButton, false, 100);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void handleResult(@NonNull final ChannelInfo result) {
|
||||
super.handleResult(result);
|
||||
|
||||
headerRootLayout.setVisibility(View.VISIBLE);
|
||||
IMAGE_LOADER.displayImage(result.getBannerUrl(), headerChannelBanner,
|
||||
headerBinding.getRoot().setVisibility(View.VISIBLE);
|
||||
IMAGE_LOADER.displayImage(result.getBannerUrl(), headerBinding.channelBannerImage,
|
||||
ImageDisplayConstants.DISPLAY_BANNER_OPTIONS);
|
||||
IMAGE_LOADER.displayImage(result.getAvatarUrl(), headerAvatarView,
|
||||
IMAGE_LOADER.displayImage(result.getAvatarUrl(), headerBinding.channelAvatarView,
|
||||
ImageDisplayConstants.DISPLAY_AVATAR_OPTIONS);
|
||||
IMAGE_LOADER.displayImage(result.getParentChannelAvatarUrl(), headerSubChannelAvatarView,
|
||||
IMAGE_LOADER.displayImage(result.getParentChannelAvatarUrl(),
|
||||
headerBinding.subChannelAvatarView,
|
||||
ImageDisplayConstants.DISPLAY_AVATAR_OPTIONS);
|
||||
|
||||
headerSubscribersTextView.setVisibility(View.VISIBLE);
|
||||
headerBinding.channelSubscriberView.setVisibility(View.VISIBLE);
|
||||
if (result.getSubscriberCount() >= 0) {
|
||||
headerSubscribersTextView.setText(Localization
|
||||
headerBinding.channelSubscriberView.setText(Localization
|
||||
.shortSubscriberCount(activity, result.getSubscriberCount()));
|
||||
} else {
|
||||
headerSubscribersTextView.setText(R.string.subscribers_count_not_available);
|
||||
headerBinding.channelSubscriberView.setText(R.string.subscribers_count_not_available);
|
||||
}
|
||||
|
||||
if (!TextUtils.isEmpty(currentInfo.getParentChannelName())) {
|
||||
headerSubChannelTitleView.setText(String.format(
|
||||
headerBinding.subChannelTitleView.setText(String.format(
|
||||
getString(R.string.channel_created_by),
|
||||
currentInfo.getParentChannelName())
|
||||
);
|
||||
headerSubChannelTitleView.setVisibility(View.VISIBLE);
|
||||
headerSubChannelAvatarView.setVisibility(View.VISIBLE);
|
||||
headerBinding.subChannelTitleView.setVisibility(View.VISIBLE);
|
||||
headerBinding.subChannelAvatarView.setVisibility(View.VISIBLE);
|
||||
} else {
|
||||
headerSubChannelTitleView.setVisibility(View.GONE);
|
||||
headerBinding.subChannelTitleView.setVisibility(View.GONE);
|
||||
}
|
||||
|
||||
if (menuRssButton != null) {
|
||||
menuRssButton.setVisible(!TextUtils.isEmpty(result.getFeedUrl()));
|
||||
}
|
||||
|
||||
playlistCtrl.setVisibility(View.VISIBLE);
|
||||
playlistControlBinding.getRoot().setVisibility(View.VISIBLE);
|
||||
|
||||
final List<Throwable> errors = new ArrayList<>(result.getErrors());
|
||||
if (!errors.isEmpty()) {
|
||||
|
@ -516,29 +504,32 @@ public class ChannelFragment extends BaseListInfoFragment<ChannelInfo>
|
|||
updateSubscription(result);
|
||||
monitorSubscription(result);
|
||||
|
||||
headerPlayAllButton.setOnClickListener(view -> NavigationHelper
|
||||
.playOnMainPlayer(activity, getPlayQueue()));
|
||||
headerPopupButton.setOnClickListener(view -> NavigationHelper
|
||||
.playOnPopupPlayer(activity, getPlayQueue(), false));
|
||||
headerBackgroundButton.setOnClickListener(view -> NavigationHelper
|
||||
.playOnBackgroundPlayer(activity, getPlayQueue(), false));
|
||||
playlistControlBinding.playlistCtrlPlayAllButton
|
||||
.setOnClickListener(view -> NavigationHelper
|
||||
.playOnMainPlayer(activity, getPlayQueue()));
|
||||
playlistControlBinding.playlistCtrlPlayPopupButton
|
||||
.setOnClickListener(view -> NavigationHelper
|
||||
.playOnPopupPlayer(activity, getPlayQueue(), false));
|
||||
playlistControlBinding.playlistCtrlPlayBgButton
|
||||
.setOnClickListener(view -> NavigationHelper
|
||||
.playOnBackgroundPlayer(activity, getPlayQueue(), false));
|
||||
|
||||
headerPopupButton.setOnLongClickListener(view -> {
|
||||
playlistControlBinding.playlistCtrlPlayPopupButton.setOnLongClickListener(view -> {
|
||||
NavigationHelper.enqueueOnPopupPlayer(activity, getPlayQueue(), true);
|
||||
return true;
|
||||
});
|
||||
|
||||
headerBackgroundButton.setOnLongClickListener(view -> {
|
||||
playlistControlBinding.playlistCtrlPlayBgButton.setOnLongClickListener(view -> {
|
||||
NavigationHelper.enqueueOnBackgroundPlayer(activity, getPlayQueue(), true);
|
||||
return true;
|
||||
});
|
||||
}
|
||||
|
||||
private void showContentNotSupported() {
|
||||
contentNotSupportedTextView.setVisibility(View.VISIBLE);
|
||||
kaomojiTextView.setText("(︶︹︺)");
|
||||
kaomojiTextView.setTextSize(TypedValue.COMPLEX_UNIT_SP, 45f);
|
||||
noVideosTextView.setVisibility(View.GONE);
|
||||
channelBinding.errorContentNotSupported.setVisibility(View.VISIBLE);
|
||||
channelBinding.channelKaomoji.setText("(︶︹︺)");
|
||||
channelBinding.channelKaomoji.setTextSize(TypedValue.COMPLEX_UNIT_SP, 45f);
|
||||
channelBinding.channelNoVideos.setVisibility(View.GONE);
|
||||
}
|
||||
|
||||
private PlayQueue getPlayQueue() {
|
||||
|
@ -596,7 +587,7 @@ public class ChannelFragment extends BaseListInfoFragment<ChannelInfo>
|
|||
public void setTitle(final String title) {
|
||||
super.setTitle(title);
|
||||
if (!useAsFrontPage) {
|
||||
headerTitleView.setText(title);
|
||||
headerBinding.channelTitleView.setText(title);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -11,18 +11,20 @@ import android.view.MenuInflater;
|
|||
import android.view.MenuItem;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.TextView;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.appcompat.app.AppCompatActivity;
|
||||
import androidx.appcompat.content.res.AppCompatResources;
|
||||
import androidx.viewbinding.ViewBinding;
|
||||
|
||||
import org.reactivestreams.Subscriber;
|
||||
import org.reactivestreams.Subscription;
|
||||
import org.schabi.newpipe.NewPipeDatabase;
|
||||
import org.schabi.newpipe.R;
|
||||
import org.schabi.newpipe.database.playlist.model.PlaylistRemoteEntity;
|
||||
import org.schabi.newpipe.databinding.PlaylistControlBinding;
|
||||
import org.schabi.newpipe.databinding.PlaylistHeaderBinding;
|
||||
import org.schabi.newpipe.extractor.InfoItem;
|
||||
import org.schabi.newpipe.extractor.ListExtractor;
|
||||
import org.schabi.newpipe.extractor.NewPipe;
|
||||
|
@ -53,7 +55,6 @@ import java.util.Arrays;
|
|||
import java.util.List;
|
||||
import java.util.concurrent.atomic.AtomicBoolean;
|
||||
|
||||
import de.hdodenhof.circleimageview.CircleImageView;
|
||||
import io.reactivex.rxjava3.android.schedulers.AndroidSchedulers;
|
||||
import io.reactivex.rxjava3.core.Flowable;
|
||||
import io.reactivex.rxjava3.core.Single;
|
||||
|
@ -74,17 +75,8 @@ public class PlaylistFragment extends BaseListInfoFragment<PlaylistInfo> {
|
|||
// Views
|
||||
//////////////////////////////////////////////////////////////////////////*/
|
||||
|
||||
private View headerRootLayout;
|
||||
private TextView headerTitleView;
|
||||
private View headerUploaderLayout;
|
||||
private TextView headerUploaderName;
|
||||
private CircleImageView headerUploaderAvatar;
|
||||
private TextView headerStreamCount;
|
||||
private View playlistCtrl;
|
||||
|
||||
private View headerPlayAllButton;
|
||||
private View headerPopupButton;
|
||||
private View headerBackgroundButton;
|
||||
private PlaylistHeaderBinding headerBinding;
|
||||
private PlaylistControlBinding playlistControlBinding;
|
||||
|
||||
private MenuItem playlistBookmarkButton;
|
||||
|
||||
|
@ -119,22 +111,13 @@ public class PlaylistFragment extends BaseListInfoFragment<PlaylistInfo> {
|
|||
// Init
|
||||
//////////////////////////////////////////////////////////////////////////*/
|
||||
|
||||
protected View getListHeader() {
|
||||
headerRootLayout = activity.getLayoutInflater()
|
||||
.inflate(R.layout.playlist_header, itemsList, false);
|
||||
headerTitleView = headerRootLayout.findViewById(R.id.playlist_title_view);
|
||||
headerUploaderLayout = headerRootLayout.findViewById(R.id.uploader_layout);
|
||||
headerUploaderName = headerRootLayout.findViewById(R.id.uploader_name);
|
||||
headerUploaderAvatar = headerRootLayout.findViewById(R.id.uploader_avatar_view);
|
||||
headerStreamCount = headerRootLayout.findViewById(R.id.playlist_stream_count);
|
||||
playlistCtrl = headerRootLayout.findViewById(R.id.playlist_control);
|
||||
@Override
|
||||
protected ViewBinding getListHeader() {
|
||||
headerBinding = PlaylistHeaderBinding
|
||||
.inflate(activity.getLayoutInflater(), itemsList, false);
|
||||
playlistControlBinding = headerBinding.playlistControl;
|
||||
|
||||
headerPlayAllButton = headerRootLayout.findViewById(R.id.playlist_ctrl_play_all_button);
|
||||
headerPopupButton = headerRootLayout.findViewById(R.id.playlist_ctrl_play_popup_button);
|
||||
headerBackgroundButton = headerRootLayout.findViewById(R.id.playlist_ctrl_play_bg_button);
|
||||
|
||||
|
||||
return headerRootLayout;
|
||||
return headerBinding;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -203,6 +186,9 @@ public class PlaylistFragment extends BaseListInfoFragment<PlaylistInfo> {
|
|||
|
||||
@Override
|
||||
public void onDestroyView() {
|
||||
headerBinding = null;
|
||||
playlistControlBinding = null;
|
||||
|
||||
super.onDestroyView();
|
||||
if (isBookmarkButtonReady != null) {
|
||||
isBookmarkButtonReady.set(false);
|
||||
|
@ -275,25 +261,25 @@ public class PlaylistFragment extends BaseListInfoFragment<PlaylistInfo> {
|
|||
@Override
|
||||
public void showLoading() {
|
||||
super.showLoading();
|
||||
animateView(headerRootLayout, false, 200);
|
||||
animateView(headerBinding.getRoot(), false, 200);
|
||||
animateView(itemsList, false, 100);
|
||||
|
||||
IMAGE_LOADER.cancelDisplayTask(headerUploaderAvatar);
|
||||
animateView(headerUploaderLayout, false, 200);
|
||||
IMAGE_LOADER.cancelDisplayTask(headerBinding.uploaderAvatarView);
|
||||
animateView(headerBinding.uploaderLayout, false, 200);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void handleResult(@NonNull final PlaylistInfo result) {
|
||||
super.handleResult(result);
|
||||
|
||||
animateView(headerRootLayout, true, 100);
|
||||
animateView(headerUploaderLayout, true, 300);
|
||||
headerUploaderLayout.setOnClickListener(null);
|
||||
animateView(headerBinding.getRoot(), true, 100);
|
||||
animateView(headerBinding.uploaderLayout, true, 300);
|
||||
headerBinding.uploaderLayout.setOnClickListener(null);
|
||||
// If we have an uploader put them into the UI
|
||||
if (!TextUtils.isEmpty(result.getUploaderName())) {
|
||||
headerUploaderName.setText(result.getUploaderName());
|
||||
headerBinding.uploaderName.setText(result.getUploaderName());
|
||||
if (!TextUtils.isEmpty(result.getUploaderUrl())) {
|
||||
headerUploaderLayout.setOnClickListener(v -> {
|
||||
headerBinding.uploaderLayout.setOnClickListener(v -> {
|
||||
try {
|
||||
NavigationHelper.openChannelFragment(getFM(), result.getServiceId(),
|
||||
result.getUploaderUrl(), result.getUploaderName());
|
||||
|
@ -303,28 +289,29 @@ public class PlaylistFragment extends BaseListInfoFragment<PlaylistInfo> {
|
|||
});
|
||||
}
|
||||
} else { // Otherwise say we have no uploader
|
||||
headerUploaderName.setText(R.string.playlist_no_uploader);
|
||||
headerBinding.uploaderName.setText(R.string.playlist_no_uploader);
|
||||
}
|
||||
|
||||
playlistCtrl.setVisibility(View.VISIBLE);
|
||||
playlistControlBinding.getRoot().setVisibility(View.VISIBLE);
|
||||
|
||||
final String avatarUrl = result.getUploaderAvatarUrl();
|
||||
if (result.getServiceId() == ServiceList.YouTube.getServiceId()
|
||||
&& (YoutubeParsingHelper.isYoutubeMixId(result.getId())
|
||||
|| YoutubeParsingHelper.isYoutubeMusicMixId(result.getId()))) {
|
||||
// this is an auto-generated playlist (e.g. Youtube mix), so a radio is shown
|
||||
headerUploaderAvatar.setDisableCircularTransformation(true);
|
||||
headerUploaderAvatar.setBorderColor(
|
||||
headerBinding.uploaderAvatarView.setDisableCircularTransformation(true);
|
||||
headerBinding.uploaderAvatarView.setBorderColor(
|
||||
getResources().getColor(R.color.transparent_background_color));
|
||||
headerUploaderAvatar.setImageDrawable(AppCompatResources.getDrawable(requireContext(),
|
||||
resolveResourceIdFromAttr(requireContext(), R.attr.ic_radio)));
|
||||
|
||||
headerBinding.uploaderAvatarView.setImageDrawable(
|
||||
AppCompatResources.getDrawable(requireContext(),
|
||||
resolveResourceIdFromAttr(requireContext(), R.attr.ic_radio))
|
||||
);
|
||||
} else {
|
||||
IMAGE_LOADER.displayImage(avatarUrl, headerUploaderAvatar,
|
||||
IMAGE_LOADER.displayImage(avatarUrl, headerBinding.uploaderAvatarView,
|
||||
ImageDisplayConstants.DISPLAY_AVATAR_OPTIONS);
|
||||
}
|
||||
|
||||
headerStreamCount.setText(Localization
|
||||
headerBinding.playlistStreamCount.setText(Localization
|
||||
.localizeStreamCount(getContext(), result.getStreamCount()));
|
||||
|
||||
if (!result.getErrors().isEmpty()) {
|
||||
|
@ -338,19 +325,19 @@ public class PlaylistFragment extends BaseListInfoFragment<PlaylistInfo> {
|
|||
.observeOn(AndroidSchedulers.mainThread())
|
||||
.subscribe(getPlaylistBookmarkSubscriber());
|
||||
|
||||
headerPlayAllButton.setOnClickListener(view ->
|
||||
playlistControlBinding.playlistCtrlPlayAllButton.setOnClickListener(view ->
|
||||
NavigationHelper.playOnMainPlayer(activity, getPlayQueue()));
|
||||
headerPopupButton.setOnClickListener(view ->
|
||||
playlistControlBinding.playlistCtrlPlayPopupButton.setOnClickListener(view ->
|
||||
NavigationHelper.playOnPopupPlayer(activity, getPlayQueue(), false));
|
||||
headerBackgroundButton.setOnClickListener(view ->
|
||||
playlistControlBinding.playlistCtrlPlayBgButton.setOnClickListener(view ->
|
||||
NavigationHelper.playOnBackgroundPlayer(activity, getPlayQueue(), false));
|
||||
|
||||
headerPopupButton.setOnLongClickListener(view -> {
|
||||
playlistControlBinding.playlistCtrlPlayPopupButton.setOnLongClickListener(view -> {
|
||||
NavigationHelper.enqueueOnPopupPlayer(activity, getPlayQueue(), true);
|
||||
return true;
|
||||
});
|
||||
|
||||
headerBackgroundButton.setOnLongClickListener(view -> {
|
||||
playlistControlBinding.playlistCtrlPlayBgButton.setOnLongClickListener(view -> {
|
||||
NavigationHelper.enqueueOnBackgroundPlayer(activity, getPlayQueue(), true);
|
||||
return true;
|
||||
});
|
||||
|
@ -459,7 +446,7 @@ public class PlaylistFragment extends BaseListInfoFragment<PlaylistInfo> {
|
|||
@Override
|
||||
public void setTitle(final String title) {
|
||||
super.setTitle(title);
|
||||
headerTitleView.setText(title);
|
||||
headerBinding.playlistTitleView.setText(title);
|
||||
}
|
||||
|
||||
private void onBookmarkClicked() {
|
||||
|
|
|
@ -37,6 +37,7 @@ import androidx.recyclerview.widget.RecyclerView;
|
|||
import org.schabi.newpipe.R;
|
||||
import org.schabi.newpipe.ReCaptchaActivity;
|
||||
import org.schabi.newpipe.database.history.model.SearchHistoryEntry;
|
||||
import org.schabi.newpipe.databinding.FragmentSearchBinding;
|
||||
import org.schabi.newpipe.extractor.InfoItem;
|
||||
import org.schabi.newpipe.extractor.ListExtractor;
|
||||
import org.schabi.newpipe.extractor.MetaInfo;
|
||||
|
@ -155,6 +156,8 @@ public class SearchFragment extends BaseListFragment<SearchInfo, ListExtractor.I
|
|||
// Views
|
||||
//////////////////////////////////////////////////////////////////////////*/
|
||||
|
||||
private FragmentSearchBinding searchBinding;
|
||||
|
||||
private View searchToolbarContainer;
|
||||
private EditText searchEditText;
|
||||
private View searchClear;
|
||||
|
@ -165,7 +168,6 @@ public class SearchFragment extends BaseListFragment<SearchInfo, ListExtractor.I
|
|||
|
||||
private View suggestionsPanel;
|
||||
private boolean suggestionsPanelVisible = false;
|
||||
private RecyclerView suggestionsRecyclerView;
|
||||
|
||||
/*////////////////////////////////////////////////////////////////////////*/
|
||||
|
||||
|
@ -301,6 +303,8 @@ public class SearchFragment extends BaseListFragment<SearchInfo, ListExtractor.I
|
|||
Log.d(TAG, "onDestroyView() called");
|
||||
}
|
||||
unsetSearchListeners();
|
||||
|
||||
searchBinding = null;
|
||||
super.onDestroyView();
|
||||
}
|
||||
|
||||
|
@ -337,9 +341,9 @@ public class SearchFragment extends BaseListFragment<SearchInfo, ListExtractor.I
|
|||
@Override
|
||||
protected void initViews(final View rootView, final Bundle savedInstanceState) {
|
||||
super.initViews(rootView, savedInstanceState);
|
||||
suggestionsPanel = rootView.findViewById(R.id.suggestions_panel);
|
||||
suggestionsRecyclerView = rootView.findViewById(R.id.suggestions_list);
|
||||
suggestionsRecyclerView.setAdapter(suggestionListAdapter);
|
||||
searchBinding = FragmentSearchBinding.bind(rootView);
|
||||
|
||||
searchBinding.suggestionsList.setAdapter(suggestionListAdapter);
|
||||
new ItemTouchHelper(new ItemTouchHelper.Callback() {
|
||||
@Override
|
||||
public int getMovementFlags(@NonNull final RecyclerView recyclerView,
|
||||
|
@ -358,7 +362,7 @@ public class SearchFragment extends BaseListFragment<SearchInfo, ListExtractor.I
|
|||
public void onSwiped(@NonNull final RecyclerView.ViewHolder viewHolder, final int i) {
|
||||
onSuggestionItemSwiped(viewHolder);
|
||||
}
|
||||
}).attachToRecyclerView(suggestionsRecyclerView);
|
||||
}).attachToRecyclerView(searchBinding.suggestionsList);
|
||||
|
||||
searchToolbarContainer = activity.findViewById(R.id.toolbar_search_container);
|
||||
searchEditText = searchToolbarContainer.findViewById(R.id.toolbar_search_edit_text);
|
||||
|
@ -523,7 +527,7 @@ public class SearchFragment extends BaseListFragment<SearchInfo, ListExtractor.I
|
|||
return;
|
||||
}
|
||||
|
||||
correctSuggestion.setVisibility(View.GONE);
|
||||
searchBinding.correctSuggestion.setVisibility(View.GONE);
|
||||
|
||||
searchEditText.setText("");
|
||||
suggestionListAdapter.setItems(new ArrayList<>());
|
||||
|
@ -640,7 +644,8 @@ public class SearchFragment extends BaseListFragment<SearchInfo, ListExtractor.I
|
|||
Log.d(TAG, "showSuggestionsPanel() called");
|
||||
}
|
||||
suggestionsPanelVisible = true;
|
||||
animateView(suggestionsPanel, AnimationUtils.Type.LIGHT_SLIDE_AND_ALPHA, true, 200);
|
||||
animateView(searchBinding.suggestionsPanel, AnimationUtils.Type.LIGHT_SLIDE_AND_ALPHA,
|
||||
true, 200);
|
||||
}
|
||||
|
||||
private void hideSuggestionsPanel() {
|
||||
|
@ -648,7 +653,8 @@ public class SearchFragment extends BaseListFragment<SearchInfo, ListExtractor.I
|
|||
Log.d(TAG, "hideSuggestionsPanel() called");
|
||||
}
|
||||
suggestionsPanelVisible = false;
|
||||
animateView(suggestionsPanel, AnimationUtils.Type.LIGHT_SLIDE_AND_ALPHA, false, 200);
|
||||
animateView(searchBinding.suggestionsPanel, AnimationUtils.Type.LIGHT_SLIDE_AND_ALPHA,
|
||||
false, 200);
|
||||
}
|
||||
|
||||
private void showKeyboardSearch() {
|
||||
|
@ -936,8 +942,8 @@ public class SearchFragment extends BaseListFragment<SearchInfo, ListExtractor.I
|
|||
if (DEBUG) {
|
||||
Log.d(TAG, "handleSuggestions() called with: suggestions = [" + suggestions + "]");
|
||||
}
|
||||
suggestionsRecyclerView.smoothScrollToPosition(0);
|
||||
suggestionsRecyclerView.post(() -> suggestionListAdapter.setItems(suggestions));
|
||||
searchBinding.suggestionsList.smoothScrollToPosition(0);
|
||||
searchBinding.suggestionsList.post(() -> suggestionListAdapter.setItems(suggestions));
|
||||
|
||||
if (suggestionsPanelVisible && errorPanelRoot.getVisibility() == View.VISIBLE) {
|
||||
hideLoading();
|
||||
|
@ -1019,7 +1025,7 @@ public class SearchFragment extends BaseListFragment<SearchInfo, ListExtractor.I
|
|||
|
||||
private void handleSearchSuggestion() {
|
||||
if (TextUtils.isEmpty(searchSuggestion)) {
|
||||
correctSuggestion.setVisibility(View.GONE);
|
||||
searchBinding.correctSuggestion.setVisibility(View.GONE);
|
||||
} else {
|
||||
final String helperText = getString(isCorrectedSearch
|
||||
? R.string.search_showing_result_for
|
||||
|
@ -1028,22 +1034,23 @@ public class SearchFragment extends BaseListFragment<SearchInfo, ListExtractor.I
|
|||
final String highlightedSearchSuggestion =
|
||||
"<b><i>" + Html.escapeHtml(searchSuggestion) + "</i></b>";
|
||||
final String text = String.format(helperText, highlightedSearchSuggestion);
|
||||
correctSuggestion.setText(HtmlCompat.fromHtml(text, HtmlCompat.FROM_HTML_MODE_LEGACY));
|
||||
searchBinding.correctSuggestion.setText(HtmlCompat.fromHtml(text,
|
||||
HtmlCompat.FROM_HTML_MODE_LEGACY));
|
||||
|
||||
correctSuggestion.setOnClickListener(v -> {
|
||||
correctSuggestion.setVisibility(View.GONE);
|
||||
searchBinding.correctSuggestion.setOnClickListener(v -> {
|
||||
searchBinding.correctSuggestion.setVisibility(View.GONE);
|
||||
search(searchSuggestion, contentFilter, sortFilter);
|
||||
searchEditText.setText(searchSuggestion);
|
||||
});
|
||||
|
||||
correctSuggestion.setOnLongClickListener(v -> {
|
||||
searchBinding.correctSuggestion.setOnLongClickListener(v -> {
|
||||
searchEditText.setText(searchSuggestion);
|
||||
searchEditText.setSelection(searchSuggestion.length());
|
||||
showKeyboardSearch();
|
||||
return true;
|
||||
});
|
||||
|
||||
correctSuggestion.setVisibility(View.VISIBLE);
|
||||
searchBinding.correctSuggestion.setVisibility(View.VISIBLE);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -8,13 +8,14 @@ import android.view.Menu;
|
|||
import android.view.MenuInflater;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.Switch;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.preference.PreferenceManager;
|
||||
import androidx.viewbinding.ViewBinding;
|
||||
|
||||
import org.schabi.newpipe.R;
|
||||
import org.schabi.newpipe.databinding.RelatedStreamsHeaderBinding;
|
||||
import org.schabi.newpipe.extractor.ListExtractor;
|
||||
import org.schabi.newpipe.extractor.NewPipe;
|
||||
import org.schabi.newpipe.extractor.stream.StreamInfo;
|
||||
|
@ -38,8 +39,7 @@ public class RelatedVideosFragment extends BaseListInfoFragment<RelatedStreamInf
|
|||
// Views
|
||||
//////////////////////////////////////////////////////////////////////////*/
|
||||
|
||||
private View headerRootLayout;
|
||||
private Switch autoplaySwitch;
|
||||
private RelatedStreamsHeaderBinding headerBinding;
|
||||
|
||||
public static RelatedVideosFragment getInstance(final StreamInfo info) {
|
||||
final RelatedVideosFragment instance = new RelatedVideosFragment();
|
||||
|
@ -66,25 +66,29 @@ public class RelatedVideosFragment extends BaseListInfoFragment<RelatedStreamInf
|
|||
@Override
|
||||
public void onDestroy() {
|
||||
super.onDestroy();
|
||||
if (disposables != null) {
|
||||
disposables.clear();
|
||||
}
|
||||
disposables.clear();
|
||||
}
|
||||
|
||||
protected View getListHeader() {
|
||||
@Override
|
||||
public void onDestroyView() {
|
||||
headerBinding = null;
|
||||
super.onDestroyView();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected ViewBinding getListHeader() {
|
||||
if (relatedStreamInfo != null && relatedStreamInfo.getRelatedItems() != null) {
|
||||
headerRootLayout = activity.getLayoutInflater()
|
||||
.inflate(R.layout.related_streams_header, itemsList, false);
|
||||
autoplaySwitch = headerRootLayout.findViewById(R.id.autoplay_switch);
|
||||
headerBinding = RelatedStreamsHeaderBinding
|
||||
.inflate(activity.getLayoutInflater(), itemsList, false);
|
||||
|
||||
final SharedPreferences pref = PreferenceManager
|
||||
.getDefaultSharedPreferences(requireContext());
|
||||
final boolean autoplay = pref.getBoolean(getString(R.string.auto_queue_key), false);
|
||||
autoplaySwitch.setChecked(autoplay);
|
||||
autoplaySwitch.setOnCheckedChangeListener((compoundButton, b) ->
|
||||
headerBinding.autoplaySwitch.setChecked(autoplay);
|
||||
headerBinding.autoplaySwitch.setOnCheckedChangeListener((compoundButton, b) ->
|
||||
PreferenceManager.getDefaultSharedPreferences(requireContext()).edit()
|
||||
.putBoolean(getString(R.string.auto_queue_key), b).apply());
|
||||
return headerRootLayout;
|
||||
return headerBinding;
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
|
@ -107,8 +111,8 @@ public class RelatedVideosFragment extends BaseListInfoFragment<RelatedStreamInf
|
|||
@Override
|
||||
public void showLoading() {
|
||||
super.showLoading();
|
||||
if (headerRootLayout != null) {
|
||||
headerRootLayout.setVisibility(View.INVISIBLE);
|
||||
if (headerBinding != null) {
|
||||
headerBinding.getRoot().setVisibility(View.INVISIBLE);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -116,8 +120,8 @@ public class RelatedVideosFragment extends BaseListInfoFragment<RelatedStreamInf
|
|||
public void handleResult(@NonNull final RelatedStreamInfo result) {
|
||||
super.handleResult(result);
|
||||
|
||||
if (headerRootLayout != null) {
|
||||
headerRootLayout.setVisibility(View.VISIBLE);
|
||||
if (headerBinding != null) {
|
||||
headerBinding.getRoot().setVisibility(View.VISIBLE);
|
||||
}
|
||||
AnimationUtils.slideUp(getView(), 120, 96, 0.06f);
|
||||
|
||||
|
@ -126,9 +130,7 @@ public class RelatedVideosFragment extends BaseListInfoFragment<RelatedStreamInf
|
|||
NewPipe.getNameOfService(result.getServiceId()), result.getUrl(), 0);
|
||||
}
|
||||
|
||||
if (disposables != null) {
|
||||
disposables.clear();
|
||||
}
|
||||
disposables.clear();
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -202,8 +204,8 @@ public class RelatedVideosFragment extends BaseListInfoFragment<RelatedStreamInf
|
|||
final SharedPreferences pref =
|
||||
PreferenceManager.getDefaultSharedPreferences(requireContext());
|
||||
final boolean autoplay = pref.getBoolean(getString(R.string.auto_queue_key), false);
|
||||
if (autoplaySwitch != null) {
|
||||
autoplaySwitch.setChecked(autoplay);
|
||||
if (headerBinding != null) {
|
||||
headerBinding.autoplaySwitch.setChecked(autoplay);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -4,6 +4,8 @@ import android.content.SharedPreferences;
|
|||
import android.content.res.Configuration;
|
||||
import android.content.res.Resources;
|
||||
import android.os.Bundle;
|
||||
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.preference.PreferenceManager;
|
||||
import android.util.Log;
|
||||
import android.view.Menu;
|
||||
|
@ -15,8 +17,10 @@ import androidx.fragment.app.Fragment;
|
|||
import androidx.recyclerview.widget.GridLayoutManager;
|
||||
import androidx.recyclerview.widget.LinearLayoutManager;
|
||||
import androidx.recyclerview.widget.RecyclerView;
|
||||
import androidx.viewbinding.ViewBinding;
|
||||
|
||||
import org.schabi.newpipe.R;
|
||||
import org.schabi.newpipe.databinding.PignateFooterBinding;
|
||||
import org.schabi.newpipe.fragments.BaseStateFragment;
|
||||
import org.schabi.newpipe.fragments.list.ListViewContract;
|
||||
|
||||
|
@ -42,8 +46,8 @@ public abstract class BaseLocalListFragment<I, N> extends BaseStateFragment<I>
|
|||
//////////////////////////////////////////////////////////////////////////*/
|
||||
|
||||
private static final int LIST_MODE_UPDATE_FLAG = 0x32;
|
||||
private View headerRootView;
|
||||
private View footerRootView;
|
||||
private ViewBinding headerRootBinding;
|
||||
private ViewBinding footerRootBinding;
|
||||
protected LocalItemListAdapter itemListAdapter;
|
||||
protected RecyclerView itemsList;
|
||||
private int updateFlags = 0;
|
||||
|
@ -86,12 +90,13 @@ public abstract class BaseLocalListFragment<I, N> extends BaseStateFragment<I>
|
|||
// Lifecycle - View
|
||||
//////////////////////////////////////////////////////////////////////////*/
|
||||
|
||||
protected View getListHeader() {
|
||||
@Nullable
|
||||
protected ViewBinding getListHeader() {
|
||||
return null;
|
||||
}
|
||||
|
||||
protected View getListFooter() {
|
||||
return activity.getLayoutInflater().inflate(R.layout.pignate_footer, itemsList, false);
|
||||
protected ViewBinding getListFooter() {
|
||||
return PignateFooterBinding.inflate(activity.getLayoutInflater(), itemsList, false);
|
||||
}
|
||||
|
||||
protected RecyclerView.LayoutManager getGridLayoutManager() {
|
||||
|
@ -120,10 +125,12 @@ public abstract class BaseLocalListFragment<I, N> extends BaseStateFragment<I>
|
|||
itemsList.setLayoutManager(useGrid ? getGridLayoutManager() : getListLayoutManager());
|
||||
|
||||
itemListAdapter.setUseGridVariant(useGrid);
|
||||
headerRootView = getListHeader();
|
||||
itemListAdapter.setHeader(headerRootView);
|
||||
footerRootView = getListFooter();
|
||||
itemListAdapter.setFooter(footerRootView);
|
||||
headerRootBinding = getListHeader();
|
||||
if (headerRootBinding != null) {
|
||||
itemListAdapter.setHeader(headerRootBinding.getRoot());
|
||||
}
|
||||
footerRootBinding = getListFooter();
|
||||
itemListAdapter.setFooter(footerRootBinding.getRoot());
|
||||
|
||||
itemsList.setAdapter(itemListAdapter);
|
||||
}
|
||||
|
@ -180,8 +187,8 @@ public abstract class BaseLocalListFragment<I, N> extends BaseStateFragment<I>
|
|||
if (itemsList != null) {
|
||||
animateView(itemsList, false, 200);
|
||||
}
|
||||
if (headerRootView != null) {
|
||||
animateView(headerRootView, false, 200);
|
||||
if (headerRootBinding != null) {
|
||||
animateView(headerRootBinding.getRoot(), false, 200);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -191,8 +198,8 @@ public abstract class BaseLocalListFragment<I, N> extends BaseStateFragment<I>
|
|||
if (itemsList != null) {
|
||||
animateView(itemsList, true, 200);
|
||||
}
|
||||
if (headerRootView != null) {
|
||||
animateView(headerRootView, true, 200);
|
||||
if (headerRootBinding != null) {
|
||||
animateView(headerRootBinding.getRoot(), true, 200);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -204,8 +211,8 @@ public abstract class BaseLocalListFragment<I, N> extends BaseStateFragment<I>
|
|||
if (itemsList != null) {
|
||||
animateView(itemsList, false, 200);
|
||||
}
|
||||
if (headerRootView != null) {
|
||||
animateView(headerRootView, false, 200);
|
||||
if (headerRootBinding != null) {
|
||||
animateView(headerRootBinding.getRoot(), false, 200);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -37,18 +37,10 @@ import androidx.lifecycle.ViewModelProvider
|
|||
import androidx.preference.PreferenceManager
|
||||
import androidx.swiperefreshlayout.widget.SwipeRefreshLayout
|
||||
import icepick.State
|
||||
import kotlinx.android.synthetic.main.error_retry.error_button_retry
|
||||
import kotlinx.android.synthetic.main.error_retry.error_message_view
|
||||
import kotlinx.android.synthetic.main.fragment_feed.empty_state_view
|
||||
import kotlinx.android.synthetic.main.fragment_feed.error_panel
|
||||
import kotlinx.android.synthetic.main.fragment_feed.items_list
|
||||
import kotlinx.android.synthetic.main.fragment_feed.loading_progress_bar
|
||||
import kotlinx.android.synthetic.main.fragment_feed.loading_progress_text
|
||||
import kotlinx.android.synthetic.main.fragment_feed.refresh_root_view
|
||||
import kotlinx.android.synthetic.main.fragment_feed.refresh_subtitle_text
|
||||
import kotlinx.android.synthetic.main.fragment_feed.refresh_text
|
||||
import org.schabi.newpipe.R
|
||||
import org.schabi.newpipe.database.feed.model.FeedGroupEntity
|
||||
import org.schabi.newpipe.databinding.ErrorRetryBinding
|
||||
import org.schabi.newpipe.databinding.FragmentFeedBinding
|
||||
import org.schabi.newpipe.fragments.list.BaseListFragment
|
||||
import org.schabi.newpipe.local.feed.service.FeedLoadService
|
||||
import org.schabi.newpipe.report.UserAction
|
||||
|
@ -57,6 +49,12 @@ import org.schabi.newpipe.util.Localization
|
|||
import java.util.Calendar
|
||||
|
||||
class FeedFragment : BaseListFragment<FeedState, Unit>() {
|
||||
private var _feedBinding: FragmentFeedBinding? = null
|
||||
private val feedBinding get() = _feedBinding!!
|
||||
|
||||
private var _errorBinding: ErrorRetryBinding? = null
|
||||
private val errorBinding get() = _errorBinding!!
|
||||
|
||||
private lateinit var viewModel: FeedViewModel
|
||||
private lateinit var swipeRefreshLayout: SwipeRefreshLayout
|
||||
@State
|
||||
|
@ -86,15 +84,17 @@ class FeedFragment : BaseListFragment<FeedState, Unit>() {
|
|||
|
||||
override fun onViewCreated(rootView: View, savedInstanceState: Bundle?) {
|
||||
super.onViewCreated(rootView, savedInstanceState)
|
||||
swipeRefreshLayout = requireView().findViewById(R.id.swiperefresh)
|
||||
swipeRefreshLayout.setOnRefreshListener { reloadContent() }
|
||||
_feedBinding = FragmentFeedBinding.bind(rootView)
|
||||
_errorBinding = feedBinding.errorPanel
|
||||
|
||||
feedBinding.swiperefresh.setOnRefreshListener { reloadContent() }
|
||||
viewModel = ViewModelProvider(this, FeedViewModel.Factory(requireContext(), groupId)).get(FeedViewModel::class.java)
|
||||
viewModel.stateLiveData.observe(viewLifecycleOwner, Observer { it?.let(::handleResult) })
|
||||
}
|
||||
|
||||
override fun onPause() {
|
||||
super.onPause()
|
||||
listState = items_list?.layoutManager?.onSaveInstanceState()
|
||||
listState = _feedBinding?.itemsList?.layoutManager?.onSaveInstanceState()
|
||||
}
|
||||
|
||||
override fun onResume() {
|
||||
|
@ -112,7 +112,8 @@ class FeedFragment : BaseListFragment<FeedState, Unit>() {
|
|||
|
||||
override fun initListeners() {
|
||||
super.initListeners()
|
||||
refresh_root_view.setOnClickListener {
|
||||
// Using the non-null property may result in a NullPointerException
|
||||
_feedBinding?.refreshRootView?.setOnClickListener {
|
||||
triggerUpdate()
|
||||
}
|
||||
}
|
||||
|
@ -169,55 +170,60 @@ class FeedFragment : BaseListFragment<FeedState, Unit>() {
|
|||
activity?.supportActionBar?.subtitle = null
|
||||
}
|
||||
|
||||
override fun onDestroyView() {
|
||||
_feedBinding = null
|
||||
super.onDestroyView()
|
||||
}
|
||||
|
||||
// /////////////////////////////////////////////////////////////////////////
|
||||
// Handling
|
||||
// /////////////////////////////////////////////////////////////////////////
|
||||
|
||||
override fun showLoading() {
|
||||
animateView(refresh_root_view, false, 0)
|
||||
animateView(items_list, false, 0)
|
||||
animateView(feedBinding.refreshRootView, false, 0)
|
||||
animateView(feedBinding.itemsList, false, 0)
|
||||
|
||||
animateView(loading_progress_bar, true, 200)
|
||||
animateView(loading_progress_text, true, 200)
|
||||
animateView(feedBinding.loadingProgressBar, true, 200)
|
||||
animateView(feedBinding.loadingProgressText, true, 200)
|
||||
|
||||
empty_state_view?.let { animateView(it, false, 0) }
|
||||
animateView(error_panel, false, 0)
|
||||
animateView(feedBinding.emptyStateView.root, false, 0)
|
||||
animateView(errorBinding.root, false, 0)
|
||||
}
|
||||
|
||||
override fun hideLoading() {
|
||||
animateView(refresh_root_view, true, 200)
|
||||
animateView(items_list, true, 300)
|
||||
animateView(feedBinding.refreshRootView, true, 200)
|
||||
animateView(feedBinding.itemsList, true, 300)
|
||||
|
||||
animateView(loading_progress_bar, false, 0)
|
||||
animateView(loading_progress_text, false, 0)
|
||||
animateView(feedBinding.loadingProgressBar, false, 0)
|
||||
animateView(feedBinding.loadingProgressText, false, 0)
|
||||
|
||||
empty_state_view?.let { animateView(it, false, 0) }
|
||||
animateView(error_panel, false, 0)
|
||||
swipeRefreshLayout.isRefreshing = false
|
||||
animateView(feedBinding.emptyStateView.root, false, 0)
|
||||
animateView(errorBinding.root, false, 0)
|
||||
feedBinding.swiperefresh.isRefreshing = false
|
||||
}
|
||||
|
||||
override fun showEmptyState() {
|
||||
animateView(refresh_root_view, true, 200)
|
||||
animateView(items_list, false, 0)
|
||||
animateView(feedBinding.refreshRootView, true, 200)
|
||||
animateView(feedBinding.itemsList, false, 0)
|
||||
|
||||
animateView(loading_progress_bar, false, 0)
|
||||
animateView(loading_progress_text, false, 0)
|
||||
animateView(feedBinding.loadingProgressBar, false, 0)
|
||||
animateView(feedBinding.loadingProgressText, false, 0)
|
||||
|
||||
empty_state_view?.let { animateView(it, true, 800) }
|
||||
animateView(error_panel, false, 0)
|
||||
animateView(feedBinding.emptyStateView.root, true, 800)
|
||||
animateView(errorBinding.root, false, 0)
|
||||
}
|
||||
|
||||
override fun showError(message: String, showRetryButton: Boolean) {
|
||||
infoListAdapter.clearStreamItemList()
|
||||
animateView(refresh_root_view, false, 120)
|
||||
animateView(items_list, false, 120)
|
||||
animateView(feedBinding.refreshRootView, false, 120)
|
||||
animateView(feedBinding.itemsList, false, 120)
|
||||
|
||||
animateView(loading_progress_bar, false, 120)
|
||||
animateView(loading_progress_text, false, 120)
|
||||
animateView(feedBinding.loadingProgressBar, false, 120)
|
||||
animateView(feedBinding.loadingProgressText, false, 120)
|
||||
|
||||
error_message_view.text = message
|
||||
animateView(error_button_retry, showRetryButton, if (showRetryButton) 600 else 0)
|
||||
animateView(error_panel, true, 300)
|
||||
errorBinding.errorMessageView.text = message
|
||||
animateView(errorBinding.errorButtonRetry, showRetryButton, if (showRetryButton) 600 else 0)
|
||||
animateView(errorBinding.root, true, 300)
|
||||
}
|
||||
|
||||
override fun handleResult(result: FeedState) {
|
||||
|
@ -237,33 +243,34 @@ class FeedFragment : BaseListFragment<FeedState, Unit>() {
|
|||
progressState.maxProgress == -1
|
||||
|
||||
if (!isIndeterminate) {
|
||||
loading_progress_text.text = "${progressState.currentProgress}/${progressState.maxProgress}"
|
||||
feedBinding.loadingProgressText.text = "${progressState.currentProgress}/${progressState.maxProgress}"
|
||||
} else if (progressState.progressMessage > 0) {
|
||||
loading_progress_text?.setText(progressState.progressMessage)
|
||||
_feedBinding?.loadingProgressText?.setText(progressState.progressMessage)
|
||||
} else {
|
||||
loading_progress_text?.text = "∞/∞"
|
||||
_feedBinding?.loadingProgressText?.text = "∞/∞"
|
||||
}
|
||||
|
||||
loading_progress_bar.isIndeterminate = isIndeterminate ||
|
||||
(progressState.maxProgress > 0 && progressState.currentProgress == 0)
|
||||
loading_progress_bar.progress = progressState.currentProgress
|
||||
feedBinding.loadingProgressBar.isIndeterminate = isIndeterminate ||
|
||||
(progressState.maxProgress > 0 && progressState.currentProgress == 0)
|
||||
feedBinding.loadingProgressBar.progress = progressState.currentProgress
|
||||
|
||||
loading_progress_bar.max = progressState.maxProgress
|
||||
feedBinding.loadingProgressBar.max = progressState.maxProgress
|
||||
}
|
||||
|
||||
private fun handleLoadedState(loadedState: FeedState.LoadedState) {
|
||||
infoListAdapter.setInfoItemList(loadedState.items)
|
||||
listState?.run {
|
||||
items_list.layoutManager?.onRestoreInstanceState(listState)
|
||||
feedBinding.itemsList.layoutManager?.onRestoreInstanceState(listState)
|
||||
listState = null
|
||||
}
|
||||
|
||||
oldestSubscriptionUpdate = loadedState.oldestUpdate
|
||||
|
||||
val loadedCount = loadedState.notLoadedCount > 0
|
||||
refresh_subtitle_text.isVisible = loadedCount
|
||||
feedBinding.refreshSubtitleText.isVisible = loadedCount
|
||||
if (loadedCount) {
|
||||
refresh_subtitle_text.text = getString(R.string.feed_subscription_not_loaded_count, loadedState.notLoadedCount)
|
||||
feedBinding.refreshSubtitleText.text = getString(R.string.feed_subscription_not_loaded_count,
|
||||
loadedState.notLoadedCount)
|
||||
}
|
||||
|
||||
if (loadedState.itemsErrors.isNotEmpty()) {
|
||||
|
@ -300,7 +307,7 @@ class FeedFragment : BaseListFragment<FeedState, Unit>() {
|
|||
else -> "—"
|
||||
}
|
||||
|
||||
refresh_text?.text = getString(R.string.feed_oldest_subscription_update, oldestSubscriptionUpdateText)
|
||||
feedBinding.refreshText.text = getString(R.string.feed_oldest_subscription_update, oldestSubscriptionUpdateText)
|
||||
}
|
||||
|
||||
// /////////////////////////////////////////////////////////////////////////
|
||||
|
|
|
@ -10,13 +10,12 @@ import android.view.MenuInflater;
|
|||
import android.view.MenuItem;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.ImageView;
|
||||
import android.widget.TextView;
|
||||
import android.widget.Toast;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.appcompat.app.AlertDialog;
|
||||
import androidx.viewbinding.ViewBinding;
|
||||
|
||||
import com.google.android.material.snackbar.Snackbar;
|
||||
|
||||
|
@ -26,6 +25,8 @@ import org.schabi.newpipe.R;
|
|||
import org.schabi.newpipe.database.LocalItem;
|
||||
import org.schabi.newpipe.database.stream.StreamStatisticsEntry;
|
||||
import org.schabi.newpipe.database.stream.model.StreamEntity;
|
||||
import org.schabi.newpipe.databinding.PlaylistControlBinding;
|
||||
import org.schabi.newpipe.databinding.StatisticPlaylistControlBinding;
|
||||
import org.schabi.newpipe.extractor.stream.StreamInfoItem;
|
||||
import org.schabi.newpipe.extractor.stream.StreamType;
|
||||
import org.schabi.newpipe.info_list.InfoItemDialog;
|
||||
|
@ -60,13 +61,10 @@ public class StatisticsPlaylistFragment
|
|||
@State
|
||||
Parcelable itemsListState;
|
||||
private StatisticSortMode sortMode = StatisticSortMode.LAST_PLAYED;
|
||||
private View headerPlayAllButton;
|
||||
private View headerPopupButton;
|
||||
private View headerBackgroundButton;
|
||||
private View playlistCtrl;
|
||||
private View sortButton;
|
||||
private ImageView sortButtonIcon;
|
||||
private TextView sortButtonText;
|
||||
|
||||
private StatisticPlaylistControlBinding headerBinding;
|
||||
private PlaylistControlBinding playlistControlBinding;
|
||||
|
||||
/* Used for independent events */
|
||||
private Subscription databaseSubscription;
|
||||
private HistoryRecordManager recordManager;
|
||||
|
@ -131,17 +129,12 @@ public class StatisticsPlaylistFragment
|
|||
}
|
||||
|
||||
@Override
|
||||
protected View getListHeader() {
|
||||
final View headerRootLayout = activity.getLayoutInflater()
|
||||
.inflate(R.layout.statistic_playlist_control, itemsList, false);
|
||||
playlistCtrl = headerRootLayout.findViewById(R.id.playlist_control);
|
||||
headerPlayAllButton = headerRootLayout.findViewById(R.id.playlist_ctrl_play_all_button);
|
||||
headerPopupButton = headerRootLayout.findViewById(R.id.playlist_ctrl_play_popup_button);
|
||||
headerBackgroundButton = headerRootLayout.findViewById(R.id.playlist_ctrl_play_bg_button);
|
||||
sortButton = headerRootLayout.findViewById(R.id.sortButton);
|
||||
sortButtonIcon = headerRootLayout.findViewById(R.id.sortButtonIcon);
|
||||
sortButtonText = headerRootLayout.findViewById(R.id.sortButtonText);
|
||||
return headerRootLayout;
|
||||
protected ViewBinding getListHeader() {
|
||||
headerBinding = StatisticPlaylistControlBinding.inflate(activity.getLayoutInflater(),
|
||||
itemsList, false);
|
||||
playlistControlBinding = headerBinding.playlistControl;
|
||||
|
||||
return headerBinding;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -245,14 +238,13 @@ public class StatisticsPlaylistFragment
|
|||
if (itemListAdapter != null) {
|
||||
itemListAdapter.unsetSelectedListener();
|
||||
}
|
||||
if (headerBackgroundButton != null) {
|
||||
headerBackgroundButton.setOnClickListener(null);
|
||||
}
|
||||
if (headerPlayAllButton != null) {
|
||||
headerPlayAllButton.setOnClickListener(null);
|
||||
}
|
||||
if (headerPopupButton != null) {
|
||||
headerPopupButton.setOnClickListener(null);
|
||||
if (playlistControlBinding != null) {
|
||||
playlistControlBinding.playlistCtrlPlayBgButton.setOnClickListener(null);
|
||||
playlistControlBinding.playlistCtrlPlayAllButton.setOnClickListener(null);
|
||||
playlistControlBinding.playlistCtrlPlayPopupButton.setOnClickListener(null);
|
||||
|
||||
headerBinding = null;
|
||||
playlistControlBinding = null;
|
||||
}
|
||||
|
||||
if (databaseSubscription != null) {
|
||||
|
@ -311,7 +303,7 @@ public class StatisticsPlaylistFragment
|
|||
return;
|
||||
}
|
||||
|
||||
playlistCtrl.setVisibility(View.VISIBLE);
|
||||
playlistControlBinding.getRoot().setVisibility(View.VISIBLE);
|
||||
|
||||
itemListAdapter.clearStreamItemList();
|
||||
|
||||
|
@ -326,13 +318,13 @@ public class StatisticsPlaylistFragment
|
|||
itemsListState = null;
|
||||
}
|
||||
|
||||
headerPlayAllButton.setOnClickListener(view ->
|
||||
playlistControlBinding.playlistCtrlPlayAllButton.setOnClickListener(view ->
|
||||
NavigationHelper.playOnMainPlayer(activity, getPlayQueue()));
|
||||
headerPopupButton.setOnClickListener(view ->
|
||||
playlistControlBinding.playlistCtrlPlayPopupButton.setOnClickListener(view ->
|
||||
NavigationHelper.playOnPopupPlayer(activity, getPlayQueue(), false));
|
||||
headerBackgroundButton.setOnClickListener(view ->
|
||||
playlistControlBinding.playlistCtrlPlayBgButton.setOnClickListener(view ->
|
||||
NavigationHelper.playOnBackgroundPlayer(activity, getPlayQueue(), false));
|
||||
sortButton.setOnClickListener(view -> toggleSortMode());
|
||||
headerBinding.sortButton.setOnClickListener(view -> toggleSortMode());
|
||||
|
||||
hideLoading();
|
||||
}
|
||||
|
@ -368,15 +360,15 @@ public class StatisticsPlaylistFragment
|
|||
if (sortMode == StatisticSortMode.LAST_PLAYED) {
|
||||
sortMode = StatisticSortMode.MOST_PLAYED;
|
||||
setTitle(getString(R.string.title_most_played));
|
||||
sortButtonIcon.setImageResource(
|
||||
headerBinding.sortButtonIcon.setImageResource(
|
||||
ThemeHelper.resolveResourceIdFromAttr(requireContext(), R.attr.ic_history));
|
||||
sortButtonText.setText(R.string.title_last_played);
|
||||
headerBinding.sortButtonText.setText(R.string.title_last_played);
|
||||
} else {
|
||||
sortMode = StatisticSortMode.LAST_PLAYED;
|
||||
setTitle(getString(R.string.title_last_played));
|
||||
sortButtonIcon.setImageResource(
|
||||
headerBinding.sortButtonIcon.setImageResource(
|
||||
ThemeHelper.resolveResourceIdFromAttr(requireContext(), R.attr.ic_filter_list));
|
||||
sortButtonText.setText(R.string.title_most_played);
|
||||
headerBinding.sortButtonText.setText(R.string.title_most_played);
|
||||
}
|
||||
startLoading(true);
|
||||
}
|
||||
|
|
|
@ -14,7 +14,6 @@ import android.view.MenuItem;
|
|||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.EditText;
|
||||
import android.widget.TextView;
|
||||
import android.widget.Toast;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
|
@ -22,6 +21,7 @@ import androidx.annotation.Nullable;
|
|||
import androidx.appcompat.app.AlertDialog;
|
||||
import androidx.recyclerview.widget.ItemTouchHelper;
|
||||
import androidx.recyclerview.widget.RecyclerView;
|
||||
import androidx.viewbinding.ViewBinding;
|
||||
|
||||
import org.reactivestreams.Subscriber;
|
||||
import org.reactivestreams.Subscription;
|
||||
|
@ -32,6 +32,8 @@ import org.schabi.newpipe.database.history.model.StreamHistoryEntry;
|
|||
import org.schabi.newpipe.database.playlist.PlaylistStreamEntry;
|
||||
import org.schabi.newpipe.database.stream.model.StreamEntity;
|
||||
import org.schabi.newpipe.database.stream.model.StreamStateEntity;
|
||||
import org.schabi.newpipe.databinding.LocalPlaylistHeaderBinding;
|
||||
import org.schabi.newpipe.databinding.PlaylistControlBinding;
|
||||
import org.schabi.newpipe.extractor.stream.StreamInfoItem;
|
||||
import org.schabi.newpipe.extractor.stream.StreamType;
|
||||
import org.schabi.newpipe.info_list.InfoItemDialog;
|
||||
|
@ -77,13 +79,8 @@ public class LocalPlaylistFragment extends BaseLocalListFragment<List<PlaylistSt
|
|||
@State
|
||||
Parcelable itemsListState;
|
||||
|
||||
private View headerRootLayout;
|
||||
private TextView headerTitleView;
|
||||
private TextView headerStreamCount;
|
||||
private View playlistControl;
|
||||
private View headerPlayAllButton;
|
||||
private View headerPopupButton;
|
||||
private View headerBackgroundButton;
|
||||
private LocalPlaylistHeaderBinding headerBinding;
|
||||
private PlaylistControlBinding playlistControlBinding;
|
||||
|
||||
private ItemTouchHelper itemTouchHelper;
|
||||
|
||||
|
@ -137,8 +134,8 @@ public class LocalPlaylistFragment extends BaseLocalListFragment<List<PlaylistSt
|
|||
public void setTitle(final String title) {
|
||||
super.setTitle(title);
|
||||
|
||||
if (headerTitleView != null) {
|
||||
headerTitleView.setText(title);
|
||||
if (headerBinding != null) {
|
||||
headerBinding.playlistTitleView.setText(title);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -149,28 +146,21 @@ public class LocalPlaylistFragment extends BaseLocalListFragment<List<PlaylistSt
|
|||
}
|
||||
|
||||
@Override
|
||||
protected View getListHeader() {
|
||||
headerRootLayout = activity.getLayoutInflater()
|
||||
.inflate(R.layout.local_playlist_header, itemsList, false);
|
||||
protected ViewBinding getListHeader() {
|
||||
headerBinding = LocalPlaylistHeaderBinding.inflate(activity.getLayoutInflater(), itemsList,
|
||||
false);
|
||||
playlistControlBinding = headerBinding.playlistControl;
|
||||
|
||||
headerTitleView = headerRootLayout.findViewById(R.id.playlist_title_view);
|
||||
headerTitleView.setSelected(true);
|
||||
headerBinding.playlistTitleView.setSelected(true);
|
||||
|
||||
headerStreamCount = headerRootLayout.findViewById(R.id.playlist_stream_count);
|
||||
|
||||
playlistControl = headerRootLayout.findViewById(R.id.playlist_control);
|
||||
headerPlayAllButton = headerRootLayout.findViewById(R.id.playlist_ctrl_play_all_button);
|
||||
headerPopupButton = headerRootLayout.findViewById(R.id.playlist_ctrl_play_popup_button);
|
||||
headerBackgroundButton = headerRootLayout.findViewById(R.id.playlist_ctrl_play_bg_button);
|
||||
|
||||
return headerRootLayout;
|
||||
return headerBinding;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void initListeners() {
|
||||
super.initListeners();
|
||||
|
||||
headerTitleView.setOnClickListener(view -> createRenameDialog());
|
||||
headerBinding.playlistTitleView.setOnClickListener(view -> createRenameDialog());
|
||||
|
||||
itemTouchHelper = new ItemTouchHelper(getItemTouchCallback());
|
||||
itemTouchHelper.attachToRecyclerView(itemsList);
|
||||
|
@ -210,22 +200,18 @@ public class LocalPlaylistFragment extends BaseLocalListFragment<List<PlaylistSt
|
|||
@Override
|
||||
public void showLoading() {
|
||||
super.showLoading();
|
||||
if (headerRootLayout != null) {
|
||||
animateView(headerRootLayout, false, 200);
|
||||
}
|
||||
if (playlistControl != null) {
|
||||
animateView(playlistControl, false, 200);
|
||||
if (headerBinding != null) {
|
||||
animateView(headerBinding.getRoot(), false, 200);
|
||||
animateView(playlistControlBinding.getRoot(), false, 200);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void hideLoading() {
|
||||
super.hideLoading();
|
||||
if (headerRootLayout != null) {
|
||||
animateView(headerRootLayout, true, 200);
|
||||
}
|
||||
if (playlistControl != null) {
|
||||
animateView(playlistControl, true, 200);
|
||||
if (headerBinding != null) {
|
||||
animateView(headerBinding.getRoot(), true, 200);
|
||||
animateView(playlistControlBinding.getRoot(), true, 200);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -277,14 +263,13 @@ public class LocalPlaylistFragment extends BaseLocalListFragment<List<PlaylistSt
|
|||
if (itemListAdapter != null) {
|
||||
itemListAdapter.unsetSelectedListener();
|
||||
}
|
||||
if (headerBackgroundButton != null) {
|
||||
headerBackgroundButton.setOnClickListener(null);
|
||||
}
|
||||
if (headerPlayAllButton != null) {
|
||||
headerPlayAllButton.setOnClickListener(null);
|
||||
}
|
||||
if (headerPopupButton != null) {
|
||||
headerPopupButton.setOnClickListener(null);
|
||||
if (playlistControlBinding != null) {
|
||||
playlistControlBinding.playlistCtrlPlayBgButton.setOnClickListener(null);
|
||||
playlistControlBinding.playlistCtrlPlayAllButton.setOnClickListener(null);
|
||||
playlistControlBinding.playlistCtrlPlayPopupButton.setOnClickListener(null);
|
||||
|
||||
headerBinding = null;
|
||||
playlistControlBinding = null;
|
||||
}
|
||||
|
||||
if (databaseSubscription != null) {
|
||||
|
@ -494,19 +479,19 @@ public class LocalPlaylistFragment extends BaseLocalListFragment<List<PlaylistSt
|
|||
}
|
||||
setVideoCount(itemListAdapter.getItemsList().size());
|
||||
|
||||
headerPlayAllButton.setOnClickListener(view ->
|
||||
playlistControlBinding.playlistCtrlPlayAllButton.setOnClickListener(view ->
|
||||
NavigationHelper.playOnMainPlayer(activity, getPlayQueue()));
|
||||
headerPopupButton.setOnClickListener(view ->
|
||||
playlistControlBinding.playlistCtrlPlayPopupButton.setOnClickListener(view ->
|
||||
NavigationHelper.playOnPopupPlayer(activity, getPlayQueue(), false));
|
||||
headerBackgroundButton.setOnClickListener(view ->
|
||||
playlistControlBinding.playlistCtrlPlayBgButton.setOnClickListener(view ->
|
||||
NavigationHelper.playOnBackgroundPlayer(activity, getPlayQueue(), false));
|
||||
|
||||
headerPopupButton.setOnLongClickListener(view -> {
|
||||
playlistControlBinding.playlistCtrlPlayPopupButton.setOnLongClickListener(view -> {
|
||||
NavigationHelper.enqueueOnPopupPlayer(activity, getPlayQueue(), true);
|
||||
return true;
|
||||
});
|
||||
|
||||
headerBackgroundButton.setOnLongClickListener(view -> {
|
||||
playlistControlBinding.playlistCtrlPlayBgButton.setOnLongClickListener(view -> {
|
||||
NavigationHelper.enqueueOnBackgroundPlayer(activity, getPlayQueue(), true);
|
||||
return true;
|
||||
});
|
||||
|
@ -806,8 +791,9 @@ public class LocalPlaylistFragment extends BaseLocalListFragment<List<PlaylistSt
|
|||
}
|
||||
|
||||
private void setVideoCount(final long count) {
|
||||
if (activity != null && headerStreamCount != null) {
|
||||
headerStreamCount.setText(Localization.localizeStreamCount(activity, count));
|
||||
if (activity != null && headerBinding != null) {
|
||||
headerBinding.playlistStreamCount.setText(Localization
|
||||
.localizeStreamCount(activity, count));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -17,6 +17,7 @@ import android.view.MenuInflater
|
|||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import android.widget.Toast
|
||||
import androidx.lifecycle.Observer
|
||||
import androidx.lifecycle.ViewModelProvider
|
||||
import androidx.localbroadcastmanager.content.LocalBroadcastManager
|
||||
import androidx.preference.PreferenceManager
|
||||
|
@ -29,11 +30,10 @@ import com.xwray.groupie.Section
|
|||
import com.xwray.groupie.kotlinandroidextensions.GroupieViewHolder
|
||||
import icepick.State
|
||||
import io.reactivex.rxjava3.disposables.CompositeDisposable
|
||||
import kotlinx.android.synthetic.main.dialog_title.view.itemAdditionalDetails
|
||||
import kotlinx.android.synthetic.main.dialog_title.view.itemTitleView
|
||||
import kotlinx.android.synthetic.main.fragment_subscription.items_list
|
||||
import org.schabi.newpipe.R
|
||||
import org.schabi.newpipe.database.feed.model.FeedGroupEntity
|
||||
import org.schabi.newpipe.databinding.DialogTitleBinding
|
||||
import org.schabi.newpipe.databinding.FragmentSubscriptionBinding
|
||||
import org.schabi.newpipe.extractor.channel.ChannelInfoItem
|
||||
import org.schabi.newpipe.fragments.BaseStateFragment
|
||||
import org.schabi.newpipe.local.subscription.SubscriptionViewModel.SubscriptionState
|
||||
|
@ -70,6 +70,9 @@ import kotlin.math.floor
|
|||
import kotlin.math.max
|
||||
|
||||
class SubscriptionFragment : BaseStateFragment<SubscriptionState>() {
|
||||
private var _binding: FragmentSubscriptionBinding? = null
|
||||
private val binding get() = _binding!!
|
||||
|
||||
private lateinit var viewModel: SubscriptionViewModel
|
||||
private lateinit var subscriptionManager: SubscriptionManager
|
||||
private val disposables: CompositeDisposable = CompositeDisposable()
|
||||
|
@ -129,7 +132,7 @@ class SubscriptionFragment : BaseStateFragment<SubscriptionState>() {
|
|||
|
||||
override fun onPause() {
|
||||
super.onPause()
|
||||
itemsListState = items_list.layoutManager?.onSaveInstanceState()
|
||||
itemsListState = binding.itemsList.layoutManager?.onSaveInstanceState()
|
||||
feedGroupsListState = feedGroupsCarousel?.onSaveInstanceState()
|
||||
importExportItemExpandedState = importExportItem.isExpanded
|
||||
|
||||
|
@ -169,7 +172,7 @@ class SubscriptionFragment : BaseStateFragment<SubscriptionState>() {
|
|||
filters.addAction(IMPORT_COMPLETE_ACTION)
|
||||
subscriptionBroadcastReceiver = object : BroadcastReceiver() {
|
||||
override fun onReceive(context: Context, intent: Intent) {
|
||||
items_list?.post {
|
||||
_binding?.itemsList?.post {
|
||||
importExportItem.isExpanded = false
|
||||
importExportItem.notifyChanged(FeedImportExportItem.REFRESH_EXPANDED_STATUS)
|
||||
}
|
||||
|
@ -275,17 +278,18 @@ class SubscriptionFragment : BaseStateFragment<SubscriptionState>() {
|
|||
|
||||
override fun initViews(rootView: View, savedInstanceState: Bundle?) {
|
||||
super.initViews(rootView, savedInstanceState)
|
||||
_binding = FragmentSubscriptionBinding.bind(rootView)
|
||||
|
||||
val shouldUseGridLayout = shouldUseGridLayout()
|
||||
groupAdapter.spanCount = if (shouldUseGridLayout) getGridSpanCount() else 1
|
||||
items_list.layoutManager = GridLayoutManager(requireContext(), groupAdapter.spanCount).apply {
|
||||
binding.itemsList.layoutManager = GridLayoutManager(requireContext(), groupAdapter.spanCount).apply {
|
||||
spanSizeLookup = groupAdapter.spanSizeLookup
|
||||
}
|
||||
items_list.adapter = groupAdapter
|
||||
binding.itemsList.adapter = groupAdapter
|
||||
|
||||
viewModel = ViewModelProvider(this).get(SubscriptionViewModel::class.java)
|
||||
viewModel.stateLiveData.observe(viewLifecycleOwner, androidx.lifecycle.Observer { it?.let(this::handleResult) })
|
||||
viewModel.feedGroupsLiveData.observe(viewLifecycleOwner, androidx.lifecycle.Observer { it?.let(this::handleFeedGroups) })
|
||||
viewModel.stateLiveData.observe(viewLifecycleOwner, Observer { it?.let(this::handleResult) })
|
||||
viewModel.feedGroupsLiveData.observe(viewLifecycleOwner, Observer { it?.let(this::handleFeedGroups) })
|
||||
}
|
||||
|
||||
private fun showLongTapDialog(selectedItem: ChannelInfoItem) {
|
||||
|
@ -301,16 +305,16 @@ class SubscriptionFragment : BaseStateFragment<SubscriptionState>() {
|
|||
}
|
||||
}
|
||||
|
||||
val bannerView = View.inflate(requireContext(), R.layout.dialog_title, null)
|
||||
bannerView.isSelected = true
|
||||
bannerView.itemTitleView.text = selectedItem.name
|
||||
bannerView.itemAdditionalDetails.visibility = View.GONE
|
||||
val dialogTitleBinding = DialogTitleBinding.inflate(LayoutInflater.from(requireContext()))
|
||||
dialogTitleBinding.root.isSelected = true
|
||||
dialogTitleBinding.itemTitleView.text = selectedItem.name
|
||||
dialogTitleBinding.itemAdditionalDetails.visibility = View.GONE
|
||||
|
||||
AlertDialog.Builder(requireContext())
|
||||
.setCustomTitle(bannerView)
|
||||
.setItems(commands, actions)
|
||||
.create()
|
||||
.show()
|
||||
.setCustomTitle(dialogTitleBinding.root)
|
||||
.setItems(commands, actions)
|
||||
.create()
|
||||
.show()
|
||||
}
|
||||
|
||||
private fun deleteChannel(selectedItem: ChannelInfoItem) {
|
||||
|
@ -368,14 +372,14 @@ class SubscriptionFragment : BaseStateFragment<SubscriptionState>() {
|
|||
subscriptionsSection.setHideWhenEmpty(false)
|
||||
|
||||
if (result.subscriptions.isEmpty() && importExportItemExpandedState == null) {
|
||||
items_list.post {
|
||||
binding.itemsList.post {
|
||||
importExportItem.isExpanded = true
|
||||
importExportItem.notifyChanged(FeedImportExportItem.REFRESH_EXPANDED_STATUS)
|
||||
}
|
||||
}
|
||||
|
||||
if (itemsListState != null) {
|
||||
items_list.layoutManager?.onRestoreInstanceState(itemsListState)
|
||||
binding.itemsList.layoutManager?.onRestoreInstanceState(itemsListState)
|
||||
itemsListState = null
|
||||
}
|
||||
}
|
||||
|
@ -394,7 +398,7 @@ class SubscriptionFragment : BaseStateFragment<SubscriptionState>() {
|
|||
}
|
||||
|
||||
feedGroupsSortMenuItem.showMenuItem = groups.size > 1
|
||||
items_list.post { feedGroupsSortMenuItem.notifyChanged(PAYLOAD_UPDATE_VISIBILITY_MENU_ITEM) }
|
||||
binding.itemsList.post { feedGroupsSortMenuItem.notifyChanged(PAYLOAD_UPDATE_VISIBILITY_MENU_ITEM) }
|
||||
}
|
||||
|
||||
// /////////////////////////////////////////////////////////////////////////
|
||||
|
@ -403,12 +407,12 @@ class SubscriptionFragment : BaseStateFragment<SubscriptionState>() {
|
|||
|
||||
override fun showLoading() {
|
||||
super.showLoading()
|
||||
animateView(items_list, false, 100)
|
||||
animateView(binding.itemsList, false, 100)
|
||||
}
|
||||
|
||||
override fun hideLoading() {
|
||||
super.hideLoading()
|
||||
animateView(items_list, true, 200)
|
||||
animateView(binding.itemsList, true, 200)
|
||||
}
|
||||
|
||||
// /////////////////////////////////////////////////////////////////////////
|
||||
|
|
|
@ -24,10 +24,10 @@ import com.xwray.groupie.Section
|
|||
import com.xwray.groupie.kotlinandroidextensions.GroupieViewHolder
|
||||
import icepick.Icepick
|
||||
import icepick.State
|
||||
import kotlinx.android.synthetic.main.dialog_feed_group_create.*
|
||||
import kotlinx.android.synthetic.main.toolbar_search_layout.*
|
||||
import org.schabi.newpipe.R
|
||||
import org.schabi.newpipe.database.feed.model.FeedGroupEntity
|
||||
import org.schabi.newpipe.databinding.DialogFeedGroupCreateBinding
|
||||
import org.schabi.newpipe.databinding.ToolbarSearchLayoutBinding
|
||||
import org.schabi.newpipe.fragments.BackPressable
|
||||
import org.schabi.newpipe.local.subscription.FeedGroupIcon
|
||||
import org.schabi.newpipe.local.subscription.dialog.FeedGroupDialog.ScreenState.DeleteScreen
|
||||
|
@ -45,6 +45,12 @@ import java.io.Serializable
|
|||
import kotlin.collections.contains
|
||||
|
||||
class FeedGroupDialog : DialogFragment(), BackPressable {
|
||||
private var _feedGroupCreateBinding: DialogFeedGroupCreateBinding? = null
|
||||
private val feedGroupCreateBinding get() = _feedGroupCreateBinding!!
|
||||
|
||||
private var _searchLayoutBinding: ToolbarSearchLayoutBinding? = null
|
||||
private val searchLayoutBinding get() = _searchLayoutBinding!!
|
||||
|
||||
private lateinit var viewModel: FeedGroupDialogViewModel
|
||||
private var groupId: Long = NO_GROUP_SELECTED
|
||||
private var groupIcon: FeedGroupIcon? = null
|
||||
|
@ -107,14 +113,16 @@ class FeedGroupDialog : DialogFragment(), BackPressable {
|
|||
override fun onSaveInstanceState(outState: Bundle) {
|
||||
super.onSaveInstanceState(outState)
|
||||
|
||||
iconsListState = icon_selector.layoutManager?.onSaveInstanceState()
|
||||
subscriptionsListState = subscriptions_selector_list.layoutManager?.onSaveInstanceState()
|
||||
iconsListState = feedGroupCreateBinding.iconSelector.layoutManager?.onSaveInstanceState()
|
||||
subscriptionsListState = feedGroupCreateBinding.subscriptionsSelectorList.layoutManager?.onSaveInstanceState()
|
||||
|
||||
Icepick.saveInstanceState(this, outState)
|
||||
}
|
||||
|
||||
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||
super.onViewCreated(view, savedInstanceState)
|
||||
_feedGroupCreateBinding = DialogFeedGroupCreateBinding.bind(view)
|
||||
_searchLayoutBinding = feedGroupCreateBinding.subscriptionsHeaderSearchContainer
|
||||
|
||||
viewModel = ViewModelProvider(
|
||||
this,
|
||||
|
@ -146,7 +154,7 @@ class FeedGroupDialog : DialogFragment(), BackPressable {
|
|||
add(subscriptionEmptyFooter)
|
||||
spanCount = 4
|
||||
}
|
||||
subscriptions_selector_list.apply {
|
||||
feedGroupCreateBinding.subscriptionsSelectorList.apply {
|
||||
// Disable animations, too distracting.
|
||||
itemAnimator = null
|
||||
adapter = subscriptionGroupAdapter
|
||||
|
@ -172,8 +180,11 @@ class FeedGroupDialog : DialogFragment(), BackPressable {
|
|||
|
||||
override fun onDestroyView() {
|
||||
super.onDestroyView()
|
||||
subscriptions_selector_list?.adapter = null
|
||||
icon_selector?.adapter = null
|
||||
feedGroupCreateBinding.subscriptionsSelectorList.adapter = null
|
||||
feedGroupCreateBinding.iconSelector.adapter = null
|
||||
|
||||
_feedGroupCreateBinding = null
|
||||
_searchLayoutBinding = null
|
||||
}
|
||||
|
||||
/*///////////////////////////////////////////////////////////////////////////
|
||||
|
@ -193,30 +204,30 @@ class FeedGroupDialog : DialogFragment(), BackPressable {
|
|||
}
|
||||
|
||||
private fun setupListeners() {
|
||||
delete_button.setOnClickListener { showScreen(DeleteScreen) }
|
||||
feedGroupCreateBinding.deleteButton.setOnClickListener { showScreen(DeleteScreen) }
|
||||
|
||||
cancel_button.setOnClickListener {
|
||||
feedGroupCreateBinding.cancelButton.setOnClickListener {
|
||||
when (currentScreen) {
|
||||
InitialScreen -> dismiss()
|
||||
else -> showScreen(InitialScreen)
|
||||
}
|
||||
}
|
||||
|
||||
group_name_input_container.error = null
|
||||
group_name_input.doOnTextChanged { text, _, _, _ ->
|
||||
if (group_name_input_container.isErrorEnabled && !text.isNullOrBlank()) {
|
||||
group_name_input_container.error = null
|
||||
feedGroupCreateBinding.groupNameInputContainer.error = null
|
||||
feedGroupCreateBinding.groupNameInput.doOnTextChanged { text, _, _, _ ->
|
||||
if (feedGroupCreateBinding.groupNameInputContainer.isErrorEnabled && !text.isNullOrBlank()) {
|
||||
feedGroupCreateBinding.groupNameInputContainer.error = null
|
||||
}
|
||||
}
|
||||
|
||||
confirm_button.setOnClickListener { handlePositiveButton() }
|
||||
feedGroupCreateBinding.confirmButton.setOnClickListener { handlePositiveButton() }
|
||||
|
||||
select_channel_button.setOnClickListener {
|
||||
subscriptions_selector_list.scrollToPosition(0)
|
||||
feedGroupCreateBinding.selectChannelButton.setOnClickListener {
|
||||
feedGroupCreateBinding.subscriptionsSelectorList.scrollToPosition(0)
|
||||
showScreen(SubscriptionsPickerScreen)
|
||||
}
|
||||
|
||||
val headerMenu = subscriptions_header_toolbar.menu
|
||||
val headerMenu = feedGroupCreateBinding.subscriptionsHeaderToolbar.menu
|
||||
requireActivity().menuInflater.inflate(R.menu.menu_feed_group_dialog, headerMenu)
|
||||
|
||||
headerMenu.findItem(R.id.action_search).setOnMenuItemClickListener {
|
||||
|
@ -234,8 +245,8 @@ class FeedGroupDialog : DialogFragment(), BackPressable {
|
|||
}
|
||||
}
|
||||
|
||||
toolbar_search_clear.setOnClickListener {
|
||||
if (toolbar_search_edit_text.text.isEmpty()) {
|
||||
searchLayoutBinding.toolbarSearchClear.setOnClickListener {
|
||||
if (searchLayoutBinding.toolbarSearchEditText.text.isNullOrEmpty()) {
|
||||
hideSearch()
|
||||
return@setOnClickListener
|
||||
}
|
||||
|
@ -243,14 +254,14 @@ class FeedGroupDialog : DialogFragment(), BackPressable {
|
|||
showKeyboardSearch()
|
||||
}
|
||||
|
||||
toolbar_search_edit_text.setOnClickListener {
|
||||
searchLayoutBinding.toolbarSearchEditText.setOnClickListener {
|
||||
if (DeviceUtils.isTv(context)) {
|
||||
showKeyboardSearch()
|
||||
}
|
||||
}
|
||||
|
||||
toolbar_search_edit_text.doOnTextChanged { _, _, _, _ ->
|
||||
val newQuery: String = toolbar_search_edit_text.text.toString()
|
||||
searchLayoutBinding.toolbarSearchEditText.doOnTextChanged { _, _, _, _ ->
|
||||
val newQuery: String = searchLayoutBinding.toolbarSearchEditText.text.toString()
|
||||
subscriptionsCurrentSearchQuery = newQuery
|
||||
viewModel.filterSubscriptionsBy(newQuery)
|
||||
}
|
||||
|
@ -266,16 +277,16 @@ class FeedGroupDialog : DialogFragment(), BackPressable {
|
|||
}
|
||||
|
||||
private fun handlePositiveButtonInitialScreen() {
|
||||
val name = group_name_input.text.toString().trim()
|
||||
val name = feedGroupCreateBinding.groupNameInput.text.toString().trim()
|
||||
val icon = selectedIcon ?: groupIcon ?: FeedGroupIcon.ALL
|
||||
|
||||
if (name.isBlank()) {
|
||||
group_name_input_container.error = getString(R.string.feed_group_dialog_empty_name)
|
||||
group_name_input.text = null
|
||||
group_name_input.requestFocus()
|
||||
feedGroupCreateBinding.groupNameInputContainer.error = getString(R.string.feed_group_dialog_empty_name)
|
||||
feedGroupCreateBinding.groupNameInput.text = null
|
||||
feedGroupCreateBinding.groupNameInput.requestFocus()
|
||||
return
|
||||
} else {
|
||||
group_name_input_container.error = null
|
||||
feedGroupCreateBinding.groupNameInputContainer.error = null
|
||||
}
|
||||
|
||||
if (selectedSubscriptions.isEmpty()) {
|
||||
|
@ -296,10 +307,10 @@ class FeedGroupDialog : DialogFragment(), BackPressable {
|
|||
groupSortOrder = feedGroupEntity?.sortOrder ?: -1
|
||||
|
||||
val feedGroupIcon = if (selectedIcon == null) icon else selectedIcon!!
|
||||
icon_preview.setImageResource(feedGroupIcon.getDrawableRes(requireContext()))
|
||||
feedGroupCreateBinding.iconPreview.setImageResource(feedGroupIcon.getDrawableRes(requireContext()))
|
||||
|
||||
if (group_name_input.text.isNullOrBlank()) {
|
||||
group_name_input.setText(name)
|
||||
if (feedGroupCreateBinding.groupNameInput.text.isNullOrBlank()) {
|
||||
feedGroupCreateBinding.groupNameInput.setText(name)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -346,10 +357,10 @@ class FeedGroupDialog : DialogFragment(), BackPressable {
|
|||
subscriptionMainSection.update(subscriptions, false)
|
||||
|
||||
if (subscriptionsListState != null) {
|
||||
subscriptions_selector_list.layoutManager?.onRestoreInstanceState(subscriptionsListState)
|
||||
feedGroupCreateBinding.subscriptionsSelectorList.layoutManager?.onRestoreInstanceState(subscriptionsListState)
|
||||
subscriptionsListState = null
|
||||
} else {
|
||||
subscriptions_selector_list.scrollToPosition(0)
|
||||
feedGroupCreateBinding.subscriptionsSelectorList.scrollToPosition(0)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -357,17 +368,16 @@ class FeedGroupDialog : DialogFragment(), BackPressable {
|
|||
val selectedCount = this.selectedSubscriptions.size
|
||||
val selectedCountText = resources.getQuantityString(
|
||||
R.plurals.feed_group_dialog_selection_count,
|
||||
selectedCount, selectedCount
|
||||
)
|
||||
selected_subscription_count_view.text = selectedCountText
|
||||
subscriptions_header_info.text = selectedCountText
|
||||
selectedCount, selectedCount)
|
||||
feedGroupCreateBinding.selectedSubscriptionCountView.text = selectedCountText
|
||||
feedGroupCreateBinding.subscriptionsHeaderInfo.text = selectedCountText
|
||||
}
|
||||
|
||||
private fun setupIconPicker() {
|
||||
val groupAdapter = GroupAdapter<GroupieViewHolder>()
|
||||
groupAdapter.addAll(FeedGroupIcon.values().map { PickerIconItem(requireContext(), it) })
|
||||
|
||||
icon_selector.apply {
|
||||
feedGroupCreateBinding.iconSelector.apply {
|
||||
layoutManager = GridLayoutManager(requireContext(), 7, RecyclerView.VERTICAL, false)
|
||||
adapter = groupAdapter
|
||||
|
||||
|
@ -381,20 +391,20 @@ class FeedGroupDialog : DialogFragment(), BackPressable {
|
|||
when (item) {
|
||||
is PickerIconItem -> {
|
||||
selectedIcon = item.icon
|
||||
icon_preview.setImageResource(item.iconRes)
|
||||
feedGroupCreateBinding.iconPreview.setImageResource(item.iconRes)
|
||||
|
||||
showScreen(InitialScreen)
|
||||
}
|
||||
}
|
||||
}
|
||||
icon_preview.setOnClickListener {
|
||||
icon_selector.scrollToPosition(0)
|
||||
feedGroupCreateBinding.iconPreview.setOnClickListener {
|
||||
feedGroupCreateBinding.iconSelector.scrollToPosition(0)
|
||||
showScreen(IconPickerScreen)
|
||||
}
|
||||
|
||||
if (groupId == NO_GROUP_SELECTED) {
|
||||
val icon = selectedIcon ?: FeedGroupIcon.ALL
|
||||
icon_preview.setImageResource(icon.getDrawableRes(requireContext()))
|
||||
feedGroupCreateBinding.iconPreview.setImageResource(icon.getDrawableRes(requireContext()))
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -405,22 +415,20 @@ class FeedGroupDialog : DialogFragment(), BackPressable {
|
|||
private fun showScreen(screen: ScreenState) {
|
||||
currentScreen = screen
|
||||
|
||||
options_root.onlyVisibleIn(InitialScreen)
|
||||
icon_selector.onlyVisibleIn(IconPickerScreen)
|
||||
subscriptions_selector.onlyVisibleIn(SubscriptionsPickerScreen)
|
||||
delete_screen_message.onlyVisibleIn(DeleteScreen)
|
||||
feedGroupCreateBinding.optionsRoot.onlyVisibleIn(InitialScreen)
|
||||
feedGroupCreateBinding.iconSelector.onlyVisibleIn(IconPickerScreen)
|
||||
feedGroupCreateBinding.subscriptionsSelector.onlyVisibleIn(SubscriptionsPickerScreen)
|
||||
feedGroupCreateBinding.deleteScreenMessage.onlyVisibleIn(DeleteScreen)
|
||||
|
||||
separator.onlyVisibleIn(SubscriptionsPickerScreen, IconPickerScreen)
|
||||
cancel_button.onlyVisibleIn(InitialScreen, DeleteScreen)
|
||||
feedGroupCreateBinding.separator.onlyVisibleIn(SubscriptionsPickerScreen, IconPickerScreen)
|
||||
feedGroupCreateBinding.cancelButton.onlyVisibleIn(InitialScreen, DeleteScreen)
|
||||
|
||||
confirm_button.setText(
|
||||
when {
|
||||
currentScreen == InitialScreen && groupId == NO_GROUP_SELECTED -> R.string.create
|
||||
else -> android.R.string.ok
|
||||
}
|
||||
)
|
||||
feedGroupCreateBinding.confirmButton.setText(when {
|
||||
currentScreen == InitialScreen && groupId == NO_GROUP_SELECTED -> R.string.create
|
||||
else -> android.R.string.ok
|
||||
})
|
||||
|
||||
delete_button.isGone = currentScreen != InitialScreen || groupId == NO_GROUP_SELECTED
|
||||
feedGroupCreateBinding.deleteButton.isGone = currentScreen != InitialScreen || groupId == NO_GROUP_SELECTED
|
||||
|
||||
hideKeyboard()
|
||||
hideSearch()
|
||||
|
@ -434,26 +442,26 @@ class FeedGroupDialog : DialogFragment(), BackPressable {
|
|||
// Utils
|
||||
////////////////////////////////////////////////////////////////////////// */
|
||||
|
||||
private fun isSearchVisible() = subscriptions_header_search_container?.visibility == View.VISIBLE
|
||||
private fun isSearchVisible() = _searchLayoutBinding?.root?.visibility == View.VISIBLE
|
||||
|
||||
private fun resetSearch() {
|
||||
toolbar_search_edit_text.setText("")
|
||||
searchLayoutBinding.toolbarSearchEditText.setText("")
|
||||
subscriptionsCurrentSearchQuery = ""
|
||||
viewModel.clearSubscriptionsFilter()
|
||||
}
|
||||
|
||||
private fun hideSearch() {
|
||||
resetSearch()
|
||||
subscriptions_header_search_container.visibility = View.GONE
|
||||
subscriptions_header_info_container.visibility = View.VISIBLE
|
||||
subscriptions_header_toolbar.menu.findItem(R.id.action_search).isVisible = true
|
||||
searchLayoutBinding.root.visibility = View.GONE
|
||||
feedGroupCreateBinding.subscriptionsHeaderInfoContainer.visibility = View.VISIBLE
|
||||
feedGroupCreateBinding.subscriptionsHeaderToolbar.menu.findItem(R.id.action_search).isVisible = true
|
||||
hideKeyboardSearch()
|
||||
}
|
||||
|
||||
private fun showSearch() {
|
||||
subscriptions_header_search_container.visibility = View.VISIBLE
|
||||
subscriptions_header_info_container.visibility = View.GONE
|
||||
subscriptions_header_toolbar.menu.findItem(R.id.action_search).isVisible = false
|
||||
searchLayoutBinding.root.visibility = View.VISIBLE
|
||||
feedGroupCreateBinding.subscriptionsHeaderInfoContainer.visibility = View.GONE
|
||||
feedGroupCreateBinding.subscriptionsHeaderToolbar.menu.findItem(R.id.action_search).isVisible = false
|
||||
showKeyboardSearch()
|
||||
}
|
||||
|
||||
|
@ -462,37 +470,35 @@ class FeedGroupDialog : DialogFragment(), BackPressable {
|
|||
}
|
||||
|
||||
private fun showKeyboardSearch() {
|
||||
if (toolbar_search_edit_text.requestFocus()) {
|
||||
inputMethodManager.showSoftInput(toolbar_search_edit_text, InputMethodManager.SHOW_IMPLICIT)
|
||||
if (searchLayoutBinding.toolbarSearchEditText.requestFocus()) {
|
||||
inputMethodManager.showSoftInput(searchLayoutBinding.toolbarSearchEditText,
|
||||
InputMethodManager.SHOW_IMPLICIT)
|
||||
}
|
||||
}
|
||||
|
||||
private fun hideKeyboardSearch() {
|
||||
inputMethodManager.hideSoftInputFromWindow(
|
||||
toolbar_search_edit_text.windowToken,
|
||||
InputMethodManager.RESULT_UNCHANGED_SHOWN
|
||||
)
|
||||
toolbar_search_edit_text.clearFocus()
|
||||
inputMethodManager.hideSoftInputFromWindow(searchLayoutBinding.toolbarSearchEditText.windowToken,
|
||||
InputMethodManager.RESULT_UNCHANGED_SHOWN)
|
||||
searchLayoutBinding.toolbarSearchEditText.clearFocus()
|
||||
}
|
||||
|
||||
private fun showKeyboard() {
|
||||
if (group_name_input.requestFocus()) {
|
||||
inputMethodManager.showSoftInput(group_name_input, InputMethodManager.SHOW_IMPLICIT)
|
||||
if (feedGroupCreateBinding.groupNameInput.requestFocus()) {
|
||||
inputMethodManager.showSoftInput(feedGroupCreateBinding.groupNameInput,
|
||||
InputMethodManager.SHOW_IMPLICIT)
|
||||
}
|
||||
}
|
||||
|
||||
private fun hideKeyboard() {
|
||||
inputMethodManager.hideSoftInputFromWindow(
|
||||
group_name_input.windowToken,
|
||||
InputMethodManager.RESULT_UNCHANGED_SHOWN
|
||||
)
|
||||
group_name_input.clearFocus()
|
||||
inputMethodManager.hideSoftInputFromWindow(feedGroupCreateBinding.groupNameInput.windowToken,
|
||||
InputMethodManager.RESULT_UNCHANGED_SHOWN)
|
||||
feedGroupCreateBinding.groupNameInput.clearFocus()
|
||||
}
|
||||
|
||||
private fun disableInput() {
|
||||
delete_button?.isEnabled = false
|
||||
confirm_button?.isEnabled = false
|
||||
cancel_button?.isEnabled = false
|
||||
_feedGroupCreateBinding?.deleteButton?.isEnabled = false
|
||||
_feedGroupCreateBinding?.confirmButton?.isEnabled = false
|
||||
_feedGroupCreateBinding?.cancelButton?.isEnabled = false
|
||||
isCancelable = false
|
||||
|
||||
hideKeyboard()
|
||||
|
|
|
@ -16,10 +16,9 @@ import com.xwray.groupie.TouchCallback
|
|||
import com.xwray.groupie.kotlinandroidextensions.GroupieViewHolder
|
||||
import icepick.Icepick
|
||||
import icepick.State
|
||||
import kotlinx.android.synthetic.main.dialog_feed_group_reorder.confirm_button
|
||||
import kotlinx.android.synthetic.main.dialog_feed_group_reorder.feed_groups_list
|
||||
import org.schabi.newpipe.R
|
||||
import org.schabi.newpipe.database.feed.model.FeedGroupEntity
|
||||
import org.schabi.newpipe.databinding.DialogFeedGroupReorderBinding
|
||||
import org.schabi.newpipe.local.subscription.dialog.FeedGroupReorderDialogViewModel.DialogEvent.ProcessingEvent
|
||||
import org.schabi.newpipe.local.subscription.dialog.FeedGroupReorderDialogViewModel.DialogEvent.SuccessEvent
|
||||
import org.schabi.newpipe.local.subscription.item.FeedGroupReorderItem
|
||||
|
@ -27,6 +26,9 @@ import org.schabi.newpipe.util.ThemeHelper
|
|||
import java.util.Collections
|
||||
|
||||
class FeedGroupReorderDialog : DialogFragment() {
|
||||
private var _binding: DialogFeedGroupReorderBinding? = null
|
||||
private val binding get() = _binding!!
|
||||
|
||||
private lateinit var viewModel: FeedGroupReorderDialogViewModel
|
||||
|
||||
@State
|
||||
|
@ -48,6 +50,7 @@ class FeedGroupReorderDialog : DialogFragment() {
|
|||
|
||||
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||
super.onViewCreated(view, savedInstanceState)
|
||||
_binding = DialogFeedGroupReorderBinding.bind(view)
|
||||
|
||||
viewModel = ViewModelProvider(this).get(FeedGroupReorderDialogViewModel::class.java)
|
||||
viewModel.groupsLiveData.observe(viewLifecycleOwner, Observer(::handleGroups))
|
||||
|
@ -61,15 +64,20 @@ class FeedGroupReorderDialog : DialogFragment() {
|
|||
}
|
||||
)
|
||||
|
||||
feed_groups_list.layoutManager = LinearLayoutManager(requireContext())
|
||||
feed_groups_list.adapter = groupAdapter
|
||||
itemTouchHelper.attachToRecyclerView(feed_groups_list)
|
||||
binding.feedGroupsList.layoutManager = LinearLayoutManager(requireContext())
|
||||
binding.feedGroupsList.adapter = groupAdapter
|
||||
itemTouchHelper.attachToRecyclerView(binding.feedGroupsList)
|
||||
|
||||
confirm_button.setOnClickListener {
|
||||
binding.confirmButton.setOnClickListener {
|
||||
viewModel.updateOrder(groupOrderedIdList)
|
||||
}
|
||||
}
|
||||
|
||||
override fun onDestroyView() {
|
||||
_binding = null
|
||||
super.onDestroyView()
|
||||
}
|
||||
|
||||
override fun onSaveInstanceState(outState: Bundle) {
|
||||
super.onSaveInstanceState(outState)
|
||||
Icepick.saveInstanceState(this, outState)
|
||||
|
@ -89,7 +97,7 @@ class FeedGroupReorderDialog : DialogFragment() {
|
|||
}
|
||||
|
||||
private fun disableInput() {
|
||||
confirm_button?.isEnabled = false
|
||||
_binding?.confirmButton?.isEnabled = false
|
||||
isCancelable = false
|
||||
}
|
||||
|
||||
|
|
|
@ -119,7 +119,10 @@
|
|||
android:layout_height="wrap_content"
|
||||
android:layout_below="@id/channel_metadata">
|
||||
|
||||
<include layout="@layout/playlist_control" />
|
||||
<include
|
||||
android:id="@+id/playlist_control"
|
||||
layout="@layout/playlist_control" />
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
</RelativeLayout>
|
||||
|
|
|
@ -40,7 +40,10 @@
|
|||
android:layout_height="wrap_content"
|
||||
android:layout_below="@id/playlist_stream_count">
|
||||
|
||||
<include layout="@layout/playlist_control" />
|
||||
<include
|
||||
android:id="@+id/playlist_control"
|
||||
layout="@layout/playlist_control" />
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
</RelativeLayout>
|
||||
|
|
|
@ -83,7 +83,9 @@
|
|||
android:layout_height="wrap_content"
|
||||
android:layout_below="@id/playlist_meta">
|
||||
|
||||
<include layout="@layout/playlist_control" />
|
||||
<include
|
||||
android:id="@+id/playlist_control"
|
||||
layout="@layout/playlist_control" />
|
||||
</LinearLayout>
|
||||
|
||||
</RelativeLayout>
|
||||
|
|
|
@ -38,6 +38,8 @@
|
|||
tools:ignore="RtlHardcoded" />
|
||||
</RelativeLayout>
|
||||
|
||||
<include layout="@layout/playlist_control" />
|
||||
<include
|
||||
android:id="@+id/playlist_control"
|
||||
layout="@layout/playlist_control" />
|
||||
|
||||
</LinearLayout>
|
||||
|
|
Loading…
Reference in New Issue