mirror of
https://github.com/TeamNewPipe/NewPipe.git
synced 2024-11-23 03:22:37 +01:00
Merge remote-tracking branch 'origin/master'
This commit is contained in:
commit
d3bb8b7651
10
README.md
10
README.md
@ -37,23 +37,27 @@ NewPipe does not use any Google framework libraries, or the YouTube API. It only
|
||||
* Listen to YouTube videos (experimental)
|
||||
* Select the streaming player to watch the video with
|
||||
* Download videos
|
||||
* Download audio only * Open a video in Kodi
|
||||
* Download audio only
|
||||
* Open a video in Kodi
|
||||
* Show Next/Related videos
|
||||
* Search YouTube in a specific language
|
||||
* Watch age restricted material
|
||||
* Display general information about channels
|
||||
* Search channels
|
||||
* Watch videos from a channel
|
||||
* Orbot/Tor support (not yet directly)
|
||||
|
||||
### Coming Features
|
||||
|
||||
* Orbot/Tor support
|
||||
* Bookmarks
|
||||
* View history
|
||||
* Search history
|
||||
* Subscribe to channels
|
||||
* Watch videos from a channel
|
||||
* Search/Watch Playlists
|
||||
* Queeing videos
|
||||
* Subtitles support
|
||||
* 1080p support
|
||||
* livestream support
|
||||
* ... and many more
|
||||
|
||||
### Multiservice support
|
||||
|
@ -8,8 +8,8 @@ android {
|
||||
applicationId "org.schabi.newpipe"
|
||||
minSdkVersion 15
|
||||
targetSdkVersion 25
|
||||
versionCode 26
|
||||
versionName "0.8.12"
|
||||
versionCode 27
|
||||
versionName "0.9.0"
|
||||
}
|
||||
buildTypes {
|
||||
release {
|
||||
|
@ -19,7 +19,7 @@ import android.widget.Toast;
|
||||
|
||||
import com.nostra13.universalimageloader.core.ImageLoader;
|
||||
|
||||
import org.schabi.newpipe.detail.VideoItemDetailFragment;
|
||||
import org.schabi.newpipe.detail.VideoItemDetailActivity;
|
||||
import org.schabi.newpipe.extractor.NewPipe;
|
||||
import org.schabi.newpipe.extractor.StreamingService;
|
||||
import org.schabi.newpipe.extractor.channel.ChannelExtractor;
|
||||
@ -31,10 +31,12 @@ import org.schabi.newpipe.info_list.InfoListAdapter;
|
||||
import org.schabi.newpipe.report.ErrorActivity;
|
||||
import org.schabi.newpipe.settings.SettingsActivity;
|
||||
import org.schabi.newpipe.util.NavStack;
|
||||
import java.io.IOException;
|
||||
import static android.os.Build.VERSION.SDK_INT;
|
||||
import org.schabi.newpipe.util.ThemeHelper;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import static android.os.Build.VERSION.SDK_INT;
|
||||
|
||||
|
||||
/**
|
||||
* Copyright (C) Christian Schabesberger 2016 <chris.schabesberger@mailbox.org>
|
||||
@ -299,7 +301,7 @@ public class ChannelActivity extends AppCompatActivity {
|
||||
postNewErrorToast(h, R.string.network_error);
|
||||
ioe.printStackTrace();
|
||||
} catch(ParsingException pe) {
|
||||
ErrorActivity.reportError(h, ChannelActivity.this, pe, VideoItemDetailFragment.class, null,
|
||||
ErrorActivity.reportError(h, ChannelActivity.this, pe, VideoItemDetailActivity.class, null,
|
||||
ErrorActivity.ErrorInfo.make(ErrorActivity.REQUESTED_CHANNEL,
|
||||
service.getServiceInfo().name, channelUrl, R.string.parsing_error));
|
||||
h.post(new Runnable() {
|
||||
@ -314,7 +316,7 @@ public class ChannelActivity extends AppCompatActivity {
|
||||
if(service != null) {
|
||||
name = service.getServiceInfo().name;
|
||||
}
|
||||
ErrorActivity.reportError(h, ChannelActivity.this, ex, VideoItemDetailFragment.class, null,
|
||||
ErrorActivity.reportError(h, ChannelActivity.this, ex, VideoItemDetailActivity.class, null,
|
||||
ErrorActivity.ErrorInfo.make(ErrorActivity.REQUESTED_CHANNEL,
|
||||
name, channelUrl, R.string.parsing_error));
|
||||
h.post(new Runnable() {
|
||||
@ -325,7 +327,7 @@ public class ChannelActivity extends AppCompatActivity {
|
||||
});
|
||||
ex.printStackTrace();
|
||||
} catch(Exception e) {
|
||||
ErrorActivity.reportError(h, ChannelActivity.this, e, VideoItemDetailFragment.class, null,
|
||||
ErrorActivity.reportError(h, ChannelActivity.this, e, VideoItemDetailActivity.class, null,
|
||||
ErrorActivity.ErrorInfo.make(ErrorActivity.REQUESTED_CHANNEL,
|
||||
service.getServiceInfo().name, channelUrl, R.string.general_error));
|
||||
h.post(new Runnable() {
|
||||
|
@ -2,14 +2,12 @@ package org.schabi.newpipe;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.content.Intent;
|
||||
import android.preference.PreferenceManager;
|
||||
import android.support.v7.app.AppCompatActivity;
|
||||
import android.os.Bundle;
|
||||
import android.preference.PreferenceManager;
|
||||
import android.util.Log;
|
||||
import android.widget.Toast;
|
||||
|
||||
import org.schabi.newpipe.detail.VideoItemDetailActivity;
|
||||
import org.schabi.newpipe.detail.VideoItemDetailFragment;
|
||||
import org.schabi.newpipe.extractor.NewPipe;
|
||||
import org.schabi.newpipe.extractor.StreamingService;
|
||||
import org.schabi.newpipe.util.NavStack;
|
||||
@ -136,7 +134,7 @@ public class RouterActivity extends Activity {
|
||||
break;
|
||||
case STREAM:
|
||||
callIntent.setClass(this, VideoItemDetailActivity.class);
|
||||
callIntent.putExtra(VideoItemDetailFragment.AUTO_PLAY,
|
||||
callIntent.putExtra(VideoItemDetailActivity.AUTO_PLAY,
|
||||
PreferenceManager.getDefaultSharedPreferences(this)
|
||||
.getBoolean(
|
||||
getString(R.string.autoplay_through_intent_key), false));
|
||||
|
@ -0,0 +1,250 @@
|
||||
package org.schabi.newpipe.detail;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.os.Handler;
|
||||
import android.util.Log;
|
||||
import android.view.View;
|
||||
|
||||
import org.schabi.newpipe.R;
|
||||
import org.schabi.newpipe.extractor.NewPipe;
|
||||
import org.schabi.newpipe.extractor.StreamingService;
|
||||
import org.schabi.newpipe.extractor.exceptions.ParsingException;
|
||||
import org.schabi.newpipe.extractor.exceptions.ReCaptchaException;
|
||||
import org.schabi.newpipe.extractor.services.youtube.YoutubeStreamExtractor;
|
||||
import org.schabi.newpipe.extractor.stream_info.StreamExtractor;
|
||||
import org.schabi.newpipe.extractor.stream_info.StreamInfo;
|
||||
import org.schabi.newpipe.report.ErrorActivity;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.concurrent.atomic.AtomicBoolean;
|
||||
|
||||
/**
|
||||
* Extract {@link StreamInfo} with {@link StreamExtractor} from the given url of the given service
|
||||
*/
|
||||
@SuppressWarnings("WeakerAccess")
|
||||
public class StreamExtractorWorker extends Thread {
|
||||
private static final String TAG = "StreamExtractorWorker";
|
||||
|
||||
private Activity activity;
|
||||
private final String videoUrl;
|
||||
private final int serviceId;
|
||||
private OnStreamInfoReceivedListener callback;
|
||||
|
||||
private final AtomicBoolean isRunning = new AtomicBoolean(false);
|
||||
private final Handler handler = new Handler();
|
||||
|
||||
|
||||
public interface OnStreamInfoReceivedListener {
|
||||
void onReceive(StreamInfo info);
|
||||
void onError(int messageId);
|
||||
void onReCaptchaException();
|
||||
void onBlockedByGemaError();
|
||||
void onContentErrorWithMessage(int messageId);
|
||||
void onContentError();
|
||||
}
|
||||
|
||||
public StreamExtractorWorker(Activity activity, String videoUrl, int serviceId, OnStreamInfoReceivedListener callback) {
|
||||
this.serviceId = serviceId;
|
||||
this.videoUrl = videoUrl;
|
||||
this.activity = activity;
|
||||
this.callback = callback;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a new instance <b>already</b> started of {@link StreamExtractorWorker}.<br>
|
||||
* The caller is responsible to check if {@link StreamExtractorWorker#isRunning()}, or {@link StreamExtractorWorker#cancel()} it
|
||||
*
|
||||
* @param serviceId id of the request service
|
||||
* @param url videoUrl of the service (e.g. https://www.youtube.com/watch?v=HyHNuVaZJ-k)
|
||||
* @param activity activity for error reporting purposes
|
||||
* @param callback listener that will be called-back when events occur (check {@link OnStreamInfoReceivedListener})
|
||||
* @return new instance already started of {@link StreamExtractorWorker}
|
||||
*/
|
||||
public static StreamExtractorWorker startExtractorThread(int serviceId, String url, Activity activity, OnStreamInfoReceivedListener callback) {
|
||||
StreamExtractorWorker extractorThread = getExtractorThread(serviceId, url, activity, callback);
|
||||
extractorThread.start();
|
||||
return extractorThread;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a new instance of {@link StreamExtractorWorker}.<br>
|
||||
* The caller is responsible to check if {@link StreamExtractorWorker#isRunning()}, or {@link StreamExtractorWorker#cancel()}
|
||||
* when it doesn't need it anymore
|
||||
* <p>
|
||||
* <b>Note:</b> this instance is <b>not</b> started yet
|
||||
*
|
||||
* @param serviceId id of the request service
|
||||
* @param url videoUrl of the service (e.g. https://www.youtube.com/watch?v=HyHNuVaZJ-k)
|
||||
* @param activity activity for error reporting purposes
|
||||
* @param callback listener that will be called-back when events occur (check {@link OnStreamInfoReceivedListener})
|
||||
* @return instance of {@link StreamExtractorWorker}
|
||||
*/
|
||||
public static StreamExtractorWorker getExtractorThread(int serviceId, String url, Activity activity, OnStreamInfoReceivedListener callback) {
|
||||
return new StreamExtractorWorker(activity, url, serviceId, callback);
|
||||
}
|
||||
|
||||
@Override
|
||||
//Just ignore the errors for now
|
||||
@SuppressWarnings("ConstantConditions")
|
||||
public void run() {
|
||||
// TODO: Improve error checking
|
||||
// and this method in general
|
||||
|
||||
StreamInfo streamInfo = null;
|
||||
StreamingService service;
|
||||
try {
|
||||
service = NewPipe.getService(serviceId);
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
ErrorActivity.reportError(handler, activity, e, VideoItemDetailActivity.class, null,
|
||||
ErrorActivity.ErrorInfo.make(ErrorActivity.REQUESTED_STREAM,
|
||||
"", videoUrl, R.string.could_not_get_stream));
|
||||
return;
|
||||
}
|
||||
try {
|
||||
isRunning.set(true);
|
||||
StreamExtractor streamExtractor = service.getExtractorInstance(videoUrl);
|
||||
streamInfo = StreamInfo.getVideoInfo(streamExtractor);
|
||||
|
||||
final StreamInfo info = streamInfo;
|
||||
if (callback != null) handler.post(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
callback.onReceive(info);
|
||||
}
|
||||
});
|
||||
isRunning.set(false);
|
||||
// look for errors during extraction
|
||||
// this if statement only covers extra information.
|
||||
// if these are not available or caused an error, they are just not available
|
||||
// but don't render the stream information unusalbe.
|
||||
if (streamInfo != null && !streamInfo.errors.isEmpty()) {
|
||||
Log.e(TAG, "OCCURRED ERRORS DURING EXTRACTION:");
|
||||
for (Throwable e : streamInfo.errors) {
|
||||
e.printStackTrace();
|
||||
Log.e(TAG, "------");
|
||||
}
|
||||
|
||||
View rootView = activity != null ? activity.findViewById(R.id.video_item_detail) : null;
|
||||
ErrorActivity.reportError(handler, activity,
|
||||
streamInfo.errors, null, rootView,
|
||||
ErrorActivity.ErrorInfo.make(ErrorActivity.REQUESTED_STREAM,
|
||||
service.getServiceInfo().name, videoUrl, 0 /* no message for the user */));
|
||||
}
|
||||
|
||||
// These errors render the stream information unusable.
|
||||
} catch (ReCaptchaException e) {
|
||||
if (callback != null) handler.post(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
callback.onReCaptchaException();
|
||||
}
|
||||
});
|
||||
} catch (IOException e) {
|
||||
if (callback != null) handler.post(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
callback.onError(R.string.network_error);
|
||||
}
|
||||
});
|
||||
if (callback != null) e.printStackTrace();
|
||||
} catch (YoutubeStreamExtractor.DecryptException de) {
|
||||
// custom service related exceptions
|
||||
ErrorActivity.reportError(handler, activity, de, VideoItemDetailActivity.class, null,
|
||||
ErrorActivity.ErrorInfo.make(ErrorActivity.REQUESTED_STREAM,
|
||||
service.getServiceInfo().name, videoUrl, R.string.youtube_signature_decryption_error));
|
||||
handler.post(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
activity.finish();
|
||||
}
|
||||
});
|
||||
de.printStackTrace();
|
||||
} catch (YoutubeStreamExtractor.GemaException ge) {
|
||||
if (callback != null) handler.post(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
callback.onBlockedByGemaError();
|
||||
}
|
||||
});
|
||||
} catch (YoutubeStreamExtractor.LiveStreamException e) {
|
||||
if (callback != null) handler.post(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
callback.onContentErrorWithMessage(R.string.live_streams_not_supported);
|
||||
}
|
||||
});
|
||||
}
|
||||
// ----------------------------------------
|
||||
catch (StreamExtractor.ContentNotAvailableException e) {
|
||||
if (callback != null) handler.post(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
callback.onContentError();
|
||||
}
|
||||
});
|
||||
e.printStackTrace();
|
||||
} catch (StreamInfo.StreamExctractException e) {
|
||||
if (!streamInfo.errors.isEmpty()) {
|
||||
// !!! if this case ever kicks in someone gets kicked out !!!
|
||||
ErrorActivity.reportError(handler, activity, e, VideoItemDetailActivity.class, null,
|
||||
ErrorActivity.ErrorInfo.make(ErrorActivity.REQUESTED_STREAM,
|
||||
service.getServiceInfo().name, videoUrl, R.string.could_not_get_stream));
|
||||
} else {
|
||||
ErrorActivity.reportError(handler, activity, streamInfo.errors, VideoItemDetailActivity.class, null,
|
||||
ErrorActivity.ErrorInfo.make(ErrorActivity.REQUESTED_STREAM,
|
||||
service.getServiceInfo().name, videoUrl, R.string.could_not_get_stream));
|
||||
}
|
||||
handler.post(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
activity.finish();
|
||||
}
|
||||
});
|
||||
e.printStackTrace();
|
||||
} catch (ParsingException e) {
|
||||
ErrorActivity.reportError(handler, activity, e, VideoItemDetailActivity.class, null,
|
||||
ErrorActivity.ErrorInfo.make(ErrorActivity.REQUESTED_STREAM,
|
||||
service.getServiceInfo().name, videoUrl, R.string.parsing_error));
|
||||
handler.post(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
activity.finish();
|
||||
}
|
||||
});
|
||||
e.printStackTrace();
|
||||
} catch (Exception e) {
|
||||
ErrorActivity.reportError(handler, activity, e, VideoItemDetailActivity.class, null,
|
||||
ErrorActivity.ErrorInfo.make(ErrorActivity.REQUESTED_STREAM,
|
||||
service.getServiceInfo().name, videoUrl, R.string.general_error));
|
||||
handler.post(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
activity.finish();
|
||||
}
|
||||
});
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Return true if the extraction is not completed yet
|
||||
*
|
||||
* @return the value of the AtomicBoolean {@link #isRunning}
|
||||
*/
|
||||
public boolean isRunning() {
|
||||
return isRunning.get();
|
||||
}
|
||||
|
||||
/**
|
||||
* Cancel this ExtractorThread, setting the callback to null, the AtomicBoolean {@link #isRunning} to false and interrupt this thread.
|
||||
* <p>
|
||||
* <b>Note:</b> Any I/O that is active in the moment that this method is called will be canceled and a Exception will be thrown, because of the {@link #interrupt()}.<br>
|
||||
* This is useful when you don't want the resulting {@link StreamInfo} anymore, but don't want to waste bandwidth, otherwise it'd run till it receives the StreamInfo.
|
||||
*/
|
||||
public void cancel() {
|
||||
this.callback = null;
|
||||
this.isRunning.set(false);
|
||||
this.interrupt();
|
||||
}
|
||||
}
|
@ -1,230 +0,0 @@
|
||||
package org.schabi.newpipe.detail;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.os.Handler;
|
||||
import android.util.Log;
|
||||
import android.view.View;
|
||||
|
||||
import org.schabi.newpipe.extractor.exceptions.ParsingException;
|
||||
import org.schabi.newpipe.extractor.exceptions.ReCaptchaException;
|
||||
import org.schabi.newpipe.extractor.stream_info.StreamExtractor;
|
||||
import org.schabi.newpipe.extractor.stream_info.StreamInfo;
|
||||
import org.schabi.newpipe.report.ErrorActivity;
|
||||
import org.schabi.newpipe.R;
|
||||
import org.schabi.newpipe.extractor.NewPipe;
|
||||
import org.schabi.newpipe.extractor.StreamingService;
|
||||
import org.schabi.newpipe.extractor.services.youtube.YoutubeStreamExtractor;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
/**
|
||||
* Created by Christian Schabesberger on 02.08.16.
|
||||
*
|
||||
* Copyright (C) Christian Schabesberger 2016 <chris.schabesberger@mailbox.org>
|
||||
* StreamInfoWorker.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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
public class StreamInfoWorker {
|
||||
|
||||
private static final String TAG = StreamInfoWorker.class.toString();
|
||||
|
||||
public interface OnStreamInfoReceivedListener {
|
||||
void onReceive(StreamInfo info);
|
||||
void onError(int messageId);
|
||||
void onReCaptchaException();
|
||||
void onBlockedByGemaError();
|
||||
void onContentErrorWithMessage(int messageId);
|
||||
void onContentError();
|
||||
}
|
||||
|
||||
private class StreamExtractorRunnable implements Runnable {
|
||||
private final Handler h = new Handler();
|
||||
private StreamExtractor streamExtractor;
|
||||
private final int serviceId;
|
||||
private final String videoUrl;
|
||||
private Activity a;
|
||||
|
||||
public StreamExtractorRunnable(Activity a, String videoUrl, int serviceId) {
|
||||
this.serviceId = serviceId;
|
||||
this.videoUrl = videoUrl;
|
||||
this.a = a;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
StreamInfo streamInfo = null;
|
||||
StreamingService service = null;
|
||||
try {
|
||||
service = NewPipe.getService(serviceId);
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
ErrorActivity.reportError(h, a, e, VideoItemDetailFragment.class, null,
|
||||
ErrorActivity.ErrorInfo.make(ErrorActivity.REQUESTED_STREAM,
|
||||
"", videoUrl, R.string.could_not_get_stream));
|
||||
return;
|
||||
}
|
||||
try {
|
||||
streamExtractor = service.getExtractorInstance(videoUrl);
|
||||
streamInfo = StreamInfo.getVideoInfo(streamExtractor);
|
||||
|
||||
final StreamInfo info = streamInfo;
|
||||
h.post(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
onStreamInfoReceivedListener.onReceive(info);
|
||||
}
|
||||
});
|
||||
|
||||
// look for errors during extraction
|
||||
// this if statement only covers extra information.
|
||||
// if these are not available or caused an error, they are just not available
|
||||
// but don't render the stream information unusalbe.
|
||||
if(streamInfo != null &&
|
||||
!streamInfo.errors.isEmpty()) {
|
||||
Log.e(TAG, "OCCURRED ERRORS DURING EXTRACTION:");
|
||||
for (Throwable e : streamInfo.errors) {
|
||||
e.printStackTrace();
|
||||
Log.e(TAG, "------");
|
||||
}
|
||||
|
||||
View rootView = a != null ? a.findViewById(R.id.video_item_detail) : null;
|
||||
ErrorActivity.reportError(h, a,
|
||||
streamInfo.errors, null, rootView,
|
||||
ErrorActivity.ErrorInfo.make(ErrorActivity.REQUESTED_STREAM,
|
||||
service.getServiceInfo().name, videoUrl, 0 /* no message for the user */));
|
||||
}
|
||||
|
||||
// These errors render the stream information unusable.
|
||||
} catch (ReCaptchaException e) {
|
||||
h.post(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
onStreamInfoReceivedListener.onReCaptchaException();
|
||||
}
|
||||
});
|
||||
} catch (IOException e) {
|
||||
h.post(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
onStreamInfoReceivedListener.onError(R.string.network_error);
|
||||
}
|
||||
});
|
||||
e.printStackTrace();
|
||||
} catch (YoutubeStreamExtractor.DecryptException de) {
|
||||
// custom service related exceptions
|
||||
ErrorActivity.reportError(h, a, de, VideoItemDetailFragment.class, null,
|
||||
ErrorActivity.ErrorInfo.make(ErrorActivity.REQUESTED_STREAM,
|
||||
service.getServiceInfo().name, videoUrl, R.string.youtube_signature_decryption_error));
|
||||
h.post(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
a.finish();
|
||||
}
|
||||
});
|
||||
de.printStackTrace();
|
||||
} catch (YoutubeStreamExtractor.GemaException ge) {
|
||||
h.post(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
onStreamInfoReceivedListener.onBlockedByGemaError();
|
||||
}
|
||||
});
|
||||
} catch(YoutubeStreamExtractor.LiveStreamException e) {
|
||||
h.post(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
onStreamInfoReceivedListener
|
||||
.onContentErrorWithMessage(R.string.live_streams_not_supported);
|
||||
}
|
||||
});
|
||||
}
|
||||
// ----------------------------------------
|
||||
catch(StreamExtractor.ContentNotAvailableException e) {
|
||||
h.post(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
onStreamInfoReceivedListener
|
||||
.onContentError();
|
||||
}
|
||||
});
|
||||
e.printStackTrace();
|
||||
} catch(StreamInfo.StreamExctractException e) {
|
||||
if(!streamInfo.errors.isEmpty()) {
|
||||
// !!! if this case ever kicks in someone gets kicked out !!!
|
||||
ErrorActivity.reportError(h, a, e, VideoItemDetailFragment.class, null,
|
||||
ErrorActivity.ErrorInfo.make(ErrorActivity.REQUESTED_STREAM,
|
||||
service.getServiceInfo().name, videoUrl, R.string.could_not_get_stream));
|
||||
} else {
|
||||
ErrorActivity.reportError(h, a, streamInfo.errors, VideoItemDetailFragment.class, null,
|
||||
ErrorActivity.ErrorInfo.make(ErrorActivity.REQUESTED_STREAM,
|
||||
service.getServiceInfo().name, videoUrl, R.string.could_not_get_stream));
|
||||
}
|
||||
h.post(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
a.finish();
|
||||
}
|
||||
});
|
||||
e.printStackTrace();
|
||||
} catch (ParsingException e) {
|
||||
ErrorActivity.reportError(h, a, e, VideoItemDetailFragment.class, null,
|
||||
ErrorActivity.ErrorInfo.make(ErrorActivity.REQUESTED_STREAM,
|
||||
service.getServiceInfo().name, videoUrl, R.string.parsing_error));
|
||||
h.post(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
a.finish();
|
||||
}
|
||||
});
|
||||
e.printStackTrace();
|
||||
} catch(Exception e) {
|
||||
ErrorActivity.reportError(h, a, e, VideoItemDetailFragment.class, null,
|
||||
ErrorActivity.ErrorInfo.make(ErrorActivity.REQUESTED_STREAM,
|
||||
service.getServiceInfo().name, videoUrl, R.string.general_error));
|
||||
h.post(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
a.finish();
|
||||
}
|
||||
});
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static StreamInfoWorker streamInfoWorker = null;
|
||||
private StreamExtractorRunnable runnable = null;
|
||||
private OnStreamInfoReceivedListener onStreamInfoReceivedListener = null;
|
||||
|
||||
private StreamInfoWorker() {
|
||||
|
||||
}
|
||||
|
||||
public static StreamInfoWorker getInstance() {
|
||||
return streamInfoWorker == null ? (streamInfoWorker = new StreamInfoWorker()) : streamInfoWorker;
|
||||
}
|
||||
|
||||
public void search(int serviceId, String url, Activity a) {
|
||||
runnable = new StreamExtractorRunnable(a, url, serviceId);
|
||||
Thread thread = new Thread(runnable);
|
||||
thread.start();
|
||||
}
|
||||
|
||||
public void setOnStreamInfoReceivedListener(
|
||||
OnStreamInfoReceivedListener onStreamInfoReceivedListener) {
|
||||
this.onStreamInfoReceivedListener = onStreamInfoReceivedListener;
|
||||
}
|
||||
}
|
@ -1,77 +1,167 @@
|
||||
package org.schabi.newpipe.detail;
|
||||
|
||||
import android.animation.Animator;
|
||||
import android.animation.AnimatorListenerAdapter;
|
||||
import android.content.DialogInterface;
|
||||
import android.content.Intent;
|
||||
import android.content.SharedPreferences;
|
||||
import android.graphics.Bitmap;
|
||||
import android.media.AudioManager;
|
||||
import android.net.Uri;
|
||||
import android.os.Build;
|
||||
import android.os.Bundle;
|
||||
import android.preference.PreferenceManager;
|
||||
import android.support.v4.content.ContextCompat;
|
||||
import android.support.v7.app.AlertDialog;
|
||||
import android.support.v7.app.AppCompatActivity;
|
||||
import android.text.Html;
|
||||
import android.text.method.LinkMovementMethod;
|
||||
import android.util.Log;
|
||||
import android.util.TypedValue;
|
||||
import android.view.Menu;
|
||||
import android.view.MenuItem;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.Button;
|
||||
import android.widget.ImageView;
|
||||
import android.widget.LinearLayout;
|
||||
import android.widget.ProgressBar;
|
||||
import android.widget.RelativeLayout;
|
||||
import android.widget.TextView;
|
||||
import android.widget.Toast;
|
||||
|
||||
import org.schabi.newpipe.App;
|
||||
import com.nirhart.parallaxscroll.views.ParallaxScrollView;
|
||||
import com.nostra13.universalimageloader.core.DisplayImageOptions;
|
||||
import com.nostra13.universalimageloader.core.ImageLoader;
|
||||
import com.nostra13.universalimageloader.core.assist.FailReason;
|
||||
import com.nostra13.universalimageloader.core.display.FadeInBitmapDisplayer;
|
||||
import com.nostra13.universalimageloader.core.listener.SimpleImageLoadingListener;
|
||||
|
||||
import org.schabi.newpipe.ActivityCommunicator;
|
||||
import org.schabi.newpipe.ImageErrorLoadingListener;
|
||||
import org.schabi.newpipe.Localization;
|
||||
import org.schabi.newpipe.R;
|
||||
import org.schabi.newpipe.ReCaptchaActivity;
|
||||
import org.schabi.newpipe.download.DownloadDialog;
|
||||
import org.schabi.newpipe.extractor.InfoItem;
|
||||
import org.schabi.newpipe.extractor.MediaFormat;
|
||||
import org.schabi.newpipe.extractor.NewPipe;
|
||||
import org.schabi.newpipe.extractor.stream_info.AudioStream;
|
||||
import org.schabi.newpipe.extractor.stream_info.StreamInfo;
|
||||
import org.schabi.newpipe.extractor.stream_info.VideoStream;
|
||||
import org.schabi.newpipe.info_list.InfoItemBuilder;
|
||||
import org.schabi.newpipe.player.AbstractPlayer;
|
||||
import org.schabi.newpipe.player.BackgroundPlayer;
|
||||
import org.schabi.newpipe.player.ExoPlayerActivity;
|
||||
import org.schabi.newpipe.player.PlayVideoActivity;
|
||||
import org.schabi.newpipe.player.PopupVideoPlayer;
|
||||
import org.schabi.newpipe.report.ErrorActivity;
|
||||
import org.schabi.newpipe.util.NavStack;
|
||||
import org.schabi.newpipe.util.PermissionHelper;
|
||||
import org.schabi.newpipe.util.ThemeHelper;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.concurrent.atomic.AtomicBoolean;
|
||||
|
||||
/**
|
||||
* Copyright (C) Christian Schabesberger 2015 <chris.schabesberger@mailbox.org>
|
||||
* VideoItemDetailActivity.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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
@SuppressWarnings("FieldCanBeLocal")
|
||||
public class VideoItemDetailActivity extends AppCompatActivity implements StreamExtractorWorker.OnStreamInfoReceivedListener, SharedPreferences.OnSharedPreferenceChangeListener {
|
||||
|
||||
public class VideoItemDetailActivity extends AppCompatActivity {
|
||||
private static final String TAG = VideoItemDetailActivity.class.toString();
|
||||
private static final String TAG = "VideoItemDetailActivity";
|
||||
private static final String KORE_PACKET = "org.xbmc.kore";
|
||||
|
||||
private VideoItemDetailFragment fragment;
|
||||
/**
|
||||
* The fragment argument representing the item ID that this fragment
|
||||
* represents.
|
||||
*/
|
||||
public static final String AUTO_PLAY = "auto_play";
|
||||
|
||||
private ActionBarHandler actionBarHandler;
|
||||
|
||||
private InfoItemBuilder infoItemBuilder = null;
|
||||
private StreamInfo currentStreamInfo = null;
|
||||
private StreamExtractorWorker curExtractorThread;
|
||||
private String videoUrl;
|
||||
private int currentStreamingService = -1;
|
||||
private int serviceId = -1;
|
||||
|
||||
protected void onCreate(Bundle savedInstanceState) {
|
||||
private AtomicBoolean isLoading = new AtomicBoolean(false);
|
||||
private boolean needUpdate = false;
|
||||
|
||||
private boolean autoPlayEnabled;
|
||||
private boolean showRelatedStreams;
|
||||
|
||||
private ImageLoader imageLoader = ImageLoader.getInstance();
|
||||
private DisplayImageOptions displayImageOptions =
|
||||
new DisplayImageOptions.Builder().displayer(new FadeInBitmapDisplayer(400)).cacheInMemory(true).build();
|
||||
private Bitmap streamThumbnail = null;
|
||||
|
||||
/*//////////////////////////////////////////////////////////////////////////
|
||||
// Views
|
||||
//////////////////////////////////////////////////////////////////////////*/
|
||||
|
||||
private ProgressBar loadingProgressBar;
|
||||
|
||||
private ParallaxScrollView parallaxScrollRootView;
|
||||
private RelativeLayout contentRootLayout;
|
||||
|
||||
private Button thumbnailBackgroundButton;
|
||||
private ImageView thumbnailImageView;
|
||||
private ImageView thumbnailPlayButton;
|
||||
|
||||
private View videoTitleRoot;
|
||||
private TextView videoTitleTextView;
|
||||
private ImageView videoTitleToggleArrow;
|
||||
private TextView videoCountView;
|
||||
|
||||
private RelativeLayout videoDescriptionRootLayout;
|
||||
private TextView videoUploadDateView;
|
||||
private TextView videoDescriptionView;
|
||||
|
||||
private Button uploaderButton;
|
||||
private TextView uploaderTextView;
|
||||
private ImageView uploaderThumb;
|
||||
|
||||
private TextView thumbsUpTextView;
|
||||
private ImageView thumbsUpImageView;
|
||||
private TextView thumbsDownTextView;
|
||||
private ImageView thumbsDownImageView;
|
||||
private TextView thumbsDisabledTextView;
|
||||
|
||||
private TextView nextStreamTitle;
|
||||
private RelativeLayout relatedStreamRootLayout;
|
||||
private LinearLayout relatedStreamsView;
|
||||
|
||||
/*//////////////////////////////////////////////////////////////////////////
|
||||
// Activity's Lifecycle
|
||||
//////////////////////////////////////////////////////////////////////////*/
|
||||
|
||||
@Override
|
||||
public void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
|
||||
showRelatedStreams = PreferenceManager.getDefaultSharedPreferences(this).getBoolean(getString(R.string.show_next_video_key), true);
|
||||
PreferenceManager.getDefaultSharedPreferences(this).registerOnSharedPreferenceChangeListener(this);
|
||||
|
||||
ThemeHelper.setTheme(this, true);
|
||||
setContentView(R.layout.activity_videoitem_detail);
|
||||
setVolumeControlStream(AudioManager.STREAM_MUSIC);
|
||||
// Show the Up button in the action bar.
|
||||
try {
|
||||
//noinspection ConstantConditions
|
||||
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
|
||||
} catch(Exception e) {
|
||||
Log.d(TAG, "Could not get SupportActionBar");
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
// savedInstanceState is non-null when there is fragment state
|
||||
// saved from previous configurations of this activity
|
||||
// (e.g. when rotating the screen from portrait to landscape).
|
||||
// In this case, the fragment will automatically be re-added
|
||||
// to its container so we don't need to manually add it.
|
||||
// For more information, see the Fragments API guide at:
|
||||
//
|
||||
// http://developer.android.com/guide/components/fragments.html
|
||||
//
|
||||
if (getSupportActionBar() != null) getSupportActionBar().setDisplayHomeAsUpEnabled(true);
|
||||
else Log.e(TAG, "Could not get SupportActionBar");
|
||||
|
||||
if (savedInstanceState == null) {
|
||||
handleIntent(getIntent());
|
||||
} else {
|
||||
videoUrl = savedInstanceState.getString(NavStack.URL);
|
||||
currentStreamingService = savedInstanceState.getInt(NavStack.SERVICE_ID);
|
||||
NavStack.getInstance()
|
||||
.restoreSavedInstanceState(savedInstanceState);
|
||||
addFragment(savedInstanceState);
|
||||
initViews();
|
||||
initListeners();
|
||||
handleIntent(getIntent());
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onResume() {
|
||||
super.onResume();
|
||||
|
||||
// Currently only used for enable/disable related videos
|
||||
// but can be extended for other live settings change
|
||||
if (needUpdate) {
|
||||
if (relatedStreamsView != null) initRelatedVideos(currentStreamInfo);
|
||||
needUpdate = false;
|
||||
}
|
||||
}
|
||||
|
||||
@ -82,74 +172,696 @@ public class VideoItemDetailActivity extends AppCompatActivity {
|
||||
handleIntent(intent);
|
||||
}
|
||||
|
||||
private void handleIntent(Intent intent) {
|
||||
Bundle arguments = new Bundle();
|
||||
boolean autoplay = false;
|
||||
|
||||
videoUrl = intent.getStringExtra(NavStack.URL);
|
||||
currentStreamingService = intent.getIntExtra(NavStack.SERVICE_ID, -1);
|
||||
if(intent.hasExtra(VideoItemDetailFragment.AUTO_PLAY)) {
|
||||
arguments.putBoolean(VideoItemDetailFragment.AUTO_PLAY,
|
||||
intent.getBooleanExtra(VideoItemDetailFragment.AUTO_PLAY, false));
|
||||
}
|
||||
arguments.putString(NavStack.URL, videoUrl);
|
||||
arguments.putInt(NavStack.SERVICE_ID, currentStreamingService);
|
||||
addFragment(arguments);
|
||||
}
|
||||
|
||||
private void addFragment(final Bundle arguments) {
|
||||
// Create the detail fragment and add it to the activity
|
||||
// using a fragment transaction.
|
||||
fragment = new VideoItemDetailFragment();
|
||||
fragment.setArguments(arguments);
|
||||
getSupportFragmentManager().beginTransaction()
|
||||
.replace(R.id.videoitem_detail_container, fragment)
|
||||
.commit();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onResume() {
|
||||
super.onResume();
|
||||
App.checkStartTor(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onSaveInstanceState(Bundle outState) {
|
||||
super.onSaveInstanceState(outState);
|
||||
outState.putString(NavStack.URL, videoUrl);
|
||||
outState.putInt(NavStack.SERVICE_ID, currentStreamingService);
|
||||
outState.putBoolean(VideoItemDetailFragment.AUTO_PLAY, false);
|
||||
NavStack.getInstance()
|
||||
.onSaveInstanceState(outState);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onOptionsItemSelected(MenuItem item) {
|
||||
super.onOptionsItemSelected(item);
|
||||
int id = item.getItemId();
|
||||
if (id == android.R.id.home) {
|
||||
// This ID represents the Home or Up button. In the case of this
|
||||
// activity, the Up button is shown. Use NavUtils to allow users
|
||||
// to navigate up one level in the application structure. For
|
||||
// more details, see the Navigation pattern on Android Design:
|
||||
|
||||
// http://developer.android.com/design/patterns/navigation.html#up-vs-back
|
||||
|
||||
NavStack.getInstance()
|
||||
.openMainActivity(this);
|
||||
return true;
|
||||
} else {
|
||||
return super.onOptionsItemSelected(item);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onBackPressed() {
|
||||
try {
|
||||
NavStack.getInstance()
|
||||
.navBack(this);
|
||||
NavStack.getInstance().navBack(this);
|
||||
} catch (Exception e) {
|
||||
ErrorActivity.reportUiError(this, e);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onActivityResult(int requestCode, int resultCode, Intent data) {
|
||||
super.onActivityResult(requestCode, resultCode, data);
|
||||
switch (requestCode) {
|
||||
case ReCaptchaActivity.RECAPTCHA_REQUEST:
|
||||
if (resultCode == RESULT_OK) {
|
||||
String videoUrl = getIntent().getStringExtra(NavStack.URL);
|
||||
NavStack.getInstance().openDetailActivity(this, videoUrl, serviceId);
|
||||
} else Log.e(TAG, "ReCaptcha failed");
|
||||
break;
|
||||
default:
|
||||
Log.e(TAG, "Request code from activity not supported [" + requestCode + "]");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String key) {
|
||||
if (key.equals(getString(R.string.show_next_video_key))) {
|
||||
showRelatedStreams = sharedPreferences.getBoolean(key, true);
|
||||
needUpdate = true;
|
||||
}
|
||||
}
|
||||
|
||||
/*//////////////////////////////////////////////////////////////////////////
|
||||
// Init
|
||||
//////////////////////////////////////////////////////////////////////////*/
|
||||
|
||||
public void initViews() {
|
||||
loadingProgressBar = (ProgressBar) findViewById(R.id.detail_loading_progress_bar);
|
||||
|
||||
parallaxScrollRootView = (ParallaxScrollView) findViewById(R.id.detail_main_content);
|
||||
|
||||
//thumbnailRootLayout = (RelativeLayout) findViewById(R.id.detail_thumbnail_root_layout);
|
||||
thumbnailBackgroundButton = (Button) findViewById(R.id.detail_stream_thumbnail_background_button);
|
||||
thumbnailImageView = (ImageView) findViewById(R.id.detail_thumbnail_image_view);
|
||||
thumbnailPlayButton = (ImageView) findViewById(R.id.detail_thumbnail_play_button);
|
||||
|
||||
contentRootLayout = (RelativeLayout) findViewById(R.id.detail_content_root_layout);
|
||||
|
||||
videoTitleRoot = findViewById(R.id.detail_title_root_layout);
|
||||
videoTitleTextView = (TextView) findViewById(R.id.detail_video_title_view);
|
||||
videoTitleToggleArrow = (ImageView) findViewById(R.id.detail_toggle_description_view);
|
||||
videoCountView = (TextView) findViewById(R.id.detail_view_count_view);
|
||||
|
||||
videoDescriptionRootLayout = (RelativeLayout) findViewById(R.id.detail_description_root_layout);
|
||||
videoUploadDateView = (TextView) findViewById(R.id.detail_upload_date_view);
|
||||
videoDescriptionView = (TextView) findViewById(R.id.detail_description_view);
|
||||
|
||||
//thumbsRootLayout = (LinearLayout) findViewById(R.id.detail_thumbs_root_layout);
|
||||
thumbsUpTextView = (TextView) findViewById(R.id.detail_thumbs_up_count_view);
|
||||
thumbsUpImageView = (ImageView) findViewById(R.id.detail_thumbs_up_img_view);
|
||||
thumbsDownTextView = (TextView) findViewById(R.id.detail_thumbs_down_count_view);
|
||||
thumbsDownImageView = (ImageView) findViewById(R.id.detail_thumbs_down_img_view);
|
||||
thumbsDisabledTextView = (TextView) findViewById(R.id.detail_thumbs_disabled_view);
|
||||
|
||||
//uploaderRootLayout = (FrameLayout) findViewById(R.id.detail_uploader_root_layout);
|
||||
uploaderButton = (Button) findViewById(R.id.detail_uploader_button);
|
||||
uploaderTextView = (TextView) findViewById(R.id.detail_uploader_text_view);
|
||||
uploaderThumb = (ImageView) findViewById(R.id.detail_uploader_thumbnail_view);
|
||||
|
||||
relatedStreamRootLayout = (RelativeLayout) findViewById(R.id.detail_related_streams_root_layout);
|
||||
nextStreamTitle = (TextView) findViewById(R.id.detail_next_stream_title);
|
||||
relatedStreamsView = (LinearLayout) findViewById(R.id.detail_related_streams_view);
|
||||
|
||||
actionBarHandler = new ActionBarHandler(this);
|
||||
actionBarHandler.setupNavMenu(this);
|
||||
videoDescriptionView.setMovementMethod(LinkMovementMethod.getInstance());
|
||||
|
||||
infoItemBuilder = new InfoItemBuilder(this, findViewById(android.R.id.content));
|
||||
|
||||
setHeightThumbnail();
|
||||
}
|
||||
|
||||
private void initListeners() {
|
||||
videoTitleRoot.setOnClickListener(new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
if (videoDescriptionRootLayout.getVisibility() == View.VISIBLE) {
|
||||
videoTitleTextView.setMaxLines(1);
|
||||
videoDescriptionRootLayout.setVisibility(View.GONE);
|
||||
videoTitleToggleArrow.setImageResource(R.drawable.arrow_down);
|
||||
} else {
|
||||
videoTitleTextView.setMaxLines(10);
|
||||
videoDescriptionRootLayout.setVisibility(View.VISIBLE);
|
||||
videoTitleToggleArrow.setImageResource(R.drawable.arrow_up);
|
||||
}
|
||||
}
|
||||
});
|
||||
thumbnailBackgroundButton.setOnClickListener(new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
if (!isLoading.get() && currentStreamInfo != null) playVideo(currentStreamInfo);
|
||||
}
|
||||
});
|
||||
|
||||
infoItemBuilder.setOnStreamInfoItemSelectedListener(new InfoItemBuilder.OnInfoItemSelectedListener() {
|
||||
@Override
|
||||
public void selected(String url, int serviceId) {
|
||||
NavStack.getInstance().openDetailActivity(VideoItemDetailActivity.this, url, serviceId);
|
||||
}
|
||||
});
|
||||
|
||||
uploaderButton.setOnClickListener(new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View view) {
|
||||
NavStack.getInstance().openChannelActivity(VideoItemDetailActivity.this, currentStreamInfo.channel_url, currentStreamInfo.service_id);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private void initThumbnailViews(StreamInfo info) {
|
||||
if (info.thumbnail_url != null && !info.thumbnail_url.isEmpty()) {
|
||||
imageLoader.displayImage(info.thumbnail_url, thumbnailImageView,
|
||||
displayImageOptions, new SimpleImageLoadingListener() {
|
||||
|
||||
@Override
|
||||
public void onLoadingComplete(String imageUri, View view, Bitmap loadedImage) {
|
||||
streamThumbnail = loadedImage;
|
||||
|
||||
if (streamThumbnail != null) {
|
||||
// TODO: Change the thumbnail implementation
|
||||
|
||||
// When the thumbnail is not loaded yet, it not passes to the service in time
|
||||
// so, I can notify the service through a broadcast, but the problem is
|
||||
// when I click in another video, another thumbnail will be load, and will
|
||||
// notify again, so I send the videoUrl and compare with the service's url
|
||||
ActivityCommunicator.getCommunicator().backgroundPlayerThumbnail = streamThumbnail;
|
||||
Intent intent = new Intent(AbstractPlayer.ACTION_UPDATE_THUMB);
|
||||
intent.putExtra(AbstractPlayer.VIDEO_URL, currentStreamInfo.webpage_url);
|
||||
sendBroadcast(intent);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onLoadingFailed(String imageUri, View view, FailReason failReason) {
|
||||
ErrorActivity.reportError(VideoItemDetailActivity.this,
|
||||
failReason.getCause(), null, findViewById(android.R.id.content),
|
||||
ErrorActivity.ErrorInfo.make(ErrorActivity.LOAD_IMAGE,
|
||||
NewPipe.getNameOfService(currentStreamInfo.service_id), imageUri,
|
||||
R.string.could_not_load_thumbnails));
|
||||
}
|
||||
|
||||
});
|
||||
} else thumbnailImageView.setImageResource(R.drawable.dummy_thumbnail_dark);
|
||||
|
||||
if (info.uploader_thumbnail_url != null && !info.uploader_thumbnail_url.isEmpty()) {
|
||||
imageLoader.displayImage(info.uploader_thumbnail_url,
|
||||
uploaderThumb, displayImageOptions,
|
||||
new ImageErrorLoadingListener(this, findViewById(android.R.id.content), info.service_id));
|
||||
}
|
||||
}
|
||||
|
||||
private void initRelatedVideos(StreamInfo info) {
|
||||
if (relatedStreamsView.getChildCount() > 0) relatedStreamsView.removeAllViews();
|
||||
|
||||
if (info.next_video != null && showRelatedStreams) {
|
||||
nextStreamTitle.setVisibility(View.VISIBLE);
|
||||
relatedStreamsView.addView(infoItemBuilder.buildView(relatedStreamsView, info.next_video));
|
||||
relatedStreamsView.addView(getSeparatorView());
|
||||
relatedStreamsView.setVisibility(View.VISIBLE);
|
||||
} else nextStreamTitle.setVisibility(View.GONE);
|
||||
|
||||
if (info.related_streams != null && !info.related_streams.isEmpty() && showRelatedStreams) {
|
||||
for (InfoItem item : info.related_streams) {
|
||||
relatedStreamsView.addView(infoItemBuilder.buildView(relatedStreamsView, item));
|
||||
}
|
||||
relatedStreamsView.setVisibility(View.VISIBLE);
|
||||
} else if (info.next_video == null) relatedStreamsView.setVisibility(View.GONE);
|
||||
}
|
||||
|
||||
/*//////////////////////////////////////////////////////////////////////////
|
||||
// Menu
|
||||
//////////////////////////////////////////////////////////////////////////*/
|
||||
|
||||
@Override
|
||||
public boolean onCreateOptionsMenu(Menu menu) {
|
||||
actionBarHandler.setupMenu(menu, getMenuInflater());
|
||||
return super.onCreateOptionsMenu(menu);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onOptionsItemSelected(MenuItem item) {
|
||||
if (item.getItemId() == android.R.id.home) {
|
||||
NavStack.getInstance().openMainActivity(this);
|
||||
return true;
|
||||
}
|
||||
return actionBarHandler.onItemSelected(item) || super.onOptionsItemSelected(item);
|
||||
}
|
||||
|
||||
private void setupActionBarHandler(final StreamInfo info) {
|
||||
actionBarHandler.setupStreamList(info.video_streams);
|
||||
actionBarHandler.setOnShareListener(new ActionBarHandler.OnActionListener() {
|
||||
@Override
|
||||
public void onActionSelected(int selectedStreamId) {
|
||||
if (isLoading.get()) return;
|
||||
|
||||
Intent intent = new Intent();
|
||||
intent.setAction(Intent.ACTION_SEND);
|
||||
intent.putExtra(Intent.EXTRA_TEXT, info.webpage_url);
|
||||
intent.setType("text/plain");
|
||||
startActivity(Intent.createChooser(intent, VideoItemDetailActivity.this.getString(R.string.share_dialog_title)));
|
||||
}
|
||||
});
|
||||
|
||||
actionBarHandler.setOnOpenInBrowserListener(new ActionBarHandler.OnActionListener() {
|
||||
@Override
|
||||
public void onActionSelected(int selectedStreamId) {
|
||||
if (isLoading.get()) return;
|
||||
|
||||
Intent intent = new Intent();
|
||||
intent.setAction(Intent.ACTION_VIEW);
|
||||
intent.setData(Uri.parse(info.webpage_url));
|
||||
startActivity(Intent.createChooser(intent, VideoItemDetailActivity.this.getString(R.string.choose_browser)));
|
||||
}
|
||||
});
|
||||
|
||||
actionBarHandler.setOnOpenInPopupListener(new ActionBarHandler.OnActionListener() {
|
||||
@Override
|
||||
public void onActionSelected(int selectedStreamId) {
|
||||
if (isLoading.get()) return;
|
||||
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M && !PermissionHelper.checkSystemAlertWindowPermission(VideoItemDetailActivity.this)) {
|
||||
Toast.makeText(VideoItemDetailActivity.this, R.string.msg_popup_permission, Toast.LENGTH_LONG).show();
|
||||
return;
|
||||
}
|
||||
if (streamThumbnail != null) ActivityCommunicator.getCommunicator().backgroundPlayerThumbnail = streamThumbnail;
|
||||
|
||||
Intent i = new Intent(VideoItemDetailActivity.this, PopupVideoPlayer.class);
|
||||
Toast.makeText(VideoItemDetailActivity.this, R.string.popup_playing_toast, Toast.LENGTH_SHORT).show();
|
||||
i.putExtra(AbstractPlayer.VIDEO_TITLE, info.title)
|
||||
.putExtra(AbstractPlayer.CHANNEL_NAME, info.uploader)
|
||||
.putExtra(AbstractPlayer.VIDEO_URL, info.webpage_url)
|
||||
.putExtra(AbstractPlayer.INDEX_SEL_VIDEO_STREAM, selectedStreamId)
|
||||
.putExtra(AbstractPlayer.VIDEO_STREAMS_LIST, new ArrayList<>(info.video_streams));
|
||||
if (info.start_position > 0) i.putExtra(AbstractPlayer.START_POSITION, info.start_position * 1000);
|
||||
VideoItemDetailActivity.this.startService(i);
|
||||
}
|
||||
});
|
||||
|
||||
actionBarHandler.setOnPlayWithKodiListener(new ActionBarHandler.OnActionListener() {
|
||||
@Override
|
||||
public void onActionSelected(int selectedStreamId) {
|
||||
if (isLoading.get()) return;
|
||||
|
||||
try {
|
||||
Intent intent = new Intent(Intent.ACTION_VIEW);
|
||||
intent.setPackage(KORE_PACKET);
|
||||
intent.setData(Uri.parse(info.webpage_url.replace("https", "http")));
|
||||
VideoItemDetailActivity.this.startActivity(intent);
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
AlertDialog.Builder builder = new AlertDialog.Builder(VideoItemDetailActivity.this);
|
||||
builder.setMessage(R.string.kore_not_found)
|
||||
.setPositiveButton(R.string.install, new DialogInterface.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(DialogInterface dialog, int which) {
|
||||
Intent intent = new Intent();
|
||||
intent.setAction(Intent.ACTION_VIEW);
|
||||
intent.setData(Uri.parse(VideoItemDetailActivity.this.getString(R.string.fdroid_kore_url)));
|
||||
VideoItemDetailActivity.this.startActivity(intent);
|
||||
}
|
||||
})
|
||||
.setNegativeButton(R.string.cancel, new DialogInterface.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(DialogInterface dialog, int which) {
|
||||
|
||||
}
|
||||
});
|
||||
builder.create().show();
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
actionBarHandler.setOnDownloadListener(new ActionBarHandler.OnActionListener() {
|
||||
@Override
|
||||
public void onActionSelected(int selectedStreamId) {
|
||||
|
||||
if (isLoading.get() || !PermissionHelper.checkStoragePermissions(VideoItemDetailActivity.this)) {
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
Bundle args = new Bundle();
|
||||
|
||||
// Sometimes it may be that some information is not available due to changes fo the
|
||||
// website which was crawled. Then the ui has to understand this and act right.
|
||||
|
||||
if (info.audio_streams != null) {
|
||||
AudioStream audioStream =
|
||||
info.audio_streams.get(getPreferredAudioStreamId(info));
|
||||
|
||||
String audioSuffix = "." + MediaFormat.getSuffixById(audioStream.format);
|
||||
args.putString(DownloadDialog.AUDIO_URL, audioStream.url);
|
||||
args.putString(DownloadDialog.FILE_SUFFIX_AUDIO, audioSuffix);
|
||||
}
|
||||
|
||||
if (info.video_streams != null) {
|
||||
VideoStream selectedStreamItem = info.video_streams.get(selectedStreamId);
|
||||
String videoSuffix = "." + MediaFormat.getSuffixById(selectedStreamItem.format);
|
||||
args.putString(DownloadDialog.FILE_SUFFIX_VIDEO, videoSuffix);
|
||||
args.putString(DownloadDialog.VIDEO_URL, selectedStreamItem.url);
|
||||
}
|
||||
|
||||
args.putString(DownloadDialog.TITLE, info.title);
|
||||
DownloadDialog downloadDialog = DownloadDialog.newInstance(args);
|
||||
downloadDialog.show(VideoItemDetailActivity.this.getSupportFragmentManager(), "downloadDialog");
|
||||
} catch (Exception e) {
|
||||
Toast.makeText(VideoItemDetailActivity.this,
|
||||
R.string.could_not_setup_download_menu, Toast.LENGTH_LONG).show();
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
if (info.audio_streams == null) {
|
||||
actionBarHandler.showAudioAction(false);
|
||||
} else {
|
||||
actionBarHandler.setOnPlayAudioListener(new ActionBarHandler.OnActionListener() {
|
||||
@Override
|
||||
public void onActionSelected(int selectedStreamId) {
|
||||
if (isLoading.get()) return;
|
||||
|
||||
boolean useExternalAudioPlayer = PreferenceManager.getDefaultSharedPreferences(VideoItemDetailActivity.this)
|
||||
.getBoolean(VideoItemDetailActivity.this.getString(R.string.use_external_audio_player_key), false);
|
||||
Intent intent;
|
||||
AudioStream audioStream =
|
||||
info.audio_streams.get(getPreferredAudioStreamId(info));
|
||||
if (!useExternalAudioPlayer && android.os.Build.VERSION.SDK_INT >= 18) {
|
||||
//internal music player: explicit intent
|
||||
if (!BackgroundPlayer.isRunning && streamThumbnail != null) {
|
||||
ActivityCommunicator.getCommunicator()
|
||||
.backgroundPlayerThumbnail = streamThumbnail;
|
||||
intent = new Intent(VideoItemDetailActivity.this, BackgroundPlayer.class);
|
||||
|
||||
intent.setAction(Intent.ACTION_VIEW);
|
||||
intent.setDataAndType(Uri.parse(audioStream.url),
|
||||
MediaFormat.getMimeById(audioStream.format));
|
||||
intent.putExtra(BackgroundPlayer.TITLE, info.title);
|
||||
intent.putExtra(BackgroundPlayer.WEB_URL, info.webpage_url);
|
||||
intent.putExtra(BackgroundPlayer.SERVICE_ID, serviceId);
|
||||
intent.putExtra(BackgroundPlayer.CHANNEL_NAME, info.uploader);
|
||||
VideoItemDetailActivity.this.startService(intent);
|
||||
}
|
||||
} else {
|
||||
intent = new Intent();
|
||||
try {
|
||||
intent.setAction(Intent.ACTION_VIEW);
|
||||
intent.setDataAndType(Uri.parse(audioStream.url),
|
||||
MediaFormat.getMimeById(audioStream.format));
|
||||
intent.putExtra(Intent.EXTRA_TITLE, info.title);
|
||||
intent.putExtra("title", info.title);
|
||||
// HERE !!!
|
||||
VideoItemDetailActivity.this.startActivity(intent);
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
AlertDialog.Builder builder = new AlertDialog.Builder(VideoItemDetailActivity.this);
|
||||
builder.setMessage(R.string.no_player_found)
|
||||
.setPositiveButton(R.string.install, new DialogInterface.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(DialogInterface dialog, int which) {
|
||||
Intent intent = new Intent();
|
||||
intent.setAction(Intent.ACTION_VIEW);
|
||||
intent.setData(Uri.parse(VideoItemDetailActivity.this.getString(R.string.fdroid_vlc_url)));
|
||||
VideoItemDetailActivity.this.startActivity(intent);
|
||||
}
|
||||
})
|
||||
.setNegativeButton(R.string.cancel, new DialogInterface.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(DialogInterface dialog, int which) {
|
||||
Log.i(TAG, "You unlocked a secret unicorn.");
|
||||
}
|
||||
});
|
||||
builder.create().show();
|
||||
Log.e(TAG, "Either no Streaming player for audio was installed, or something important crashed:");
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
/*//////////////////////////////////////////////////////////////////////////
|
||||
// Utils
|
||||
//////////////////////////////////////////////////////////////////////////*/
|
||||
|
||||
private void handleIntent(Intent intent) {
|
||||
if (intent == null) return;
|
||||
|
||||
serviceId = intent.getIntExtra(NavStack.SERVICE_ID, 0);
|
||||
videoUrl = intent.getStringExtra(NavStack.URL);
|
||||
autoPlayEnabled = intent.getBooleanExtra(AUTO_PLAY, false);
|
||||
selectVideo(videoUrl, serviceId);
|
||||
}
|
||||
|
||||
private void selectVideo(String url, int serviceId) {
|
||||
if (curExtractorThread != null && curExtractorThread.isRunning()) curExtractorThread.cancel();
|
||||
|
||||
animateView(contentRootLayout, false, 200, null);
|
||||
|
||||
thumbnailPlayButton.setVisibility(View.GONE);
|
||||
loadingProgressBar.setVisibility(View.VISIBLE);
|
||||
|
||||
imageLoader.cancelDisplayTask(thumbnailImageView);
|
||||
imageLoader.cancelDisplayTask(uploaderThumb);
|
||||
thumbnailImageView.setImageDrawable(null);
|
||||
|
||||
curExtractorThread = StreamExtractorWorker.startExtractorThread(serviceId, url, this, this);
|
||||
isLoading.set(true);
|
||||
}
|
||||
|
||||
public void playVideo(StreamInfo info) {
|
||||
// ----------- THE MAGIC MOMENT ---------------
|
||||
VideoStream selectedVideoStream = info.video_streams.get(actionBarHandler.getSelectedVideoStream());
|
||||
|
||||
if (PreferenceManager.getDefaultSharedPreferences(this).getBoolean(this.getString(R.string.use_external_video_player_key), false)) {
|
||||
|
||||
// External Player
|
||||
Intent intent = new Intent();
|
||||
try {
|
||||
intent.setAction(Intent.ACTION_VIEW)
|
||||
.setDataAndType(Uri.parse(selectedVideoStream.url), MediaFormat.getMimeById(selectedVideoStream.format))
|
||||
.putExtra(Intent.EXTRA_TITLE, info.title)
|
||||
.putExtra("title", info.title);
|
||||
this.startActivity(intent);
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
AlertDialog.Builder builder = new AlertDialog.Builder(this);
|
||||
builder.setMessage(R.string.no_player_found)
|
||||
.setPositiveButton(R.string.install, new DialogInterface.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(DialogInterface dialog, int which) {
|
||||
Intent intent = new Intent()
|
||||
.setAction(Intent.ACTION_VIEW)
|
||||
.setData(Uri.parse(getString(R.string.fdroid_vlc_url)));
|
||||
startActivity(intent);
|
||||
}
|
||||
})
|
||||
.setNegativeButton(R.string.cancel, new DialogInterface.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(DialogInterface dialog, int which) {
|
||||
}
|
||||
});
|
||||
builder.create().show();
|
||||
}
|
||||
} else {
|
||||
Intent intent;
|
||||
boolean useOldPlayer = PreferenceManager
|
||||
.getDefaultSharedPreferences(this)
|
||||
.getBoolean(getString(R.string.use_old_player_key), false)
|
||||
|| (Build.VERSION.SDK_INT < 16);
|
||||
if (!useOldPlayer) {
|
||||
// ExoPlayer
|
||||
if (streamThumbnail != null) ActivityCommunicator.getCommunicator().backgroundPlayerThumbnail = streamThumbnail;
|
||||
intent = new Intent(this, ExoPlayerActivity.class)
|
||||
.putExtra(AbstractPlayer.VIDEO_TITLE, info.title)
|
||||
.putExtra(AbstractPlayer.VIDEO_URL, info.webpage_url)
|
||||
.putExtra(AbstractPlayer.CHANNEL_NAME, info.uploader)
|
||||
.putExtra(AbstractPlayer.INDEX_SEL_VIDEO_STREAM, actionBarHandler.getSelectedVideoStream())
|
||||
.putExtra(AbstractPlayer.VIDEO_STREAMS_LIST, new ArrayList<>(info.video_streams));
|
||||
if (info.start_position > 0) intent.putExtra(AbstractPlayer.START_POSITION, info.start_position * 1000);
|
||||
} else {
|
||||
// Internal Player
|
||||
intent = new Intent(this, PlayVideoActivity.class)
|
||||
.putExtra(PlayVideoActivity.VIDEO_TITLE, info.title)
|
||||
.putExtra(PlayVideoActivity.STREAM_URL, selectedVideoStream.url)
|
||||
.putExtra(PlayVideoActivity.VIDEO_URL, info.webpage_url)
|
||||
.putExtra(PlayVideoActivity.START_POSITION, info.start_position);
|
||||
}
|
||||
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
|
||||
startActivity(intent);
|
||||
}
|
||||
}
|
||||
|
||||
private int getPreferredAudioStreamId(final StreamInfo info) {
|
||||
String preferredFormatString = PreferenceManager.getDefaultSharedPreferences(this)
|
||||
.getString(getString(R.string.default_audio_format_key), "webm");
|
||||
|
||||
int preferredFormat = MediaFormat.WEBMA.id;
|
||||
switch (preferredFormatString) {
|
||||
case "webm":
|
||||
preferredFormat = MediaFormat.WEBMA.id;
|
||||
break;
|
||||
case "m4a":
|
||||
preferredFormat = MediaFormat.M4A.id;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
for (int i = 0; i < info.audio_streams.size(); i++) {
|
||||
if (info.audio_streams.get(i).format == preferredFormat) {
|
||||
return i;
|
||||
}
|
||||
}
|
||||
|
||||
//todo: make this a proper error
|
||||
Log.e(TAG, "FAILED to set audioStream value!");
|
||||
return 0;
|
||||
}
|
||||
|
||||
private View getSeparatorView() {
|
||||
View separator = new View(this);
|
||||
LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, 1);
|
||||
int m8 = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 8, getResources().getDisplayMetrics());
|
||||
int m5 = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 5, getResources().getDisplayMetrics());
|
||||
params.setMargins(m8, m5, m8, m5);
|
||||
separator.setLayoutParams(params);
|
||||
|
||||
TypedValue typedValue = new TypedValue();
|
||||
getTheme().resolveAttribute(R.attr.separatorColor, typedValue, true);
|
||||
separator.setBackgroundColor(typedValue.data);
|
||||
return separator;
|
||||
}
|
||||
|
||||
private void setHeightThumbnail() {
|
||||
boolean isPortrait = getResources().getDisplayMetrics().heightPixels > getResources().getDisplayMetrics().widthPixels;
|
||||
int height = isPortrait ? (int) (getResources().getDisplayMetrics().widthPixels / (16.0f / 9.0f))
|
||||
: (int) (getResources().getDisplayMetrics().heightPixels / 2f);
|
||||
thumbnailImageView.setScaleType(isPortrait ? ImageView.ScaleType.CENTER_CROP : ImageView.ScaleType.FIT_CENTER);
|
||||
thumbnailImageView.setLayoutParams(new RelativeLayout.LayoutParams(RelativeLayout.LayoutParams.MATCH_PARENT, height));
|
||||
thumbnailImageView.setMinimumHeight(height);
|
||||
thumbnailBackgroundButton.setLayoutParams(new RelativeLayout.LayoutParams(RelativeLayout.LayoutParams.MATCH_PARENT, height));
|
||||
thumbnailBackgroundButton.setMinimumHeight(height);
|
||||
}
|
||||
|
||||
/**
|
||||
* Animate the view
|
||||
*
|
||||
* @param view view that will be animated
|
||||
* @param enterOrExit true to enter, false to exit
|
||||
* @param duration how long the animation will take, in milliseconds
|
||||
* @param execOnEnd runnable that will be executed when the animation ends
|
||||
*/
|
||||
public void animateView(final View view, final boolean enterOrExit, long duration, final Runnable execOnEnd) {
|
||||
if (view.getVisibility() == View.VISIBLE && enterOrExit) {
|
||||
view.animate().setListener(null).cancel();
|
||||
view.setVisibility(View.VISIBLE);
|
||||
view.setAlpha(1f);
|
||||
if (execOnEnd != null) execOnEnd.run();
|
||||
return;
|
||||
} else if ((view.getVisibility() == View.GONE || view.getVisibility() == View.INVISIBLE) && !enterOrExit) {
|
||||
view.animate().setListener(null).cancel();
|
||||
view.setVisibility(View.GONE);
|
||||
view.setAlpha(0f);
|
||||
if (execOnEnd != null) execOnEnd.run();
|
||||
return;
|
||||
}
|
||||
|
||||
view.animate().setListener(null).cancel();
|
||||
view.setVisibility(View.VISIBLE);
|
||||
|
||||
if (enterOrExit) {
|
||||
view.animate().alpha(1f).setDuration(duration)
|
||||
.setListener(new AnimatorListenerAdapter() {
|
||||
@Override
|
||||
public void onAnimationEnd(Animator animation) {
|
||||
if (execOnEnd != null) execOnEnd.run();
|
||||
}
|
||||
}).start();
|
||||
} else {
|
||||
view.animate().alpha(0f)
|
||||
.setDuration(duration)
|
||||
.setListener(new AnimatorListenerAdapter() {
|
||||
@Override
|
||||
public void onAnimationEnd(Animator animation) {
|
||||
view.setVisibility(View.GONE);
|
||||
if (execOnEnd != null) execOnEnd.run();
|
||||
}
|
||||
})
|
||||
.start();
|
||||
}
|
||||
}
|
||||
|
||||
/*//////////////////////////////////////////////////////////////////////////
|
||||
// OnStreamInfoReceivedListener callbacks
|
||||
//////////////////////////////////////////////////////////////////////////*/
|
||||
|
||||
@Override
|
||||
public void onReceive(StreamInfo info) {
|
||||
currentStreamInfo = info;
|
||||
|
||||
loadingProgressBar.setVisibility(View.GONE);
|
||||
thumbnailPlayButton.setVisibility(View.VISIBLE);
|
||||
relatedStreamRootLayout.setVisibility(showRelatedStreams ? View.VISIBLE : View.GONE);
|
||||
parallaxScrollRootView.scrollTo(0, 0);
|
||||
|
||||
// Since newpipe is designed to work even if certain information is not available,
|
||||
// the UI has to react on missing information.
|
||||
videoTitleTextView.setText(info.title);
|
||||
if (!info.uploader.isEmpty()) uploaderTextView.setText(info.uploader);
|
||||
uploaderTextView.setVisibility(!info.uploader.isEmpty() ? View.VISIBLE : View.GONE);
|
||||
uploaderButton.setVisibility(!info.channel_url.isEmpty() ? View.VISIBLE : View.GONE);
|
||||
uploaderThumb.setImageDrawable(ContextCompat.getDrawable(this, R.drawable.buddy));
|
||||
|
||||
if (info.view_count >= 0) videoCountView.setText(Localization.localizeViewCount(info.view_count, this));
|
||||
videoCountView.setVisibility(info.view_count >= 0 ? View.VISIBLE : View.GONE);
|
||||
|
||||
if (info.dislike_count == -1 && info.like_count == -1) {
|
||||
thumbsDownImageView.setVisibility(View.VISIBLE);
|
||||
thumbsUpImageView.setVisibility(View.VISIBLE);
|
||||
thumbsUpTextView.setVisibility(View.GONE);
|
||||
thumbsDownTextView.setVisibility(View.GONE);
|
||||
|
||||
thumbsDisabledTextView.setVisibility(View.VISIBLE);
|
||||
} else {
|
||||
thumbsDisabledTextView.setVisibility(View.GONE);
|
||||
|
||||
if (info.dislike_count >= 0) thumbsDownTextView.setText(Localization.localizeNumber(info.dislike_count, this));
|
||||
thumbsDownTextView.setVisibility(info.dislike_count >= 0 ? View.VISIBLE : View.GONE);
|
||||
thumbsDownImageView.setVisibility(info.dislike_count >= 0 ? View.VISIBLE : View.GONE);
|
||||
|
||||
if (info.like_count >= 0) thumbsUpTextView.setText(Localization.localizeNumber(info.like_count, this));
|
||||
thumbsUpTextView.setVisibility(info.like_count >= 0 ? View.VISIBLE : View.GONE);
|
||||
thumbsUpImageView.setVisibility(info.like_count >= 0 ? View.VISIBLE : View.GONE);
|
||||
}
|
||||
|
||||
if (!info.upload_date.isEmpty()) videoUploadDateView.setText(Localization.localizeDate(info.upload_date, this));
|
||||
videoUploadDateView.setVisibility(!info.upload_date.isEmpty() ? View.VISIBLE : View.GONE);
|
||||
|
||||
if (!info.description.isEmpty()) videoDescriptionView.setText(
|
||||
Build.VERSION.SDK_INT >= 24 ? Html.fromHtml(info.description, 0) : Html.fromHtml(info.description)
|
||||
);
|
||||
videoDescriptionView.setVisibility(!info.description.isEmpty() ? View.VISIBLE : View.GONE);
|
||||
|
||||
videoDescriptionRootLayout.setVisibility(View.GONE);
|
||||
videoTitleToggleArrow.setImageResource(R.drawable.arrow_down);
|
||||
|
||||
setupActionBarHandler(info);
|
||||
initRelatedVideos(info);
|
||||
initThumbnailViews(info);
|
||||
|
||||
animateView(contentRootLayout, true, 200, null);
|
||||
|
||||
isLoading.set(false);
|
||||
if (autoPlayEnabled) playVideo(info);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onError(int messageId) {
|
||||
Toast.makeText(this, messageId, Toast.LENGTH_LONG).show();
|
||||
loadingProgressBar.setVisibility(View.GONE);
|
||||
thumbnailImageView.setImageDrawable(ContextCompat.getDrawable(this, R.drawable.not_available_monkey));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onReCaptchaException() {
|
||||
Toast.makeText(this, R.string.recaptcha_request_toast, Toast.LENGTH_LONG).show();
|
||||
// Starting ReCaptcha Challenge Activity
|
||||
startActivityForResult(new Intent(this, ReCaptchaActivity.class), ReCaptchaActivity.RECAPTCHA_REQUEST);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onBlockedByGemaError() {
|
||||
loadingProgressBar.setVisibility(View.GONE);
|
||||
thumbnailImageView.setImageDrawable(ContextCompat.getDrawable(this, R.drawable.gruese_die_gema));
|
||||
thumbnailBackgroundButton.setOnClickListener(new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
Intent intent = new Intent();
|
||||
intent.setAction(Intent.ACTION_VIEW);
|
||||
intent.setData(Uri.parse(getString(R.string.c3s_url)));
|
||||
startActivity(intent);
|
||||
}
|
||||
});
|
||||
|
||||
Toast.makeText(this, R.string.blocked_by_gema, Toast.LENGTH_LONG).show();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onContentErrorWithMessage(int messageId) {
|
||||
loadingProgressBar.setVisibility(View.GONE);
|
||||
thumbnailImageView.setImageDrawable(ContextCompat.getDrawable(this, R.drawable.not_available_monkey));
|
||||
Toast.makeText(this, messageId, Toast.LENGTH_LONG).show();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onContentError() {
|
||||
loadingProgressBar.setVisibility(View.GONE);
|
||||
thumbnailImageView.setImageDrawable(ContextCompat.getDrawable(this, R.drawable.not_available_monkey));
|
||||
Toast.makeText(this, R.string.content_not_available, Toast.LENGTH_LONG).show();
|
||||
}
|
||||
}
|
||||
|
@ -1,866 +0,0 @@
|
||||
package org.schabi.newpipe.detail;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.content.DialogInterface;
|
||||
import android.content.Intent;
|
||||
import android.graphics.Bitmap;
|
||||
import android.graphics.BitmapFactory;
|
||||
import android.graphics.Point;
|
||||
import android.net.Uri;
|
||||
import android.os.Build;
|
||||
import android.os.Bundle;
|
||||
import android.preference.PreferenceManager;
|
||||
import android.support.design.widget.FloatingActionButton;
|
||||
import android.support.v4.app.Fragment;
|
||||
import android.support.v7.app.AlertDialog;
|
||||
import android.support.v7.app.AppCompatActivity;
|
||||
import android.support.v7.widget.RecyclerView;
|
||||
import android.text.Html;
|
||||
import android.text.method.LinkMovementMethod;
|
||||
import android.util.Log;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.Menu;
|
||||
import android.view.MenuInflater;
|
||||
import android.view.MenuItem;
|
||||
import android.view.MotionEvent;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.Button;
|
||||
import android.widget.ImageView;
|
||||
import android.widget.LinearLayout;
|
||||
import android.widget.ProgressBar;
|
||||
import android.widget.RelativeLayout;
|
||||
import android.widget.TextView;
|
||||
import android.widget.Toast;
|
||||
|
||||
import com.nostra13.universalimageloader.core.DisplayImageOptions;
|
||||
import com.nostra13.universalimageloader.core.ImageLoader;
|
||||
import com.nostra13.universalimageloader.core.assist.FailReason;
|
||||
import com.nostra13.universalimageloader.core.listener.ImageLoadingListener;
|
||||
|
||||
import org.schabi.newpipe.ActivityCommunicator;
|
||||
import org.schabi.newpipe.ImageErrorLoadingListener;
|
||||
import org.schabi.newpipe.Localization;
|
||||
import org.schabi.newpipe.R;
|
||||
import org.schabi.newpipe.ReCaptchaActivity;
|
||||
import org.schabi.newpipe.download.DownloadDialog;
|
||||
import org.schabi.newpipe.extractor.InfoItem;
|
||||
import org.schabi.newpipe.extractor.MediaFormat;
|
||||
import org.schabi.newpipe.extractor.NewPipe;
|
||||
import org.schabi.newpipe.extractor.stream_info.AudioStream;
|
||||
import org.schabi.newpipe.extractor.stream_info.StreamInfo;
|
||||
import org.schabi.newpipe.extractor.stream_info.VideoStream;
|
||||
import org.schabi.newpipe.info_list.InfoItemBuilder;
|
||||
import org.schabi.newpipe.player.AbstractPlayer;
|
||||
import org.schabi.newpipe.player.BackgroundPlayer;
|
||||
import org.schabi.newpipe.player.ExoPlayerActivity;
|
||||
import org.schabi.newpipe.player.PlayVideoActivity;
|
||||
import org.schabi.newpipe.player.PopupVideoPlayer;
|
||||
import org.schabi.newpipe.report.ErrorActivity;
|
||||
import org.schabi.newpipe.util.NavStack;
|
||||
import org.schabi.newpipe.util.PermissionHelper;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Vector;
|
||||
|
||||
import static android.app.Activity.RESULT_OK;
|
||||
import static org.schabi.newpipe.ReCaptchaActivity.RECAPTCHA_REQUEST;
|
||||
|
||||
|
||||
/**
|
||||
* Copyright (C) Christian Schabesberger 2015 <chris.schabesberger@mailbox.org>
|
||||
* VideoItemDetailFragment.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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
public class VideoItemDetailFragment extends Fragment {
|
||||
|
||||
private static final String TAG = VideoItemDetailFragment.class.toString();
|
||||
private static final String KORE_PACKET = "org.xbmc.kore";
|
||||
|
||||
/**
|
||||
* The fragment argument representing the item ID that this fragment
|
||||
* represents.
|
||||
*/
|
||||
public static final String AUTO_PLAY = "auto_play";
|
||||
|
||||
private AppCompatActivity activity;
|
||||
private ActionBarHandler actionBarHandler;
|
||||
private ProgressBar progressBar;
|
||||
|
||||
private int streamingServiceId = -1;
|
||||
|
||||
private boolean autoPlayEnabled;
|
||||
private boolean showNextStreamItem;
|
||||
|
||||
private View thumbnailWindowLayout;
|
||||
//this only remains due to downwards compatibility
|
||||
private FloatingActionButton playVideoButton;
|
||||
private final Point initialThumbnailPos = new Point(0, 0);
|
||||
private View rootView = null;
|
||||
private Bitmap streamThumbnail = null;
|
||||
|
||||
private ImageLoader imageLoader = ImageLoader.getInstance();
|
||||
private DisplayImageOptions displayImageOptions =
|
||||
new DisplayImageOptions.Builder().cacheInMemory(true).build();
|
||||
|
||||
private InfoItemBuilder infoItemBuilder = null;
|
||||
|
||||
public interface OnInvokeCreateOptionsMenuListener {
|
||||
void createOptionsMenu();
|
||||
}
|
||||
|
||||
private OnInvokeCreateOptionsMenuListener onInvokeCreateOptionsMenuListener;
|
||||
|
||||
private void updateInfo(final StreamInfo info) {
|
||||
Activity a = getActivity();
|
||||
|
||||
RelativeLayout textContentLayout =
|
||||
(RelativeLayout) activity.findViewById(R.id.detail_text_content_layout);
|
||||
final TextView videoTitleView =
|
||||
(TextView) activity.findViewById(R.id.detail_video_title_view);
|
||||
TextView uploaderView = (TextView) activity.findViewById(R.id.detail_uploader_view);
|
||||
TextView viewCountView = (TextView) activity.findViewById(R.id.detail_view_count_view);
|
||||
TextView thumbsUpView = (TextView) activity.findViewById(R.id.detail_thumbs_up_count_view);
|
||||
TextView thumbsDownView =
|
||||
(TextView) activity.findViewById(R.id.detail_thumbs_down_count_view);
|
||||
TextView uploadDateView = (TextView) activity.findViewById(R.id.detail_upload_date_view);
|
||||
TextView descriptionView = (TextView) activity.findViewById(R.id.detail_description_view);
|
||||
RecyclerView nextStreamView =
|
||||
(RecyclerView) activity.findViewById(R.id.detail_next_stream_content);
|
||||
RelativeLayout nextVideoRootFrame =
|
||||
(RelativeLayout) activity.findViewById(R.id.detail_next_stream_root_layout);
|
||||
TextView similarTitle = (TextView) activity.findViewById(R.id.detail_similar_title);
|
||||
Button backgroundButton = (Button)
|
||||
activity.findViewById(R.id.detail_stream_thumbnail_window_background_button);
|
||||
View thumbnailView = activity.findViewById(R.id.detail_thumbnail_view);
|
||||
View topView = activity.findViewById(R.id.detailTopView);
|
||||
Button channelButton = (Button) activity.findViewById(R.id.channel_button);
|
||||
|
||||
// prevents a crash if the activity/fragment was already left when the response came
|
||||
if(channelButton != null) {
|
||||
|
||||
progressBar.setVisibility(View.GONE);
|
||||
if (info.next_video != null) {
|
||||
// todo: activate this function or remove it
|
||||
nextStreamView.setVisibility(View.GONE);
|
||||
} else {
|
||||
nextStreamView.setVisibility(View.GONE);
|
||||
activity.findViewById(R.id.detail_similar_title).setVisibility(View.GONE);
|
||||
}
|
||||
|
||||
textContentLayout.setVisibility(View.VISIBLE);
|
||||
if (android.os.Build.VERSION.SDK_INT < 18) {
|
||||
playVideoButton.setVisibility(View.VISIBLE);
|
||||
} else {
|
||||
ImageView playArrowView = (ImageView) activity.findViewById(R.id.play_arrow_view);
|
||||
playArrowView.setVisibility(View.VISIBLE);
|
||||
}
|
||||
|
||||
if (!showNextStreamItem) {
|
||||
nextVideoRootFrame.setVisibility(View.GONE);
|
||||
similarTitle.setVisibility(View.GONE);
|
||||
}
|
||||
|
||||
videoTitleView.setText(info.title);
|
||||
|
||||
topView.setOnTouchListener(new View.OnTouchListener() {
|
||||
@Override
|
||||
public boolean onTouch(View v, MotionEvent event) {
|
||||
if (event.getAction() == android.view.MotionEvent.ACTION_UP) {
|
||||
ImageView arrow = (ImageView) activity.findViewById(R.id.toggle_description_view);
|
||||
View extra = activity.findViewById(R.id.detailExtraView);
|
||||
if (extra.getVisibility() == View.VISIBLE) {
|
||||
extra.setVisibility(View.GONE);
|
||||
arrow.setImageResource(R.drawable.arrow_down);
|
||||
} else {
|
||||
extra.setVisibility(View.VISIBLE);
|
||||
arrow.setImageResource(R.drawable.arrow_up);
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
});
|
||||
|
||||
// Since newpipe is designed to work even if certain information is not available,
|
||||
// the UI has to react on missing information.
|
||||
videoTitleView.setText(info.title);
|
||||
if (!info.uploader.isEmpty()) {
|
||||
uploaderView.setText(info.uploader);
|
||||
} else {
|
||||
activity.findViewById(R.id.detail_uploader_view).setVisibility(View.GONE);
|
||||
}
|
||||
if (info.view_count >= 0) {
|
||||
viewCountView.setText(Localization.localizeViewCount(info.view_count, a));
|
||||
} else {
|
||||
viewCountView.setVisibility(View.GONE);
|
||||
}
|
||||
if (info.dislike_count >= 0) {
|
||||
thumbsDownView.setText(Localization.localizeNumber(info.dislike_count, a));
|
||||
} else {
|
||||
thumbsDownView.setVisibility(View.INVISIBLE);
|
||||
activity.findViewById(R.id.detail_thumbs_down_count_view).setVisibility(View.GONE);
|
||||
}
|
||||
if (info.like_count >= 0) {
|
||||
thumbsUpView.setText(Localization.localizeNumber(info.like_count, a));
|
||||
} else {
|
||||
thumbsUpView.setVisibility(View.GONE);
|
||||
activity.findViewById(R.id.detail_thumbs_up_img_view).setVisibility(View.GONE);
|
||||
thumbsDownView.setVisibility(View.GONE);
|
||||
activity.findViewById(R.id.detail_thumbs_down_img_view).setVisibility(View.GONE);
|
||||
}
|
||||
if (!info.upload_date.isEmpty()) {
|
||||
uploadDateView.setText(Localization.localizeDate(info.upload_date, a));
|
||||
} else {
|
||||
uploadDateView.setVisibility(View.GONE);
|
||||
}
|
||||
if (!info.description.isEmpty()) {
|
||||
descriptionView.setText(Html.fromHtml(info.description));
|
||||
} else {
|
||||
descriptionView.setVisibility(View.GONE);
|
||||
}
|
||||
|
||||
descriptionView.setMovementMethod(LinkMovementMethod.getInstance());
|
||||
|
||||
// parse streams
|
||||
Vector<VideoStream> streamsToUse = new Vector<>();
|
||||
for (VideoStream i : info.video_streams) {
|
||||
if (useStream(i, streamsToUse)) {
|
||||
streamsToUse.add(i);
|
||||
}
|
||||
}
|
||||
|
||||
textContentLayout.setVisibility(View.VISIBLE);
|
||||
|
||||
if (info.next_video == null) {
|
||||
activity.findViewById(R.id.detail_next_stream_title).setVisibility(View.GONE);
|
||||
}
|
||||
|
||||
if (info.related_streams != null && !info.related_streams.isEmpty()) {
|
||||
initSimilarVideos(info);
|
||||
} else {
|
||||
activity.findViewById(R.id.detail_similar_title).setVisibility(View.GONE);
|
||||
activity.findViewById(R.id.similar_streams_view).setVisibility(View.GONE);
|
||||
}
|
||||
|
||||
setupActionBarHandler(info);
|
||||
|
||||
if (autoPlayEnabled) {
|
||||
playVideo(info);
|
||||
}
|
||||
|
||||
if (android.os.Build.VERSION.SDK_INT < 18) {
|
||||
playVideoButton.setOnClickListener(new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
playVideo(info);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
backgroundButton.setOnClickListener(new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
playVideo(info);
|
||||
}
|
||||
});
|
||||
|
||||
//todo: make backgroundButton handle this
|
||||
thumbnailView.setOnClickListener(new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
playVideo(info);
|
||||
}
|
||||
});
|
||||
|
||||
if (info.channel_url != null && info.channel_url != "") {
|
||||
channelButton.setOnClickListener(new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View view) {
|
||||
NavStack.getInstance()
|
||||
.openChannelActivity(getActivity(), info.channel_url, info.service_id);
|
||||
}
|
||||
});
|
||||
} else {
|
||||
channelButton.setVisibility(Button.GONE);
|
||||
}
|
||||
|
||||
initThumbnailViews(info);
|
||||
}
|
||||
}
|
||||
|
||||
private void initThumbnailViews(final StreamInfo info) {
|
||||
ImageView videoThumbnailView = (ImageView) activity.findViewById(R.id.detail_thumbnail_view);
|
||||
ImageView uploaderThumb
|
||||
= (ImageView) activity.findViewById(R.id.detail_uploader_thumbnail_view);
|
||||
|
||||
if (info.thumbnail_url != null && !info.thumbnail_url.isEmpty()) {
|
||||
imageLoader.displayImage(info.thumbnail_url, videoThumbnailView,
|
||||
displayImageOptions, new ImageLoadingListener() {
|
||||
@Override
|
||||
public void onLoadingStarted(String imageUri, View view) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onLoadingFailed(String imageUri, View view, FailReason failReason) {
|
||||
ErrorActivity.reportError(getActivity(),
|
||||
failReason.getCause(), null, rootView,
|
||||
ErrorActivity.ErrorInfo.make(ErrorActivity.LOAD_IMAGE,
|
||||
NewPipe.getNameOfService(info.service_id), imageUri,
|
||||
R.string.could_not_load_thumbnails));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onLoadingComplete(String imageUri, View view, Bitmap loadedImage) {
|
||||
streamThumbnail = loadedImage;
|
||||
|
||||
if (streamThumbnail != null) {
|
||||
// TODO: Change the thumbnail implementation
|
||||
|
||||
// When the thumbnail is not loaded yet, it not passes to the service in time
|
||||
// so, I can notify the service through a broadcast, but the problem is
|
||||
// when I click in another video, another thumbnail will be load, and will
|
||||
// notify again, so I send the videoUrl and compare with the service's url
|
||||
if (getContext() != null) {
|
||||
ActivityCommunicator.getCommunicator().backgroundPlayerThumbnail = streamThumbnail;
|
||||
Intent intent = new Intent(AbstractPlayer.ACTION_UPDATE_THUMB);
|
||||
intent.putExtra(AbstractPlayer.VIDEO_URL, info.webpage_url);
|
||||
getContext().sendBroadcast(intent);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onLoadingCancelled(String imageUri, View view) {
|
||||
}
|
||||
});
|
||||
} else {
|
||||
videoThumbnailView.setImageResource(R.drawable.dummy_thumbnail_dark);
|
||||
}
|
||||
if (info.uploader_thumbnail_url != null && !info.uploader_thumbnail_url.isEmpty()) {
|
||||
imageLoader.displayImage(info.uploader_thumbnail_url,
|
||||
uploaderThumb, displayImageOptions,
|
||||
new ImageErrorLoadingListener(activity, rootView, info.service_id));
|
||||
}
|
||||
}
|
||||
|
||||
private void setupActionBarHandler(final StreamInfo info) {
|
||||
actionBarHandler.setupStreamList(info.video_streams);
|
||||
|
||||
actionBarHandler.setOnShareListener(new ActionBarHandler.OnActionListener() {
|
||||
@Override
|
||||
public void onActionSelected(int selectedStreamId) {
|
||||
Intent intent = new Intent();
|
||||
intent.setAction(Intent.ACTION_SEND);
|
||||
intent.putExtra(Intent.EXTRA_TEXT, info.webpage_url);
|
||||
intent.setType("text/plain");
|
||||
activity.startActivity(Intent.createChooser(intent, activity.getString(R.string.share_dialog_title)));
|
||||
}
|
||||
});
|
||||
|
||||
actionBarHandler.setOnOpenInBrowserListener(new ActionBarHandler.OnActionListener() {
|
||||
@Override
|
||||
public void onActionSelected(int selectedStreamId) {
|
||||
Intent intent = new Intent();
|
||||
intent.setAction(Intent.ACTION_VIEW);
|
||||
intent.setData(Uri.parse(info.webpage_url));
|
||||
|
||||
activity.startActivity(Intent.createChooser(intent, activity.getString(R.string.choose_browser)));
|
||||
}
|
||||
});
|
||||
|
||||
actionBarHandler.setOnOpenInPopupListener(new ActionBarHandler.OnActionListener() {
|
||||
@Override
|
||||
public void onActionSelected(int selectedStreamId) {
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M
|
||||
&& !PermissionHelper.checkSystemAlertWindowPermission(activity)) {
|
||||
Toast.makeText(activity, R.string.msg_popup_permission, Toast.LENGTH_LONG).show();
|
||||
return;
|
||||
}
|
||||
if (streamThumbnail != null)
|
||||
ActivityCommunicator.getCommunicator().backgroundPlayerThumbnail = streamThumbnail;
|
||||
|
||||
Intent i = new Intent(activity, PopupVideoPlayer.class);
|
||||
Toast.makeText(activity, R.string.popup_playing_toast, Toast.LENGTH_SHORT).show();
|
||||
i.putExtra(AbstractPlayer.VIDEO_TITLE, info.title)
|
||||
.putExtra(AbstractPlayer.CHANNEL_NAME, info.uploader)
|
||||
.putExtra(AbstractPlayer.VIDEO_URL, info.webpage_url)
|
||||
.putExtra(AbstractPlayer.INDEX_SEL_VIDEO_STREAM, selectedStreamId)
|
||||
.putExtra(AbstractPlayer.VIDEO_STREAMS_LIST, new ArrayList<>(info.video_streams));
|
||||
if (info.start_position > 0) i.putExtra(AbstractPlayer.START_POSITION, info.start_position * 1000);
|
||||
|
||||
activity.startService(i);
|
||||
}
|
||||
});
|
||||
|
||||
actionBarHandler.setOnPlayWithKodiListener(new ActionBarHandler.OnActionListener() {
|
||||
@Override
|
||||
public void onActionSelected(int selectedStreamId) {
|
||||
try {
|
||||
Intent intent = new Intent(Intent.ACTION_VIEW);
|
||||
intent.setPackage(KORE_PACKET);
|
||||
intent.setData(Uri.parse(info.webpage_url.replace("https", "http")));
|
||||
activity.startActivity(intent);
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
AlertDialog.Builder builder = new AlertDialog.Builder(activity);
|
||||
builder.setMessage(R.string.kore_not_found)
|
||||
.setPositiveButton(R.string.install, new DialogInterface.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(DialogInterface dialog, int which) {
|
||||
Intent intent = new Intent();
|
||||
intent.setAction(Intent.ACTION_VIEW);
|
||||
intent.setData(Uri.parse(activity.getString(R.string.fdroid_kore_url)));
|
||||
activity.startActivity(intent);
|
||||
}
|
||||
})
|
||||
.setNegativeButton(R.string.cancel, new DialogInterface.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(DialogInterface dialog, int which) {
|
||||
|
||||
}
|
||||
});
|
||||
builder.create().show();
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
actionBarHandler.setOnDownloadListener(new ActionBarHandler.OnActionListener() {
|
||||
@Override
|
||||
public void onActionSelected(int selectedStreamId) {
|
||||
if(!PermissionHelper.checkStoragePermissions(getActivity())) {
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
Bundle args = new Bundle();
|
||||
|
||||
// Sometimes it may be that some information is not available due to changes fo the
|
||||
// website which was crawled. Then the ui has to understand this and act right.
|
||||
|
||||
if (info.audio_streams != null) {
|
||||
AudioStream audioStream =
|
||||
info.audio_streams.get(getPreferredAudioStreamId(info));
|
||||
|
||||
String audioSuffix = "." + MediaFormat.getSuffixById(audioStream.format);
|
||||
args.putString(DownloadDialog.AUDIO_URL, audioStream.url);
|
||||
args.putString(DownloadDialog.FILE_SUFFIX_AUDIO, audioSuffix);
|
||||
}
|
||||
|
||||
if (info.video_streams != null) {
|
||||
VideoStream selectedStreamItem = info.video_streams.get(selectedStreamId);
|
||||
String videoSuffix = "." + MediaFormat.getSuffixById(selectedStreamItem.format);
|
||||
args.putString(DownloadDialog.FILE_SUFFIX_VIDEO, videoSuffix);
|
||||
args.putString(DownloadDialog.VIDEO_URL, selectedStreamItem.url);
|
||||
}
|
||||
|
||||
args.putString(DownloadDialog.TITLE, info.title);
|
||||
DownloadDialog downloadDialog = DownloadDialog.newInstance(args);
|
||||
downloadDialog.show(activity.getSupportFragmentManager(), "downloadDialog");
|
||||
} catch (Exception e) {
|
||||
Toast.makeText(VideoItemDetailFragment.this.getActivity(),
|
||||
R.string.could_not_setup_download_menu, Toast.LENGTH_LONG).show();
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
if (info.audio_streams == null) {
|
||||
actionBarHandler.showAudioAction(false);
|
||||
} else {
|
||||
actionBarHandler.setOnPlayAudioListener(new ActionBarHandler.OnActionListener() {
|
||||
@Override
|
||||
public void onActionSelected(int selectedStreamId) {
|
||||
boolean useExternalAudioPlayer = PreferenceManager.getDefaultSharedPreferences(activity)
|
||||
.getBoolean(activity.getString(R.string.use_external_audio_player_key), false);
|
||||
Intent intent;
|
||||
AudioStream audioStream =
|
||||
info.audio_streams.get(getPreferredAudioStreamId(info));
|
||||
if (!useExternalAudioPlayer && android.os.Build.VERSION.SDK_INT >= 18) {
|
||||
//internal music player: explicit intent
|
||||
if (!BackgroundPlayer.isRunning && streamThumbnail != null) {
|
||||
ActivityCommunicator.getCommunicator()
|
||||
.backgroundPlayerThumbnail = streamThumbnail;
|
||||
intent = new Intent(activity, BackgroundPlayer.class);
|
||||
|
||||
intent.setAction(Intent.ACTION_VIEW);
|
||||
Log.i(TAG, "audioStream is null:" + (audioStream == null));
|
||||
Log.i(TAG, "audioStream.url is null:" + (audioStream.url == null));
|
||||
intent.setDataAndType(Uri.parse(audioStream.url),
|
||||
MediaFormat.getMimeById(audioStream.format));
|
||||
intent.putExtra(BackgroundPlayer.TITLE, info.title);
|
||||
intent.putExtra(BackgroundPlayer.WEB_URL, info.webpage_url);
|
||||
intent.putExtra(BackgroundPlayer.SERVICE_ID, streamingServiceId);
|
||||
intent.putExtra(BackgroundPlayer.CHANNEL_NAME, info.uploader);
|
||||
activity.startService(intent);
|
||||
}
|
||||
} else {
|
||||
intent = new Intent();
|
||||
try {
|
||||
intent.setAction(Intent.ACTION_VIEW);
|
||||
intent.setDataAndType(Uri.parse(audioStream.url),
|
||||
MediaFormat.getMimeById(audioStream.format));
|
||||
intent.putExtra(Intent.EXTRA_TITLE, info.title);
|
||||
intent.putExtra("title", info.title);
|
||||
// HERE !!!
|
||||
activity.startActivity(intent);
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
AlertDialog.Builder builder = new AlertDialog.Builder(activity);
|
||||
builder.setMessage(R.string.no_player_found)
|
||||
.setPositiveButton(R.string.install, new DialogInterface.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(DialogInterface dialog, int which) {
|
||||
Intent intent = new Intent();
|
||||
intent.setAction(Intent.ACTION_VIEW);
|
||||
intent.setData(Uri.parse(activity.getString(R.string.fdroid_vlc_url)));
|
||||
activity.startActivity(intent);
|
||||
}
|
||||
})
|
||||
.setNegativeButton(R.string.cancel, new DialogInterface.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(DialogInterface dialog, int which) {
|
||||
Log.i(TAG, "You unlocked a secret unicorn.");
|
||||
}
|
||||
});
|
||||
builder.create().show();
|
||||
Log.e(TAG, "Either no Streaming player for audio was installed, or something important crashed:");
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
private int getPreferredAudioStreamId(final StreamInfo info) {
|
||||
String preferredFormatString = PreferenceManager.getDefaultSharedPreferences(getActivity())
|
||||
.getString(activity.getString(R.string.default_audio_format_key), "webm");
|
||||
|
||||
int preferredFormat = MediaFormat.WEBMA.id;
|
||||
switch(preferredFormatString) {
|
||||
case "webm":
|
||||
preferredFormat = MediaFormat.WEBMA.id;
|
||||
break;
|
||||
case "m4a":
|
||||
preferredFormat = MediaFormat.M4A.id;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
for(int i = 0; i < info.audio_streams.size(); i++) {
|
||||
if(info.audio_streams.get(i).format == preferredFormat) {
|
||||
return i;
|
||||
}
|
||||
}
|
||||
|
||||
//todo: make this a proper error
|
||||
Log.e(TAG, "FAILED to set audioStream value!");
|
||||
return 0;
|
||||
}
|
||||
|
||||
private void initSimilarVideos(final StreamInfo info) {
|
||||
LinearLayout similarLayout = (LinearLayout) activity.findViewById(R.id.similar_streams_view);
|
||||
for (final InfoItem item : info.related_streams) {
|
||||
similarLayout.addView(infoItemBuilder.buildView(similarLayout, item));
|
||||
}
|
||||
infoItemBuilder.setOnStreamInfoItemSelectedListener(
|
||||
new InfoItemBuilder.OnInfoItemSelectedListener() {
|
||||
@Override
|
||||
public void selected(String url, int serviceId) {
|
||||
NavStack.getInstance()
|
||||
.openDetailActivity(getContext(), url, serviceId);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private void onErrorBlockedByGema() {
|
||||
Button backgroundButton = (Button)
|
||||
activity.findViewById(R.id.detail_stream_thumbnail_window_background_button);
|
||||
ImageView thumbnailView = (ImageView) activity.findViewById(R.id.detail_thumbnail_view);
|
||||
|
||||
progressBar.setVisibility(View.GONE);
|
||||
thumbnailView.setImageBitmap(BitmapFactory.decodeResource(
|
||||
getResources(), R.drawable.gruese_die_gema));
|
||||
backgroundButton.setOnClickListener(new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
Intent intent = new Intent();
|
||||
intent.setAction(Intent.ACTION_VIEW);
|
||||
intent.setData(Uri.parse(activity.getString(R.string.c3s_url)));
|
||||
activity.startActivity(intent);
|
||||
}
|
||||
});
|
||||
|
||||
Toast.makeText(VideoItemDetailFragment.this.getActivity(),
|
||||
R.string.blocked_by_gema, Toast.LENGTH_LONG).show();
|
||||
}
|
||||
|
||||
private void onNotSpecifiedContentError() {
|
||||
ImageView thumbnailView = (ImageView) activity.findViewById(R.id.detail_thumbnail_view);
|
||||
progressBar.setVisibility(View.GONE);
|
||||
thumbnailView.setImageBitmap(BitmapFactory.decodeResource(
|
||||
getResources(), R.drawable.not_available_monkey));
|
||||
Toast.makeText(activity, R.string.content_not_available, Toast.LENGTH_LONG)
|
||||
.show();
|
||||
}
|
||||
|
||||
private void onNotSpecifiedContentErrorWithMessage(int resourceId) {
|
||||
ImageView thumbnailView = (ImageView) activity.findViewById(R.id.detail_thumbnail_view);
|
||||
progressBar.setVisibility(View.GONE);
|
||||
thumbnailView.setImageBitmap(BitmapFactory.decodeResource(
|
||||
getResources(), R.drawable.not_available_monkey));
|
||||
Toast.makeText(activity, resourceId, Toast.LENGTH_LONG)
|
||||
.show();
|
||||
}
|
||||
|
||||
private boolean useStream(VideoStream stream, Vector<VideoStream> streams) {
|
||||
for(VideoStream i : streams) {
|
||||
if(i.resolution.equals(stream.resolution)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
activity = (AppCompatActivity) getActivity();
|
||||
showNextStreamItem = PreferenceManager.getDefaultSharedPreferences(getActivity())
|
||||
.getBoolean(activity.getString(R.string.show_next_video_key), true);
|
||||
|
||||
|
||||
StreamInfoWorker siw = StreamInfoWorker.getInstance();
|
||||
siw.setOnStreamInfoReceivedListener(new StreamInfoWorker.OnStreamInfoReceivedListener() {
|
||||
@Override
|
||||
public void onReceive(StreamInfo info) {
|
||||
updateInfo(info);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onError(int messageId) {
|
||||
postNewErrorToast(messageId);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onReCaptchaException() {
|
||||
Toast.makeText(getActivity(), R.string.recaptcha_request_toast,
|
||||
Toast.LENGTH_LONG).show();
|
||||
|
||||
// Starting ReCaptcha Challenge Activity
|
||||
startActivityForResult(
|
||||
new Intent(getActivity(), ReCaptchaActivity.class),
|
||||
RECAPTCHA_REQUEST);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onBlockedByGemaError() {
|
||||
onErrorBlockedByGema();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onContentErrorWithMessage(int messageId) {
|
||||
onNotSpecifiedContentErrorWithMessage(messageId);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onContentError() {
|
||||
onNotSpecifiedContentError();
|
||||
}
|
||||
});
|
||||
setHasOptionsMenu(true);
|
||||
}
|
||||
|
||||
@Override
|
||||
public View onCreateView(LayoutInflater inflater, ViewGroup container,
|
||||
Bundle savedInstanceState) {
|
||||
rootView = inflater.inflate(R.layout.fragment_videoitem_detail, container, false);
|
||||
progressBar = (ProgressBar) rootView.findViewById(R.id.detail_progress_bar);
|
||||
|
||||
actionBarHandler = new ActionBarHandler(activity);
|
||||
actionBarHandler.setupNavMenu(activity);
|
||||
if(onInvokeCreateOptionsMenuListener != null) {
|
||||
onInvokeCreateOptionsMenuListener.createOptionsMenu();
|
||||
}
|
||||
|
||||
return rootView;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onStart() {
|
||||
super.onStart();
|
||||
Activity a = getActivity();
|
||||
infoItemBuilder = new InfoItemBuilder(a, a.findViewById(android.R.id.content));
|
||||
|
||||
if (android.os.Build.VERSION.SDK_INT < 18) {
|
||||
playVideoButton = (FloatingActionButton) a.findViewById(R.id.play_video_button);
|
||||
}
|
||||
thumbnailWindowLayout = a.findViewById(R.id.detail_stream_thumbnail_window_layout);
|
||||
Button backgroundButton = (Button)
|
||||
a.findViewById(R.id.detail_stream_thumbnail_window_background_button);
|
||||
|
||||
// Sometimes when this fragment is not visible it still gets initiated
|
||||
// then we must not try to access objects of this fragment.
|
||||
// Otherwise the applications would crash.
|
||||
if(backgroundButton != null) {
|
||||
streamingServiceId = getArguments().getInt(NavStack.SERVICE_ID);
|
||||
String videoUrl = getArguments().getString(NavStack.URL);
|
||||
StreamInfoWorker siw = StreamInfoWorker.getInstance();
|
||||
siw.search(streamingServiceId, videoUrl, getActivity());
|
||||
|
||||
autoPlayEnabled = getArguments().getBoolean(AUTO_PLAY);
|
||||
|
||||
if(Build.VERSION.SDK_INT >= 18) {
|
||||
ImageView thumbnailView = (ImageView) activity.findViewById(R.id.detail_thumbnail_view);
|
||||
thumbnailView.addOnLayoutChangeListener(new View.OnLayoutChangeListener() {
|
||||
// This is used to synchronize the thumbnailWindowButton and the playVideoButton
|
||||
// inside the ScrollView with the actual size of the thumbnail.
|
||||
//todo: onLayoutChage sometimes not triggered
|
||||
// background buttons area seem to overlap the thumbnail view
|
||||
// So although you just clicked slightly beneath the thumbnail the action still
|
||||
// gets triggered.
|
||||
@Override
|
||||
public void onLayoutChange(View v, int left, int top, int right, int bottom,
|
||||
int oldLeft, int oldTop, int oldRight, int oldBottom) {
|
||||
RelativeLayout.LayoutParams newWindowLayoutParams =
|
||||
(RelativeLayout.LayoutParams) thumbnailWindowLayout.getLayoutParams();
|
||||
newWindowLayoutParams.height = bottom - top;
|
||||
thumbnailWindowLayout.setLayoutParams(newWindowLayoutParams);
|
||||
|
||||
//noinspection SuspiciousNameCombination
|
||||
initialThumbnailPos.set(top, left);
|
||||
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void playVideo(final StreamInfo info) {
|
||||
// ----------- THE MAGIC MOMENT ---------------
|
||||
VideoStream selectedVideoStream =
|
||||
info.video_streams.get(actionBarHandler.getSelectedVideoStream());
|
||||
|
||||
if (PreferenceManager.getDefaultSharedPreferences(activity)
|
||||
.getBoolean(activity.getString(R.string.use_external_video_player_key), false)) {
|
||||
|
||||
// External Player
|
||||
Intent intent = new Intent();
|
||||
try {
|
||||
intent.setAction(Intent.ACTION_VIEW)
|
||||
.setDataAndType(Uri.parse(selectedVideoStream.url),
|
||||
MediaFormat.getMimeById(selectedVideoStream.format))
|
||||
.putExtra(Intent.EXTRA_TITLE, info.title)
|
||||
.putExtra("title", info.title);
|
||||
|
||||
activity.startActivity(intent); // HERE !!!
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
AlertDialog.Builder builder = new AlertDialog.Builder(activity);
|
||||
builder.setMessage(R.string.no_player_found)
|
||||
.setPositiveButton(R.string.install, new DialogInterface.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(DialogInterface dialog, int which) {
|
||||
Intent intent = new Intent()
|
||||
.setAction(Intent.ACTION_VIEW)
|
||||
.setData(Uri.parse(activity.getString(R.string.fdroid_vlc_url)));
|
||||
activity.startActivity(intent);
|
||||
}
|
||||
})
|
||||
.setNegativeButton(R.string.cancel, new DialogInterface.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(DialogInterface dialog, int which) {
|
||||
|
||||
}
|
||||
});
|
||||
builder.create().show();
|
||||
}
|
||||
} else {
|
||||
Intent intent;
|
||||
boolean useOldPlayer = PreferenceManager
|
||||
.getDefaultSharedPreferences(activity)
|
||||
.getBoolean(activity.getString(R.string.use_old_player_key), false)
|
||||
|| (Build.VERSION.SDK_INT < 16);
|
||||
if (!useOldPlayer) {
|
||||
// ExoPlayer
|
||||
if (streamThumbnail != null) ActivityCommunicator.getCommunicator().backgroundPlayerThumbnail = streamThumbnail;
|
||||
intent = new Intent(activity, ExoPlayerActivity.class)
|
||||
.putExtra(AbstractPlayer.VIDEO_TITLE, info.title)
|
||||
.putExtra(AbstractPlayer.VIDEO_URL, info.webpage_url)
|
||||
.putExtra(AbstractPlayer.CHANNEL_NAME, info.uploader)
|
||||
.putExtra(AbstractPlayer.INDEX_SEL_VIDEO_STREAM, actionBarHandler.getSelectedVideoStream())
|
||||
.putExtra(AbstractPlayer.VIDEO_STREAMS_LIST, new ArrayList<>(info.video_streams));
|
||||
if (info.start_position > 0) intent.putExtra(AbstractPlayer.START_POSITION, info.start_position * 1000);
|
||||
} else {
|
||||
// Internal Player
|
||||
intent = new Intent(activity, PlayVideoActivity.class)
|
||||
.putExtra(PlayVideoActivity.VIDEO_TITLE, info.title)
|
||||
.putExtra(PlayVideoActivity.STREAM_URL, selectedVideoStream.url)
|
||||
.putExtra(PlayVideoActivity.VIDEO_URL, info.webpage_url)
|
||||
.putExtra(PlayVideoActivity.START_POSITION, info.start_position);
|
||||
}
|
||||
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
|
||||
activity.startActivity(intent);
|
||||
}
|
||||
|
||||
// --------------------------------------------
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
|
||||
super.onCreateOptionsMenu(menu, inflater);
|
||||
actionBarHandler.setupMenu(menu, inflater);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onOptionsItemSelected(MenuItem item) {
|
||||
if(!actionBarHandler.onItemSelected(item)) {
|
||||
return super.onOptionsItemSelected(item);
|
||||
} else {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
public void setOnInvokeCreateOptionsMenuListener(OnInvokeCreateOptionsMenuListener listener) {
|
||||
this.onInvokeCreateOptionsMenuListener = listener;
|
||||
}
|
||||
|
||||
private void postNewErrorToast(final int stringResource) {
|
||||
Toast.makeText(VideoItemDetailFragment.this.getActivity(),
|
||||
stringResource, Toast.LENGTH_LONG).show();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onActivityResult(int requestCode, int resultCode, Intent data) {
|
||||
super.onActivityResult(requestCode, resultCode, data);
|
||||
switch (requestCode) {
|
||||
case RECAPTCHA_REQUEST:
|
||||
if (resultCode == RESULT_OK) {
|
||||
String videoUrl = getArguments().getString(NavStack.URL);
|
||||
StreamInfoWorker siw = StreamInfoWorker.getInstance();
|
||||
siw.search(streamingServiceId, videoUrl, getActivity());
|
||||
} else {
|
||||
Log.d(TAG, "ReCaptcha failed");
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
Log.e(TAG, "Request code from activity not supported [" + requestCode + "]");
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
@ -273,7 +273,7 @@ public class PopupVideoPlayer extends Service {
|
||||
.putExtra(NavStack.URL, videoUrl)
|
||||
.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
|
||||
context.startActivity(i);
|
||||
//NavStack.getInstance().openDetailActivity(context, videoUrl, 0);
|
||||
context.sendBroadcast(new Intent(Intent.ACTION_CLOSE_SYSTEM_DIALOGS));
|
||||
}
|
||||
|
||||
/*//////////////////////////////////////////////////////////////////////////
|
||||
|
@ -5,13 +5,10 @@ import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.os.Bundle;
|
||||
import android.support.v4.app.NavUtils;
|
||||
import android.support.v7.app.AppCompatActivity;
|
||||
import android.util.Log;
|
||||
|
||||
import org.schabi.newpipe.ChannelActivity;
|
||||
import org.schabi.newpipe.MainActivity;
|
||||
import org.schabi.newpipe.detail.VideoItemDetailActivity;
|
||||
import org.schabi.newpipe.detail.VideoItemDetailFragment;
|
||||
import org.schabi.newpipe.extractor.NewPipe;
|
||||
import org.schabi.newpipe.extractor.StreamingService;
|
||||
|
||||
|
@ -7,18 +7,21 @@ import org.schabi.newpipe.R;
|
||||
|
||||
public class ThemeHelper {
|
||||
|
||||
public static void setTheme(Context context, boolean mode) {
|
||||
// mode is true for normal theme, false for no action bar theme.
|
||||
|
||||
/**
|
||||
* Apply the selected theme (on NewPipe settings) in the context
|
||||
*
|
||||
* @param context context that the theme will be applied
|
||||
* @param useActionbarTheme whether to use an action bar theme or not
|
||||
*/
|
||||
public static void setTheme(Context context, boolean useActionbarTheme) {
|
||||
String themeKey = context.getString(R.string.theme_key);
|
||||
//String lightTheme = context.getResources().getString(R.string.light_theme_title);
|
||||
String darkTheme = context.getResources().getString(R.string.dark_theme_title);
|
||||
String blackTheme = context.getResources().getString(R.string.black_theme_title);
|
||||
|
||||
String sp = PreferenceManager.getDefaultSharedPreferences(context)
|
||||
.getString(themeKey, context.getResources().getString(R.string.light_theme_title));
|
||||
|
||||
if (mode) {
|
||||
if (useActionbarTheme) {
|
||||
if (sp.equals(darkTheme)) context.setTheme(R.style.DarkTheme);
|
||||
else if (sp.equals(blackTheme)) context.setTheme(R.style.BlackTheme);
|
||||
else context.setTheme(R.style.AppTheme);
|
||||
|
@ -1,279 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
|
||||
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
tools:context=".detail.VideoItemDetailFragment"
|
||||
android:textIsSelectable="true"
|
||||
style="?android:attr/textAppearanceLarge"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:id="@+id/video_item_detail">
|
||||
|
||||
<ProgressBar android:id="@+id/detail_progress_bar"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_centerInParent="true"
|
||||
android:indeterminate="true"/>
|
||||
|
||||
<com.nirhart.parallaxscroll.views.ParallaxScrollView
|
||||
android:id="@+id/detail_main_content"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:visibility="visible"
|
||||
app:parallax_factor="1.9"
|
||||
tools:ignore="UselessParent">
|
||||
|
||||
<RelativeLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content">
|
||||
|
||||
<RelativeLayout
|
||||
android:id="@+id/detail_stream_thumbnail_window_layout"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:background="?attr/selectableItemBackground">
|
||||
|
||||
<ImageView android:id="@+id/detail_thumbnail_view"
|
||||
android:contentDescription="@string/detail_thumbnail_view_description"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:scaleType="fitCenter"
|
||||
android:adjustViewBounds="true"
|
||||
android:layout_alignParentLeft="true"
|
||||
android:layout_alignParentStart="true"
|
||||
android:layout_alignParentTop="true"
|
||||
android:background="@android:color/black"
|
||||
android:src="@drawable/dummy_thumbnail_dark"/>
|
||||
|
||||
<ImageView android:id="@+id/play_arrow_view"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:background="@android:color/transparent"
|
||||
android:layout_centerInParent="true"
|
||||
android:src="@drawable/new_play_arrow"
|
||||
android:visibility="invisible"/>
|
||||
|
||||
<Button
|
||||
android:id="@+id/detail_stream_thumbnail_window_background_button"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:background="?attr/selectableItemBackground"/>
|
||||
|
||||
</RelativeLayout>
|
||||
|
||||
<RelativeLayout android:id="@+id/detail_text_content_layout"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_below="@id/detail_stream_thumbnail_window_layout"
|
||||
android:background="?android:windowBackground"
|
||||
android:visibility="gone">
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:id="@+id/detailTopView">
|
||||
|
||||
<TextView android:id="@+id/detail_video_title_view"
|
||||
android:layout_width="0dp"
|
||||
android:layout_weight=".7"
|
||||
android:layout_height="wrap_content"
|
||||
android:textSize="@dimen/video_item_detail_title_text_size"
|
||||
android:textAppearance="?android:attr/textAppearanceLarge"
|
||||
android:layout_marginTop="12dp"
|
||||
android:layout_marginLeft="12dp"
|
||||
android:layout_marginStart="12dp"
|
||||
android:text="Title"/>
|
||||
|
||||
<ImageView
|
||||
android:layout_width="15dp"
|
||||
android:layout_height="30dp"
|
||||
android:id="@+id/toggle_description_view"
|
||||
android:src="@drawable/arrow_down"
|
||||
android:layout_marginLeft="10dp"
|
||||
android:layout_marginStart="10dp"
|
||||
android:layout_marginRight="10dp"
|
||||
android:layout_marginEnd="10dp"
|
||||
android:layout_marginTop="8dp"/>
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
<TextView android:id="@+id/detail_view_count_view"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:textSize="@dimen/video_item_detail_views_text_size"
|
||||
android:textAppearance="?android:attr/textAppearanceLarge"
|
||||
android:layout_marginLeft="12dp"
|
||||
android:layout_marginStart="12dp"
|
||||
android:text="10,069,948 views"
|
||||
android:layout_below="@id/detailTopView"
|
||||
android:layout_alignParentLeft="true"
|
||||
android:layout_alignParentStart="true"
|
||||
android:layout_marginTop="5dp" />
|
||||
|
||||
<RelativeLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_below="@id/detail_view_count_view"
|
||||
android:id="@+id/detailExtraView"
|
||||
android:layout_marginLeft="12dp"
|
||||
android:layout_marginStart="12dp"
|
||||
android:layout_marginRight="12dp"
|
||||
android:layout_marginEnd="12dp"
|
||||
android:visibility="gone">
|
||||
<TextView android:id="@+id/detail_upload_date_view"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:textSize="@dimen/video_item_detail_upload_date_text_size"
|
||||
android:textAppearance="?android:attr/textAppearanceMedium"
|
||||
android:text="Upload date"
|
||||
android:layout_marginTop="3dp" />
|
||||
|
||||
<TextView android:id="@+id/detail_description_view"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:textSize="@dimen/video_item_detail_description_text_size"
|
||||
android:textAppearance="?android:attr/textAppearanceMedium"
|
||||
android:layout_below="@id/detail_upload_date_view"
|
||||
android:text="Description............."
|
||||
android:layout_marginTop="3dp" />
|
||||
</RelativeLayout>
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:id="@+id/stream_info_layout"
|
||||
android:layout_marginLeft="12dp"
|
||||
android:layout_marginStart="12dp"
|
||||
android:layout_below="@+id/detailExtraView"
|
||||
android:layout_alignParentRight="true"
|
||||
android:layout_alignParentEnd="true"
|
||||
android:layout_marginTop="5dp">
|
||||
<ImageView android:id="@+id/detail_thumbs_up_img_view"
|
||||
android:contentDescription="@string/detail_likes_img_view_description"
|
||||
android:layout_width="@dimen/video_item_detail_like_image_width"
|
||||
android:layout_height="@dimen/video_item_detail_like_image_height"
|
||||
android:src="?attr/thumbs_up"/>
|
||||
|
||||
<TextView android:id="@+id/detail_thumbs_up_count_view"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:textSize="@dimen/video_item_detail_likes_text_size"
|
||||
android:textAppearance="?android:attr/textAppearanceMedium"
|
||||
android:text="200" />
|
||||
|
||||
<ImageView android:id="@+id/detail_thumbs_down_img_view"
|
||||
android:contentDescription="@string/detail_dislikes_img_view_description"
|
||||
android:layout_width="@dimen/video_item_detail_like_image_width"
|
||||
android:layout_height="@dimen/video_item_detail_like_image_height"
|
||||
android:src="?attr/thumbs_down"
|
||||
android:layout_marginLeft="10dp"
|
||||
android:layout_marginStart="10dp"/>
|
||||
|
||||
<TextView android:id="@+id/detail_thumbs_down_count_view"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:textSize="@dimen/video_item_detail_likes_text_size"
|
||||
android:textAppearance="?android:attr/textAppearanceMedium"
|
||||
android:text="100" />
|
||||
</LinearLayout>
|
||||
|
||||
<FrameLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:id="@+id/detail_uploader_frame"
|
||||
android:layout_below="@id/stream_info_layout">
|
||||
<RelativeLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:id="@+id/detail_uploader_layout"
|
||||
android:layout_marginTop="12dp">
|
||||
|
||||
<View
|
||||
android:background="#000"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="1px" />
|
||||
|
||||
<de.hdodenhof.circleimageview.CircleImageView
|
||||
android:id="@+id/detail_uploader_thumbnail_view"
|
||||
android:contentDescription="@string/detail_uploader_thumbnail_view_description"
|
||||
android:layout_width="@dimen/video_item_detail_uploader_image_size"
|
||||
android:layout_height="@dimen/video_item_detail_uploader_image_size"
|
||||
android:src="@drawable/buddy"
|
||||
android:layout_marginLeft="10dp"
|
||||
android:layout_marginStart="10dp"
|
||||
android:layout_alignParentLeft="true"
|
||||
android:layout_alignParentStart="true"
|
||||
android:layout_marginTop="5dp"
|
||||
android:layout_marginBottom="5dp"/>
|
||||
|
||||
<TextView android:id="@+id/detail_uploader_view"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:textStyle="bold"
|
||||
android:textSize="@dimen/video_item_detail_uploader_text_size"
|
||||
android:textAppearance="?android:attr/textAppearanceLarge"
|
||||
android:text="Uploader"
|
||||
android:layout_centerVertical="true"
|
||||
android:layout_toRightOf="@+id/detail_uploader_thumbnail_view"
|
||||
android:layout_toEndOf="@+id/detail_uploader_thumbnail_view"
|
||||
android:layout_marginLeft="15dp"
|
||||
android:layout_marginStart="28dp" />
|
||||
|
||||
<View
|
||||
android:background="#000"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="1px"
|
||||
android:layout_below="@id/detail_uploader_thumbnail_view"/>
|
||||
</RelativeLayout>
|
||||
<Button
|
||||
android:layout_marginTop="13dp"
|
||||
android:id="@+id/channel_button"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:background="?attr/selectableItemBackground"/>
|
||||
</FrameLayout>
|
||||
|
||||
<RelativeLayout android:id="@+id/detail_next_stream_root_layout"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_gravity="center_horizontal|bottom"
|
||||
android:layout_below="@+id/detail_uploader_frame"
|
||||
android:layout_centerHorizontal="true"
|
||||
android:layout_marginTop="10dp">
|
||||
|
||||
<TextView
|
||||
android:id="@+id/detail_next_stream_title"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_centerHorizontal="true"
|
||||
android:textSize="@dimen/video_item_detail_next_text_size"
|
||||
android:textAppearance="?android:attr/textAppearanceMedium"
|
||||
android:text="@string/next_video_title"
|
||||
android:textAllCaps="true" />
|
||||
|
||||
<android.support.v7.widget.RecyclerView
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:id="@+id/detail_next_stream_content"/>
|
||||
<TextView android:id="@+id/detail_similar_title"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_centerHorizontal="true"
|
||||
android:textSize="@dimen/video_item_detail_next_text_size"
|
||||
android:textAppearance="?android:attr/textAppearanceMedium"
|
||||
android:text="@string/similar_videos_btn_text"
|
||||
android:layout_below="@id/detail_next_stream_content"
|
||||
android:textAllCaps="true" />
|
||||
<LinearLayout
|
||||
android:id="@+id/similar_streams_view"
|
||||
android:orientation="vertical"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_below="@id/detail_similar_title">
|
||||
</LinearLayout>
|
||||
</RelativeLayout>
|
||||
</RelativeLayout>
|
||||
</RelativeLayout>
|
||||
</com.nirhart.parallaxscroll.views.ParallaxScrollView>
|
||||
</RelativeLayout>
|
@ -1,4 +1,325 @@
|
||||
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:tools="http://schemas.android.com/tools" android:id="@+id/videoitem_detail_container"
|
||||
android:layout_width="match_parent" android:layout_height="match_parent"
|
||||
tools:context=".detail.VideoItemDetailActivity" tools:ignore="MergeRootFrame" />
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:id="@+id/video_item_detail"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent">
|
||||
|
||||
<com.nirhart.parallaxscroll.views.ParallaxScrollView
|
||||
android:id="@+id/detail_main_content"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:visibility="visible"
|
||||
app:parallax_factor="1.9">
|
||||
|
||||
<RelativeLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content">
|
||||
|
||||
<RelativeLayout
|
||||
android:id="@+id/detail_thumbnail_root_layout"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:background="@android:color/black">
|
||||
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/detail_thumbnail_image_view"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_alignParentLeft="true"
|
||||
android:layout_alignParentRight="true"
|
||||
android:layout_alignParentTop="true"
|
||||
android:background="@android:color/transparent"
|
||||
android:contentDescription="@string/detail_thumbnail_view_description"
|
||||
android:scaleType="centerCrop"
|
||||
tools:ignore="RtlHardcoded"
|
||||
tools:layout_height="200dp"
|
||||
tools:src="@drawable/dummy_thumbnail"/>
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/detail_thumbnail_play_button"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_centerInParent="true"
|
||||
android:background="@android:color/transparent"
|
||||
android:src="@drawable/new_play_arrow"
|
||||
android:visibility="invisible"
|
||||
tools:ignore="ContentDescription"
|
||||
tools:visibility="visible"/>
|
||||
|
||||
<Button
|
||||
android:id="@+id/detail_stream_thumbnail_background_button"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:background="?attr/selectableItemBackground"/>
|
||||
|
||||
</RelativeLayout>
|
||||
|
||||
<RelativeLayout
|
||||
android:id="@+id/detail_content_root_layout"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_below="@id/detail_thumbnail_root_layout"
|
||||
android:background="?android:windowBackground"
|
||||
android:visibility="gone"
|
||||
tools:visibility="visible">
|
||||
|
||||
<RelativeLayout
|
||||
android:id="@+id/detail_title_root_layout"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:background="?attr/selectableItemBackground"
|
||||
android:clickable="true"
|
||||
android:paddingLeft="12dp"
|
||||
android:paddingRight="12dp"
|
||||
android:paddingTop="12dp">
|
||||
|
||||
<TextView
|
||||
android:id="@+id/detail_video_title_view"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_alignParentLeft="true"
|
||||
android:layout_centerVertical="true"
|
||||
android:layout_toLeftOf="@+id/detail_toggle_description_view"
|
||||
android:ellipsize="end"
|
||||
android:gravity="center_vertical"
|
||||
android:maxLines="1"
|
||||
android:paddingBottom="2dp"
|
||||
android:paddingTop="6dp"
|
||||
android:textAppearance="?android:attr/textAppearanceLarge"
|
||||
android:textSize="@dimen/video_item_detail_title_text_size"
|
||||
tools:ignore="RtlHardcoded"
|
||||
tools:text="Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed a ultricies ex. Integer sit amet sodales risus. Duis non mi et urna pretium bibendum. Nunc eleifend est quis ipsum porttitor egestas. Sed facilisis, nisl quis eleifend pellentesque, orci metus egestas dolor, at accumsan eros metus quis libero."/>
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/detail_toggle_description_view"
|
||||
android:layout_width="15dp"
|
||||
android:layout_height="15dp"
|
||||
android:layout_alignParentRight="true"
|
||||
android:layout_alignParentTop="true"
|
||||
android:layout_marginLeft="5dp"
|
||||
android:layout_marginTop="6dp"
|
||||
android:src="@drawable/arrow_down"
|
||||
tools:ignore="ContentDescription,RtlHardcoded"/>
|
||||
|
||||
</RelativeLayout>
|
||||
|
||||
<TextView
|
||||
android:id="@+id/detail_view_count_view"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_alignParentLeft="true"
|
||||
android:layout_alignParentStart="true"
|
||||
android:layout_below="@id/detail_title_root_layout"
|
||||
android:layout_marginLeft="12dp"
|
||||
android:layout_marginRight="12dp"
|
||||
android:layout_marginTop="5dp"
|
||||
android:textAppearance="?android:attr/textAppearanceLarge"
|
||||
android:textSize="@dimen/video_item_detail_views_text_size"
|
||||
tools:ignore="RtlHardcoded"
|
||||
tools:text="10,069,948 views"/>
|
||||
|
||||
<RelativeLayout
|
||||
android:id="@+id/detail_description_root_layout"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_below="@id/detail_view_count_view"
|
||||
android:layout_marginLeft="12dp"
|
||||
android:layout_marginRight="12dp"
|
||||
android:layout_marginTop="5dp"
|
||||
android:visibility="gone"
|
||||
tools:visibility="visible">
|
||||
|
||||
<TextView
|
||||
android:id="@+id/detail_upload_date_view"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:textAppearance="?android:attr/textAppearanceMedium"
|
||||
android:textSize="@dimen/video_item_detail_upload_date_text_size"
|
||||
android:textStyle="bold"
|
||||
tools:text="Upload date"/>
|
||||
|
||||
<TextView
|
||||
android:id="@+id/detail_description_view"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_below="@+id/detail_upload_date_view"
|
||||
android:layout_marginTop="3dp"
|
||||
android:textAppearance="?android:attr/textAppearanceMedium"
|
||||
android:textSize="@dimen/video_item_detail_description_text_size"
|
||||
tools:text="Description Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed a ultricies ex. Integer sit amet sodales risus. Duis non mi et urna pretium bibendum."/>
|
||||
</RelativeLayout>
|
||||
|
||||
<LinearLayout
|
||||
android:id="@+id/detail_thumbs_root_layout"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_alignParentEnd="true"
|
||||
android:layout_alignParentRight="true"
|
||||
android:layout_below="@id/detail_description_root_layout"
|
||||
android:layout_marginLeft="12dp"
|
||||
android:layout_marginStart="12dp"
|
||||
android:layout_marginTop="5dp"
|
||||
android:gravity="center_vertical"
|
||||
android:minHeight="30dp">
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/detail_thumbs_up_img_view"
|
||||
android:layout_width="@dimen/video_item_detail_like_image_width"
|
||||
android:layout_height="@dimen/video_item_detail_like_image_height"
|
||||
android:contentDescription="@string/detail_likes_img_view_description"
|
||||
android:src="?attr/thumbs_up"/>
|
||||
|
||||
<TextView
|
||||
android:id="@+id/detail_thumbs_up_count_view"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_marginLeft="5dp"
|
||||
android:gravity="left|center_vertical"
|
||||
android:textAppearance="?android:attr/textAppearanceMedium"
|
||||
android:textSize="@dimen/video_item_detail_likes_text_size"
|
||||
tools:ignore="RtlHardcoded"
|
||||
tools:text="200"/>
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/detail_thumbs_down_img_view"
|
||||
android:layout_width="@dimen/video_item_detail_like_image_width"
|
||||
android:layout_height="@dimen/video_item_detail_like_image_height"
|
||||
android:layout_marginLeft="15dp"
|
||||
android:contentDescription="@string/detail_dislikes_img_view_description"
|
||||
android:src="?attr/thumbs_down"
|
||||
tools:ignore="RtlHardcoded"/>
|
||||
|
||||
<TextView
|
||||
android:id="@+id/detail_thumbs_down_count_view"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_marginLeft="5dp"
|
||||
android:gravity="left|center_vertical"
|
||||
android:textAppearance="?android:attr/textAppearanceMedium"
|
||||
android:textSize="@dimen/video_item_detail_likes_text_size"
|
||||
tools:ignore="RtlHardcoded"
|
||||
tools:text="100"/>
|
||||
|
||||
<TextView
|
||||
android:id="@+id/detail_thumbs_disabled_view"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_marginLeft="15dp"
|
||||
android:gravity="left|center_vertical"
|
||||
android:text="@string/disabled"
|
||||
android:textAppearance="?android:attr/textAppearanceLarge"
|
||||
android:textSize="@dimen/video_item_detail_likes_text_size"
|
||||
android:textStyle="bold"
|
||||
android:visibility="gone"
|
||||
tools:ignore="RtlHardcoded"
|
||||
tools:visibility="visible"/>
|
||||
</LinearLayout>
|
||||
|
||||
<FrameLayout
|
||||
android:id="@+id/detail_uploader_root_layout"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_below="@+id/detail_thumbs_root_layout">
|
||||
|
||||
<RelativeLayout
|
||||
android:id="@+id/detail_uploader_layout"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginBottom="8dp"
|
||||
android:layout_marginLeft="12dp"
|
||||
android:layout_marginRight="12dp"
|
||||
android:layout_marginTop="8dp">
|
||||
|
||||
|
||||
<de.hdodenhof.circleimageview.CircleImageView
|
||||
android:id="@+id/detail_uploader_thumbnail_view"
|
||||
android:layout_width="@dimen/video_item_detail_uploader_image_size"
|
||||
android:layout_height="@dimen/video_item_detail_uploader_image_size"
|
||||
android:layout_alignParentLeft="true"
|
||||
android:contentDescription="@string/detail_uploader_thumbnail_view_description"
|
||||
android:src="@drawable/buddy"
|
||||
tools:ignore="RtlHardcoded"/>
|
||||
|
||||
<TextView
|
||||
android:id="@+id/detail_uploader_text_view"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_centerVertical="true"
|
||||
android:layout_marginLeft="15dp"
|
||||
android:layout_toEndOf="@+id/detail_uploader_thumbnail_view"
|
||||
android:layout_toRightOf="@+id/detail_uploader_thumbnail_view"
|
||||
android:textAppearance="?android:attr/textAppearanceLarge"
|
||||
android:textSize="@dimen/video_item_detail_uploader_text_size"
|
||||
android:textStyle="bold"
|
||||
tools:ignore="RtlHardcoded"
|
||||
tools:text="Uploader"/>
|
||||
|
||||
</RelativeLayout>
|
||||
|
||||
<View
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="1px"
|
||||
android:layout_gravity="bottom"
|
||||
android:layout_marginLeft="8dp"
|
||||
android:layout_marginRight="8dp"
|
||||
android:background="?attr/separatorColor"/>
|
||||
|
||||
<Button
|
||||
android:id="@+id/detail_uploader_button"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:background="?attr/selectableItemBackground"
|
||||
tools:visibility="gone"/>
|
||||
</FrameLayout>
|
||||
|
||||
<RelativeLayout
|
||||
android:id="@+id/detail_related_streams_root_layout"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_below="@+id/detail_uploader_root_layout"
|
||||
android:layout_centerHorizontal="true"
|
||||
android:layout_gravity="center_horizontal|bottom"
|
||||
android:layout_marginTop="14dp">
|
||||
|
||||
<TextView
|
||||
android:id="@+id/detail_next_stream_title"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_alignParentLeft="true"
|
||||
android:layout_marginLeft="12dp"
|
||||
android:text="@string/next_video_title"
|
||||
android:textAllCaps="true"
|
||||
android:textAppearance="?android:attr/textAppearanceMedium"
|
||||
android:textSize="@dimen/video_item_detail_next_text_size"
|
||||
tools:ignore="RtlHardcoded"/>
|
||||
|
||||
<LinearLayout
|
||||
android:id="@+id/detail_related_streams_view"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_below="@id/detail_next_stream_title"
|
||||
android:layout_marginTop="2dp"
|
||||
android:orientation="vertical"
|
||||
tools:minHeight="100dp">
|
||||
</LinearLayout>
|
||||
</RelativeLayout>
|
||||
|
||||
</RelativeLayout>
|
||||
|
||||
<ProgressBar
|
||||
android:id="@+id/detail_loading_progress_bar"
|
||||
style="@style/Widget.AppCompat.ProgressBar"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_below="@+id/detail_thumbnail_root_layout"
|
||||
android:layout_centerHorizontal="true"
|
||||
android:layout_marginTop="30dp"
|
||||
android:indeterminate="true"/>
|
||||
|
||||
</RelativeLayout>
|
||||
</com.nirhart.parallaxscroll.views.ParallaxScrollView>
|
||||
|
||||
</RelativeLayout>
|
@ -1,91 +1,94 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
|
||||
<FrameLayout android:id="@+id/item_main_layout"
|
||||
<FrameLayout
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto">
|
||||
<LinearLayout
|
||||
android:layout_height="wrap_content">
|
||||
|
||||
<RelativeLayout
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content" >
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_margin="12dp"
|
||||
android:orientation="vertical">
|
||||
|
||||
<RelativeLayout
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:orientation="vertical"
|
||||
android:layout_width="match_parent"
|
||||
android:id="@+id/itemThumbnailViewContainer"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_margin="12dp">
|
||||
android:layout_marginRight="@dimen/video_item_search_image_right_margin"
|
||||
tools:ignore="RtlHardcoded">
|
||||
|
||||
<RelativeLayout android:id="@+id/itemThumbnailViewContainer"
|
||||
android:layout_marginRight="@dimen/video_item_search_image_right_margin"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
tools:ignore="RtlHardcoded">
|
||||
|
||||
<de.hdodenhof.circleimageview.CircleImageView android:id="@+id/itemThumbnailView"
|
||||
android:contentDescription="@string/list_thumbnail_view_description"
|
||||
android:layout_width="@dimen/video_item_search_thumbnail_image_width"
|
||||
android:layout_height="@dimen/video_item_search_thumbnail_image_height"
|
||||
android:layout_alignParentLeft="true"
|
||||
android:layout_alignParentStart="true"
|
||||
android:layout_alignParentTop="true"
|
||||
android:src="@drawable/buddy_channel_item"/>
|
||||
|
||||
</RelativeLayout>
|
||||
|
||||
<LinearLayout
|
||||
android:orientation="vertical"
|
||||
android:layout_width="fill_parent"
|
||||
<de.hdodenhof.circleimageview.CircleImageView
|
||||
android:id="@+id/itemThumbnailView"
|
||||
android:layout_width="@dimen/video_item_search_thumbnail_image_width"
|
||||
android:layout_height="@dimen/video_item_search_thumbnail_image_height"
|
||||
android:layout_toRightOf="@id/itemThumbnailViewContainer"
|
||||
tools:ignore="RtlHardcoded">
|
||||
|
||||
<TextView android:id="@+id/itemChannelTitleView"
|
||||
android:layout_weight="1"
|
||||
android:layout_width="fill_parent"
|
||||
android:layout_height="0dp"
|
||||
android:textAppearance="?android:attr/textAppearanceLarge"
|
||||
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
|
||||
android:orientation="horizontal"
|
||||
android:layout_width="match_parent"
|
||||
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>
|
||||
android:layout_alignParentLeft="true"
|
||||
android:layout_alignParentStart="true"
|
||||
android:layout_alignParentTop="true"
|
||||
android:contentDescription="@string/list_thumbnail_view_description"
|
||||
android:src="@drawable/buddy_channel_item"/>
|
||||
|
||||
</RelativeLayout>
|
||||
</LinearLayout>
|
||||
|
||||
<RelativeLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="@dimen/video_item_search_thumbnail_image_height"
|
||||
android:layout_toRightOf="@id/itemThumbnailViewContainer"
|
||||
android:orientation="vertical"
|
||||
tools:ignore="RtlHardcoded">
|
||||
|
||||
<TextView
|
||||
android:id="@+id/itemChannelTitleView"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_alignParentTop="true"
|
||||
android:ellipsize="end"
|
||||
android:maxLines="1"
|
||||
android:textAppearance="?android:attr/textAppearanceLarge"
|
||||
android:textSize="@dimen/channel_item_detail_title_text_size"
|
||||
tools:text="Channel Title, Lorem ipsum"/>
|
||||
|
||||
<TextView
|
||||
android:id="@+id/itemChannelDescriptionView"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_above="@+id/itemSubscriberCountView"
|
||||
android:layout_below="@+id/itemChannelTitleView"
|
||||
android:ellipsize="end"
|
||||
android:maxLines="2"
|
||||
android:textAppearance="?android:attr/textAppearanceSmall"
|
||||
android:textSize="@dimen/video_item_search_uploader_text_size"
|
||||
tools:text="Channel description, Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nunc tristique vitae sem vitae blanditLorem ipsum dolor sit amet, consectetur adipiscing elit. Nunc tristique vitae sem vitae blanditLorem ipsum dolor sit amet, consectetur adipiscing elit. Nunc tristique vitae sem vitae blandit"/>
|
||||
|
||||
<TextView
|
||||
android:id="@+id/itemSubscriberCountView"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_alignParentBottom="true"
|
||||
android:maxLines="1"
|
||||
android:textAppearance="?android:attr/textAppearanceSmall"
|
||||
android:textSize="@dimen/video_item_search_upload_date_text_size"
|
||||
tools:text="10M subscribers • "/>
|
||||
|
||||
<TextView
|
||||
android:id="@+id/itemVideoCountView"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_alignParentBottom="true"
|
||||
android:layout_toRightOf="@+id/itemSubscriberCountView"
|
||||
android:maxLines="1"
|
||||
android:textAppearance="?android:attr/textAppearanceSmall"
|
||||
android:textSize="@dimen/video_item_search_upload_date_text_size"
|
||||
tools:text="1000 videos"/>
|
||||
</RelativeLayout>
|
||||
</RelativeLayout>
|
||||
|
||||
<Button
|
||||
android:id="@+id/item_button"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:background="?attr/selectableItemBackground"/>
|
||||
android:background="?attr/selectableItemBackground"
|
||||
tools:visibility="gone"/>
|
||||
</FrameLayout>
|
@ -1,284 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
|
||||
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
tools:context=".detail.VideoItemDetailFragment"
|
||||
android:textIsSelectable="true"
|
||||
style="?android:attr/textAppearanceLarge"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:id="@+id/video_item_detail">
|
||||
|
||||
<com.nirhart.parallaxscroll.views.ParallaxScrollView
|
||||
android:id="@+id/detail_main_content"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:visibility="visible"
|
||||
app:parallax_factor="1.9"
|
||||
tools:ignore="UselessParent">
|
||||
|
||||
<RelativeLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content">
|
||||
|
||||
<RelativeLayout
|
||||
android:id="@+id/detail_stream_thumbnail_window_layout"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:background="?attr/selectableItemBackground">
|
||||
|
||||
<ImageView android:id="@+id/detail_thumbnail_view"
|
||||
android:contentDescription="@string/detail_thumbnail_view_description"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:scaleType="fitCenter"
|
||||
android:adjustViewBounds="true"
|
||||
android:layout_alignParentLeft="true"
|
||||
android:layout_alignParentStart="true"
|
||||
android:layout_alignParentTop="true"
|
||||
android:background="@android:color/black"
|
||||
android:src="@drawable/dummy_thumbnail_dark"/>
|
||||
|
||||
<ProgressBar android:id="@+id/detail_progress_bar"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_centerInParent="true"
|
||||
android:indeterminate="true"/>
|
||||
|
||||
<android.support.design.widget.FloatingActionButton
|
||||
android:id="@+id/play_video_button"
|
||||
android:visibility="invisible"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_centerInParent="true"
|
||||
app:backgroundTint="@color/light_youtube_primary_color"
|
||||
android:src="@drawable/ic_play_arrow_black"
|
||||
android:layout_margin="@dimen/video_item_detail_play_fab_margin"/>
|
||||
|
||||
<Button
|
||||
android:id="@+id/detail_stream_thumbnail_window_background_button"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:background="?attr/selectableItemBackground"/>
|
||||
|
||||
</RelativeLayout>
|
||||
|
||||
<RelativeLayout android:id="@+id/detail_text_content_layout"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_below="@id/detail_stream_thumbnail_window_layout"
|
||||
android:background="?android:windowBackground"
|
||||
android:visibility="visible">
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:id="@+id/detailTopView">
|
||||
|
||||
<TextView android:id="@+id/detail_video_title_view"
|
||||
android:layout_width="0dp"
|
||||
android:layout_weight=".7"
|
||||
android:layout_height="wrap_content"
|
||||
android:textSize="@dimen/video_item_detail_title_text_size"
|
||||
android:textAppearance="?android:attr/textAppearanceLarge"
|
||||
android:layout_marginTop="12dp"
|
||||
android:layout_marginLeft="12dp"
|
||||
android:layout_marginStart="12dp"
|
||||
android:text="Title"/>
|
||||
|
||||
<ImageView
|
||||
android:layout_width="15dp"
|
||||
android:layout_height="30dp"
|
||||
android:id="@+id/toggle_description_view"
|
||||
android:src="@drawable/arrow_down"
|
||||
android:layout_marginLeft="10dp"
|
||||
android:layout_marginStart="10dp"
|
||||
android:layout_marginRight="10dp"
|
||||
android:layout_marginEnd="10dp"
|
||||
android:layout_marginTop="8dp"/>
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
<TextView android:id="@+id/detail_view_count_view"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:textSize="@dimen/video_item_detail_views_text_size"
|
||||
android:textAppearance="?android:attr/textAppearanceLarge"
|
||||
android:layout_marginLeft="12dp"
|
||||
android:layout_marginStart="12dp"
|
||||
android:text="10,069,948 views"
|
||||
android:layout_below="@id/detailTopView"
|
||||
android:layout_alignParentLeft="true"
|
||||
android:layout_alignParentStart="true"
|
||||
android:layout_marginTop="5dp" />
|
||||
|
||||
<RelativeLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_below="@id/detail_view_count_view"
|
||||
android:id="@+id/detailExtraView"
|
||||
android:layout_marginLeft="12dp"
|
||||
android:layout_marginStart="12dp"
|
||||
android:layout_marginRight="12dp"
|
||||
android:layout_marginEnd="12dp"
|
||||
android:visibility="gone">
|
||||
<TextView android:id="@+id/detail_upload_date_view"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:textSize="@dimen/video_item_detail_upload_date_text_size"
|
||||
android:textAppearance="?android:attr/textAppearanceMedium"
|
||||
android:text="Upload date"
|
||||
android:layout_marginTop="3dp" />
|
||||
|
||||
<TextView android:id="@+id/detail_description_view"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:textSize="@dimen/video_item_detail_description_text_size"
|
||||
android:textAppearance="?android:attr/textAppearanceMedium"
|
||||
android:layout_below="@id/detail_upload_date_view"
|
||||
android:text="Description............."
|
||||
android:layout_marginTop="3dp" />
|
||||
</RelativeLayout>
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:id="@+id/stream_info_layout"
|
||||
android:layout_marginLeft="12dp"
|
||||
android:layout_marginStart="12dp"
|
||||
android:layout_below="@+id/detailExtraView"
|
||||
android:layout_alignParentRight="true"
|
||||
android:layout_alignParentEnd="true"
|
||||
android:layout_marginTop="5dp">
|
||||
<ImageView android:id="@+id/detail_thumbs_up_img_view"
|
||||
android:contentDescription="@string/detail_likes_img_view_description"
|
||||
android:layout_width="@dimen/video_item_detail_like_image_width"
|
||||
android:layout_height="@dimen/video_item_detail_like_image_height"
|
||||
android:src="?attr/thumbs_up" />
|
||||
|
||||
<TextView android:id="@+id/detail_thumbs_up_count_view"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:textSize="@dimen/video_item_detail_likes_text_size"
|
||||
android:textAppearance="?android:attr/textAppearanceMedium"
|
||||
android:text="200" />
|
||||
|
||||
<ImageView android:id="@+id/detail_thumbs_down_img_view"
|
||||
android:contentDescription="@string/detail_dislikes_img_view_description"
|
||||
android:layout_width="@dimen/video_item_detail_like_image_width"
|
||||
android:layout_height="@dimen/video_item_detail_like_image_height"
|
||||
android:src="?attr/thumbs_down"
|
||||
android:layout_marginLeft="10dp"
|
||||
android:layout_marginStart="10dp"/>
|
||||
|
||||
<TextView android:id="@+id/detail_thumbs_down_count_view"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:textSize="@dimen/video_item_detail_likes_text_size"
|
||||
android:textAppearance="?android:attr/textAppearanceMedium"
|
||||
android:text="100" />
|
||||
</LinearLayout>
|
||||
|
||||
<FrameLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:id="@+id/detail_uploader_frame"
|
||||
android:layout_below="@id/stream_info_layout">
|
||||
<RelativeLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:id="@+id/detail_uploader_layout"
|
||||
android:layout_marginTop="12dp">
|
||||
|
||||
<View
|
||||
android:background="#000"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="1px" />
|
||||
|
||||
<de.hdodenhof.circleimageview.CircleImageView
|
||||
android:id="@+id/detail_uploader_thumbnail_view"
|
||||
android:contentDescription="@string/detail_uploader_thumbnail_view_description"
|
||||
android:layout_width="@dimen/video_item_detail_uploader_image_size"
|
||||
android:layout_height="@dimen/video_item_detail_uploader_image_size"
|
||||
android:src="@drawable/buddy"
|
||||
android:layout_marginLeft="10dp"
|
||||
android:layout_marginStart="10dp"
|
||||
android:layout_alignParentLeft="true"
|
||||
android:layout_alignParentStart="true"
|
||||
android:layout_marginTop="5dp"
|
||||
android:layout_marginBottom="5dp"/>
|
||||
|
||||
<TextView android:id="@+id/detail_uploader_view"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:textStyle="bold"
|
||||
android:textSize="@dimen/video_item_detail_uploader_text_size"
|
||||
android:textAppearance="?android:attr/textAppearanceLarge"
|
||||
android:text="Uploader"
|
||||
android:layout_centerVertical="true"
|
||||
android:layout_toRightOf="@+id/detail_uploader_thumbnail_view"
|
||||
android:layout_toEndOf="@+id/detail_uploader_thumbnail_view"
|
||||
android:layout_marginLeft="15dp"
|
||||
android:layout_marginStart="28dp" />
|
||||
|
||||
<View
|
||||
android:background="#000"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="1px"
|
||||
|
||||
android:layout_toRightOf="@+id/detail_uploader_thumbnail_view"
|
||||
android:layout_toEndOf="@+id/detail_uploader_thumbnail_view"
|
||||
android:layout_below="@id/detail_uploader_thumbnail_view"/>
|
||||
</RelativeLayout>
|
||||
<Button
|
||||
android:layout_marginTop="13dp"
|
||||
android:id="@+id/channel_button"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:background="?attr/selectableItemBackground"/>
|
||||
</FrameLayout>
|
||||
|
||||
<RelativeLayout android:id="@+id/detail_next_stream_root_layout"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_gravity="center_horizontal|bottom"
|
||||
android:layout_below="@+id/detail_uploader_frame"
|
||||
android:layout_centerHorizontal="true"
|
||||
android:layout_marginTop="10dp">
|
||||
|
||||
<TextView
|
||||
android:id="@+id/detail_next_stream_title"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_centerHorizontal="true"
|
||||
android:textSize="@dimen/video_item_detail_next_text_size"
|
||||
android:textAppearance="?android:attr/textAppearanceMedium"
|
||||
android:text="@string/next_video_title"
|
||||
android:textAllCaps="true" />
|
||||
|
||||
<android.support.v7.widget.RecyclerView
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:id="@+id/detail_next_stream_content"/>
|
||||
<TextView android:id="@+id/detail_similar_title"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_centerHorizontal="true"
|
||||
android:textSize="@dimen/video_item_detail_next_text_size"
|
||||
android:textAppearance="?android:attr/textAppearanceMedium"
|
||||
android:text="@string/similar_videos_btn_text"
|
||||
android:layout_below="@id/detail_next_stream_content"
|
||||
android:textAllCaps="true" />
|
||||
<LinearLayout
|
||||
android:id="@+id/similar_streams_view"
|
||||
android:orientation="vertical"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_below="@id/detail_similar_title">
|
||||
</LinearLayout>
|
||||
</RelativeLayout>
|
||||
</RelativeLayout>
|
||||
</RelativeLayout>
|
||||
</com.nirhart.parallaxscroll.views.ParallaxScrollView>
|
||||
</FrameLayout>
|
@ -1,108 +1,117 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
|
||||
<FrameLayout
|
||||
android:id="@+id/item_main_layout"
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:id="@+id/item_main_layout"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content">
|
||||
<LinearLayout
|
||||
|
||||
<RelativeLayout
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content" >
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_margin="12dp"
|
||||
android:orientation="vertical">
|
||||
|
||||
<RelativeLayout
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:orientation="vertical"
|
||||
android:layout_width="match_parent"
|
||||
android:id="@+id/itemThumbnailViewContainer"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_margin="12dp">
|
||||
android:layout_marginRight="@dimen/video_item_search_image_right_margin"
|
||||
tools:ignore="RtlHardcoded">
|
||||
|
||||
<RelativeLayout android:id="@+id/itemThumbnailViewContainer"
|
||||
android:layout_marginRight="@dimen/video_item_search_image_right_margin"
|
||||
<ImageView
|
||||
android:id="@+id/itemThumbnailView"
|
||||
android:layout_width="@dimen/video_item_search_thumbnail_image_width"
|
||||
android:layout_height="@dimen/video_item_search_thumbnail_image_height"
|
||||
android:layout_alignParentLeft="true"
|
||||
android:layout_alignParentStart="true"
|
||||
android:layout_alignParentTop="true"
|
||||
android:contentDescription="@string/list_thumbnail_view_description"
|
||||
android:scaleType="centerCrop"
|
||||
android:src="@drawable/dummy_thumbnail"/>
|
||||
|
||||
<TextView
|
||||
android:id="@+id/itemDurationView"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
tools:ignore="RtlHardcoded">
|
||||
|
||||
<ImageView android:id="@+id/itemThumbnailView"
|
||||
android:contentDescription="@string/list_thumbnail_view_description"
|
||||
android:layout_width="@dimen/video_item_search_thumbnail_image_width"
|
||||
android:layout_height="@dimen/video_item_search_thumbnail_image_height"
|
||||
android:scaleType="centerCrop"
|
||||
android:layout_alignParentLeft="true"
|
||||
android:layout_alignParentStart="true"
|
||||
android:layout_alignParentTop="true"
|
||||
android:src="@drawable/dummy_thumbnail"/>
|
||||
|
||||
<TextView android:id="@+id/itemDurationView"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_alignBottom="@id/itemThumbnailView"
|
||||
android:layout_alignRight="@id/itemThumbnailView"
|
||||
android:layout_alignEnd="@id/itemThumbnailView"
|
||||
android:layout_marginRight="@dimen/video_item_search_duration_margin"
|
||||
android:layout_marginEnd="@dimen/video_item_search_duration_margin"
|
||||
android:layout_marginBottom="@dimen/video_item_search_duration_margin"
|
||||
android:paddingTop="@dimen/video_item_search_duration_vertical_padding"
|
||||
android:paddingBottom="@dimen/video_item_search_duration_vertical_padding"
|
||||
android:paddingRight="@dimen/video_item_search_duration_horizontal_padding"
|
||||
android:paddingLeft="@dimen/video_item_search_duration_horizontal_padding"
|
||||
android:textAppearance="?android:attr/textAppearanceSmall"
|
||||
android:textSize="@dimen/video_item_search_duration_text_size"
|
||||
android:background="@color/duration_background_color"
|
||||
android:textColor="@color/duration_text_color"/>
|
||||
|
||||
</RelativeLayout>
|
||||
|
||||
<LinearLayout
|
||||
android:orientation="vertical"
|
||||
android:layout_width="fill_parent"
|
||||
android:layout_height="@dimen/video_item_search_thumbnail_image_height"
|
||||
android:layout_toRightOf="@id/itemThumbnailViewContainer"
|
||||
tools:ignore="RtlHardcoded">
|
||||
|
||||
<TextView android:id="@+id/itemVideoTitleView"
|
||||
android:layout_weight="1"
|
||||
android:layout_width="fill_parent"
|
||||
android:layout_height="0dp"
|
||||
android:textAppearance="?android:attr/textAppearanceLarge"
|
||||
android:textSize="@dimen/video_item_search_title_text_size"/>
|
||||
|
||||
<TextView android:id="@+id/itemUploaderView"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:singleLine="true"
|
||||
android:textAppearance="?android:attr/textAppearanceSmall"
|
||||
android:textSize="@dimen/video_item_search_uploader_text_size"/>
|
||||
<LinearLayout
|
||||
android:orientation="horizontal"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content">
|
||||
|
||||
<TextView android:id="@+id/itemUploadDateView"
|
||||
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"/>
|
||||
|
||||
<TextView android:id="@+id/itemViewCountView"
|
||||
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"/>
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
|
||||
</LinearLayout>
|
||||
android:layout_alignBottom="@id/itemThumbnailView"
|
||||
android:layout_alignRight="@id/itemThumbnailView"
|
||||
android:layout_marginBottom="@dimen/video_item_search_duration_margin"
|
||||
android:layout_marginRight="@dimen/video_item_search_duration_margin"
|
||||
android:background="@color/duration_background_color"
|
||||
android:paddingBottom="@dimen/video_item_search_duration_vertical_padding"
|
||||
android:paddingLeft="@dimen/video_item_search_duration_horizontal_padding"
|
||||
android:paddingRight="@dimen/video_item_search_duration_horizontal_padding"
|
||||
android:paddingTop="@dimen/video_item_search_duration_vertical_padding"
|
||||
android:textAppearance="?android:attr/textAppearanceSmall"
|
||||
android:textColor="@color/duration_text_color"
|
||||
android:textSize="@dimen/video_item_search_duration_text_size"
|
||||
tools:text="1:09:10"/>
|
||||
|
||||
</RelativeLayout>
|
||||
</LinearLayout>
|
||||
|
||||
<RelativeLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="@dimen/video_item_search_thumbnail_image_height"
|
||||
android:layout_toRightOf="@id/itemThumbnailViewContainer"
|
||||
android:orientation="vertical"
|
||||
tools:ignore="RtlHardcoded">
|
||||
|
||||
<TextView
|
||||
android:id="@+id/itemVideoTitleView"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_above="@+id/itemUploaderView"
|
||||
android:layout_alignParentTop="true"
|
||||
android:ellipsize="end"
|
||||
android:maxLines="2"
|
||||
android:textAppearance="?android:attr/textAppearanceLarge"
|
||||
android:textSize="@dimen/video_item_search_title_text_size"
|
||||
tools:text="Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nunc tristique vitae sem vitae blanditLorem ipsumLorem ipsumLorem ipsumLorem ipsumLorem ipsumLorem ipsumLorem ipsum"/>
|
||||
|
||||
<TextView
|
||||
android:id="@+id/itemUploaderView"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_above="@+id/itemUploadDateView"
|
||||
android:maxLines="1"
|
||||
android:textAppearance="?android:attr/textAppearanceSmall"
|
||||
android:textSize="@dimen/video_item_search_uploader_text_size"
|
||||
tools:text="Uploader"/>
|
||||
|
||||
|
||||
<TextView
|
||||
android:id="@+id/itemUploadDateView"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_alignParentBottom="true"
|
||||
android:maxLines="1"
|
||||
android:textAppearance="?android:attr/textAppearanceSmall"
|
||||
android:textSize="@dimen/video_item_search_upload_date_text_size"
|
||||
tools:text="2 years ago • "/>
|
||||
|
||||
<TextView
|
||||
android:id="@+id/itemViewCountView"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_alignParentBottom="true"
|
||||
android:layout_toRightOf="@+id/itemUploadDateView"
|
||||
android:maxLines="1"
|
||||
android:textAppearance="?android:attr/textAppearanceSmall"
|
||||
android:textSize="@dimen/video_item_search_upload_date_text_size"
|
||||
tools:text="10M views"/>
|
||||
|
||||
|
||||
</RelativeLayout>
|
||||
|
||||
</RelativeLayout>
|
||||
|
||||
<Button
|
||||
android:id="@+id/item_button"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:background="?attr/selectableItemBackground"/>
|
||||
android:background="?attr/selectableItemBackground"
|
||||
tools:visibility="gone"/>
|
||||
</FrameLayout>
|
@ -3,14 +3,15 @@
|
||||
|
||||
<!-- Video Item Search View Dimensions-->
|
||||
<!-- 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_duration_text_size">16sp</dimen>
|
||||
<dimen name="video_item_search_uploader_text_size">18sp</dimen>
|
||||
<dimen name="video_item_search_upload_date_text_size">18sp</dimen>
|
||||
<dimen name="channel_item_detail_title_text_size">18sp</dimen>
|
||||
<dimen name="video_item_search_title_text_size">16sp</dimen>
|
||||
<dimen name="video_item_search_duration_text_size">12sp</dimen>
|
||||
<dimen name="video_item_search_uploader_text_size">14sp</dimen>
|
||||
<dimen name="video_item_search_upload_date_text_size">14sp</dimen>
|
||||
<!-- Elements Size -->
|
||||
<dimen name="video_item_search_thumbnail_image_width">210dp</dimen>
|
||||
<dimen name="video_item_search_thumbnail_image_height">130dp</dimen>
|
||||
<!-- 16 / 9 ratio-->
|
||||
<dimen name="video_item_search_thumbnail_image_width">142dp</dimen>
|
||||
<dimen name="video_item_search_thumbnail_image_height">80dp</dimen>
|
||||
<!-- Paddings & Margins -->
|
||||
<dimen name="video_item_search_card_vertical_margin">5dp</dimen>
|
||||
<dimen name="video_item_search_card_horizontal_margin">10dp</dimen>
|
||||
@ -24,17 +25,15 @@
|
||||
|
||||
<!-- Video Item Detail View Dimensions-->
|
||||
<!-- Text Size -->
|
||||
<dimen name="video_item_detail_title_text_size">24sp</dimen>
|
||||
<dimen name="video_item_detail_views_text_size">18sp</dimen>
|
||||
<dimen name="video_item_detail_likes_text_size">16sp</dimen>
|
||||
<dimen name="video_item_detail_uploader_text_size">18sp</dimen>
|
||||
<dimen name="video_item_detail_upload_date_text_size">18sp</dimen>
|
||||
<dimen name="video_item_detail_description_text_size">18sp</dimen>
|
||||
<dimen name="video_item_detail_next_text_size">20sp</dimen>
|
||||
<dimen name="video_item_detail_similar_text_size">20sp</dimen>
|
||||
<dimen name="video_item_detail_title_text_size">20sp</dimen>
|
||||
<dimen name="video_item_detail_views_text_size">14sp</dimen>
|
||||
<dimen name="video_item_detail_likes_text_size">13sp</dimen>
|
||||
<dimen name="video_item_detail_uploader_text_size">16sp</dimen>
|
||||
<dimen name="video_item_detail_upload_date_text_size">14sp</dimen>
|
||||
<dimen name="video_item_detail_description_text_size">14sp</dimen>
|
||||
<dimen name="video_item_detail_next_text_size">17sp</dimen>
|
||||
<!-- Elements Size -->
|
||||
<dimen name="video_item_detail_thumbnail_image_height">240dp</dimen>
|
||||
<dimen name="video_item_detail_uploader_image_size">100dp</dimen>
|
||||
<dimen name="video_item_detail_uploader_image_size">70dp</dimen>
|
||||
<dimen name="video_item_detail_like_image_height">20sp</dimen>
|
||||
<dimen name="video_item_detail_like_image_width">20sp</dimen>
|
||||
<!-- Paddings & Margins -->
|
||||
|
@ -8,9 +8,6 @@
|
||||
<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_upload_date_text_size">12sp</dimen>
|
||||
<!-- Elements Size -->
|
||||
<dimen name="video_item_search_thumbnail_image_width">140dp</dimen>
|
||||
<dimen name="video_item_search_thumbnail_image_height">85dp</dimen>
|
||||
<!-- Paddings & Margins -->
|
||||
<dimen name="video_item_search_card_vertical_margin">3dp</dimen>
|
||||
<dimen name="video_item_search_card_horizontal_margin">6dp</dimen>
|
||||
|
@ -3,7 +3,7 @@
|
||||
|
||||
<!-- Video Item Detail View Dimensions-->
|
||||
<!-- Text Size -->
|
||||
<dimen name="channel_item_detail_title_text_size">30sp</dimen>
|
||||
<dimen name="channel_item_detail_title_text_size">21sp</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_likes_text_size">14sp</dimen>
|
||||
@ -13,13 +13,11 @@
|
||||
<dimen name="video_item_detail_next_text_size">18sp</dimen>
|
||||
<dimen name="video_item_detail_similar_text_size">18sp</dimen>
|
||||
<!-- Elements Size -->
|
||||
<dimen name="video_item_detail_thumbnail_image_height">300dp</dimen>
|
||||
<dimen name="video_item_detail_uploader_image_size">100dp</dimen>
|
||||
<dimen name="video_item_detail_like_image_height">18sp</dimen>
|
||||
<dimen name="video_item_detail_like_image_width">18sp</dimen>
|
||||
<!-- Paddings & Margins -->
|
||||
<dimen name="video_item_detail_info_text_padding">10sp</dimen>
|
||||
<dimen name="video_item_detail_like_margin">10sp</dimen>
|
||||
<dimen name="video_item_detail_play_fab_margin">20dp</dimen>
|
||||
|
||||
</resources>
|
@ -1,67 +1,9 @@
|
||||
<resources>
|
||||
<style name="AppTheme" parent="Theme.AppCompat.Light">
|
||||
<item name="android:actionBarStyle">@style/NewPipeActionbarTheme</item>
|
||||
<item name="actionBarStyle">@style/NewPipeActionbarTheme</item>
|
||||
<item name="colorPrimary">@color/light_youtube_primary_color</item>
|
||||
<item name="colorPrimaryDark">@color/light_youtube_dark_color</item>
|
||||
<item name="colorAccent">@color/light_youtube_accent_color</item>
|
||||
<item name="android:windowBackground">@color/light_background_color</item>
|
||||
<item name="thumbs_up">@drawable/ic_thumb_up_black_24dp</item>
|
||||
<item name="thumbs_down">@drawable/ic_thumb_down_black_24dp</item>
|
||||
<item name="audio">@drawable/ic_headset_black_24dp</item>
|
||||
<item name="download">@drawable/ic_file_download_black_24dp</item>
|
||||
<item name="share">@drawable/ic_share_black_24dp</item>
|
||||
<item name="cast">@drawable/ic_cast_black_24dp</item>
|
||||
<item name="rss">@drawable/ic_rss_feed_white_24dp</item>
|
||||
</style>
|
||||
|
||||
|
||||
<!-- Dark Theme-->
|
||||
<style name="DarkTheme" parent="Theme.AppCompat">
|
||||
<item name="android:actionBarStyle">@style/NewPipeActionbarTheme</item>
|
||||
<item name="actionBarStyle">@style/NewPipeActionbarTheme</item>
|
||||
<item name="colorPrimary">@color/dark_youtube_primary_color</item>
|
||||
<item name="colorPrimaryDark">@color/light_youtube_dark_color</item>
|
||||
<item name="colorAccent">@color/dark_youtube_accent_color</item>
|
||||
<item name="android:windowBackground">@color/dark_background_color</item>
|
||||
<item name="thumbs_up">@drawable/ic_thumb_up_white_24dp</item>
|
||||
<item name="thumbs_down">@drawable/ic_thumb_down_white_24dp</item>
|
||||
<item name="audio">@drawable/ic_headset_white_24dp</item>
|
||||
<item name="download">@drawable/ic_file_download_white_24dp</item>
|
||||
<item name="share">@drawable/ic_share_white_24dp</item>
|
||||
<item name="cast">@drawable/ic_cast_white_24dp</item>
|
||||
<item name="rss">@drawable/ic_rss_feed_black_24dp</item>
|
||||
</style>
|
||||
|
||||
|
||||
<style name="NewPipeActionbarTheme" parent="Widget.AppCompat.Light.ActionBar.Solid">
|
||||
<item name="android:displayOptions">showHome</item>
|
||||
<item name="displayOptions">showHome</item>
|
||||
<item name="android:background">@color/light_youtube_primary_color</item>
|
||||
<item name="background">@color/light_youtube_primary_color</item>
|
||||
</style>
|
||||
|
||||
<style name="VideoPlayerTheme" parent="Theme.AppCompat.Light.DarkActionBar">
|
||||
<item name="android:windowFullscreen">false</item>
|
||||
<item name="android:windowActionBarOverlay">true</item>
|
||||
<item name="windowActionBarOverlay">true</item>
|
||||
<item name="android:actionBarStyle">@style/VideoPlayerActionBarTheme</item>
|
||||
<item name="actionBarStyle">@style/VideoPlayerActionBarTheme</item>
|
||||
<item name="colorAccent">@color/light_youtube_primary_color</item>
|
||||
<item name="android:colorAccent">@color/light_youtube_primary_color</item>
|
||||
<item name="android:windowBackground">@android:color/black</item>
|
||||
</style>
|
||||
|
||||
<style name="VideoPlayerActionBarTheme" parent="Widget.AppCompat.Light.ActionBar.Solid.Inverse">
|
||||
<item name="android:displayOptions">showHome</item>
|
||||
<item name="displayOptions">showHome</item>
|
||||
<item name="android:background">@color/video_overlay_color</item>
|
||||
<item name="background">@color/video_overlay_color</item>
|
||||
</style>
|
||||
|
||||
<style name="AppTheme.NoActionBar">
|
||||
<item name="windowActionBar">false</item>
|
||||
<item name="windowNoTitle">true</item>
|
||||
<item name="android:windowDrawsSystemBarBackgrounds">true</item>
|
||||
<item name="android:statusBarColor">@android:color/transparent</item>
|
||||
</style>
|
||||
|
@ -7,4 +7,5 @@
|
||||
<attr name="share" format="reference"/>
|
||||
<attr name="cast" format="reference"/>
|
||||
<attr name="rss" format="reference"/>
|
||||
<attr name="separatorColor" format="color"/>
|
||||
</resources>
|
@ -5,12 +5,17 @@
|
||||
<color name="light_youtube_primary_color">#CD322E</color>
|
||||
<color name="light_youtube_dark_color">#BC211D</color>
|
||||
<color name="light_youtube_accent_color">#000000</color>
|
||||
<color name="light_separator_color">#32000000</color>
|
||||
|
||||
<!-- Dark Theme -->
|
||||
<color name="dark_background_color">#222222</color>
|
||||
<color name="dark_youtube_primary_color">#CD322E</color>
|
||||
<color name="dark_youtube_dark_color">#BC211D</color>
|
||||
<color name="dark_youtube_accent_color">#FFFFFF</color>
|
||||
<color name="dark_separator_color">#0affffff</color>
|
||||
|
||||
<!-- Black Theme -->
|
||||
<color name="black_separator_color">#1effffff</color>
|
||||
|
||||
<!-- Miscellaneous -->
|
||||
<color name="duration_background_color">#AA000000</color>
|
||||
|
@ -2,14 +2,15 @@
|
||||
<resources>
|
||||
<!-- Video Item Search View Dimensions-->
|
||||
<!-- Text Size -->
|
||||
<dimen name="channel_item_detail_title_text_size">21sp</dimen>
|
||||
<dimen name="channel_item_detail_title_text_size">16sp</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_uploader_text_size">12sp</dimen>
|
||||
<dimen name="video_item_search_uploader_text_size">11sp</dimen>
|
||||
<dimen name="video_item_search_upload_date_text_size">12sp</dimen>
|
||||
<!-- Elements Size -->
|
||||
<dimen name="video_item_search_thumbnail_image_width">140dp</dimen>
|
||||
<dimen name="video_item_search_thumbnail_image_height">85dp</dimen>
|
||||
<!-- 16 / 9 ratio-->
|
||||
<dimen name="video_item_search_thumbnail_image_width">124dp</dimen>
|
||||
<dimen name="video_item_search_thumbnail_image_height">70dp</dimen>
|
||||
<!-- Paddings & Margins -->
|
||||
<dimen name="video_item_search_image_right_margin">6dp</dimen>
|
||||
<dimen name="video_item_search_duration_vertical_padding">1sp</dimen>
|
||||
@ -19,16 +20,14 @@
|
||||
|
||||
<!-- Video Item Detail View Dimensions-->
|
||||
<!-- Text Size -->
|
||||
<dimen name="video_item_detail_title_text_size">20sp</dimen>
|
||||
<dimen name="video_item_detail_views_text_size">14sp</dimen>
|
||||
<dimen name="video_item_detail_likes_text_size">14sp</dimen>
|
||||
<dimen name="video_item_detail_title_text_size">18sp</dimen>
|
||||
<dimen name="video_item_detail_views_text_size">13sp</dimen>
|
||||
<dimen name="video_item_detail_likes_text_size">12sp</dimen>
|
||||
<dimen name="video_item_detail_uploader_text_size">14sp</dimen>
|
||||
<dimen name="video_item_detail_upload_date_text_size">14sp</dimen>
|
||||
<dimen name="video_item_detail_description_text_size">14sp</dimen>
|
||||
<dimen name="video_item_detail_next_text_size">16sp</dimen>
|
||||
<dimen name="video_item_detail_similar_text_size">16sp</dimen>
|
||||
<dimen name="video_item_detail_upload_date_text_size">13sp</dimen>
|
||||
<dimen name="video_item_detail_description_text_size">13sp</dimen>
|
||||
<dimen name="video_item_detail_next_text_size">15sp</dimen>
|
||||
<!-- Elements Size -->
|
||||
<dimen name="video_item_detail_thumbnail_image_height">200dp</dimen>
|
||||
<dimen name="video_item_detail_uploader_image_size">50dp</dimen>
|
||||
<dimen name="video_item_detail_like_image_height">18sp</dimen>
|
||||
<dimen name="video_item_detail_like_image_width">18sp</dimen>
|
||||
@ -36,7 +35,6 @@
|
||||
<dimen name="channel_avatar_halo_size">74dp</dimen>
|
||||
<!-- Paddings & Margins -->
|
||||
<dimen name="video_item_detail_like_margin">6sp</dimen>
|
||||
<dimen name="video_item_detail_play_fab_margin">20dp</dimen>
|
||||
<!-- Default screen margins, per the Android Design guidelines. -->
|
||||
<dimen name="activity_horizontal_margin">16dp</dimen>
|
||||
<dimen name="activity_vertical_margin">16dp</dimen>
|
||||
|
@ -91,6 +91,7 @@
|
||||
<string name="channel">Channel</string>
|
||||
<string name="yes">Yes</string>
|
||||
<string name="later">Later</string>
|
||||
<string name="disabled">Disabled</string>
|
||||
|
||||
<!-- error strings -->
|
||||
<string name="general_error">Error</string>
|
||||
|
@ -22,6 +22,7 @@
|
||||
<item name="share">@drawable/ic_share_black_24dp</item>
|
||||
<item name="cast">@drawable/ic_cast_black_24dp</item>
|
||||
<item name="rss">@drawable/ic_rss_feed_white_24dp</item>
|
||||
<item name="separatorColor">@color/light_separator_color</item>
|
||||
</style>
|
||||
|
||||
|
||||
@ -40,10 +41,12 @@
|
||||
<item name="share">@drawable/ic_share_white_24dp</item>
|
||||
<item name="cast">@drawable/ic_cast_white_24dp</item>
|
||||
<item name="rss">@drawable/ic_rss_feed_black_24dp</item>
|
||||
<item name="separatorColor">@color/dark_separator_color</item>
|
||||
</style>
|
||||
|
||||
<style name="BlackTheme" parent="DarkTheme">
|
||||
<item name="android:windowBackground">@color/black</item>
|
||||
<item name="separatorColor">@color/black_separator_color</item>
|
||||
</style>
|
||||
|
||||
<style name="NewPipeActionbarTheme" parent="Widget.AppCompat.Light.ActionBar.Solid">
|
||||
|
Loading…
Reference in New Issue
Block a user