Show download size preview
This commit is contained in:
parent
8f73c8c98b
commit
35b3bf2edb
9 changed files with 454 additions and 216 deletions
196
app/src/main/java/org/schabi/newpipe/util/StreamItemAdapter.java
Normal file
196
app/src/main/java/org/schabi/newpipe/util/StreamItemAdapter.java
Normal file
|
|
@ -0,0 +1,196 @@
|
|||
package org.schabi.newpipe.util;
|
||||
|
||||
import android.content.Context;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.BaseAdapter;
|
||||
import android.widget.ImageView;
|
||||
import android.widget.Spinner;
|
||||
import android.widget.TextView;
|
||||
|
||||
import org.schabi.newpipe.Downloader;
|
||||
import org.schabi.newpipe.R;
|
||||
import org.schabi.newpipe.extractor.stream.AudioStream;
|
||||
import org.schabi.newpipe.extractor.stream.Stream;
|
||||
import org.schabi.newpipe.extractor.stream.VideoStream;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.Callable;
|
||||
|
||||
import io.reactivex.Single;
|
||||
import io.reactivex.android.schedulers.AndroidSchedulers;
|
||||
import io.reactivex.schedulers.Schedulers;
|
||||
import us.shandian.giga.util.Utility;
|
||||
|
||||
/**
|
||||
* A list adapter for a list of {@link Stream streams}, currently supporting {@link VideoStream} and {@link AudioStream}.
|
||||
*/
|
||||
public class StreamItemAdapter<T extends Stream> extends BaseAdapter {
|
||||
private final Context context;
|
||||
|
||||
private StreamSizeWrapper<T> streamsWrapper;
|
||||
private final boolean showIconNoAudio;
|
||||
|
||||
public StreamItemAdapter(Context context, StreamSizeWrapper<T> streamsWrapper, boolean showIconNoAudio) {
|
||||
this.context = context;
|
||||
this.streamsWrapper = streamsWrapper;
|
||||
this.showIconNoAudio = showIconNoAudio;
|
||||
}
|
||||
|
||||
public StreamItemAdapter(Context context, StreamSizeWrapper<T> streamsWrapper) {
|
||||
this(context, streamsWrapper, false);
|
||||
}
|
||||
|
||||
public List<T> getAll() {
|
||||
return streamsWrapper.getStreamsList();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getCount() {
|
||||
return streamsWrapper.getStreamsList().size();
|
||||
}
|
||||
|
||||
@Override
|
||||
public T getItem(int position) {
|
||||
return streamsWrapper.getStreamsList().get(position);
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getItemId(int position) {
|
||||
return position;
|
||||
}
|
||||
|
||||
@Override
|
||||
public View getDropDownView(int position, View convertView, ViewGroup parent) {
|
||||
return getCustomView(position, convertView, parent, true);
|
||||
}
|
||||
|
||||
@Override
|
||||
public View getView(int position, View convertView, ViewGroup parent) {
|
||||
return getCustomView(((Spinner) parent).getSelectedItemPosition(), convertView, parent, false);
|
||||
}
|
||||
|
||||
private View getCustomView(int position, View convertView, ViewGroup parent, boolean isDropdownItem) {
|
||||
if (convertView == null) {
|
||||
convertView = LayoutInflater.from(context).inflate(R.layout.stream_quality_item, parent, false);
|
||||
}
|
||||
|
||||
final ImageView woSoundIconView = convertView.findViewById(R.id.wo_sound_icon);
|
||||
final TextView formatNameView = convertView.findViewById(R.id.stream_format_name);
|
||||
final TextView qualityView = convertView.findViewById(R.id.stream_quality);
|
||||
final TextView sizeView = convertView.findViewById(R.id.stream_size);
|
||||
|
||||
final T stream = getItem(position);
|
||||
|
||||
int woSoundIconVisibility = View.GONE;
|
||||
String qualityString;
|
||||
|
||||
if (stream instanceof VideoStream) {
|
||||
qualityString = ((VideoStream) stream).getResolution();
|
||||
|
||||
if (!showIconNoAudio) {
|
||||
woSoundIconVisibility = View.GONE;
|
||||
} else if (((VideoStream) stream).isVideoOnly()) {
|
||||
woSoundIconVisibility = View.VISIBLE;
|
||||
} else if (isDropdownItem) {
|
||||
woSoundIconVisibility = View.INVISIBLE;
|
||||
}
|
||||
} else if (stream instanceof AudioStream) {
|
||||
qualityString = ((AudioStream) stream).getAverageBitrate() + "kbps";
|
||||
} else {
|
||||
qualityString = stream.getFormat().getSuffix();
|
||||
}
|
||||
|
||||
if (streamsWrapper.getSizeInBytes(position) > 0) {
|
||||
sizeView.setText(streamsWrapper.getFormattedSize(position));
|
||||
sizeView.setVisibility(View.VISIBLE);
|
||||
} else {
|
||||
sizeView.setVisibility(View.GONE);
|
||||
}
|
||||
|
||||
formatNameView.setText(stream.getFormat().getName());
|
||||
qualityView.setText(qualityString);
|
||||
woSoundIconView.setVisibility(woSoundIconVisibility);
|
||||
|
||||
return convertView;
|
||||
}
|
||||
|
||||
/**
|
||||
* A wrapper class that includes a way of storing the stream sizes.
|
||||
*/
|
||||
public static class StreamSizeWrapper<T extends Stream> implements Serializable {
|
||||
private static final StreamSizeWrapper<Stream> EMPTY = new StreamSizeWrapper<>(Collections.emptyList());
|
||||
private final List<T> streamsList;
|
||||
private long[] streamSizes;
|
||||
|
||||
public StreamSizeWrapper(List<T> streamsList) {
|
||||
this.streamsList = streamsList;
|
||||
this.streamSizes = new long[streamsList.size()];
|
||||
|
||||
for (int i = 0; i < streamSizes.length; i++) streamSizes[i] = -1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper method to fetch the sizes of all the streams in a wrapper.
|
||||
*
|
||||
* @param streamsWrapper the wrapper
|
||||
* @return a {@link Single} that returns a boolean indicating if any elements were changed
|
||||
*/
|
||||
public static <X extends Stream> Single<Boolean> fetchSizeForWrapper(StreamSizeWrapper<X> streamsWrapper) {
|
||||
final Callable<Boolean> fetchAndSet = () -> {
|
||||
boolean hasChanged = false;
|
||||
for (X stream : streamsWrapper.getStreamsList()) {
|
||||
if (streamsWrapper.getSizeInBytes(stream) > 0) {
|
||||
continue;
|
||||
}
|
||||
|
||||
final long contentLength = Downloader.getInstance().getContentLength(stream.getUrl());
|
||||
streamsWrapper.setSize(stream, contentLength);
|
||||
hasChanged = true;
|
||||
}
|
||||
return hasChanged;
|
||||
};
|
||||
|
||||
return Single.fromCallable(fetchAndSet)
|
||||
.subscribeOn(Schedulers.io())
|
||||
.observeOn(AndroidSchedulers.mainThread())
|
||||
.onErrorReturnItem(true);
|
||||
}
|
||||
|
||||
public List<T> getStreamsList() {
|
||||
return streamsList;
|
||||
}
|
||||
|
||||
public long getSizeInBytes(int streamIndex) {
|
||||
return streamSizes[streamIndex];
|
||||
}
|
||||
|
||||
public long getSizeInBytes(T stream) {
|
||||
return streamSizes[streamsList.indexOf(stream)];
|
||||
}
|
||||
|
||||
public String getFormattedSize(int streamIndex) {
|
||||
return Utility.formatBytes(getSizeInBytes(streamIndex));
|
||||
}
|
||||
|
||||
public String getFormattedSize(T stream) {
|
||||
return Utility.formatBytes(getSizeInBytes(stream));
|
||||
}
|
||||
|
||||
public void setSize(int streamIndex, long sizeInBytes) {
|
||||
streamSizes[streamIndex] = sizeInBytes;
|
||||
}
|
||||
|
||||
public void setSize(T stream, long sizeInBytes) {
|
||||
streamSizes[streamsList.indexOf(stream)] = sizeInBytes;
|
||||
}
|
||||
|
||||
public static <X extends Stream> StreamSizeWrapper<X> empty() {
|
||||
//noinspection unchecked
|
||||
return (StreamSizeWrapper<X>) EMPTY;
|
||||
}
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue