git channel item running

This commit is contained in:
Christian Schabesberger 2017-02-15 12:59:36 +01:00
parent 91434dd2ac
commit 3f0078f38a
21 changed files with 233 additions and 40 deletions

View file

@ -1,18 +1,24 @@
package org.schabi.newpipe; package org.schabi.newpipe;
import android.annotation.TargetApi;
import android.content.Context;
import android.content.Intent; import android.content.Intent;
import android.net.Uri; import android.net.Uri;
import android.os.Build;
import android.os.Bundle; import android.os.Bundle;
import android.os.Handler; import android.os.Handler;
import android.preference.PreferenceManager; import android.preference.PreferenceManager;
import android.support.design.widget.CollapsingToolbarLayout; import android.support.design.widget.CollapsingToolbarLayout;
import android.support.design.widget.FloatingActionButton; import android.support.design.widget.FloatingActionButton;
import android.support.v4.content.ContextCompat;
import android.support.v7.app.AppCompatActivity; import android.support.v7.app.AppCompatActivity;
import android.support.v7.widget.LinearLayoutManager; import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView; import android.support.v7.widget.RecyclerView;
import android.support.v7.widget.Toolbar; import android.support.v7.widget.Toolbar;
import android.util.Log; import android.util.Log;
import android.view.View; import android.view.View;
import android.view.Window;
import android.view.WindowManager;
import android.widget.ImageView; import android.widget.ImageView;
import android.widget.ProgressBar; import android.widget.ProgressBar;
import android.widget.Toast; import android.widget.Toast;
@ -34,6 +40,9 @@ import org.schabi.newpipe.report.ErrorActivity;
import java.io.IOException; import java.io.IOException;
import java.util.Objects; import java.util.Objects;
import static android.os.Build.VERSION.SDK;
import static android.os.Build.VERSION.SDK_INT;
/** /**
* Copyright (C) Christian Schabesberger 2016 <chris.schabesberger@mailbox.org> * Copyright (C) Christian Schabesberger 2016 <chris.schabesberger@mailbox.org>
* ChannelActivity.java is part of NewPipe. * ChannelActivity.java is part of NewPipe.
@ -87,15 +96,17 @@ public class ChannelActivity extends AppCompatActivity {
channelUrl = i.getStringExtra(CHANNEL_URL); channelUrl = i.getStringExtra(CHANNEL_URL);
serviceId = i.getIntExtra(SERVICE_ID, -1); serviceId = i.getIntExtra(SERVICE_ID, -1);
setTranslucentStatusBar(getWindow());
infoListAdapter = new InfoListAdapter(this, rootView); infoListAdapter = new InfoListAdapter(this, rootView);
RecyclerView recyclerView = (RecyclerView) findViewById(R.id.channel_streams_view); RecyclerView recyclerView = (RecyclerView) findViewById(R.id.channel_streams_view);
final LinearLayoutManager layoutManager = new LinearLayoutManager(this); final LinearLayoutManager layoutManager = new LinearLayoutManager(this);
recyclerView.setLayoutManager(layoutManager); recyclerView.setLayoutManager(layoutManager);
recyclerView.setAdapter(infoListAdapter); recyclerView.setAdapter(infoListAdapter);
infoListAdapter.setOnStreamItemSelectedListener( infoListAdapter.setOnStreamInfoItemSelectedListener(
new InfoItemBuilder.OnInfoItemSelectedListener() { new InfoItemBuilder.OnInfoItemSelectedListener() {
@Override @Override
public void selected(String url) { public void selected(String url, int serviceId) {
Intent detailIntent = new Intent(ChannelActivity.this, VideoItemDetailActivity.class); Intent detailIntent = new Intent(ChannelActivity.this, VideoItemDetailActivity.class);
detailIntent.putExtra(VideoItemDetailFragment.VIDEO_URL, url); detailIntent.putExtra(VideoItemDetailFragment.VIDEO_URL, url);
detailIntent.putExtra( detailIntent.putExtra(
@ -245,9 +256,13 @@ public class ChannelActivity extends AppCompatActivity {
}); });
pe.printStackTrace(); pe.printStackTrace();
} catch(ExtractionException ex) { } catch(ExtractionException ex) {
String name = "none";
if(service != null) {
name = service.getServiceInfo().name;
}
ErrorActivity.reportError(h, ChannelActivity.this, ex, VideoItemDetailFragment.class, null, ErrorActivity.reportError(h, ChannelActivity.this, ex, VideoItemDetailFragment.class, null,
ErrorActivity.ErrorInfo.make(ErrorActivity.REQUESTED_CHANNEL, ErrorActivity.ErrorInfo.make(ErrorActivity.REQUESTED_CHANNEL,
service.getServiceInfo().name, channelUrl, R.string.parsing_error)); name, channelUrl, R.string.parsing_error));
h.post(new Runnable() { h.post(new Runnable() {
@Override @Override
public void run() { public void run() {
@ -273,4 +288,28 @@ public class ChannelActivity extends AppCompatActivity {
channelExtractorThread.start(); channelExtractorThread.start();
} }
// fix transparent statusbar fuckup (fuck google why can't they just leave something that worked
// as it is, and everyone gets happy)
public static void setTranslucentStatusBar(Window window) {
if (window == null) return;
int sdkInt = Build.VERSION.SDK_INT;
if (sdkInt >= Build.VERSION_CODES.LOLLIPOP) {
setTranslucentStatusBarLollipop(window);
} else if (sdkInt >= Build.VERSION_CODES.KITKAT) {
setTranslucentStatusBarKiKat(window);
}
}
@TargetApi(Build.VERSION_CODES.LOLLIPOP)
private static void setTranslucentStatusBarLollipop(Window window) {
window.setStatusBarColor(
ContextCompat.getColor(window.getContext(), android.R.color.transparent));
}
@TargetApi(Build.VERSION_CODES.KITKAT)
private static void setTranslucentStatusBarKiKat(Window window) {
window.addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);
}
} }

View file

@ -543,7 +543,7 @@ public class VideoItemDetailFragment extends Fragment {
infoItemBuilder.setOnStreamInfoItemSelectedListener( infoItemBuilder.setOnStreamInfoItemSelectedListener(
new InfoItemBuilder.OnInfoItemSelectedListener() { new InfoItemBuilder.OnInfoItemSelectedListener() {
@Override @Override
public void selected(String url) { public void selected(String url, int serviceId) {
openStreamUrl(url); openStreamUrl(url);
} }
}); });

View file

@ -26,17 +26,19 @@ public class ChannelInfoItem implements InfoItem {
public int serviceId = -1; public int serviceId = -1;
public String channelName = ""; public String channelName = "";
public String thumbnailUrl = "";
public String webPageUrl = ""; public String webPageUrl = "";
public int subscriberCount = -1; public String description = "";
public long subscriberCount = -1;
public int videoAmount = -1; public int videoAmount = -1;
public InfoType infoType() { public InfoType infoType() {
return InfoType.CHANNEL; return InfoType.CHANNEL;
} }
public String getTitle() { public String getTitle() {
return ""; return channelName;
} }
public String getLink() { public String getLink() {
return ""; return webPageUrl;
} }
} }

View file

@ -52,6 +52,16 @@ public class ChannelInfoItemCollector extends InfoItemCollector {
} catch (Exception e) { } catch (Exception e) {
addError(e); addError(e);
} }
try {
resultItem.thumbnailUrl = extractor.getThumbnailUrl();
} catch (Exception e) {
addError(e);
}
try {
resultItem.description = extractor.getDescription();
} catch (Exception e) {
addError(e);
}
addItem(resultItem); addItem(resultItem);
} catch (Exception e) { } catch (Exception e) {

View file

@ -23,8 +23,10 @@ import org.schabi.newpipe.extractor.exceptions.ParsingException;
*/ */
public interface ChannelInfoItemExtractor { public interface ChannelInfoItemExtractor {
String getThumbnailUrl() throws ParsingException;
String getChannelName() throws ParsingException; String getChannelName() throws ParsingException;
String getWebPageUrl() throws ParsingException; String getWebPageUrl() throws ParsingException;
int getSubscriberCount() throws ParsingException; String getDescription() throws ParsingException;
long getSubscriberCount() throws ParsingException;
int getVideoAmount() throws ParsingException; int getVideoAmount() throws ParsingException;
} }

