2016-09-26 17:02:55 +02:00
|
|
|
package org.schabi.newpipe.info_list;
|
|
|
|
|
2017-04-09 19:34:00 +02:00
|
|
|
import android.content.Context;
|
2017-04-26 21:32:04 +02:00
|
|
|
import android.text.TextUtils;
|
2017-02-12 13:33:03 +01:00
|
|
|
import android.util.Log;
|
2016-09-26 17:02:55 +02:00
|
|
|
import android.view.LayoutInflater;
|
|
|
|
import android.view.View;
|
|
|
|
import android.view.ViewGroup;
|
|
|
|
|
|
|
|
import com.nostra13.universalimageloader.core.DisplayImageOptions;
|
|
|
|
import com.nostra13.universalimageloader.core.ImageLoader;
|
|
|
|
|
|
|
|
import org.schabi.newpipe.ImageErrorLoadingListener;
|
|
|
|
import org.schabi.newpipe.R;
|
2016-09-28 17:13:15 +02:00
|
|
|
import org.schabi.newpipe.extractor.AbstractStreamInfo;
|
2017-02-12 13:33:03 +01:00
|
|
|
import org.schabi.newpipe.extractor.InfoItem;
|
2017-02-13 00:55:05 +01:00
|
|
|
import org.schabi.newpipe.extractor.channel.ChannelInfoItem;
|
2017-02-11 21:33:01 +01:00
|
|
|
import org.schabi.newpipe.extractor.stream_info.StreamInfoItem;
|
2016-09-26 17:02:55 +02:00
|
|
|
|
2017-06-15 16:26:48 +02:00
|
|
|
import java.util.Locale;
|
|
|
|
|
2016-09-26 17:02:55 +02:00
|
|
|
/**
|
|
|
|
* Created by Christian Schabesberger on 26.09.16.
|
2017-04-26 21:32:04 +02:00
|
|
|
* <p>
|
2016-09-26 17:02:55 +02:00
|
|
|
* Copyright (C) Christian Schabesberger 2016 <chris.schabesberger@mailbox.org>
|
|
|
|
* InfoItemBuilder.java is part of NewPipe.
|
2017-04-26 21:32:04 +02:00
|
|
|
* <p>
|
2016-09-26 17:02:55 +02:00
|
|
|
* NewPipe is free software: you can redistribute it and/or modify
|
|
|
|
* it under the terms of the GNU General Public License as published by
|
|
|
|
* the Free Software Foundation, either version 3 of the License, or
|
|
|
|
* (at your option) any later version.
|
2017-04-26 21:32:04 +02:00
|
|
|
* <p>
|
2016-09-26 17:02:55 +02:00
|
|
|
* NewPipe is distributed in the hope that it will be useful,
|
|
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
|
* GNU General Public License for more details.
|
2017-04-26 21:32:04 +02:00
|
|
|
* <p>
|
2016-09-26 17:02:55 +02:00
|
|
|
* You should have received a copy of the GNU General Public License
|
|
|
|
* along with NewPipe. If not, see <http://www.gnu.org/licenses/>.
|
|
|
|
*/
|
|
|
|
|
|
|
|
public class InfoItemBuilder {
|
|
|
|
|
2017-04-09 19:34:00 +02:00
|
|
|
private final String viewsS;
|
|
|
|
private final String videosS;
|
|
|
|
private final String subsS;
|
|
|
|
private final String subsPluralS;
|
2017-02-15 12:59:36 +01:00
|
|
|
|
2017-04-09 19:34:00 +02:00
|
|
|
private final String thousand;
|
|
|
|
private final String million;
|
|
|
|
private final String billion;
|
2017-02-15 12:59:36 +01:00
|
|
|
|
2017-02-13 00:55:05 +01:00
|
|
|
private static final String TAG = InfoItemBuilder.class.toString();
|
2017-04-26 21:32:04 +02:00
|
|
|
|
2017-02-13 00:55:05 +01:00
|
|
|
public interface OnInfoItemSelectedListener {
|
2017-04-09 19:34:00 +02:00
|
|
|
void selected(int serviceId, String url, String title);
|
2016-09-26 17:02:55 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
private ImageLoader imageLoader = ImageLoader.getInstance();
|
2017-06-15 16:26:48 +02:00
|
|
|
private static final DisplayImageOptions DISPLAY_IMAGE_OPTIONS =
|
|
|
|
new DisplayImageOptions.Builder()
|
|
|
|
.cacheInMemory(true)
|
|
|
|
.build();
|
|
|
|
private static final DisplayImageOptions DISPLAY_STREAM_THUMBNAIL_OPTIONS =
|
|
|
|
new DisplayImageOptions.Builder()
|
|
|
|
.cloneFrom(DISPLAY_IMAGE_OPTIONS)
|
|
|
|
.showImageOnFail(R.drawable.dummy_thumbnail)
|
|
|
|
.showImageForEmptyUri(R.drawable.dummy_thumbnail)
|
|
|
|
.showImageOnLoading(R.drawable.dummy_thumbnail)
|
|
|
|
.build();
|
|
|
|
|
|
|
|
private static final DisplayImageOptions DISPLAY_CHANNEL_THUMBNAIL_OPTIONS =
|
|
|
|
new DisplayImageOptions.Builder()
|
|
|
|
.cloneFrom(DISPLAY_IMAGE_OPTIONS)
|
|
|
|
.showImageOnLoading(R.drawable.buddy_channel_item)
|
|
|
|
.showImageForEmptyUri(R.drawable.buddy_channel_item)
|
|
|
|
.showImageOnFail(R.drawable.buddy_channel_item)
|
|
|
|
.build();
|
2017-02-13 00:55:05 +01:00
|
|
|
private OnInfoItemSelectedListener onStreamInfoItemSelectedListener;
|
|
|
|
private OnInfoItemSelectedListener onChannelInfoItemSelectedListener;
|
2016-09-26 17:02:55 +02:00
|
|
|
|
2017-06-15 16:26:48 +02:00
|
|
|
public InfoItemBuilder(Context context) {
|
2017-04-09 19:34:00 +02:00
|
|
|
viewsS = context.getString(R.string.views);
|
|
|
|
videosS = context.getString(R.string.videos);
|
|
|
|
subsS = context.getString(R.string.subscriber);
|
|
|
|
subsPluralS = context.getString(R.string.subscriber_plural);
|
|
|
|
thousand = context.getString(R.string.short_thousand);
|
|
|
|
million = context.getString(R.string.short_million);
|
|
|
|
billion = context.getString(R.string.short_billion);
|
2016-09-26 17:02:55 +02:00
|
|
|
}
|
|
|
|
|
2017-02-13 00:55:05 +01:00
|
|
|
public void setOnStreamInfoItemSelectedListener(
|
|
|
|
OnInfoItemSelectedListener listener) {
|
|
|
|
this.onStreamInfoItemSelectedListener = listener;
|
|
|
|
}
|
|
|
|
|
|
|
|
public void setOnChannelInfoItemSelectedListener(
|
|
|
|
OnInfoItemSelectedListener listener) {
|
|
|
|
this.onChannelInfoItemSelectedListener = listener;
|
2016-09-26 17:02:55 +02:00
|
|
|
}
|
|
|
|
|
2017-02-12 13:33:03 +01:00
|
|
|
public void buildByHolder(InfoItemHolder holder, final InfoItem i) {
|
2017-04-26 21:32:04 +02:00
|
|
|
if (i.infoType() != holder.infoType())
|
2017-02-15 15:21:36 +01:00
|
|
|
return;
|
2017-04-26 21:32:04 +02:00
|
|
|
switch (i.infoType()) {
|
2017-02-13 00:55:05 +01:00
|
|
|
case STREAM:
|
|
|
|
buildStreamInfoItem((StreamInfoItemHolder) holder, (StreamInfoItem) i);
|
|
|
|
break;
|
|
|
|
case CHANNEL:
|
|
|
|
buildChannelInfoItem((ChannelInfoItemHolder) holder, (ChannelInfoItem) i);
|
|
|
|
break;
|
|
|
|
case PLAYLIST:
|
|
|
|
Log.e(TAG, "Not yet implemented");
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
Log.e(TAG, "Trollolo");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-06-15 16:26:48 +02:00
|
|
|
private String getStreamInfoDetailLine(final StreamInfoItem info) {
|
|
|
|
String viewsAndDate = "";
|
|
|
|
if(info.view_count >= 0) {
|
|
|
|
viewsAndDate = shortViewCount(info.view_count);
|
2017-02-13 00:55:05 +01:00
|
|
|
}
|
2017-06-15 16:26:48 +02:00
|
|
|
if(!TextUtils.isEmpty(info.upload_date)) {
|
|
|
|
if(viewsAndDate.isEmpty()) {
|
|
|
|
viewsAndDate = info.upload_date;
|
|
|
|
} else {
|
|
|
|
viewsAndDate += " • " + info.upload_date;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return viewsAndDate;
|
2017-02-13 00:55:05 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
private void buildStreamInfoItem(StreamInfoItemHolder holder, final StreamInfoItem info) {
|
2017-04-26 21:32:04 +02:00
|
|
|
if (info.infoType() != InfoItem.InfoType.STREAM) {
|
2017-02-12 13:33:03 +01:00
|
|
|
Log.e("InfoItemBuilder", "Info type not yet supported");
|
|
|
|
}
|
2016-09-26 17:02:55 +02:00
|
|
|
// fill holder with information
|
2017-04-26 21:32:04 +02:00
|
|
|
if (!TextUtils.isEmpty(info.title)) holder.itemVideoTitleView.setText(info.title);
|
|
|
|
|
|
|
|
if (!TextUtils.isEmpty(info.uploader)) holder.itemUploaderView.setText(info.uploader);
|
|
|
|
else holder.itemUploaderView.setVisibility(View.INVISIBLE);
|
|
|
|
|
|
|
|
if (info.duration > 0) {
|
2016-09-26 17:02:55 +02:00
|
|
|
holder.itemDurationView.setText(getDurationString(info.duration));
|
|
|
|
} else {
|
2017-04-26 21:32:04 +02:00
|
|
|
if (info.stream_type == AbstractStreamInfo.StreamType.LIVE_STREAM) {
|
2016-09-26 17:02:55 +02:00
|
|
|
holder.itemDurationView.setText(R.string.duration_live);
|
|
|
|
} else {
|
|
|
|
holder.itemDurationView.setVisibility(View.GONE);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-06-15 16:26:48 +02:00
|
|
|
holder.itemAdditionalDetails.setText(getStreamInfoDetailLine(info));
|
|
|
|
|
|
|
|
// Default thumbnail is shown on error, while loading and if the url is empty
|
|
|
|
imageLoader.displayImage(info.thumbnail_url,
|
|
|
|
holder.itemThumbnailView,
|
|
|
|
DISPLAY_STREAM_THUMBNAIL_OPTIONS,
|
|
|
|
new ImageErrorLoadingListener(holder.itemRoot.getContext(), holder.itemRoot.getRootView(), info.service_id));
|
|
|
|
|
2016-09-26 17:02:55 +02:00
|
|
|
|
2017-04-26 21:32:04 +02:00
|
|
|
holder.itemRoot.setOnClickListener(new View.OnClickListener() {
|
2016-09-26 17:02:55 +02:00
|
|
|
@Override
|
|
|
|
public void onClick(View view) {
|
2017-06-15 16:26:48 +02:00
|
|
|
if(onStreamInfoItemSelectedListener != null) {
|
|
|
|
onStreamInfoItemSelectedListener.selected(info.service_id, info.webpage_url, info.getTitle());
|
|
|
|
}
|
2016-09-26 17:02:55 +02:00
|
|
|
}
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
2017-06-15 16:26:48 +02:00
|
|
|
private String getChannelInfoDetailLine(final ChannelInfoItem info) {
|
|
|
|
String details = "";
|
|
|
|
if(info.subscriberCount >= 0) {
|
|
|
|
details = shortSubscriber(info.subscriberCount);
|
|
|
|
}
|
|
|
|
if(info.videoAmount >= 0) {
|
|
|
|
String formattedVideoAmount = info.videoAmount + " " + videosS;
|
|
|
|
if(!details.isEmpty()) {
|
|
|
|
details += " • " + formattedVideoAmount;
|
|
|
|
} else {
|
|
|
|
details = formattedVideoAmount;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return details;
|
|
|
|
}
|
|
|
|
|
2017-02-13 00:55:05 +01:00
|
|
|
private void buildChannelInfoItem(ChannelInfoItemHolder holder, final ChannelInfoItem info) {
|
2017-04-26 21:32:04 +02:00
|
|
|
if (!TextUtils.isEmpty(info.getTitle())) holder.itemChannelTitleView.setText(info.getTitle());
|
2017-06-15 16:26:48 +02:00
|
|
|
holder.itemAdditionalDetailView.setText(getChannelInfoDetailLine(info));
|
2017-04-26 21:32:04 +02:00
|
|
|
if (!TextUtils.isEmpty(info.description)) holder.itemChannelDescriptionView.setText(info.description);
|
2017-02-15 12:59:36 +01:00
|
|
|
|
2017-06-15 16:26:48 +02:00
|
|
|
imageLoader.displayImage(info.thumbnailUrl,
|
|
|
|
holder.itemThumbnailView,
|
|
|
|
DISPLAY_CHANNEL_THUMBNAIL_OPTIONS,
|
|
|
|
new ImageErrorLoadingListener(holder.itemRoot.getContext(), holder.itemRoot.getRootView(), info.serviceId));
|
|
|
|
|
2017-02-15 12:59:36 +01:00
|
|
|
|
2017-04-26 21:32:04 +02:00
|
|
|
holder.itemRoot.setOnClickListener(new View.OnClickListener() {
|
2017-02-13 00:55:05 +01:00
|
|
|
@Override
|
|
|
|
public void onClick(View view) {
|
2017-06-15 16:26:48 +02:00
|
|
|
if(onStreamInfoItemSelectedListener != null) {
|
|
|
|
onChannelInfoItemSelectedListener.selected(info.serviceId, info.getLink(), info.channelName);
|
|
|
|
}
|
2017-02-13 00:55:05 +01:00
|
|
|
}
|
|
|
|
});
|
2016-09-26 17:02:55 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2017-04-26 21:32:04 +02:00
|
|
|
public String shortViewCount(Long viewCount) {
|
|
|
|
if (viewCount >= 1000000000) {
|
|
|
|
return Long.toString(viewCount / 1000000000) + billion + " " + viewsS;
|
|
|
|
} else if (viewCount >= 1000000) {
|
|
|
|
return Long.toString(viewCount / 1000000) + million + " " + viewsS;
|
|
|
|
} else if (viewCount >= 1000) {
|
|
|
|
return Long.toString(viewCount / 1000) + thousand + " " + viewsS;
|
|
|
|
} else {
|
|
|
|
return Long.toString(viewCount) + " " + viewsS;
|
2017-02-15 12:59:36 +01:00
|
|
|
}
|
|
|
|
}
|
2017-02-13 00:55:05 +01:00
|
|
|
|
2017-04-09 19:34:00 +02:00
|
|
|
public String shortSubscriber(Long count) {
|
|
|
|
String curSubString = count > 1 ? subsPluralS : subsS;
|
|
|
|
|
|
|
|
if (count >= 1000000000) {
|
|
|
|
return Long.toString(count / 1000000000) + billion + " " + curSubString;
|
|
|
|
} else if (count >= 1000000) {
|
|
|
|
return Long.toString(count / 1000000) + million + " " + curSubString;
|
|
|
|
} else if (count >= 1000) {
|
|
|
|
return Long.toString(count / 1000) + thousand + " " + curSubString;
|
|
|
|
} else {
|
|
|
|
return Long.toString(count) + " " + curSubString;
|
2016-09-26 17:02:55 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
public static String getDurationString(int duration) {
|
2017-06-15 16:26:48 +02:00
|
|
|
if(duration < 0) {
|
|
|
|
duration = 0;
|
|
|
|
}
|
|
|
|
String output;
|
2016-09-26 17:02:55 +02:00
|
|
|
int days = duration / (24 * 60 * 60); /* greater than a day */
|
|
|
|
duration %= (24 * 60 * 60);
|
|
|
|
int hours = duration / (60 * 60); /* greater than an hour */
|
|
|
|
duration %= (60 * 60);
|
|
|
|
int minutes = duration / 60;
|
|
|
|
int seconds = duration % 60;
|
|
|
|
|
|
|
|
//handle days
|
2017-04-26 21:32:04 +02:00
|
|
|
if (days > 0) {
|
2017-06-15 16:26:48 +02:00
|
|
|
output = String.format(Locale.US, "%d:%02d:%02d:%02d", days, hours, minutes, seconds);
|
|
|
|
} else if(hours > 0) {
|
|
|
|
output = String.format(Locale.US, "%d:%02d:%02d", hours, minutes, seconds);
|
2016-09-26 17:02:55 +02:00
|
|
|
} else {
|
2017-06-15 16:26:48 +02:00
|
|
|
output = String.format(Locale.US, "%d:%02d", minutes, seconds);
|
2016-09-26 17:02:55 +02:00
|
|
|
}
|
|
|
|
return output;
|
|
|
|
}
|
|
|
|
}
|