diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml
index 26788cd1b..d18a30f57 100644
--- a/app/src/main/AndroidManifest.xml
+++ b/app/src/main/AndroidManifest.xml
@@ -79,12 +79,14 @@
android:name=".player.PlayVideoActivity"
android:configChanges="orientation|keyboardHidden|screenSize"
android:theme="@style/VideoPlayerTheme"
- tools:ignore="UnusedAttribute"/>
+ tools:ignore="UnusedAttribute" />
+
-
+
+
+
+ android:exported="false"
+ android:label="@string/background_player_name" />
+
@@ -124,25 +128,26 @@
android:name=".ExitActivity"
android:label="@string/general_error"
android:theme="@android:style/Theme.NoDisplay" />
-
+
-
+ android:launchMode="singleTask"
+ android:theme="@style/AppTheme">
-
+
-
-
+ android:launchMode="singleTask"
+ android:theme="@style/FilePickerTheme">
+
-
+
+
\ No newline at end of file
diff --git a/app/src/main/java/org/schabi/newpipe/ChannelActivity.java b/app/src/main/java/org/schabi/newpipe/ChannelActivity.java
new file mode 100644
index 000000000..3d5d204a9
--- /dev/null
+++ b/app/src/main/java/org/schabi/newpipe/ChannelActivity.java
@@ -0,0 +1,28 @@
+package org.schabi.newpipe;
+
+import android.os.Bundle;
+import android.support.design.widget.FloatingActionButton;
+import android.support.design.widget.Snackbar;
+import android.support.v7.app.AppCompatActivity;
+import android.support.v7.widget.Toolbar;
+import android.view.View;
+
+public class ChannelActivity extends AppCompatActivity {
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ setContentView(R.layout.activity_channel);
+ Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
+ setSupportActionBar(toolbar);
+
+ FloatingActionButton fab = (FloatingActionButton) findViewById(R.id.fab);
+ fab.setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View view) {
+ Snackbar.make(view, "Replace with your own action", Snackbar.LENGTH_LONG)
+ .setAction("Action", null).show();
+ }
+ });
+ }
+}
diff --git a/app/src/main/java/org/schabi/newpipe/VideoItemDetailActivity.java b/app/src/main/java/org/schabi/newpipe/VideoItemDetailActivity.java
index 9ba18bdcc..3089741a5 100644
--- a/app/src/main/java/org/schabi/newpipe/VideoItemDetailActivity.java
+++ b/app/src/main/java/org/schabi/newpipe/VideoItemDetailActivity.java
@@ -85,7 +85,7 @@ public class VideoItemDetailActivity extends AppCompatActivity {
.show();
}
//arguments.putString(VideoItemDetailFragment.VIDEO_URL,
- // videoExtractor.getVideoUrl(videoExtractor.getVideoId(videoUrl)));//cleans URL
+ // videoExtractor.getUrl(videoExtractor.getId(videoUrl)));//cleans URL
arguments.putString(VideoItemDetailFragment.VIDEO_URL, videoUrl);
arguments.putBoolean(VideoItemDetailFragment.AUTO_PLAY,
diff --git a/app/src/main/java/org/schabi/newpipe/VideoItemDetailFragment.java b/app/src/main/java/org/schabi/newpipe/VideoItemDetailFragment.java
index c9f277562..a0c3f3c26 100644
--- a/app/src/main/java/org/schabi/newpipe/VideoItemDetailFragment.java
+++ b/app/src/main/java/org/schabi/newpipe/VideoItemDetailFragment.java
@@ -50,6 +50,7 @@ import java.util.Vector;
import org.schabi.newpipe.download.DownloadDialog;
import org.schabi.newpipe.extractor.AudioStream;
+import org.schabi.newpipe.extractor.ChannelExtractor;
import org.schabi.newpipe.extractor.MediaFormat;
import org.schabi.newpipe.extractor.ParsingException;
import org.schabi.newpipe.extractor.ServiceList;
@@ -306,6 +307,7 @@ public class VideoItemDetailFragment extends Fragment {
activity.findViewById(R.id.detailVideoThumbnailWindowBackgroundButton);
View topView = activity.findViewById(R.id.detailTopView);
View nextVideoView = null;
+ Button channelButton = (Button) activity.findViewById(R.id.channelButton);
if(info.next_video != null) {
nextVideoView = videoItemViewCreator
.getViewFromVideoInfoItem(null, nextVideoFrame, info.next_video);
@@ -447,6 +449,14 @@ public class VideoItemDetailFragment extends Fragment {
}
});
+ channelButton.setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View view) {
+ Intent i = new Intent(activity, ChannelActivity.class);
+ startActivity(i);
+ }
+ });
+
} catch (java.lang.NullPointerException e) {
Log.w(TAG, "updateInfo(): Fragment closed before thread ended work... or else");
e.printStackTrace();
diff --git a/app/src/main/java/org/schabi/newpipe/extractor/ChannelExtractor.java b/app/src/main/java/org/schabi/newpipe/extractor/ChannelExtractor.java
new file mode 100644
index 000000000..77459b933
--- /dev/null
+++ b/app/src/main/java/org/schabi/newpipe/extractor/ChannelExtractor.java
@@ -0,0 +1,46 @@
+package org.schabi.newpipe.extractor;
+
+import java.io.IOException;
+
+/**
+ * Created by Christian Schabesberger on 25.07.16.
+ *
+ * Copyright (C) Christian Schabesberger 2016
+ * ChannelExtractor.java is part of NewPipe.
+ *
+ * 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.
+ *
+ * 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.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with NewPipe. If not, see .
+ */
+
+public abstract class ChannelExtractor {
+ private int serviceId;
+ private String url;
+ private UrlIdHandler urlIdHandler;
+ private Downloader downloader;
+ private StreamPreviewInfoCollector previewInfoCollector;
+
+ public ChannelExtractor(UrlIdHandler urlIdHandler, String url, Downloader dl, int serviceId)
+ throws ExtractionException, IOException {
+ this.serviceId = serviceId;
+ this.urlIdHandler = urlIdHandler;
+ previewInfoCollector = new StreamPreviewInfoCollector(urlIdHandler, serviceId);
+ }
+
+ public String getUrl() { return url; }
+ public UrlIdHandler getUrlIdHandler() { return urlIdHandler; }
+ public Downloader getDownloader() { return downloader; }
+
+ public abstract String getChannelName() throws ParsingException;
+ public abstract String getAvatarUrl() throws ParsingException;
+ public abstract String getBannerUrl() throws ParsingException;
+}
diff --git a/app/src/main/java/org/schabi/newpipe/extractor/SearchEngine.java b/app/src/main/java/org/schabi/newpipe/extractor/SearchEngine.java
index a9c01fc22..3b700f129 100644
--- a/app/src/main/java/org/schabi/newpipe/extractor/SearchEngine.java
+++ b/app/src/main/java/org/schabi/newpipe/extractor/SearchEngine.java
@@ -33,7 +33,7 @@ public abstract class SearchEngine {
private StreamPreviewInfoSearchCollector collector;
- public SearchEngine(StreamUrlIdHandler urlIdHandler, int serviceId) {
+ public SearchEngine(UrlIdHandler urlIdHandler, int serviceId) {
collector = new StreamPreviewInfoSearchCollector(urlIdHandler, serviceId);
}
diff --git a/app/src/main/java/org/schabi/newpipe/extractor/StreamExtractor.java b/app/src/main/java/org/schabi/newpipe/extractor/StreamExtractor.java
index eddac4ce5..4b6e8df1c 100644
--- a/app/src/main/java/org/schabi/newpipe/extractor/StreamExtractor.java
+++ b/app/src/main/java/org/schabi/newpipe/extractor/StreamExtractor.java
@@ -30,7 +30,7 @@ public abstract class StreamExtractor {
private int serviceId;
private String url;
- private StreamUrlIdHandler urlIdHandler;
+ private UrlIdHandler urlIdHandler;
private Downloader downloader;
private StreamPreviewInfoCollector previewInfoCollector;
@@ -55,7 +55,7 @@ public abstract class StreamExtractor {
}
}
- public StreamExtractor(StreamUrlIdHandler urlIdHandler, String url, Downloader dl, int serviceId) {
+ public StreamExtractor(UrlIdHandler urlIdHandler, String url, Downloader dl, int serviceId) {
this.serviceId = serviceId;
this.urlIdHandler = urlIdHandler;
previewInfoCollector = new StreamPreviewInfoCollector(urlIdHandler, serviceId);
@@ -69,7 +69,7 @@ public abstract class StreamExtractor {
return url;
}
- public StreamUrlIdHandler getUrlIdHandler() {
+ public UrlIdHandler getUrlIdHandler() {
return urlIdHandler;
}
diff --git a/app/src/main/java/org/schabi/newpipe/extractor/StreamInfo.java b/app/src/main/java/org/schabi/newpipe/extractor/StreamInfo.java
index cd79e463f..815663c00 100644
--- a/app/src/main/java/org/schabi/newpipe/extractor/StreamInfo.java
+++ b/app/src/main/java/org/schabi/newpipe/extractor/StreamInfo.java
@@ -85,12 +85,12 @@ public class StreamInfo extends AbstractVideoInfo {
/* ---- importand data, withoug the video can't be displayed goes here: ---- */
// if one of these is not available an exception is ment to be thrown directly into the frontend.
- StreamUrlIdHandler uiconv = extractor.getUrlIdHandler();
+ UrlIdHandler uiconv = extractor.getUrlIdHandler();
streamInfo.service_id = extractor.getServiceId();
streamInfo.webpage_url = extractor.getPageUrl();
streamInfo.stream_type = extractor.getStreamType();
- streamInfo.id = uiconv.getVideoId(extractor.getPageUrl());
+ streamInfo.id = uiconv.getId(extractor.getPageUrl());
streamInfo.title = extractor.getTitle();
streamInfo.age_limit = extractor.getAgeLimit();
diff --git a/app/src/main/java/org/schabi/newpipe/extractor/StreamPreviewInfoCollector.java b/app/src/main/java/org/schabi/newpipe/extractor/StreamPreviewInfoCollector.java
index 013bbbc1d..6fbb24b38 100644
--- a/app/src/main/java/org/schabi/newpipe/extractor/StreamPreviewInfoCollector.java
+++ b/app/src/main/java/org/schabi/newpipe/extractor/StreamPreviewInfoCollector.java
@@ -28,10 +28,10 @@ import java.util.Vector;
public class StreamPreviewInfoCollector {
private List itemList = new Vector<>();
private List errors = new Vector<>();
- private StreamUrlIdHandler urlIdHandler;
+ private UrlIdHandler urlIdHandler;
private int serviceId = -1;
- public StreamPreviewInfoCollector(StreamUrlIdHandler handler, int serviceId) {
+ public StreamPreviewInfoCollector(UrlIdHandler handler, int serviceId) {
urlIdHandler = handler;
this.serviceId = serviceId;
}
@@ -57,7 +57,7 @@ public class StreamPreviewInfoCollector {
if (urlIdHandler == null) {
throw new ParsingException("Error: UrlIdHandler not set");
} else if(!resultItem.webpage_url.isEmpty()) {
- resultItem.id = (new YoutubeStreamUrlIdHandler()).getVideoId(resultItem.webpage_url);
+ resultItem.id = (new YoutubeStreamUrlIdHandler()).getId(resultItem.webpage_url);
}
resultItem.title = extractor.getTitle();
resultItem.stream_type = extractor.getStreamType();
diff --git a/app/src/main/java/org/schabi/newpipe/extractor/StreamPreviewInfoSearchCollector.java b/app/src/main/java/org/schabi/newpipe/extractor/StreamPreviewInfoSearchCollector.java
index e0f02f461..905543be0 100644
--- a/app/src/main/java/org/schabi/newpipe/extractor/StreamPreviewInfoSearchCollector.java
+++ b/app/src/main/java/org/schabi/newpipe/extractor/StreamPreviewInfoSearchCollector.java
@@ -24,7 +24,7 @@ public class StreamPreviewInfoSearchCollector extends StreamPreviewInfoCollector
private String suggestion = "";
- public StreamPreviewInfoSearchCollector(StreamUrlIdHandler handler, int serviceId) {
+ public StreamPreviewInfoSearchCollector(UrlIdHandler handler, int serviceId) {
super(handler, serviceId);
}
diff --git a/app/src/main/java/org/schabi/newpipe/extractor/StreamingService.java b/app/src/main/java/org/schabi/newpipe/extractor/StreamingService.java
index de9a4ebfe..d9acdefff 100644
--- a/app/src/main/java/org/schabi/newpipe/extractor/StreamingService.java
+++ b/app/src/main/java/org/schabi/newpipe/extractor/StreamingService.java
@@ -38,7 +38,10 @@ public abstract class StreamingService {
public abstract StreamExtractor getExtractorInstance(String url, Downloader downloader)
throws IOException, ExtractionException;
public abstract SearchEngine getSearchEngineInstance(Downloader downloader);
- public abstract StreamUrlIdHandler getUrlIdHandlerInstance();
+ public abstract UrlIdHandler getUrlIdHandlerInstance();
+ public abstract UrlIdHandler getChannelUrlIdHandlerInstance();
+ public abstract ChannelExtractor getChannelExtractorInstance(String url, Downloader downloader)
+ throws ExtractionException, IOException;
public final int getServiceId() {
return serviceId;
diff --git a/app/src/main/java/org/schabi/newpipe/extractor/StreamUrlIdHandler.java b/app/src/main/java/org/schabi/newpipe/extractor/UrlIdHandler.java
similarity index 82%
rename from app/src/main/java/org/schabi/newpipe/extractor/StreamUrlIdHandler.java
rename to app/src/main/java/org/schabi/newpipe/extractor/UrlIdHandler.java
index 4f91ac80e..f38f60658 100644
--- a/app/src/main/java/org/schabi/newpipe/extractor/StreamUrlIdHandler.java
+++ b/app/src/main/java/org/schabi/newpipe/extractor/UrlIdHandler.java
@@ -1,10 +1,10 @@
package org.schabi.newpipe.extractor;
/**
- * Created by Christian Schabesberger on 02.02.16.
+ * Created by Christian Schabesberger on 26.07.16.
*
* Copyright (C) Christian Schabesberger 2016
- * StreamUrlIdHandler.java is part of NewPipe.
+ * UrlIdHandler.java is part of NewPipe.
*
* NewPipe is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -20,9 +20,9 @@ package org.schabi.newpipe.extractor;
* along with NewPipe. If not, see .
*/
-public interface StreamUrlIdHandler {
- String getVideoUrl(String videoId);
- String getVideoId(String siteUrl) throws ParsingException;
+public interface UrlIdHandler {
+ String getUrl(String videoId);
+ String getId(String siteUrl) throws ParsingException;
String cleanUrl(String siteUrl) throws ParsingException;
/**When a VIEW_ACTION is caught this function will test if the url delivered within the calling
diff --git a/app/src/main/java/org/schabi/newpipe/extractor/services/youtube/YoutubeChannelExtractor.java b/app/src/main/java/org/schabi/newpipe/extractor/services/youtube/YoutubeChannelExtractor.java
new file mode 100644
index 000000000..c30384711
--- /dev/null
+++ b/app/src/main/java/org/schabi/newpipe/extractor/services/youtube/YoutubeChannelExtractor.java
@@ -0,0 +1,75 @@
+package org.schabi.newpipe.extractor.services.youtube;
+
+import android.util.Log;
+
+import org.jsoup.Jsoup;
+import org.jsoup.nodes.Document;
+import org.schabi.newpipe.extractor.ChannelExtractor;
+import org.schabi.newpipe.extractor.Downloader;
+import org.schabi.newpipe.extractor.ExtractionException;
+import org.schabi.newpipe.extractor.ParsingException;
+import org.schabi.newpipe.extractor.UrlIdHandler;
+
+import java.io.IOException;
+
+/**
+ * Created by Christian Schabesberger on 25.07.16.
+ *
+ * Copyright (C) Christian Schabesberger 2016
+ * YoutubeChannelExtractor.java is part of NewPipe.
+ *
+ * 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.
+ *
+ * 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.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with NewPipe. If not, see .
+ */
+
+public class YoutubeChannelExtractor extends ChannelExtractor {
+
+ private static final String TAG = YoutubeChannelExtractor.class.toString();
+
+ private Downloader downloader;
+ private final Document doc;
+ private final String siteUrl;
+
+
+ public YoutubeChannelExtractor(UrlIdHandler urlIdHandler, String url, Downloader dl, int serviceId)
+ throws ExtractionException, IOException {
+ super(urlIdHandler, url, dl, serviceId);
+
+ siteUrl = url;
+ downloader = dl;
+ String pageContent = downloader.download(url);
+ doc = Jsoup.parse(pageContent, url);
+
+ Log.d(TAG, pageContent);
+ }
+
+ @Override
+ public String getChannelName() throws ParsingException {
+ return getUrlIdHandler().getId(siteUrl);
+ }
+
+ @Override
+ public String getAvatarUrl() throws ParsingException {
+ try {
+ return doc.select("img[class=\"channel-header-profile-image\"]")
+ .first().attr("abs:src");
+ } catch(Exception e) {
+ throw new ParsingException("Could not get avatar", e);
+ }
+ }
+
+ @Override
+ public String getBannerUrl() throws ParsingException {
+ return "https://yt3.ggpht.com/-oF0YbeAGkaA/VBgrKvEGY1I/AAAAAAAACdw/nx02iZSseFw/w2120-fcrop64=1,00005a57ffffa5a8-nd-c0xffffffff-rj-k-no/Channel-Art-Template-%2528Photoshop%2529.png";
+ }
+}
diff --git a/app/src/main/java/org/schabi/newpipe/extractor/services/youtube/YoutubeChannelUrlIdHandler.java b/app/src/main/java/org/schabi/newpipe/extractor/services/youtube/YoutubeChannelUrlIdHandler.java
new file mode 100644
index 000000000..fc3a65118
--- /dev/null
+++ b/app/src/main/java/org/schabi/newpipe/extractor/services/youtube/YoutubeChannelUrlIdHandler.java
@@ -0,0 +1,50 @@
+package org.schabi.newpipe.extractor.services.youtube;
+
+import org.schabi.newpipe.extractor.Parser;
+import org.schabi.newpipe.extractor.ParsingException;
+import org.schabi.newpipe.extractor.UrlIdHandler;
+
+/**
+ * Created by Christian Schabesberger on 25.07.16.
+ *
+ * Copyright (C) Christian Schabesberger 2016
+ * YoutubeChannelUrlIdHandler.java is part of NewPipe.
+ *
+ * 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.
+ *
+ * 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.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with NewPipe. If not, see .
+ */
+
+public class YoutubeChannelUrlIdHandler implements UrlIdHandler {
+
+ public String getUrl(String channelId) {
+ return "https://www.youtube.com/user/" + channelId + "/videos";
+ }
+
+ public String getId(String siteUrl) throws ParsingException {
+ try {
+ return Parser.matchGroup1("/user/(.*)", siteUrl);
+ } catch(Exception e) {
+ throw new ParsingException("Could not get channel/user id", e);
+ }
+ }
+
+ public String cleanUrl(String siteUrl) throws ParsingException {
+ return getUrl(getId(siteUrl));
+ }
+
+ public boolean acceptUrl(String videoUrl) {
+ return (videoUrl.contains("youtube") ||
+ videoUrl.contains("youtu.be")) &&
+ videoUrl.contains("/user/");
+ }
+}
diff --git a/app/src/main/java/org/schabi/newpipe/extractor/services/youtube/YoutubeSearchEngine.java b/app/src/main/java/org/schabi/newpipe/extractor/services/youtube/YoutubeSearchEngine.java
index 249814248..547635097 100644
--- a/app/src/main/java/org/schabi/newpipe/extractor/services/youtube/YoutubeSearchEngine.java
+++ b/app/src/main/java/org/schabi/newpipe/extractor/services/youtube/YoutubeSearchEngine.java
@@ -14,7 +14,7 @@ import org.schabi.newpipe.extractor.SearchEngine;
import org.schabi.newpipe.extractor.StreamPreviewInfoCollector;
import org.schabi.newpipe.extractor.StreamPreviewInfoExtractor;
import org.schabi.newpipe.extractor.StreamPreviewInfoSearchCollector;
-import org.schabi.newpipe.extractor.StreamUrlIdHandler;
+import org.schabi.newpipe.extractor.UrlIdHandler;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.xml.sax.InputSource;
@@ -55,7 +55,7 @@ public class YoutubeSearchEngine extends SearchEngine {
private static final String TAG = YoutubeSearchEngine.class.toString();
public static final String CHARSET_UTF_8 = "UTF-8";
- public YoutubeSearchEngine(StreamUrlIdHandler urlIdHandler, int serviceId) {
+ public YoutubeSearchEngine(UrlIdHandler urlIdHandler, int serviceId) {
super(urlIdHandler, serviceId);
}
diff --git a/app/src/main/java/org/schabi/newpipe/extractor/services/youtube/YoutubeService.java b/app/src/main/java/org/schabi/newpipe/extractor/services/youtube/YoutubeService.java
index f2d56bcab..812b74771 100644
--- a/app/src/main/java/org/schabi/newpipe/extractor/services/youtube/YoutubeService.java
+++ b/app/src/main/java/org/schabi/newpipe/extractor/services/youtube/YoutubeService.java
@@ -1,10 +1,11 @@
package org.schabi.newpipe.extractor.services.youtube;
+import org.schabi.newpipe.extractor.ChannelExtractor;
import org.schabi.newpipe.extractor.ExtractionException;
import org.schabi.newpipe.extractor.Downloader;
import org.schabi.newpipe.extractor.StreamExtractor;
import org.schabi.newpipe.extractor.StreamingService;
-import org.schabi.newpipe.extractor.StreamUrlIdHandler;
+import org.schabi.newpipe.extractor.UrlIdHandler;
import org.schabi.newpipe.extractor.SearchEngine;
import java.io.IOException;
@@ -45,7 +46,7 @@ public class YoutubeService extends StreamingService {
@Override
public StreamExtractor getExtractorInstance(String url, Downloader downloader)
throws ExtractionException, IOException {
- StreamUrlIdHandler urlIdHandler = new YoutubeStreamUrlIdHandler();
+ UrlIdHandler urlIdHandler = new YoutubeStreamUrlIdHandler();
if(urlIdHandler.acceptUrl(url)) {
return new YoutubeStreamExtractor(urlIdHandler, url, downloader, getServiceId());
}
@@ -59,7 +60,18 @@ public class YoutubeService extends StreamingService {
}
@Override
- public StreamUrlIdHandler getUrlIdHandlerInstance() {
+ public UrlIdHandler getUrlIdHandlerInstance() {
return new YoutubeStreamUrlIdHandler();
}
+
+ @Override
+ public UrlIdHandler getChannelUrlIdHandlerInstance() {
+ return new YoutubeChannelUrlIdHandler();
+ }
+
+ @Override
+ public ChannelExtractor getChannelExtractorInstance(String url, Downloader downloader)
+ throws ExtractionException, IOException {
+ return new YoutubeChannelExtractor(getChannelUrlIdHandlerInstance(), url, downloader, getServiceId());
+ }
}
diff --git a/app/src/main/java/org/schabi/newpipe/extractor/services/youtube/YoutubeStreamExtractor.java b/app/src/main/java/org/schabi/newpipe/extractor/services/youtube/YoutubeStreamExtractor.java
index afdaff3a9..b5e25acf5 100644
--- a/app/src/main/java/org/schabi/newpipe/extractor/services/youtube/YoutubeStreamExtractor.java
+++ b/app/src/main/java/org/schabi/newpipe/extractor/services/youtube/YoutubeStreamExtractor.java
@@ -15,10 +15,9 @@ import org.schabi.newpipe.extractor.Downloader;
import org.schabi.newpipe.extractor.Parser;
import org.schabi.newpipe.extractor.ParsingException;
import org.schabi.newpipe.extractor.StreamInfo;
-import org.schabi.newpipe.extractor.StreamPreviewInfo;
import org.schabi.newpipe.extractor.StreamPreviewInfoCollector;
import org.schabi.newpipe.extractor.StreamPreviewInfoExtractor;
-import org.schabi.newpipe.extractor.StreamUrlIdHandler;
+import org.schabi.newpipe.extractor.UrlIdHandler;
import org.schabi.newpipe.extractor.StreamExtractor;
import org.schabi.newpipe.extractor.MediaFormat;
import org.schabi.newpipe.extractor.VideoStream;
@@ -183,12 +182,12 @@ public class YoutubeStreamExtractor extends StreamExtractor {
// cached values
private static volatile String decryptionCode = "";
- StreamUrlIdHandler urlidhandler = new YoutubeStreamUrlIdHandler();
+ UrlIdHandler urlidhandler = new YoutubeStreamUrlIdHandler();
String pageUrl = "";
private Downloader downloader;
- public YoutubeStreamExtractor(StreamUrlIdHandler urlIdHandler, String pageUrl,
+ public YoutubeStreamExtractor(UrlIdHandler urlIdHandler, String pageUrl,
Downloader dl, int serviceId)
throws ExtractionException, IOException {
super(urlIdHandler ,pageUrl, dl, serviceId);
@@ -203,7 +202,7 @@ public class YoutubeStreamExtractor extends StreamExtractor {
// Check if the video is age restricted
if (pageContent.contains(".
*/
-public class YoutubeStreamUrlIdHandler implements StreamUrlIdHandler {
+public class YoutubeStreamUrlIdHandler implements UrlIdHandler {
@SuppressWarnings("WeakerAccess")
@Override
- public String getVideoUrl(String videoId) {
+ public String getUrl(String videoId) {
return "https://www.youtube.com/watch?v=" + videoId;
}
@SuppressWarnings("WeakerAccess")
@Override
- public String getVideoId(String url) throws ParsingException, IllegalArgumentException {
+ public String getId(String url) throws ParsingException, IllegalArgumentException {
if(url.isEmpty())
{
throw new IllegalArgumentException("The url parameter should not be empty");
@@ -81,7 +81,7 @@ public class YoutubeStreamUrlIdHandler implements StreamUrlIdHandler {
}
public String cleanUrl(String complexUrl) throws ParsingException {
- return getVideoUrl(getVideoId(complexUrl));
+ return getUrl(getId(complexUrl));
}
@Override
diff --git a/app/src/main/res/layout-v18/fragment_videoitem_detail.xml b/app/src/main/res/layout-v18/fragment_videoitem_detail.xml
index 8473c098c..78f52961d 100644
--- a/app/src/main/res/layout-v18/fragment_videoitem_detail.xml
+++ b/app/src/main/res/layout-v18/fragment_videoitem_detail.xml
@@ -179,55 +179,70 @@
android:text="100" />
-
-
-
+
-
-
-
-
+ android:id="@+id/detailUploaderLayout"
+ android:layout_marginTop="12dp">
-
+
+
+
+
+
+
+
+
+
-
+ android:layout_height="match_parent"
+ android:background="?attr/selectableItemBackground"/>
+
+
+
diff --git a/app/src/main/res/layout/activity_channel.xml b/app/src/main/res/layout/activity_channel.xml
new file mode 100644
index 000000000..110b64a21
--- /dev/null
+++ b/app/src/main/res/layout/activity_channel.xml
@@ -0,0 +1,46 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/app/src/main/res/layout/content_channel.xml b/app/src/main/res/layout/content_channel.xml
new file mode 100644
index 000000000..79a41a628
--- /dev/null
+++ b/app/src/main/res/layout/content_channel.xml
@@ -0,0 +1,17 @@
+
+
+
+
+
+
diff --git a/app/src/main/res/menu/menu_channel.xml b/app/src/main/res/menu/menu_channel.xml
new file mode 100644
index 000000000..e296e17ad
--- /dev/null
+++ b/app/src/main/res/menu/menu_channel.xml
@@ -0,0 +1,10 @@
+
diff --git a/app/src/main/res/values-v21/styles.xml b/app/src/main/res/values-v21/styles.xml
index 2a278569f..ab385422f 100644
--- a/app/src/main/res/values-v21/styles.xml
+++ b/app/src/main/res/values-v21/styles.xml
@@ -10,7 +10,7 @@
@color/light_background_color
-
-
+
+
\ No newline at end of file
diff --git a/app/src/main/res/values/dimens.xml b/app/src/main/res/values/dimens.xml
index afb085f6d..0c648debb 100644
--- a/app/src/main/res/values/dimens.xml
+++ b/app/src/main/res/values/dimens.xml
@@ -37,5 +37,8 @@
16dp16dp
+ 180dp
+ 16dp
+ 16dp
diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml
index 14fbd56fa..4db613260 100644
--- a/app/src/main/res/values/strings.xml
+++ b/app/src/main/res/values/strings.xml
@@ -125,7 +125,7 @@
Cannot create download directory \'%1$s\'Created download directory \'%1$s\'
- Play in background
+ Play in backgroundVideoAudioText
@@ -176,6 +176,97 @@
MD5SHA1
+ ChannelActivity
+
+ "Material is the metaphor.\n\n"
+
+ "A material metaphor is the unifying theory of a rationalized space and a system of motion."
+ "The material is grounded in tactile reality, inspired by the study of paper and ink, yet "
+ "technologically advanced and open to imagination and magic.\n"
+ "Surfaces and edges of the material provide visual cues that are grounded in reality. The "
+ "use of familiar tactile attributes helps users quickly understand affordances. Yet the "
+ "flexibility of the material creates new affordances that supercede those in the physical "
+ "world, without breaking the rules of physics.\n"
+ "The fundamentals of light, surface, and movement are key to conveying how objects move, "
+ "interact, and exist in space and in relation to each other. Realistic lighting shows "
+ "seams, divides space, and indicates moving parts.\n\n"
+
+ "Bold, graphic, intentional.\n\n"
+
+ "The foundational elements of print based design typography, grids, space, scale, color, "
+ "and use of imagery guide visual treatments. These elements do far more than please the "
+ "eye. They create hierarchy, meaning, and focus. Deliberate color choices, edge to edge "
+ "imagery, large scale typography, and intentional white space create a bold and graphic "
+ "interface that immerse the user in the experience.\n"
+ "An emphasis on user actions makes core functionality immediately apparent and provides "
+ "waypoints for the user.\n\n"
+
+ "Motion provides meaning.\n\n"
+
+ "Motion respects and reinforces the user as the prime mover. Primary user actions are "
+ "inflection points that initiate motion, transforming the whole design.\n"
+ "All action takes place in a single environment. Objects are presented to the user without "
+ "breaking the continuity of experience even as they transform and reorganize.\n"
+ "Motion is meaningful and appropriate, serving to focus attention and maintain continuity. "
+ "Feedback is subtle yet clear. Transitions are efficient yet coherent.\n\n"
+
+ "3D world.\n\n"
+
+ "The material environment is a 3D space, which means all objects have x, y, and z "
+ "dimensions. The z-axis is perpendicularly aligned to the plane of the display, with the "
+ "positive z-axis extending towards the viewer. Every sheet of material occupies a single "
+ "position along the z-axis and has a standard 1dp thickness.\n"
+ "On the web, the z-axis is used for layering and not for perspective. The 3D world is "
+ "emulated by manipulating the y-axis.\n\n"
+
+ "Light and shadow.\n\n"
+
+ "Within the material environment, virtual lights illuminate the scene. Key lights create "
+ "directional shadows, while ambient light creates soft shadows from all angles.\n"
+ "Shadows in the material environment are cast by these two light sources. In Android "
+ "development, shadows occur when light sources are blocked by sheets of material at "
+ "various positions along the z-axis. On the web, shadows are depicted by manipulating the "
+ "y-axis only. The following example shows the card with a height of 6dp.\n\n"
+
+ "Resting elevation.\n\n"
+
+ "All material objects, regardless of size, have a resting elevation, or default elevation "
+ "that does not change. If an object changes elevation, it should return to its resting "
+ "elevation as soon as possible.\n\n"
+
+ "Component elevations.\n\n"
+
+ "The resting elevation for a component type is consistent across apps (e.g., FAB elevation "
+ "does not vary from 6dp in one app to 16dp in another app).\n"
+ "Components may have different resting elevations across platforms, depending on the depth "
+ "of the environment (e.g., TV has a greater depth than mobile or desktop).\n\n"
+
+ "Responsive elevation and dynamic elevation offsets.\n\n"
+
+ "Some component types have responsive elevation, meaning they change elevation in response "
+ "to user input (e.g., normal, focused, and pressed) or system events. These elevation "
+ "changes are consistently implemented using dynamic elevation offsets.\n"
+ "Dynamic elevation offsets are the goal elevation that a component moves towards, relative "
+ "to the component’s resting state. They ensure that elevation changes are consistent "
+ "across actions and component types. For example, all components that lift on press have "
+ "the same elevation change relative to their resting elevation.\n"
+ "Once the input event is completed or cancelled, the component will return to its resting "
+ "elevation.\n\n"
+
+ "Avoiding elevation interference.\n\n"
+
+ "Components with responsive elevations may encounter other components as they move between "
+ "their resting elevations and dynamic elevation offsets. Because material cannot pass "
+ "through other material, components avoid interfering with one another any number of ways, "
+ "whether on a per component basis or using the entire app layout.\n"
+ "On a component level, components can move or be removed before they cause interference. "
+ "For example, a floating action button (FAB) can disappear or move off screen before a "
+ "user picks up a card, or it can move if a snackbar appears.\n"
+ "On the layout level, design your app layout to minimize opportunities for interference. "
+ "For example, position the FAB to one side of stream of a cards so the FAB won’t interfere "
+ "when a user tries to pick up one of cards.\n\n"
+
+ Settings
diff --git a/app/src/main/res/values/styles.xml b/app/src/main/res/values/styles.xml
index 1c8dca48f..d690d72bf 100644
--- a/app/src/main/res/values/styles.xml
+++ b/app/src/main/res/values/styles.xml
@@ -1,18 +1,17 @@
-
+
-
+
-
+
-
-
+
+
+
+
+
+