View file

@ -39,7 +39,9 @@ public class SearchResult {
.getSearchResult(); .getSearchResult();
if(result.resultList.isEmpty()) { if(result.resultList.isEmpty()) {
if(result.suggestion.isEmpty()) { if(result.suggestion.isEmpty()) {
throw new ExtractionException("Empty result despite no error"); if(result.errors.isEmpty()) {
throw new ExtractionException("Empty result despite no error");
}
} else { } else {
// This is used as a fallback. Do not relay on it !!! // This is used as a fallback. Do not relay on it !!!
throw new SearchEngine.NothingFoundException(result.suggestion); throw new SearchEngine.NothingFoundException(result.suggestion);

View file

@ -136,8 +136,9 @@ public class YoutubeChannelExtractor extends ChannelExtractor {
if(!isAjaxPage) { if(!isAjaxPage) {
Element el = doc.select("div[id=\"gh-banner\"]").first().select("style").first(); Element el = doc.select("div[id=\"gh-banner\"]").first().select("style").first();
String cssContent = el.html(); String cssContent = el.html();
String url = "https:" + Parser.matchGroup1("url\\(([^)]+)\\)", cssContent); String url = Parser.matchGroup1("url\\(([^)]+)\\)", cssContent);
if (url.contains("s.ytimg.com")) {
if (url.contains("s.ytimg.com") || url.contains("default_banner")) {
bannerUrl = null; bannerUrl = null;
} else { } else {
bannerUrl = url; bannerUrl = url;

View file

@ -1,5 +1,6 @@
package org.schabi.newpipe.extractor.services.youtube; package org.schabi.newpipe.extractor.services.youtube;
import org.schabi.newpipe.extractor.Parser;
import org.schabi.newpipe.extractor.channel.ChannelInfoItemExtractor; import org.schabi.newpipe.extractor.channel.ChannelInfoItemExtractor;
import org.schabi.newpipe.extractor.exceptions.ParsingException; import org.schabi.newpipe.extractor.exceptions.ParsingException;
import org.jsoup.nodes.Element; import org.jsoup.nodes.Element;
@ -31,19 +32,48 @@ public class YoutubeChannelInfoItemExtractor implements ChannelInfoItemExtractor
this.el = el; this.el = el;
} }
public String getThumbnailUrl() throws ParsingException {
Element img = el.select("span[class*=\"yt-thumb-simple\"]").first()
.select("img").first();
String url = img.attr("abs:src");
if(url.contains("gif")) {
url = img.attr("abs:data-thumb");
}
return url;
}
public String getChannelName() throws ParsingException { public String getChannelName() throws ParsingException {
return ""; return el.select("a[class*=\"yt-uix-tile-link\"]").first()
.text();
} }
public String getWebPageUrl() throws ParsingException { public String getWebPageUrl() throws ParsingException {
return ""; return el.select("a[class*=\"yt-uix-tile-link\"]").first()
.attr("abs:href");
} }
public int getSubscriberCount() throws ParsingException { public long getSubscriberCount() throws ParsingException {
return 0; return Long.parseLong(el.select("span[class*=\"yt-subscriber-count\"]").first()
.text().replaceAll("\\D+",""));
} }
public int getVideoAmount() throws ParsingException { public int getVideoAmount() throws ParsingException {
return 0; Element metaEl = el.select("ul[class*=\"yt-lockup-meta-info\"]").first();
if(metaEl == null) {
return 0;
} else {
return Integer.parseInt(metaEl.text().replaceAll("\\D+",""));
}
}
public String getDescription() throws ParsingException {
Element desEl = el.select("div[class*=\"yt-lockup-description\"]").first();
if(desEl == null) {
return "";
} else {
return desEl.text();
}
} }
} }

View file

@ -109,7 +109,7 @@ public class YoutubeSearchEngine extends SearchEngine {
collector.commit(new YoutubeChannelInfoItemExtractor(el)); collector.commit(new YoutubeChannelInfoItemExtractor(el));
} else { } else {
//noinspection ConstantConditions //noinspection ConstantConditions
throw new ExtractionException("unexpected element found:\"" + el + "\""); throw new ExtractionException("unexpected element found: \"" + el + "\"");
} }
} }

View file

@ -32,12 +32,18 @@ import de.hdodenhof.circleimageview.CircleImageView;
public class ChannelInfoItemHolder extends InfoItemHolder { public class ChannelInfoItemHolder extends InfoItemHolder {
public final CircleImageView itemThumbnailView; public final CircleImageView itemThumbnailView;
public final TextView itemChannelTitleView; public final TextView itemChannelTitleView;
public final TextView itemSubscriberCountView;
public final TextView itemVideoCountView;
public final TextView itemChannelDescriptionView;
public final Button itemButton; public final Button itemButton;
ChannelInfoItemHolder(View v) { ChannelInfoItemHolder(View v) {
super(v); super(v);
itemThumbnailView = (CircleImageView) v.findViewById(R.id.itemThumbnailView); itemThumbnailView = (CircleImageView) v.findViewById(R.id.itemThumbnailView);
itemChannelTitleView = (TextView) v.findViewById(R.id.itemChannelTitleView); itemChannelTitleView = (TextView) v.findViewById(R.id.itemChannelTitleView);
itemSubscriberCountView = (TextView) v.findViewById(R.id.itemSubscriberCountView);
itemVideoCountView = (TextView) v.findViewById(R.id.itemVideoCountView);
itemChannelDescriptionView = (TextView) v.findViewById(R.id.itemChannelDescriptionView);
itemButton = (Button) v.findViewById(R.id.item_button); itemButton = (Button) v.findViewById(R.id.item_button);
} }

View file

@ -39,9 +39,17 @@ import org.schabi.newpipe.extractor.stream_info.StreamInfoItem;
public class InfoItemBuilder { public class InfoItemBuilder {
final String viewsS;
final String videosS;
final String subsS;
final String thousand;
final String million;
final String billion;
private static final String TAG = InfoItemBuilder.class.toString(); private static final String TAG = InfoItemBuilder.class.toString();
public interface OnInfoItemSelectedListener { public interface OnInfoItemSelectedListener {
void selected(String url); void selected(String url, int serviceId);
} }
private Activity activity = null; private Activity activity = null;
@ -55,6 +63,12 @@ public class InfoItemBuilder {
public InfoItemBuilder(Activity a, View rootView) { public InfoItemBuilder(Activity a, View rootView) {
activity = a; activity = a;
this.rootView = rootView; this.rootView = rootView;
viewsS = a.getString(R.string.views);
videosS = a.getString(R.string.videos);
subsS = a.getString(R.string.subscriber);
thousand = a.getString(R.string.short_thousand);
million = a.getString(R.string.short_million);
billion = a.getString(R.string.short_billion);
} }
public void setOnStreamInfoItemSelectedListener( public void setOnStreamInfoItemSelectedListener(
@ -146,32 +160,55 @@ public class InfoItemBuilder {
holder.itemButton.setOnClickListener(new View.OnClickListener() { holder.itemButton.setOnClickListener(new View.OnClickListener() {
@Override @Override
public void onClick(View view) { public void onClick(View view) {
onStreamInfoItemSelectedListener.selected(info.webpage_url); onStreamInfoItemSelectedListener.selected(info.webpage_url, info.service_id);
} }
}); });
} }
private void buildChannelInfoItem(ChannelInfoItemHolder holder, final ChannelInfoItem info) { private void buildChannelInfoItem(ChannelInfoItemHolder holder, final ChannelInfoItem info) {
holder.itemChannelTitleView.setText(info.getTitle()); holder.itemChannelTitleView.setText(info.getTitle());
holder.itemSubscriberCountView.setText(shortSubscriber(info.subscriberCount) + "");
holder.itemVideoCountView.setText(info.videoAmount + " " + videosS);
holder.itemChannelDescriptionView.setText(info.description);
holder.itemThumbnailView.setImageResource(R.drawable.buddy_channel_item);
if(info.thumbnailUrl != null && !info.thumbnailUrl.isEmpty()) {
imageLoader.displayImage(info.thumbnailUrl,
holder.itemThumbnailView,
displayImageOptions,
new ImageErrorLoadingListener(activity, rootView, info.serviceId));
}
holder.itemButton.setOnClickListener(new View.OnClickListener() { holder.itemButton.setOnClickListener(new View.OnClickListener() {
@Override @Override
public void onClick(View view) { public void onClick(View view) {
onChannelInfoItemSelectedListener.selected(info.getLink()); onChannelInfoItemSelectedListener.selected(info.getLink(), info.serviceId);
} }
}); });
} }
public String shortViewCount(Long viewCount){
public static String shortViewCount(Long viewCount){
if(viewCount >= 1000000000){ if(viewCount >= 1000000000){
return Long.toString(viewCount/1000000000)+"B views"; return Long.toString(viewCount/1000000000)+ billion + " " + viewsS;
}else if(viewCount>=1000000){ }else if(viewCount>=1000000){
return Long.toString(viewCount/1000000)+"M views"; return Long.toString(viewCount/1000000)+ million + " " + viewsS;
}else if(viewCount>=1000){ }else if(viewCount>=1000){
return Long.toString(viewCount/1000)+"K views"; return Long.toString(viewCount/1000)+ thousand + " " + viewsS;
}else { }else {
return Long.toString(viewCount)+" views"; return Long.toString(viewCount)+ " " + viewsS;
}
}
public String shortSubscriber(Long viewCount){
if(viewCount >= 1000000000){
return Long.toString(viewCount/1000000000)+ billion + " " + subsS;
}else if(viewCount>=1000000){
return Long.toString(viewCount/1000000)+ million + " " + subsS;
}else if(viewCount>=1000){
return Long.toString(viewCount/1000)+ thousand + " " + subsS;
}else {
return Long.toString(viewCount)+ " " + subsS;
} }
} }

View file

@ -44,9 +44,14 @@ public class InfoListAdapter extends RecyclerView.Adapter<InfoItemHolder> {
infoItemList = new Vector<>(); infoItemList = new Vector<>();
} }
public void setOnStreamItemSelectedListener public void setOnStreamInfoItemSelectedListener
(InfoItemBuilder.OnInfoItemSelectedListener onItemSelectedListener) { (InfoItemBuilder.OnInfoItemSelectedListener listener) {
infoItemBuilder.setOnStreamInfoItemSelectedListener(onItemSelectedListener); infoItemBuilder.setOnStreamInfoItemSelectedListener(listener);
}
public void setOnChannelInfoItemSelectedListener
(InfoItemBuilder.OnInfoItemSelectedListener listener) {
infoItemBuilder.setOnChannelInfoItemSelectedListener(listener);
} }
public void addInfoItemList(List<InfoItem> videos) { public void addInfoItemList(List<InfoItem> videos) {

View file

@ -19,6 +19,7 @@ import android.view.inputmethod.InputMethodManager;
import android.widget.ProgressBar; import android.widget.ProgressBar;
import android.widget.Toast; import android.widget.Toast;
import org.schabi.newpipe.ChannelActivity;
import org.schabi.newpipe.ReCaptchaActivity; import org.schabi.newpipe.ReCaptchaActivity;
import org.schabi.newpipe.extractor.NewPipe; import org.schabi.newpipe.extractor.NewPipe;
import org.schabi.newpipe.extractor.search.SearchEngine; import org.schabi.newpipe.extractor.search.SearchEngine;
@ -216,13 +217,19 @@ public class SearchInfoItemFragment extends Fragment {
infoListAdapter = new InfoListAdapter(getActivity(), infoListAdapter = new InfoListAdapter(getActivity(),
getActivity().findViewById(android.R.id.content)); getActivity().findViewById(android.R.id.content));
infoListAdapter.setOnStreamItemSelectedListener( infoListAdapter.setOnStreamInfoItemSelectedListener(
new InfoItemBuilder.OnInfoItemSelectedListener() { new InfoItemBuilder.OnInfoItemSelectedListener() {
@Override @Override
public void selected(String url) { public void selected(String url, int serviceId) {
startDetailActivity(url); startDetailActivity(url);
} }
}); });
infoListAdapter.setOnChannelInfoItemSelectedListener(new InfoItemBuilder.OnInfoItemSelectedListener() {
@Override
public void selected(String url, int serviceId) {
startChannelActivity(url, serviceId);
}
});
recyclerView.setAdapter(infoListAdapter); recyclerView.setAdapter(infoListAdapter);
recyclerView.clearOnScrollListeners(); recyclerView.clearOnScrollListeners();
recyclerView.addOnScrollListener(new RecyclerView.OnScrollListener() { recyclerView.addOnScrollListener(new RecyclerView.OnScrollListener() {
@ -254,6 +261,13 @@ public class SearchInfoItemFragment extends Fragment {
getActivity().startActivity(i); getActivity().startActivity(i);
} }
private void startChannelActivity(String url, int serviceId) {
Intent i = new Intent(getActivity(), ChannelActivity.class);
i.putExtra(ChannelActivity.CHANNEL_URL, url);
i.putExtra(ChannelActivity.SERVICE_ID, serviceId);
startActivity(i);
}
@Override @Override
public void onStart() { public void onStart() {
super.onStart(); super.onStart();

View file

@ -117,6 +117,7 @@ public class SearchWorker {
// look for errors during extraction // look for errors during extraction
// soft errors: // soft errors:
View rootView = a.findViewById(android.R.id.content);
if(result != null && if(result != null &&
!result.errors.isEmpty()) { !result.errors.isEmpty()) {
Log.e(TAG, "OCCURRED ERRORS DURING SEARCH EXTRACTION:"); Log.e(TAG, "OCCURRED ERRORS DURING SEARCH EXTRACTION:");
@ -125,11 +126,17 @@ public class SearchWorker {
Log.e(TAG, "------"); Log.e(TAG, "------");
} }
View rootView = a.findViewById(android.R.id.content); if(result.resultList.isEmpty()&& !result.errors.isEmpty()) {
ErrorActivity.reportError(h, a, result.errors, null, rootView, // if it compleatly failes dont show snackbar, instead show error directlry
ErrorActivity.ErrorInfo.make(ErrorActivity.SEARCHED, ErrorActivity.reportError(h, a, result.errors, null, null,
serviceName, query, R.string.light_parsing_error)); ErrorActivity.ErrorInfo.make(ErrorActivity.SEARCHED,
serviceName, query, R.string.parsing_error));
} else {
// if it partly show snackbar
ErrorActivity.reportError(h, a, result.errors, null, rootView,
ErrorActivity.ErrorInfo.make(ErrorActivity.SEARCHED,
serviceName, query, R.string.light_parsing_error));
}
} }
// hard errors: // hard errors:
} catch (ReCaptchaException e) { } catch (ReCaptchaException e) {

View file

@ -1,11 +1,11 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<FrameLayout <FrameLayout android:id="@+id/item_main_layout"
android:id="@+id/item_main_layout"
xmlns:android="http://schemas.android.com/apk/res/android" xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools" xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content"> android:layout_height="wrap_content"
xmlns:app="http://schemas.android.com/apk/res-auto">
<LinearLayout <LinearLayout
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" > android:layout_height="wrap_content" >
@ -46,13 +46,35 @@
android:layout_width="fill_parent" android:layout_width="fill_parent"
android:layout_height="0dp" android:layout_height="0dp"
android:textAppearance="?android:attr/textAppearanceLarge" android:textAppearance="?android:attr/textAppearanceLarge"
android:textSize="@dimen/video_item_search_title_text_size"/> android:textSize="@dimen/channel_item_detail_title_text_size"/>
<TextView android:id="@+id/itemChannelDescriptionView"
android:layout_weight="2"
android:layout_width="fill_parent"
android:layout_height="0dp"
android:textAppearance="?android:attr/textAppearanceSmall"
android:textSize="@dimen/video_item_search_uploader_text_size"/>
<LinearLayout <LinearLayout
android:orientation="horizontal" android:orientation="horizontal"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content"> android:layout_height="wrap_content">
<TextView android:id="@+id/itemSubscriberCountView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:singleLine="true"
android:textAppearance="?android:attr/textAppearanceSmall"
android:textSize="@dimen/video_item_search_upload_date_text_size"
android:text="1000 subs"/>
<TextView android:id="@+id/itemVideoCountView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:singleLine="true"
android:textAppearance="?android:attr/textAppearanceSmall"
android:textSize="@dimen/video_item_search_upload_date_text_size"
android:text="1000 vids"/>
</LinearLayout> </LinearLayout>

View file

@ -138,6 +138,12 @@
<string name="switch_mode">Zwischen Liste und Gitter umschalten</string> <string name="switch_mode">Zwischen Liste und Gitter umschalten</string>
<string name="videos">Videos</string>
<string name="subscriber">Abonenten</string>
<string name="views">Aufrufe</string>
<string name="short_thousand">Tsd.</string>
<string name="short_million">Mio.</string>
<string name="short_billion">Mrd.</string>
<string name="msg_url">Download-URL</string> <string name="msg_url">Download-URL</string>
<string name="msg_name">Dateiname</string> <string name="msg_name">Dateiname</string>

View file

@ -3,6 +3,7 @@
<!-- Video Item Search View Dimensions--> <!-- Video Item Search View Dimensions-->
<!-- Text Size --> <!-- Text Size -->
<dimen name="channel_item_detail_title_text_size">33sp</dimen>
<dimen name="video_item_search_title_text_size">22sp</dimen> <dimen name="video_item_search_title_text_size">22sp</dimen>
<dimen name="video_item_search_duration_text_size">16sp</dimen> <dimen name="video_item_search_duration_text_size">16sp</dimen>
<dimen name="video_item_search_uploader_text_size">18sp</dimen> <dimen name="video_item_search_uploader_text_size">18sp</dimen>

View file

@ -3,6 +3,7 @@
<!-- Video Item Search View Dimensions--> <!-- Video Item Search View Dimensions-->
<!-- Text Size --> <!-- Text Size -->
<dimen name="channel_item_detail_title_text_size">21sp</dimen>
<dimen name="video_item_search_title_text_size">14sp</dimen> <dimen name="video_item_search_title_text_size">14sp</dimen>
<dimen name="video_item_search_duration_text_size">11sp</dimen> <dimen name="video_item_search_duration_text_size">11sp</dimen>
<dimen name="video_item_search_uploader_text_size">12sp</dimen> <dimen name="video_item_search_uploader_text_size">12sp</dimen>

View file

@ -3,6 +3,7 @@
<!-- Video Item Detail View Dimensions--> <!-- Video Item Detail View Dimensions-->
<!-- Text Size --> <!-- Text Size -->
<dimen name="channel_item_detail_title_text_size">30sp</dimen>
<dimen name="video_item_detail_title_text_size">20sp</dimen> <dimen name="video_item_detail_title_text_size">20sp</dimen>
<dimen name="video_item_detail_views_text_size">16sp</dimen> <dimen name="video_item_detail_views_text_size">16sp</dimen>
<dimen name="video_item_detail_likes_text_size">14sp</dimen> <dimen name="video_item_detail_likes_text_size">14sp</dimen>

View file

@ -2,6 +2,7 @@
<resources> <resources>
<!-- Video Item Search View Dimensions--> <!-- Video Item Search View Dimensions-->
<!-- Text Size --> <!-- Text Size -->
<dimen name="channel_item_detail_title_text_size">21sp</dimen>
<dimen name="video_item_search_title_text_size">14sp</dimen> <dimen name="video_item_search_title_text_size">14sp</dimen>
<dimen name="video_item_search_duration_text_size">11sp</dimen> <dimen name="video_item_search_duration_text_size">11sp</dimen>
<dimen name="video_item_search_uploader_text_size">12sp</dimen> <dimen name="video_item_search_uploader_text_size">12sp</dimen>

View file

@ -147,6 +147,12 @@
<string name="storage_permission_denied">Permission to access storage was denied</string> <string name="storage_permission_denied">Permission to access storage was denied</string>
<string name="use_exoplayer_title">Use ExoPlayer</string> <string name="use_exoplayer_title">Use ExoPlayer</string>
<string name="use_exoplayer_summary">Experimental</string> <string name="use_exoplayer_summary">Experimental</string>
<string name="videos">videos</string>
<string name="subscriber">subscriber</string>
<string name="views">views</string>
<string name="short_thousand">T</string>
<string name="short_million">M</string>
<string name="short_billion">B</string>
<!-- Missions --> <!-- Missions -->
<string name="start">Start</string> <string name="start">Start</string>