mirror of
https://github.com/MaintainTeam/LastPipeBender.git
synced 2025-03-01 05:48:22 +03:00
implemented locale-specific formatting of view, like and dislike counts, and video published date
This commit is contained in:
parent
c5084901b5
commit
67ba126602
5 changed files with 86 additions and 39 deletions
|
@ -2,6 +2,8 @@ package org.schabi.newpipe;
|
||||||
|
|
||||||
import android.graphics.Bitmap;
|
import android.graphics.Bitmap;
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
|
|
||||||
|
import java.util.Date;
|
||||||
import java.util.Vector;
|
import java.util.Vector;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -33,15 +35,15 @@ public class VideoInfo {
|
||||||
public Bitmap thumbnail = null;
|
public Bitmap thumbnail = null;
|
||||||
public String webpage_url = "";
|
public String webpage_url = "";
|
||||||
public String upload_date = "";
|
public String upload_date = "";
|
||||||
public String view_count = "";
|
public long view_count = 0;
|
||||||
|
|
||||||
public String uploader_thumbnail_url = "";
|
public String uploader_thumbnail_url = "";
|
||||||
public Bitmap uploader_thumbnail = null;
|
public Bitmap uploader_thumbnail = null;
|
||||||
public String description = "";
|
public String description = "";
|
||||||
public int duration = -1;
|
public int duration = -1;
|
||||||
public int age_limit = 0;
|
public int age_limit = 0;
|
||||||
public String like_count = "";
|
public int like_count = 0;
|
||||||
public String dislike_count = "";
|
public int dislike_count = 0;
|
||||||
public String average_rating = "";
|
public String average_rating = "";
|
||||||
public VideoStream[] videoStreams = null;
|
public VideoStream[] videoStreams = null;
|
||||||
public AudioStream[] audioStreams = null;
|
public AudioStream[] audioStreams = null;
|
||||||
|
@ -64,11 +66,6 @@ public class VideoInfo {
|
||||||
public String resolution = "";
|
public String resolution = "";
|
||||||
}
|
}
|
||||||
|
|
||||||
protected static void formatNotKnown(int id) {
|
|
||||||
Log.e(TAG, "format not known: \"" +
|
|
||||||
Integer.toString(id) + "\". Call the programmers, they messed it up!");
|
|
||||||
}
|
|
||||||
|
|
||||||
public static class AudioStream {
|
public static class AudioStream {
|
||||||
public AudioStream(String url, int format, int bandwidth, int samplingRate) {
|
public AudioStream(String url, int format, int bandwidth, int samplingRate) {
|
||||||
this.url = url; this.format = format;
|
this.url = url; this.format = format;
|
||||||
|
@ -78,7 +75,5 @@ public class VideoInfo {
|
||||||
public int format = -1;
|
public int format = -1;
|
||||||
public int bandwidth = -1;
|
public int bandwidth = -1;
|
||||||
public int samplingRate = -1;
|
public int samplingRate = -1;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
|
@ -5,6 +5,7 @@ import android.os.Bundle;
|
||||||
import android.preference.PreferenceManager;
|
import android.preference.PreferenceManager;
|
||||||
import android.support.v4.app.NavUtils;
|
import android.support.v4.app.NavUtils;
|
||||||
import android.support.v7.app.AppCompatActivity;
|
import android.support.v7.app.AppCompatActivity;
|
||||||
|
import android.util.Log;
|
||||||
import android.view.Menu;
|
import android.view.Menu;
|
||||||
import android.view.MenuInflater;
|
import android.view.MenuInflater;
|
||||||
import android.view.MenuItem;
|
import android.view.MenuItem;
|
||||||
|
@ -60,6 +61,7 @@ public class VideoItemDetailActivity extends AppCompatActivity {
|
||||||
// this means the video was called though another app
|
// this means the video was called though another app
|
||||||
if (getIntent().getData() != null) {
|
if (getIntent().getData() != null) {
|
||||||
videoUrl = getIntent().getData().toString();
|
videoUrl = getIntent().getData().toString();
|
||||||
|
Log.i(TAG, "video URL passed:\"" + videoUrl + "\"");
|
||||||
StreamingService[] serviceList = ServiceList.getServices();
|
StreamingService[] serviceList = ServiceList.getServices();
|
||||||
Extractor extractor = null;
|
Extractor extractor = null;
|
||||||
for (int i = 0; i < serviceList.length; i++) {
|
for (int i = 0; i < serviceList.length; i++) {
|
||||||
|
|
|
@ -2,6 +2,7 @@ package org.schabi.newpipe;
|
||||||
|
|
||||||
import android.app.Activity;
|
import android.app.Activity;
|
||||||
import android.content.Intent;
|
import android.content.Intent;
|
||||||
|
import android.content.SharedPreferences;
|
||||||
import android.graphics.Bitmap;
|
import android.graphics.Bitmap;
|
||||||
import android.graphics.BitmapFactory;
|
import android.graphics.BitmapFactory;
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
|
@ -29,6 +30,11 @@ import android.widget.TextView;
|
||||||
import android.view.MenuItem;
|
import android.view.MenuItem;
|
||||||
|
|
||||||
import java.net.URL;
|
import java.net.URL;
|
||||||
|
import java.text.DateFormat;
|
||||||
|
import java.text.NumberFormat;
|
||||||
|
import java.util.Calendar;
|
||||||
|
import java.util.Date;
|
||||||
|
import java.util.Locale;
|
||||||
import java.util.Vector;
|
import java.util.Vector;
|
||||||
|
|
||||||
|
|
||||||
|
@ -216,12 +222,31 @@ public class VideoItemDetailFragment extends Fragment {
|
||||||
case VideoInfo.VIDEO_AVAILABLE: {
|
case VideoInfo.VIDEO_AVAILABLE: {
|
||||||
videoTitleView.setText(info.title);
|
videoTitleView.setText(info.title);
|
||||||
uploaderView.setText(info.uploader);
|
uploaderView.setText(info.uploader);
|
||||||
viewCountView.setText(info.view_count
|
|
||||||
|
Locale locale = getPreferredLocale();
|
||||||
|
NumberFormat nf = NumberFormat.getInstance(locale);
|
||||||
|
String localisedViewCount = nf.format(info.view_count);
|
||||||
|
viewCountView.setText(localisedViewCount
|
||||||
+ " " + activity.getString(R.string.viewSufix));
|
+ " " + activity.getString(R.string.viewSufix));
|
||||||
thumbsUpView.setText(info.like_count);
|
|
||||||
thumbsDownView.setText(info.dislike_count);
|
|
||||||
|
thumbsUpView.setText(nf.format(info.like_count));
|
||||||
|
thumbsDownView.setText(nf.format(info.dislike_count));
|
||||||
|
|
||||||
|
//this is horribly convoluted
|
||||||
|
//TODO: find a better way to convert YYYY-MM-DD to a locale-specific date
|
||||||
|
//suggestions welcome
|
||||||
|
int year = Integer.parseInt(info.upload_date.substring(0, 4));
|
||||||
|
int month = Integer.parseInt(info.upload_date.substring(5, 7));
|
||||||
|
int date = Integer.parseInt(info.upload_date.substring(8, 10));
|
||||||
|
Calendar cal = Calendar.getInstance();
|
||||||
|
cal.set(year, month, date);
|
||||||
|
Date datum = cal.getTime();
|
||||||
|
DateFormat df = DateFormat.getDateInstance(DateFormat.MEDIUM, locale);
|
||||||
|
|
||||||
|
String localisedDate = df.format(datum);
|
||||||
uploadDateView.setText(
|
uploadDateView.setText(
|
||||||
activity.getString(R.string.uploadDatePrefix) + " " + info.upload_date);
|
activity.getString(R.string.uploadDatePrefix) + " " + localisedDate);
|
||||||
descriptionView.setText(Html.fromHtml(info.description));
|
descriptionView.setText(Html.fromHtml(info.description));
|
||||||
descriptionView.setMovementMethod(LinkMovementMethod.getInstance());
|
descriptionView.setMovementMethod(LinkMovementMethod.getInstance());
|
||||||
|
|
||||||
|
@ -369,6 +394,23 @@ public class VideoItemDetailFragment extends Fragment {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Locale getPreferredLocale() {
|
||||||
|
SharedPreferences sp = PreferenceManager.getDefaultSharedPreferences(getContext());
|
||||||
|
String languageKey = getContext().getString(R.string.searchLanguage);
|
||||||
|
String languageCode = "en";//i know the following lines defaults languageCode to "en", but java is picky about uninitialised values
|
||||||
|
languageCode = sp.getString(languageKey, "en");
|
||||||
|
|
||||||
|
if(languageCode.length() == 2) {
|
||||||
|
return new Locale(languageCode);
|
||||||
|
}
|
||||||
|
else if(languageCode.contains("_")) {
|
||||||
|
String country = languageCode
|
||||||
|
.substring(languageCode.indexOf("_"), languageCode.length());
|
||||||
|
return new Locale(languageCode.substring(0, 2), country);
|
||||||
|
}
|
||||||
|
return Locale.getDefault();
|
||||||
|
}
|
||||||
|
|
||||||
public boolean checkIfLandscape() {
|
public boolean checkIfLandscape() {
|
||||||
DisplayMetrics displayMetrics = new DisplayMetrics();
|
DisplayMetrics displayMetrics = new DisplayMetrics();
|
||||||
getActivity().getWindowManager().getDefaultDisplay().getMetrics(displayMetrics);
|
getActivity().getWindowManager().getDefaultDisplay().getMetrics(displayMetrics);
|
||||||
|
|
|
@ -103,7 +103,7 @@ public class VideoItemListActivity extends AppCompatActivity
|
||||||
super.onCreate(savedInstanceState);
|
super.onCreate(savedInstanceState);
|
||||||
setContentView(R.layout.activity_videoitem_list);
|
setContentView(R.layout.activity_videoitem_list);
|
||||||
|
|
||||||
//-------- remove this line when multiservice support is implemented ----------
|
//------ todo: remove this line when multiservice support is implemented ------
|
||||||
currentStreamingServiceId = ServiceList.getIdOfService("Youtube");
|
currentStreamingServiceId = ServiceList.getIdOfService("Youtube");
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
|
|
@ -133,22 +133,27 @@ public class YoutubeExtractor implements Extractor {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String getVideoId(String videoUrl) {
|
public String getVideoId(String videoUrl) {
|
||||||
//https://www.youtube.com/watch?v=laF2D3QyAFQ
|
String id = "";
|
||||||
String id;
|
|
||||||
Pattern pat;
|
Pattern pat;
|
||||||
|
|
||||||
if(videoUrl.contains("youtube")) {
|
if(videoUrl.contains("youtube")) {
|
||||||
pat = Pattern.compile("youtube\\.com/watch\\?v=([a-zA-Z0-9_]{11})");
|
pat = Pattern.compile("youtube\\.com/watch\\?v=([\\-a-zA-Z0-9_]{11})");
|
||||||
}
|
}
|
||||||
else if(videoUrl.contains("youtu.be")) {
|
else if(videoUrl.contains("youtu.be")) {
|
||||||
pat = Pattern.compile("youtu\\.be/([a-zA-Z0-9_]{11})");
|
pat = Pattern.compile("youtu\\.be/([a-zA-Z0-9_-]{11})");
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
Log.e(TAG, "Error could not parse url: " + videoUrl);
|
Log.e(TAG, "Error could not parse url: " + videoUrl);
|
||||||
return "";
|
return "";
|
||||||
}
|
}
|
||||||
Matcher mat = pat.matcher(videoUrl);
|
Matcher mat = pat.matcher(videoUrl);
|
||||||
|
boolean foundMatch = mat.find();
|
||||||
|
if(foundMatch){
|
||||||
id = mat.group(1);
|
id = mat.group(1);
|
||||||
return (id == null ? "" : id);
|
Log.i(TAG, "string \""+videoUrl+"\" matches!");
|
||||||
|
}
|
||||||
|
Log.i(TAG, "string \""+videoUrl+"\" does not match.");
|
||||||
|
return id;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -163,7 +168,7 @@ public class YoutubeExtractor implements Extractor {
|
||||||
|
|
||||||
Document doc = Jsoup.parse(site, siteUrl);
|
Document doc = Jsoup.parse(site, siteUrl);
|
||||||
|
|
||||||
videoInfo.id = matchGroup1("v=([0-9a-zA-Z]{10,})", siteUrl);
|
videoInfo.id = matchGroup1("v=([0-9a-zA-Z_-]{11})", siteUrl);
|
||||||
|
|
||||||
videoInfo.age_limit = 0;
|
videoInfo.age_limit = 0;
|
||||||
videoInfo.webpage_url = siteUrl;
|
videoInfo.webpage_url = siteUrl;
|
||||||
|
@ -173,7 +178,7 @@ public class YoutubeExtractor implements Extractor {
|
||||||
//-------------------------------------
|
//-------------------------------------
|
||||||
// extracting form player args
|
// extracting form player args
|
||||||
//-------------------------------------
|
//-------------------------------------
|
||||||
JSONObject playerArgs;
|
JSONObject playerArgs = null;
|
||||||
{
|
{
|
||||||
try {
|
try {
|
||||||
String jsonString = matchGroup1("ytplayer.config\\s*=\\s*(\\{.*?\\});", site);
|
String jsonString = matchGroup1("ytplayer.config\\s*=\\s*(\\{.*?\\});", site);
|
||||||
|
@ -185,8 +190,6 @@ public class YoutubeExtractor implements Extractor {
|
||||||
// If we fail in this part the video is most likely not available.
|
// If we fail in this part the video is most likely not available.
|
||||||
// Determining why is done later.
|
// Determining why is done later.
|
||||||
videoInfo.videoAvailableStatus = VideoInfo.VIDEO_UNAVAILABLE;
|
videoInfo.videoAvailableStatus = VideoInfo.VIDEO_UNAVAILABLE;
|
||||||
//exit early, since we can't extract other args
|
|
||||||
return videoInfo;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -277,23 +280,27 @@ public class YoutubeExtractor implements Extractor {
|
||||||
|
|
||||||
|
|
||||||
// description
|
// description
|
||||||
videoInfo.description = doc.select("p[id=\"eow-description\"]").first()
|
videoInfo.description = doc.select("p[id=\"eow-description\"]").first().html();
|
||||||
.html();
|
String likesString = "";
|
||||||
|
String dislikesString = "";
|
||||||
try {
|
try {
|
||||||
// likes
|
// likes
|
||||||
videoInfo.like_count = doc.select("span[class=\"like-button-renderer \"]").first()
|
likesString = doc.select("button.like-button-renderer-like-button").first()
|
||||||
.getAllElements().select("button")
|
.select("span.yt-uix-button-content").first().text();
|
||||||
.select("span").get(0).text();
|
videoInfo.like_count = Integer.parseInt(likesString.replace(",", ""));
|
||||||
|
|
||||||
// dislikes
|
// dislikes
|
||||||
videoInfo.dislike_count = doc.select("span[class=\"like-button-renderer \"]").first()
|
dislikesString = doc.select("button.like-button-renderer-dislike-button").first()
|
||||||
.getAllElements().select("button")
|
.select("span.yt-uix-button-content").first().text();
|
||||||
.select("span").get(2).text();
|
|
||||||
|
videoInfo.dislike_count = Integer.parseInt(dislikesString.replace(",", ""));
|
||||||
|
} catch(NumberFormatException nfe) {
|
||||||
|
Log.e(TAG, "failed to parse likesString \""+likesString+"\" and dislikesString \""+
|
||||||
|
dislikesString+"\" as integers");
|
||||||
} catch(Exception e) {
|
} catch(Exception e) {
|
||||||
// if it fails we know that the video does not offer dislikes.
|
// if it fails we know that the video does not offer dislikes.
|
||||||
videoInfo.like_count = "0";
|
e.printStackTrace();
|
||||||
videoInfo.dislike_count = "0";
|
videoInfo.like_count = 0;
|
||||||
|
videoInfo.dislike_count = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
// uploader thumbnail
|
// uploader thumbnail
|
||||||
|
@ -301,8 +308,9 @@ public class YoutubeExtractor implements Extractor {
|
||||||
.select("img").first()
|
.select("img").first()
|
||||||
.attr("abs:data-thumb");
|
.attr("abs:data-thumb");
|
||||||
|
|
||||||
// view count TODO: format locale-specifically
|
// view count TODO: locale-specific formatting
|
||||||
videoInfo.view_count = doc.select("meta[itemprop=interactionCount]").attr("content");
|
String viewCountString = doc.select("meta[itemprop=interactionCount]").attr("content");
|
||||||
|
videoInfo.view_count = Integer.parseInt(viewCountString);
|
||||||
|
|
||||||
// next video
|
// next video
|
||||||
videoInfo.nextVideo = extractVideoInfoItem(doc.select("div[class=\"watch-sidebar-section\"]").first()
|
videoInfo.nextVideo = extractVideoInfoItem(doc.select("div[class=\"watch-sidebar-section\"]").first()
|
||||||
|
|
Loading…
Add table
Reference in a new issue