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