Merge branch 'master' of github.com:theScrabi/NewPipe
|
@ -7,3 +7,4 @@
|
||||||
/app/app.iml
|
/app/app.iml
|
||||||
/.idea
|
/.idea
|
||||||
/*.iml
|
/*.iml
|
||||||
|
gradle.properties
|
||||||
|
|
|
@ -8,8 +8,8 @@ android {
|
||||||
applicationId "org.schabi.newpipe"
|
applicationId "org.schabi.newpipe"
|
||||||
minSdkVersion 15
|
minSdkVersion 15
|
||||||
targetSdkVersion 23
|
targetSdkVersion 23
|
||||||
versionCode 9
|
versionCode 10
|
||||||
versionName "0.7.0"
|
versionName "0.7.1"
|
||||||
}
|
}
|
||||||
buildTypes {
|
buildTypes {
|
||||||
release {
|
release {
|
||||||
|
@ -17,7 +17,7 @@ android {
|
||||||
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
|
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
lintOptions {
|
lintOptions {
|
||||||
checkReleaseBuilds false
|
checkReleaseBuilds false
|
||||||
// Or, if you prefer, you can continue to check for errors in release builds,
|
// Or, if you prefer, you can continue to check for errors in release builds,
|
||||||
|
@ -35,4 +35,5 @@ dependencies {
|
||||||
compile 'com.android.support:recyclerview-v7:23.1.1'
|
compile 'com.android.support:recyclerview-v7:23.1.1'
|
||||||
compile 'org.jsoup:jsoup:1.8.3'
|
compile 'org.jsoup:jsoup:1.8.3'
|
||||||
compile 'org.mozilla:rhino:1.7.7'
|
compile 'org.mozilla:rhino:1.7.7'
|
||||||
|
compile 'info.guardianproject.netcipher:netcipher:1.2'
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,6 +7,7 @@
|
||||||
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
|
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
|
||||||
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
|
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
|
||||||
<application
|
<application
|
||||||
|
android:name=".App"
|
||||||
android:allowBackup="true"
|
android:allowBackup="true"
|
||||||
android:icon="@mipmap/ic_launcher"
|
android:icon="@mipmap/ic_launcher"
|
||||||
android:logo="@mipmap/ic_launcher"
|
android:logo="@mipmap/ic_launcher"
|
||||||
|
@ -29,43 +30,46 @@
|
||||||
<meta-data
|
<meta-data
|
||||||
android:name="android.support.PARENT_ACTIVITY"
|
android:name="android.support.PARENT_ACTIVITY"
|
||||||
android:value=".VideoItemListActivity" />
|
android:value=".VideoItemListActivity" />
|
||||||
|
|
||||||
<intent-filter>
|
<intent-filter>
|
||||||
<action android:name="android.intent.action.VIEW"/>
|
<action android:name="android.intent.action.VIEW" />
|
||||||
|
<action android:name="android.media.action.MEDIA_PLAY_FROM_SEARCH" />
|
||||||
|
<action android:name="android.nfc.action.NDEF_DISCOVERED" />
|
||||||
|
|
||||||
<category android:name="android.intent.category.DEFAULT" />
|
<category android:name="android.intent.category.DEFAULT" />
|
||||||
<category android:name="android.intent.category.BROWSABLE" />
|
<category android:name="android.intent.category.BROWSABLE" />
|
||||||
|
|
||||||
<data
|
<data android:scheme="http" />
|
||||||
android:host="youtube.com"
|
<data android:scheme="https" />
|
||||||
android:scheme="http"
|
<data android:host="youtube.com" />
|
||||||
android:pathPattern="/?*#*/*watch"/>
|
<data android:host="m.youtube.com" />
|
||||||
<data
|
<data android:host="www.youtube.com" />
|
||||||
android:host="youtube.com"
|
<data android:pathPrefix="/v/" />
|
||||||
android:scheme="https"
|
<data android:pathPrefix="/watch" />
|
||||||
android:pathPattern="/?*#*/*watch"/>
|
</intent-filter>
|
||||||
<data
|
<intent-filter>
|
||||||
android:host="www.youtube.com"
|
<action android:name="android.intent.action.VIEW" />
|
||||||
android:scheme="http"
|
<action android:name="android.media.action.MEDIA_PLAY_FROM_SEARCH" />
|
||||||
android:pathPattern="/?*#*/*watch"/>
|
<action android:name="android.nfc.action.NDEF_DISCOVERED" />
|
||||||
<data
|
|
||||||
android:host="www.youtube.com"
|
<category android:name="android.intent.category.DEFAULT" />
|
||||||
android:scheme="https"
|
<category android:name="android.intent.category.BROWSABLE" />
|
||||||
android:pathPattern="/?*#*/*watch"/>
|
|
||||||
<data
|
<data android:scheme="http" />
|
||||||
android:host="m.youtube.com"
|
<data android:scheme="https" />
|
||||||
android:scheme="http"
|
<data android:host="youtu.be" />
|
||||||
android:pathPattern="/?*#*/*watch"/>
|
<data android:pathPrefix="/" />
|
||||||
<data
|
</intent-filter>
|
||||||
android:host="m.youtube.com"
|
<intent-filter>
|
||||||
android:scheme="https"
|
<action android:name="android.intent.action.VIEW" />
|
||||||
android:pathPattern="/?*#*/*watch"/>
|
<action android:name="android.media.action.MEDIA_PLAY_FROM_SEARCH" />
|
||||||
<data
|
<action android:name="android.nfc.action.NDEF_DISCOVERED" />
|
||||||
android:host="youtu.be"
|
|
||||||
android:scheme="https"
|
<category android:name="android.intent.category.DEFAULT" />
|
||||||
android:pathPrefix="/"/>
|
<category android:name="android.intent.category.BROWSABLE" />
|
||||||
<data
|
|
||||||
android:host="youtu.be"
|
<data android:scheme="vnd.youtube" />
|
||||||
android:scheme="http"
|
<data android:scheme="vnd.youtube.launch" />
|
||||||
android:pathPrefix="/"/>
|
|
||||||
</intent-filter>
|
</intent-filter>
|
||||||
</activity>
|
</activity>
|
||||||
<activity android:name=".PlayVideoActivity"
|
<activity android:name=".PlayVideoActivity"
|
||||||
|
@ -74,15 +78,26 @@
|
||||||
android:parentActivityName=".VideoItemDetailActivity"
|
android:parentActivityName=".VideoItemDetailActivity"
|
||||||
tools:ignore="UnusedAttribute">
|
tools:ignore="UnusedAttribute">
|
||||||
</activity>
|
</activity>
|
||||||
<!--TODO: make label a translatable string -->
|
|
||||||
<service
|
<service
|
||||||
android:name=".BackgroundPlayer"
|
android:name=".BackgroundPlayer"
|
||||||
android:label="NewPipe Background Player"
|
android:label="@string/background_player_name"
|
||||||
android:exported="false" >
|
android:exported="false" />
|
||||||
</service>
|
|
||||||
<activity
|
<activity
|
||||||
android:name=".SettingsActivity"
|
android:name=".SettingsActivity"
|
||||||
android:label="@string/title_activity_settings" >
|
android:label="@string/title_activity_settings" >
|
||||||
</activity>
|
</activity>
|
||||||
|
<activity
|
||||||
|
android:name=".PanicResponderActivity"
|
||||||
|
android:launchMode="singleInstance"
|
||||||
|
android:noHistory="true"
|
||||||
|
android:theme="@android:style/Theme.NoDisplay">
|
||||||
|
<intent-filter>
|
||||||
|
<action android:name="info.guardianproject.panic.action.TRIGGER" />
|
||||||
|
<category android:name="android.intent.category.DEFAULT" />
|
||||||
|
</intent-filter>
|
||||||
|
</activity>
|
||||||
|
<activity
|
||||||
|
android:name=".ExitActivity"
|
||||||
|
android:theme="@android:style/Theme.NoDisplay" />
|
||||||
</application>
|
</application>
|
||||||
</manifest>
|
</manifest>
|
||||||
|
|
|
@ -0,0 +1,46 @@
|
||||||
|
package org.schabi.newpipe;
|
||||||
|
|
||||||
|
import android.app.Application;
|
||||||
|
import android.content.Context;
|
||||||
|
import android.content.SharedPreferences;
|
||||||
|
import android.preference.PreferenceManager;
|
||||||
|
|
||||||
|
import info.guardianproject.netcipher.NetCipher;
|
||||||
|
import info.guardianproject.netcipher.proxy.OrbotHelper;
|
||||||
|
|
||||||
|
public class App extends Application {
|
||||||
|
|
||||||
|
private static boolean useTor;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onCreate() {
|
||||||
|
super.onCreate();
|
||||||
|
// if Orbot is installed, then default to using Tor, the user can still override
|
||||||
|
if (OrbotHelper.requestStartTor(this)) {
|
||||||
|
SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(this);
|
||||||
|
configureTor(prefs.getBoolean(getString(R.string.useTor), true));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set the proxy settings based on whether Tor should be enabled or not.
|
||||||
|
*/
|
||||||
|
static void configureTor(boolean enabled) {
|
||||||
|
useTor = enabled;
|
||||||
|
if (useTor) {
|
||||||
|
NetCipher.useTor();
|
||||||
|
} else {
|
||||||
|
NetCipher.setProxy(null);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void checkStartTor(Context context) {
|
||||||
|
if (useTor) {
|
||||||
|
OrbotHelper.requestStartTor(context);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static boolean isUsingTor() {
|
||||||
|
return useTor;
|
||||||
|
}
|
||||||
|
}
|
|
@ -17,6 +17,7 @@ import android.os.IBinder;
|
||||||
import android.os.PowerManager;
|
import android.os.PowerManager;
|
||||||
import android.support.v7.app.NotificationCompat;
|
import android.support.v7.app.NotificationCompat;
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
|
import android.widget.RemoteViews;
|
||||||
import android.widget.Toast;
|
import android.widget.Toast;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
@ -113,9 +114,9 @@ public class BackgroundPlayer extends Service /*implements MediaPlayer.OnPrepare
|
||||||
private int noteID = TAG.hashCode();
|
private int noteID = TAG.hashCode();
|
||||||
private BackgroundPlayer owner;
|
private BackgroundPlayer owner;
|
||||||
private NotificationManager noteMgr;
|
private NotificationManager noteMgr;
|
||||||
private NotificationCompat.Builder noteBuilder;
|
|
||||||
private WifiManager.WifiLock wifiLock;
|
private WifiManager.WifiLock wifiLock;
|
||||||
private Bitmap videoThumbnail = null;
|
private Bitmap videoThumbnail = null;
|
||||||
|
private NotificationCompat.Builder noteBuilder;
|
||||||
|
|
||||||
public PlayerThread(String src, String title, BackgroundPlayer owner) {
|
public PlayerThread(String src, String title, BackgroundPlayer owner) {
|
||||||
this.source = src;
|
this.source = src;
|
||||||
|
@ -124,10 +125,9 @@ public class BackgroundPlayer extends Service /*implements MediaPlayer.OnPrepare
|
||||||
mediaPlayer = new MediaPlayer();
|
mediaPlayer = new MediaPlayer();
|
||||||
mediaPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC);
|
mediaPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void run() {
|
public void run() {
|
||||||
Resources res = getApplicationContext().getResources();
|
|
||||||
|
|
||||||
mediaPlayer.setWakeMode(getApplicationContext(), PowerManager.PARTIAL_WAKE_LOCK);//cpu lock
|
mediaPlayer.setWakeMode(getApplicationContext(), PowerManager.PARTIAL_WAKE_LOCK);//cpu lock
|
||||||
try {
|
try {
|
||||||
mediaPlayer.setDataSource(source);
|
mediaPlayer.setDataSource(source);
|
||||||
|
@ -174,54 +174,7 @@ public class BackgroundPlayer extends Service /*implements MediaPlayer.OnPrepare
|
||||||
filter.addAction(ACTION_STOP);
|
filter.addAction(ACTION_STOP);
|
||||||
registerReceiver(broadcastReceiver, filter);
|
registerReceiver(broadcastReceiver, filter);
|
||||||
|
|
||||||
PendingIntent playPI = PendingIntent.getBroadcast(owner, noteID,
|
Notification note = buildNotification();
|
||||||
new Intent(ACTION_PLAYPAUSE), PendingIntent.FLAG_UPDATE_CURRENT);
|
|
||||||
|
|
||||||
NotificationCompat.Action playButton = new NotificationCompat.Action.Builder
|
|
||||||
(R.drawable.ic_play_arrow_white_48dp, "Play", playPI).build();
|
|
||||||
|
|
||||||
/*
|
|
||||||
NotificationCompat.Action pauseButton = new NotificationCompat.Action.Builder
|
|
||||||
(R.drawable.ic_pause_white_24dp, "Pause", playPI).build();
|
|
||||||
*/
|
|
||||||
|
|
||||||
PendingIntent stopPI = PendingIntent.getBroadcast(owner, noteID,
|
|
||||||
new Intent(ACTION_STOP), PendingIntent.FLAG_UPDATE_CURRENT);
|
|
||||||
|
|
||||||
noteBuilder = new NotificationCompat.Builder(owner);
|
|
||||||
noteBuilder
|
|
||||||
.setContentTitle(title)
|
|
||||||
//really? Id like to put something more helpful here.
|
|
||||||
//.setContentText("NewPipe is playing in the background")
|
|
||||||
.setContentText(channelName)
|
|
||||||
//.setAutoCancel(!mediaPlayer.isPlaying())
|
|
||||||
.setOngoing(true)
|
|
||||||
.setDeleteIntent(stopPI)
|
|
||||||
//doesn't fit with Notification.MediaStyle
|
|
||||||
//.setProgress(vidLength, 0, false)
|
|
||||||
.setSmallIcon(R.drawable.ic_play_circle_filled_white_24dp)
|
|
||||||
.setLargeIcon(videoThumbnail)
|
|
||||||
.setTicker(
|
|
||||||
String.format(res.getString(
|
|
||||||
R.string.backgroundPlayerTickerText), title))
|
|
||||||
.addAction(playButton);
|
|
||||||
//.setVisibility(NotificationCompat.VISIBILITY_PUBLIC)
|
|
||||||
//.setLargeIcon(cover)
|
|
||||||
if(android.os.Build.VERSION.SDK_INT >= 16)
|
|
||||||
noteBuilder.setPriority(Notification.PRIORITY_LOW);
|
|
||||||
if(android.os.Build.VERSION.SDK_INT >= 21)
|
|
||||||
noteBuilder.setCategory(Notification.CATEGORY_TRANSPORT);
|
|
||||||
|
|
||||||
noteBuilder.setStyle(new NotificationCompat.MediaStyle()
|
|
||||||
//.setMediaSession(mMediaSession.getSessionToken())
|
|
||||||
.setShowActionsInCompactView(new int[]{0})
|
|
||||||
.setShowCancelButton(true)
|
|
||||||
.setCancelButtonIntent(stopPI));
|
|
||||||
if(videoThumbnail != null) {
|
|
||||||
noteBuilder.setLargeIcon(videoThumbnail);
|
|
||||||
}
|
|
||||||
|
|
||||||
Notification note = noteBuilder.build();
|
|
||||||
|
|
||||||
Intent openDetailView = new Intent(getApplicationContext(),
|
Intent openDetailView = new Intent(getApplicationContext(),
|
||||||
VideoItemDetailActivity.class);
|
VideoItemDetailActivity.class);
|
||||||
|
@ -249,7 +202,6 @@ public class BackgroundPlayer extends Service /*implements MediaPlayer.OnPrepare
|
||||||
Log.d(TAG, "sleep failure");
|
Log.d(TAG, "sleep failure");
|
||||||
}
|
}
|
||||||
}*/
|
}*/
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private final BroadcastReceiver broadcastReceiver = new BroadcastReceiver() {
|
private final BroadcastReceiver broadcastReceiver = new BroadcastReceiver() {
|
||||||
|
@ -303,5 +255,93 @@ public class BackgroundPlayer extends Service /*implements MediaPlayer.OnPrepare
|
||||||
afterPlayCleanup();
|
afterPlayCleanup();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private Notification buildNotification() {
|
||||||
|
Notification note;
|
||||||
|
Resources res = getApplicationContext().getResources();
|
||||||
|
noteBuilder = new NotificationCompat.Builder(owner);
|
||||||
|
|
||||||
|
PendingIntent playPI = PendingIntent.getBroadcast(owner, noteID,
|
||||||
|
new Intent(ACTION_PLAYPAUSE), PendingIntent.FLAG_UPDATE_CURRENT);
|
||||||
|
PendingIntent stopPI = PendingIntent.getBroadcast(owner, noteID,
|
||||||
|
new Intent(ACTION_STOP), PendingIntent.FLAG_UPDATE_CURRENT);
|
||||||
|
/*
|
||||||
|
NotificationCompat.Action pauseButton = new NotificationCompat.Action.Builder
|
||||||
|
(R.drawable.ic_pause_white_24dp, "Pause", playPI).build();
|
||||||
|
*/
|
||||||
|
|
||||||
|
noteBuilder
|
||||||
|
.setOngoing(true)
|
||||||
|
.setDeleteIntent(stopPI)
|
||||||
|
//doesn't fit with Notification.MediaStyle
|
||||||
|
//.setProgress(vidLength, 0, false)
|
||||||
|
.setSmallIcon(R.drawable.ic_play_circle_filled_white_24dp)
|
||||||
|
.setTicker(
|
||||||
|
String.format(res.getString(
|
||||||
|
R.string.backgroundPlayerTickerText), title));
|
||||||
|
|
||||||
|
if (android.os.Build.VERSION.SDK_INT < 21) {
|
||||||
|
|
||||||
|
NotificationCompat.Action playButton = new NotificationCompat.Action.Builder
|
||||||
|
(R.drawable.ic_play_arrow_white_48dp,
|
||||||
|
res.getString(R.string.play), playPI).build();
|
||||||
|
|
||||||
|
noteBuilder
|
||||||
|
.setContentTitle(title)
|
||||||
|
//really? Id like to put something more helpful here.
|
||||||
|
//.setContentText("NewPipe is playing in the background")
|
||||||
|
.setContentText(channelName)
|
||||||
|
//.setAutoCancel(!mediaPlayer.isPlaying())
|
||||||
|
.setDeleteIntent(stopPI)
|
||||||
|
//doesn't fit with Notification.MediaStyle
|
||||||
|
//.setProgress(vidLength, 0, false)
|
||||||
|
.setLargeIcon(videoThumbnail)
|
||||||
|
.addAction(playButton);
|
||||||
|
//.setVisibility(NotificationCompat.VISIBILITY_PUBLIC)
|
||||||
|
//.setLargeIcon(cover)
|
||||||
|
|
||||||
|
if (android.os.Build.VERSION.SDK_INT >= 16)
|
||||||
|
noteBuilder.setPriority(Notification.PRIORITY_LOW);
|
||||||
|
|
||||||
|
noteBuilder.setStyle(new NotificationCompat.MediaStyle()
|
||||||
|
//.setMediaSession(mMediaSession.getSessionToken())
|
||||||
|
.setShowActionsInCompactView(new int[]{0})
|
||||||
|
.setShowCancelButton(true)
|
||||||
|
.setCancelButtonIntent(stopPI));
|
||||||
|
if (videoThumbnail != null) {
|
||||||
|
noteBuilder.setLargeIcon(videoThumbnail);
|
||||||
|
}
|
||||||
|
note = noteBuilder.build();
|
||||||
|
} else {
|
||||||
|
RemoteViews view =
|
||||||
|
new RemoteViews(BuildConfig.APPLICATION_ID, R.layout.player_notification);
|
||||||
|
view.setImageViewBitmap(R.id.backgroundCover, videoThumbnail);
|
||||||
|
view.setTextViewText(R.id.backgroundSongName, title);
|
||||||
|
view.setTextViewText(R.id.backgroundArtist, channelName);
|
||||||
|
view.setOnClickPendingIntent(R.id.backgroundStop, stopPI);
|
||||||
|
view.setOnClickPendingIntent(R.id.backgroundPlayPause, playPI);
|
||||||
|
|
||||||
|
RemoteViews expandedView =
|
||||||
|
new RemoteViews(BuildConfig.APPLICATION_ID, R.layout.player_notification);
|
||||||
|
expandedView.setImageViewBitmap(R.id.backgroundCover, videoThumbnail);
|
||||||
|
expandedView.setTextViewText(R.id.backgroundSongName, title);
|
||||||
|
expandedView.setTextViewText(R.id.backgroundArtist, channelName);
|
||||||
|
expandedView.setOnClickPendingIntent(R.id.backgroundStop, stopPI);
|
||||||
|
expandedView.setOnClickPendingIntent(R.id.backgroundPlayPause, playPI);
|
||||||
|
|
||||||
|
noteBuilder.setCategory(Notification.CATEGORY_TRANSPORT);
|
||||||
|
|
||||||
|
//Make notification appear on lockscreen
|
||||||
|
noteBuilder.setVisibility(Notification.VISIBILITY_PUBLIC);
|
||||||
|
|
||||||
|
note = noteBuilder.build();
|
||||||
|
note.contentView = view;
|
||||||
|
|
||||||
|
//todo: This never shows up. I was not able to figure out why:
|
||||||
|
note.bigContentView = expandedView;
|
||||||
|
}
|
||||||
|
|
||||||
|
return note;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -57,26 +57,29 @@ public class DownloadDialog extends DialogFragment {
|
||||||
@Override
|
@Override
|
||||||
public void onClick(DialogInterface dialog, int which) {
|
public void onClick(DialogInterface dialog, int which) {
|
||||||
Context context = getActivity();
|
Context context = getActivity();
|
||||||
SharedPreferences defaultPreferences = PreferenceManager.getDefaultSharedPreferences(context);
|
SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(context);
|
||||||
String suffix = "";
|
String suffix = "";
|
||||||
String title = arguments.getString(TITLE);
|
String title = arguments.getString(TITLE);
|
||||||
String url = "";
|
String url = "";
|
||||||
|
String downloadFolder = Environment.DIRECTORY_DOWNLOADS;
|
||||||
switch(which) {
|
switch(which) {
|
||||||
case 0: // Video
|
case 0: // Video
|
||||||
suffix = arguments.getString(FILE_SUFFIX_VIDEO);
|
suffix = arguments.getString(FILE_SUFFIX_VIDEO);
|
||||||
url = arguments.getString(VIDEO_URL);
|
url = arguments.getString(VIDEO_URL);
|
||||||
|
downloadFolder = Environment.DIRECTORY_MOVIES;
|
||||||
break;
|
break;
|
||||||
case 1:
|
case 1:
|
||||||
suffix = arguments.getString(FILE_SUFFIX_AUDIO);
|
suffix = arguments.getString(FILE_SUFFIX_AUDIO);
|
||||||
url = arguments.getString(AUDIO_URL);
|
url = arguments.getString(AUDIO_URL);
|
||||||
|
downloadFolder = Environment.DIRECTORY_MUSIC;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
Log.d(TAG, "lolz");
|
Log.d(TAG, "lolz");
|
||||||
}
|
}
|
||||||
//to avoid hard-coded string like "/storage/emulated/0/NewPipe"
|
//to avoid hard-coded string like "/storage/emulated/0/Movies"
|
||||||
final File dir = new File(defaultPreferences.getString(
|
String downloadPath = prefs.getString(getString(R.string.downloadPathPreference),
|
||||||
"download_path_preference",
|
Environment.getExternalStorageDirectory().getAbsolutePath() + "/" + downloadFolder);
|
||||||
Environment.getExternalStorageDirectory().getAbsolutePath() + "/NewPipe"));
|
final File dir = new File(downloadPath);
|
||||||
if(!dir.exists()) {
|
if(!dir.exists()) {
|
||||||
boolean mkdir = dir.mkdir(); //attempt to create directory
|
boolean mkdir = dir.mkdir(); //attempt to create directory
|
||||||
if(!mkdir && !dir.isDirectory()) {
|
if(!mkdir && !dir.isDirectory()) {
|
||||||
|
@ -84,17 +87,21 @@ public class DownloadDialog extends DialogFragment {
|
||||||
//TODO notify user "download directory should be changed" ?
|
//TODO notify user "download directory should be changed" ?
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
DownloadManager dm = (DownloadManager) context.getSystemService(Context.DOWNLOAD_SERVICE);
|
String saveFilePath = dir + "/" + title + suffix;
|
||||||
DownloadManager.Request request = new DownloadManager.Request(
|
if (App.isUsingTor()) {
|
||||||
Uri.parse(url));
|
// if using Tor, do not use DownloadManager because the proxy cannot be set
|
||||||
request.setDestinationUri(Uri.fromFile(new File(
|
Downloader.downloadFile(getContext(), url, saveFilePath);
|
||||||
defaultPreferences.getString("download_path_preference", "/storage/emulated/0/NewPipe")
|
} else {
|
||||||
+ "/" + title + suffix)));
|
DownloadManager dm = (DownloadManager) context.getSystemService(Context.DOWNLOAD_SERVICE);
|
||||||
request.setNotificationVisibility(DownloadManager.Request.VISIBILITY_VISIBLE_NOTIFY_COMPLETED);
|
DownloadManager.Request request = new DownloadManager.Request(
|
||||||
try {
|
Uri.parse(url));
|
||||||
dm.enqueue(request);
|
request.setDestinationUri(Uri.fromFile(new File(saveFilePath)));
|
||||||
} catch (Exception e) {
|
request.setNotificationVisibility(DownloadManager.Request.VISIBILITY_VISIBLE_NOTIFY_COMPLETED);
|
||||||
e.printStackTrace();
|
try {
|
||||||
|
dm.enqueue(request);
|
||||||
|
} catch (Exception e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
|
@ -1,12 +1,30 @@
|
||||||
package org.schabi.newpipe;
|
package org.schabi.newpipe;
|
||||||
|
|
||||||
|
import android.app.Notification;
|
||||||
|
import android.app.NotificationManager;
|
||||||
|
import android.content.Context;
|
||||||
|
import android.graphics.drawable.BitmapDrawable;
|
||||||
|
import android.graphics.drawable.Drawable;
|
||||||
|
import android.os.AsyncTask;
|
||||||
|
import android.support.v4.app.NotificationCompat;
|
||||||
|
import android.util.Log;
|
||||||
|
|
||||||
|
import java.io.BufferedInputStream;
|
||||||
import java.io.BufferedReader;
|
import java.io.BufferedReader;
|
||||||
|
import java.io.File;
|
||||||
|
import java.io.FileOutputStream;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
import java.io.InputStream;
|
||||||
import java.io.InputStreamReader;
|
import java.io.InputStreamReader;
|
||||||
import java.net.HttpURLConnection;
|
import java.net.HttpURLConnection;
|
||||||
|
import java.net.MalformedURLException;
|
||||||
import java.net.URL;
|
import java.net.URL;
|
||||||
import java.net.UnknownHostException;
|
import java.net.UnknownHostException;
|
||||||
|
|
||||||
|
import javax.net.ssl.HttpsURLConnection;
|
||||||
|
|
||||||
|
import info.guardianproject.netcipher.NetCipher;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Created by Christian Schabesberger on 14.08.15.
|
* Created by Christian Schabesberger on 14.08.15.
|
||||||
*
|
*
|
||||||
|
@ -28,6 +46,7 @@ import java.net.UnknownHostException;
|
||||||
*/
|
*/
|
||||||
|
|
||||||
public class Downloader {
|
public class Downloader {
|
||||||
|
public static final String TAG = "Downloader";
|
||||||
|
|
||||||
private static final String USER_AGENT = "Mozilla/5.0";
|
private static final String USER_AGENT = "Mozilla/5.0";
|
||||||
|
|
||||||
|
@ -40,7 +59,7 @@ public class Downloader {
|
||||||
String ret = "";
|
String ret = "";
|
||||||
try {
|
try {
|
||||||
URL url = new URL(siteUrl);
|
URL url = new URL(siteUrl);
|
||||||
HttpURLConnection con = (HttpURLConnection) url.openConnection();
|
HttpsURLConnection con = NetCipher.getHttpsURLConnection(url);
|
||||||
con.setRequestProperty("Accept-Language", language);
|
con.setRequestProperty("Accept-Language", language);
|
||||||
ret = dl(con);
|
ret = dl(con);
|
||||||
}
|
}
|
||||||
|
@ -84,7 +103,7 @@ public class Downloader {
|
||||||
|
|
||||||
try {
|
try {
|
||||||
URL url = new URL(siteUrl);
|
URL url = new URL(siteUrl);
|
||||||
HttpURLConnection con = (HttpURLConnection) url.openConnection();
|
HttpsURLConnection con = NetCipher.getHttpsURLConnection(url);
|
||||||
ret = dl(con);
|
ret = dl(con);
|
||||||
}
|
}
|
||||||
catch(Exception e) {
|
catch(Exception e) {
|
||||||
|
@ -93,4 +112,92 @@ public class Downloader {
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Downloads a file from a URL in the background using an {@link AsyncTask}.
|
||||||
|
*
|
||||||
|
* @param fileURL HTTP URL of the file to be downloaded
|
||||||
|
* @param saveFilePath path of the directory to save the file
|
||||||
|
* @throws IOException
|
||||||
|
*/
|
||||||
|
public static void downloadFile(final Context context, final String fileURL, final String saveFilePath) {
|
||||||
|
new AsyncTask<Void, Integer, Void>() {
|
||||||
|
|
||||||
|
private NotificationManager nm;
|
||||||
|
private NotificationCompat.Builder builder;
|
||||||
|
private int notifyId = 0x1234;
|
||||||
|
private int fileSize = 0xffffffff;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void onPreExecute() {
|
||||||
|
super.onPreExecute();
|
||||||
|
nm = (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);
|
||||||
|
Drawable icon = context.getResources().getDrawable(R.mipmap.ic_launcher);
|
||||||
|
builder = new NotificationCompat.Builder(context)
|
||||||
|
.setSmallIcon(android.R.drawable.stat_sys_download)
|
||||||
|
.setLargeIcon(((BitmapDrawable) icon).getBitmap())
|
||||||
|
.setContentTitle(saveFilePath.substring(saveFilePath.lastIndexOf('/') + 1))
|
||||||
|
.setContentText(saveFilePath)
|
||||||
|
.setProgress(fileSize, 0, false);
|
||||||
|
nm.notify(notifyId, builder.build());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected Void doInBackground(Void... voids) {
|
||||||
|
HttpsURLConnection con = null;
|
||||||
|
try {
|
||||||
|
con = NetCipher.getHttpsURLConnection(fileURL);
|
||||||
|
int responseCode = con.getResponseCode();
|
||||||
|
|
||||||
|
// always check HTTP response code first
|
||||||
|
if (responseCode == HttpURLConnection.HTTP_OK) {
|
||||||
|
fileSize = con.getContentLength();
|
||||||
|
InputStream inputStream = new BufferedInputStream(con.getInputStream());
|
||||||
|
FileOutputStream outputStream = new FileOutputStream(saveFilePath);
|
||||||
|
|
||||||
|
int bufferSize = 8192;
|
||||||
|
int downloaded = 0;
|
||||||
|
|
||||||
|
int bytesRead = -1;
|
||||||
|
byte[] buffer = new byte[bufferSize];
|
||||||
|
while ((bytesRead = inputStream.read(buffer)) != -1) {
|
||||||
|
outputStream.write(buffer, 0, bytesRead);
|
||||||
|
downloaded += bytesRead;
|
||||||
|
if (downloaded % 50000 < bufferSize) {
|
||||||
|
publishProgress(downloaded);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
outputStream.close();
|
||||||
|
inputStream.close();
|
||||||
|
publishProgress(bufferSize);
|
||||||
|
|
||||||
|
} else {
|
||||||
|
Log.i(TAG, "No file to download. Server replied HTTP code: " + responseCode);
|
||||||
|
}
|
||||||
|
} catch (IOException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
} finally {
|
||||||
|
if (con != null) {
|
||||||
|
con.disconnect();
|
||||||
|
con = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void onProgressUpdate(Integer... progress) {
|
||||||
|
builder.setProgress(fileSize, progress[0], false);
|
||||||
|
nm.notify(notifyId, builder.build());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void onPostExecute(Void aVoid) {
|
||||||
|
super.onPostExecute(aVoid);
|
||||||
|
nm.cancel(notifyId);
|
||||||
|
}
|
||||||
|
}.execute();
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,36 @@
|
||||||
|
|
||||||
|
package org.schabi.newpipe;
|
||||||
|
|
||||||
|
import android.annotation.SuppressLint;
|
||||||
|
import android.app.Activity;
|
||||||
|
import android.content.Intent;
|
||||||
|
import android.os.Build;
|
||||||
|
import android.os.Bundle;
|
||||||
|
|
||||||
|
public class ExitActivity extends Activity {
|
||||||
|
|
||||||
|
@SuppressLint("NewApi")
|
||||||
|
@Override
|
||||||
|
protected void onCreate(Bundle savedInstanceState) {
|
||||||
|
super.onCreate(savedInstanceState);
|
||||||
|
|
||||||
|
if (Build.VERSION.SDK_INT >= 21) {
|
||||||
|
finishAndRemoveTask();
|
||||||
|
} else {
|
||||||
|
finish();
|
||||||
|
}
|
||||||
|
|
||||||
|
System.exit(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void exitAndRemoveFromRecentApps(Activity activity) {
|
||||||
|
Intent intent = new Intent(activity, ExitActivity.class);
|
||||||
|
|
||||||
|
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK
|
||||||
|
| Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS
|
||||||
|
| Intent.FLAG_ACTIVITY_CLEAR_TASK
|
||||||
|
| Intent.FLAG_ACTIVITY_NO_ANIMATION);
|
||||||
|
|
||||||
|
activity.startActivity(intent);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,77 @@
|
||||||
|
package org.schabi.newpipe;
|
||||||
|
|
||||||
|
import android.annotation.SuppressLint;
|
||||||
|
import android.content.Context;
|
||||||
|
import android.content.SharedPreferences;
|
||||||
|
import android.content.res.Resources;
|
||||||
|
import android.preference.PreferenceManager;
|
||||||
|
|
||||||
|
import java.text.DateFormat;
|
||||||
|
import java.text.NumberFormat;
|
||||||
|
import java.text.ParseException;
|
||||||
|
import java.text.SimpleDateFormat;
|
||||||
|
import java.util.Date;
|
||||||
|
import java.util.Locale;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Created by chschtsch on 12/29/15.
|
||||||
|
*/
|
||||||
|
|
||||||
|
public class Localization {
|
||||||
|
|
||||||
|
public static Locale getPreferredLocale(Context context) {
|
||||||
|
SharedPreferences sp = PreferenceManager.getDefaultSharedPreferences(context);
|
||||||
|
|
||||||
|
String languageCode = sp.getString(String.valueOf(R.string.searchLanguage), "en");
|
||||||
|
|
||||||
|
if(languageCode.length() == 2) {
|
||||||
|
return new Locale(languageCode);
|
||||||
|
}
|
||||||
|
else if(languageCode.contains("_")) {
|
||||||
|
String country = languageCode
|
||||||
|
.substring(languageCode.indexOf("_"), languageCode.length());
|
||||||
|
return new Locale(languageCode.substring(0, 2), country);
|
||||||
|
}
|
||||||
|
return Locale.getDefault();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static String localizeViewCount(long viewCount, Context context) {
|
||||||
|
Locale locale = getPreferredLocale(context);
|
||||||
|
|
||||||
|
Resources res = context.getResources();
|
||||||
|
String viewsString = res.getString(R.string.viewCountText);
|
||||||
|
|
||||||
|
NumberFormat nf = NumberFormat.getInstance(locale);
|
||||||
|
String formattedViewCount = nf.format(viewCount);
|
||||||
|
return String.format(viewsString, formattedViewCount);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static String localizeNumber(long number, Context context) {
|
||||||
|
Locale locale = getPreferredLocale(context);
|
||||||
|
NumberFormat nf = NumberFormat.getInstance(locale);
|
||||||
|
return nf.format(number);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static String formatDate(String date, Context context) {
|
||||||
|
Locale locale = getPreferredLocale(context);
|
||||||
|
SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd");
|
||||||
|
Date datum = null;
|
||||||
|
try {
|
||||||
|
datum = formatter.parse(date);
|
||||||
|
} catch (ParseException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
|
||||||
|
DateFormat df = DateFormat.getDateInstance(DateFormat.MEDIUM, locale);
|
||||||
|
|
||||||
|
return df.format(datum);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static String localizeDate(String date, Context context) {
|
||||||
|
Resources res = context.getResources();
|
||||||
|
String dateString = res.getString(R.string.uploadDateText);
|
||||||
|
|
||||||
|
String formattedDate = formatDate(date, context);
|
||||||
|
return String.format(dateString, formattedDate);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,32 @@
|
||||||
|
|
||||||
|
package org.schabi.newpipe;
|
||||||
|
|
||||||
|
import android.annotation.SuppressLint;
|
||||||
|
import android.app.Activity;
|
||||||
|
import android.content.Intent;
|
||||||
|
import android.os.Build;
|
||||||
|
import android.os.Bundle;
|
||||||
|
|
||||||
|
public class PanicResponderActivity extends Activity {
|
||||||
|
|
||||||
|
public static final String PANIC_TRIGGER_ACTION = "info.guardianproject.panic.action.TRIGGER";
|
||||||
|
|
||||||
|
@SuppressLint("NewApi")
|
||||||
|
@Override
|
||||||
|
protected void onCreate(Bundle savedInstanceState) {
|
||||||
|
super.onCreate(savedInstanceState);
|
||||||
|
|
||||||
|
Intent intent = getIntent();
|
||||||
|
if (intent != null && PANIC_TRIGGER_ACTION.equals(intent.getAction())) {
|
||||||
|
// TODO explicitly clear the search results once they are restored when the app restarts
|
||||||
|
// or if the app reloads the current video after being killed, that should be cleared also
|
||||||
|
ExitActivity.exitAndRemoveFromRecentApps(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Build.VERSION.SDK_INT >= 21) {
|
||||||
|
finishAndRemoveTask();
|
||||||
|
} else {
|
||||||
|
finish();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -187,6 +187,18 @@ public class PlayVideoActivity extends AppCompatActivity {
|
||||||
videoView.pause();
|
videoView.pause();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onResume() {
|
||||||
|
super.onResume();
|
||||||
|
App.checkStartTor(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void onDestroy() {
|
||||||
|
super.onDestroy();
|
||||||
|
prefs = getPreferences(Context.MODE_PRIVATE);
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean onOptionsItemSelected(MenuItem item) {
|
public boolean onOptionsItemSelected(MenuItem item) {
|
||||||
int id = item.getItemId();
|
int id = item.getItemId();
|
||||||
|
|
|
@ -1,13 +1,14 @@
|
||||||
package org.schabi.newpipe;
|
package org.schabi.newpipe;
|
||||||
|
|
||||||
|
import android.app.Activity;
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.content.SharedPreferences;
|
import android.content.Intent;
|
||||||
import android.content.res.Configuration;
|
import android.content.res.Configuration;
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
import android.os.Environment;
|
import android.preference.CheckBoxPreference;
|
||||||
|
import android.preference.Preference;
|
||||||
import android.preference.PreferenceActivity;
|
import android.preference.PreferenceActivity;
|
||||||
import android.preference.PreferenceFragment;
|
import android.preference.PreferenceFragment;
|
||||||
import android.preference.PreferenceManager;
|
|
||||||
import android.support.annotation.LayoutRes;
|
import android.support.annotation.LayoutRes;
|
||||||
import android.support.annotation.NonNull;
|
import android.support.annotation.NonNull;
|
||||||
import android.support.v7.app.ActionBar;
|
import android.support.v7.app.ActionBar;
|
||||||
|
@ -17,6 +18,8 @@ import android.view.MenuItem;
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
import android.view.ViewGroup;
|
import android.view.ViewGroup;
|
||||||
|
|
||||||
|
import info.guardianproject.netcipher.proxy.OrbotHelper;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Created by Christian Schabesberger on 31.08.15.
|
* Created by Christian Schabesberger on 31.08.15.
|
||||||
*
|
*
|
||||||
|
@ -39,6 +42,7 @@ import android.view.ViewGroup;
|
||||||
|
|
||||||
public class SettingsActivity extends PreferenceActivity {
|
public class SettingsActivity extends PreferenceActivity {
|
||||||
|
|
||||||
|
private static final int REQUEST_INSTALL_ORBOT = 0x1234;
|
||||||
private AppCompatDelegate mDelegate = null;
|
private AppCompatDelegate mDelegate = null;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -56,13 +60,48 @@ public class SettingsActivity extends PreferenceActivity {
|
||||||
}
|
}
|
||||||
|
|
||||||
public static class SettingsFragment extends PreferenceFragment {
|
public static class SettingsFragment extends PreferenceFragment {
|
||||||
|
private CheckBoxPreference useTorCheckBox;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onCreate(Bundle savedInstanceState) {
|
public void onCreate(Bundle savedInstanceState) {
|
||||||
super.onCreate(savedInstanceState);
|
super.onCreate(savedInstanceState);
|
||||||
addPreferencesFromResource(R.xml.settings_screen);
|
addPreferencesFromResource(R.xml.settings_screen);
|
||||||
|
|
||||||
|
// if Orbot is installed, then default to using Tor, the user can still override
|
||||||
|
useTorCheckBox = (CheckBoxPreference) findPreference(getString(R.string.useTor));
|
||||||
|
final Activity activity = getActivity();
|
||||||
|
final boolean useTor = OrbotHelper.isOrbotInstalled(activity);
|
||||||
|
useTorCheckBox.setDefaultValue(useTor);
|
||||||
|
useTorCheckBox.setChecked(useTor);
|
||||||
|
useTorCheckBox.setOnPreferenceChangeListener(new Preference.OnPreferenceChangeListener() {
|
||||||
|
@Override
|
||||||
|
public boolean onPreferenceChange(Preference preference, Object o) {
|
||||||
|
boolean useTor = (Boolean) o;
|
||||||
|
if (useTor) {
|
||||||
|
if (OrbotHelper.isOrbotInstalled(activity)) {
|
||||||
|
App.configureTor(true);
|
||||||
|
} else {
|
||||||
|
Intent intent = OrbotHelper.getOrbotInstallIntent(activity);
|
||||||
|
activity.startActivityForResult(intent, REQUEST_INSTALL_ORBOT);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
App.configureTor(false);
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
|
||||||
|
super.onActivityResult(requestCode, resultCode, data);
|
||||||
|
// try to start tor regardless of resultCode since clicking back after
|
||||||
|
// installing the app does not necessarily return RESULT_OK
|
||||||
|
App.configureTor(requestCode == REQUEST_INSTALL_ORBOT
|
||||||
|
&& OrbotHelper.requestStartTor(this));
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void onPostCreate(Bundle savedInstanceState) {
|
protected void onPostCreate(Bundle savedInstanceState) {
|
||||||
super.onPostCreate(savedInstanceState);
|
super.onPostCreate(savedInstanceState);
|
||||||
|
@ -148,17 +187,4 @@ public class SettingsActivity extends PreferenceActivity {
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void initSettings(Context context) {
|
|
||||||
PreferenceManager.setDefaultValues(context, R.xml.settings_screen, false);
|
|
||||||
SharedPreferences sp = PreferenceManager.getDefaultSharedPreferences(context);
|
|
||||||
if(sp.getString(context.getString(R.string.downloadPathPreference), "").isEmpty()){
|
|
||||||
SharedPreferences.Editor spEditor = sp.edit();
|
|
||||||
String newPipeDownloadStorage =
|
|
||||||
Environment.getExternalStorageDirectory().getAbsolutePath() + "/NewPipe";
|
|
||||||
spEditor.putString(context.getString(R.string.downloadPathPreference)
|
|
||||||
, newPipeDownloadStorage);
|
|
||||||
spEditor.apply();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
package org.schabi.newpipe;
|
package org.schabi.newpipe;
|
||||||
|
|
||||||
|
import android.content.Context;
|
||||||
import android.view.LayoutInflater;
|
import android.view.LayoutInflater;
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
import android.view.ViewGroup;
|
import android.view.ViewGroup;
|
||||||
|
@ -33,7 +34,7 @@ class VideoInfoItemViewCreator {
|
||||||
this.inflater = inflater;
|
this.inflater = inflater;
|
||||||
}
|
}
|
||||||
|
|
||||||
public View getViewFromVideoInfoItem(View convertView, ViewGroup parent, VideoPreviewInfo info) {
|
public View getViewFromVideoInfoItem(View convertView, ViewGroup parent, VideoPreviewInfo info, Context context) {
|
||||||
ViewHolder holder;
|
ViewHolder holder;
|
||||||
if(convertView == null) {
|
if(convertView == null) {
|
||||||
convertView = inflater.inflate(R.layout.video_item, parent, false);
|
convertView = inflater.inflate(R.layout.video_item, parent, false);
|
||||||
|
@ -59,8 +60,7 @@ class VideoInfoItemViewCreator {
|
||||||
if(!info.upload_date.isEmpty()) {
|
if(!info.upload_date.isEmpty()) {
|
||||||
holder.itemUploadDateView.setText(info.upload_date);
|
holder.itemUploadDateView.setText(info.upload_date);
|
||||||
} else {
|
} else {
|
||||||
//tweak if necessary: This is a hack to prevent having white space in the layout :P
|
holder.itemUploadDateView.setText(Localization.localizeViewCount(info.view_count, context));
|
||||||
holder.itemUploadDateView.setText(String.format("%d", info.view_count));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return convertView;
|
return convertView;
|
||||||
|
|
|
@ -113,6 +113,12 @@ public class VideoItemDetailActivity extends AppCompatActivity {
|
||||||
.commit();
|
.commit();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onResume() {
|
||||||
|
super.onResume();
|
||||||
|
App.checkStartTor(this);
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onSaveInstanceState(Bundle outState) {
|
public void onSaveInstanceState(Bundle outState) {
|
||||||
outState.putString(VideoItemDetailFragment.VIDEO_URL, videoUrl);
|
outState.putString(VideoItemDetailFragment.VIDEO_URL, videoUrl);
|
||||||
|
|
|
@ -1,9 +1,7 @@
|
||||||
package org.schabi.newpipe;
|
package org.schabi.newpipe;
|
||||||
|
|
||||||
import android.annotation.SuppressLint;
|
|
||||||
import android.app.Activity;
|
import android.app.Activity;
|
||||||
import android.content.Intent;
|
import android.content.Intent;
|
||||||
import android.content.SharedPreferences;
|
|
||||||
import android.content.res.Resources;
|
import android.content.res.Resources;
|
||||||
import android.graphics.Bitmap;
|
import android.graphics.Bitmap;
|
||||||
import android.graphics.BitmapFactory;
|
import android.graphics.BitmapFactory;
|
||||||
|
@ -35,13 +33,7 @@ import android.view.MenuItem;
|
||||||
import android.widget.Toast;
|
import android.widget.Toast;
|
||||||
|
|
||||||
import java.net.URL;
|
import java.net.URL;
|
||||||
import java.text.DateFormat;
|
|
||||||
import java.text.NumberFormat;
|
|
||||||
import java.text.ParseException;
|
|
||||||
import java.text.SimpleDateFormat;
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Date;
|
|
||||||
import java.util.Locale;
|
|
||||||
import java.util.Vector;
|
import java.util.Vector;
|
||||||
|
|
||||||
import org.schabi.newpipe.services.VideoExtractor;
|
import org.schabi.newpipe.services.VideoExtractor;
|
||||||
|
@ -235,7 +227,7 @@ public class VideoItemDetailFragment extends Fragment {
|
||||||
switch (info.errorCode) {
|
switch (info.errorCode) {
|
||||||
case VideoInfo.NO_ERROR: {
|
case VideoInfo.NO_ERROR: {
|
||||||
View nextVideoView = videoItemViewCreator
|
View nextVideoView = videoItemViewCreator
|
||||||
.getViewFromVideoInfoItem(null, nextVideoFrame, info.nextVideo);
|
.getViewFromVideoInfoItem(null, nextVideoFrame, info.nextVideo, getContext());
|
||||||
nextVideoFrame.addView(nextVideoView);
|
nextVideoFrame.addView(nextVideoView);
|
||||||
|
|
||||||
|
|
||||||
|
@ -253,31 +245,20 @@ public class VideoItemDetailFragment extends Fragment {
|
||||||
uploaderView.setText(info.uploader);
|
uploaderView.setText(info.uploader);
|
||||||
actionBarHandler.setChannelName(info.uploader);
|
actionBarHandler.setChannelName(info.uploader);
|
||||||
|
|
||||||
Locale locale = getPreferredLocale();
|
String localizedViewCount = Localization.localizeViewCount(info.view_count, getContext());
|
||||||
NumberFormat nf = NumberFormat.getInstance(locale);
|
viewCountView.setText(localizedViewCount);
|
||||||
String localisedViewCount = nf.format(info.view_count);
|
|
||||||
viewCountView.setText(
|
|
||||||
String.format(
|
|
||||||
res.getString(R.string.viewCountText), localisedViewCount));
|
|
||||||
|
|
||||||
thumbsUpView.setText(nf.format(info.like_count));
|
String localizedLikeCount = Localization.localizeNumber(info.like_count, getContext());
|
||||||
thumbsDownView.setText(nf.format(info.dislike_count));
|
thumbsUpView.setText(localizedLikeCount);
|
||||||
|
|
||||||
@SuppressLint("SimpleDateFormat")
|
String localizedDislikeCount = Localization.localizeNumber(info.dislike_count, getContext());
|
||||||
SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd");
|
thumbsDownView.setText(localizedDislikeCount);
|
||||||
Date datum = null;
|
|
||||||
try {
|
|
||||||
datum = formatter.parse(info.upload_date);
|
|
||||||
} catch (ParseException e) {
|
|
||||||
e.printStackTrace();
|
|
||||||
}
|
|
||||||
|
|
||||||
DateFormat df = DateFormat.getDateInstance(DateFormat.MEDIUM, locale);
|
String localizedDate = Localization.localizeDate(info.upload_date, getContext());
|
||||||
|
uploadDateView.setText(localizedDate);
|
||||||
|
|
||||||
String localisedDate = df.format(datum);
|
|
||||||
uploadDateView.setText(
|
|
||||||
String.format(res.getString(R.string.uploadDateText), localisedDate));
|
|
||||||
descriptionView.setText(Html.fromHtml(info.description));
|
descriptionView.setText(Html.fromHtml(info.description));
|
||||||
|
|
||||||
descriptionView.setMovementMethod(LinkMovementMethod.getInstance());
|
descriptionView.setMovementMethod(LinkMovementMethod.getInstance());
|
||||||
|
|
||||||
actionBarHandler.setServiceId(streamingServiceId);
|
actionBarHandler.setServiceId(streamingServiceId);
|
||||||
|
@ -306,7 +287,7 @@ public class VideoItemDetailFragment extends Fragment {
|
||||||
VideoItemDetailFragment.ARG_ITEM_ID, currentVideoInfo.nextVideo.id); */
|
VideoItemDetailFragment.ARG_ITEM_ID, currentVideoInfo.nextVideo.id); */
|
||||||
detailIntent.putExtra(
|
detailIntent.putExtra(
|
||||||
VideoItemDetailFragment.VIDEO_URL, currentVideoInfo.nextVideo.webpage_url);
|
VideoItemDetailFragment.VIDEO_URL, currentVideoInfo.nextVideo.webpage_url);
|
||||||
//todo: make id dynamic the following line is crap
|
|
||||||
detailIntent.putExtra(VideoItemDetailFragment.STREAMING_SERVICE, streamingServiceId);
|
detailIntent.putExtra(VideoItemDetailFragment.STREAMING_SERVICE, streamingServiceId);
|
||||||
startActivity(detailIntent);
|
startActivity(detailIntent);
|
||||||
}
|
}
|
||||||
|
@ -315,7 +296,7 @@ public class VideoItemDetailFragment extends Fragment {
|
||||||
break;
|
break;
|
||||||
case VideoInfo.ERROR_BLOCKED_BY_GEMA:
|
case VideoInfo.ERROR_BLOCKED_BY_GEMA:
|
||||||
thumbnailView.setImageBitmap(BitmapFactory.decodeResource(
|
thumbnailView.setImageBitmap(BitmapFactory.decodeResource(
|
||||||
getResources(), R.drawable.gruese_die_gema_unangebracht));
|
getResources(), R.drawable.gruese_die_gema));
|
||||||
backgroundButton.setOnClickListener(new View.OnClickListener() {
|
backgroundButton.setOnClickListener(new View.OnClickListener() {
|
||||||
@Override
|
@Override
|
||||||
public void onClick(View v) {
|
public void onClick(View v) {
|
||||||
|
@ -458,30 +439,6 @@ public class VideoItemDetailFragment extends Fragment {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/**Returns the java.util.Locale object which corresponds to the locale set in NewPipe's preferences.
|
|
||||||
* Currently not affected by the device's locale.*/
|
|
||||||
private Locale getPreferredLocale() {
|
|
||||||
SharedPreferences sp = PreferenceManager.getDefaultSharedPreferences(getContext());
|
|
||||||
String languageKey = getContext().getString(R.string.searchLanguage);
|
|
||||||
//i know the following line defaults languageCode to "en", but java is picky about uninitialised values
|
|
||||||
// Schabi: well lint tels me the value is redundant. I'll suppress it for now.
|
|
||||||
@SuppressWarnings("UnusedAssignment")
|
|
||||||
String languageCode = "en";
|
|
||||||
languageCode = sp.getString(languageKey, "en");
|
|
||||||
|
|
||||||
if(languageCode.length() == 2) {
|
|
||||||
return new Locale(languageCode);
|
|
||||||
}
|
|
||||||
else if(languageCode.contains("_")) {
|
|
||||||
String country = languageCode
|
|
||||||
.substring(languageCode.indexOf("_"), languageCode.length());
|
|
||||||
return new Locale(languageCode.substring(0, 2), country);
|
|
||||||
}
|
|
||||||
return Locale.getDefault();
|
|
||||||
}
|
|
||||||
|
|
||||||
private boolean checkIfLandscape() {
|
private boolean checkIfLandscape() {
|
||||||
DisplayMetrics displayMetrics = new DisplayMetrics();
|
DisplayMetrics displayMetrics = new DisplayMetrics();
|
||||||
getActivity().getWindowManager().getDefaultDisplay().getMetrics(displayMetrics);
|
getActivity().getWindowManager().getDefaultDisplay().getMetrics(displayMetrics);
|
||||||
|
|
|
@ -3,6 +3,7 @@ package org.schabi.newpipe;
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.content.Intent;
|
import android.content.Intent;
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
|
import android.preference.PreferenceManager;
|
||||||
import android.support.v4.app.NavUtils;
|
import android.support.v4.app.NavUtils;
|
||||||
import android.support.v7.app.AppCompatActivity;
|
import android.support.v7.app.AppCompatActivity;
|
||||||
import android.support.v7.widget.SearchView;
|
import android.support.v7.widget.SearchView;
|
||||||
|
@ -171,7 +172,13 @@ public class VideoItemListActivity extends AppCompatActivity
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
SettingsActivity.initSettings(this);
|
PreferenceManager.setDefaultValues(this, R.xml.settings_screen, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onResume() {
|
||||||
|
super.onResume();
|
||||||
|
App.checkStartTor(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -96,7 +96,7 @@ class VideoListAdapter extends BaseAdapter {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public View getView(int position, View convertView, ViewGroup parent) {
|
public View getView(int position, View convertView, ViewGroup parent) {
|
||||||
convertView = viewCreator.getViewFromVideoInfoItem(convertView, parent, videoList.get(position));
|
convertView = viewCreator.getViewFromVideoInfoItem(convertView, parent, videoList.get(position), context);
|
||||||
|
|
||||||
if(listView.isItemChecked(position)) {
|
if(listView.isItemChecked(position)) {
|
||||||
convertView.setBackgroundColor(ContextCompat.getColor(context,R.color.primaryColorYoutube));
|
convertView.setBackgroundColor(ContextCompat.getColor(context,R.color.primaryColorYoutube));
|
||||||
|
|
After Width: | Height: | Size: 221 B |
After Width: | Height: | Size: 175 B |
After Width: | Height: | Size: 89 KiB |
Before Width: | Height: | Size: 16 KiB |
After Width: | Height: | Size: 257 B |
After Width: | Height: | Size: 347 B |
After Width: | Height: | Size: 436 B |
|
@ -8,7 +8,7 @@
|
||||||
<TextView
|
<TextView
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:text="Loading"
|
android:text="@string/loading"
|
||||||
android:textAppearance="?android:attr/textAppearanceMedium" />
|
android:textAppearance="?android:attr/textAppearanceMedium" />
|
||||||
|
|
||||||
<ProgressBar
|
<ProgressBar
|
||||||
|
|
|
@ -0,0 +1,66 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
xmlns:tools="http://schemas.android.com/tools"
|
||||||
|
android:id="@+id/content"
|
||||||
|
android:layout_width="fill_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:clickable="true"
|
||||||
|
android:gravity="center_vertical"
|
||||||
|
android:orientation="horizontal"
|
||||||
|
android:background="@color/background_notification_color"
|
||||||
|
tools:targetApi="jelly_bean">
|
||||||
|
|
||||||
|
<ImageView
|
||||||
|
android:id="@+id/backgroundCover"
|
||||||
|
android:layout_width="64dp"
|
||||||
|
android:layout_height="64dp"
|
||||||
|
android:src="@drawable/dummy_thumbnail"
|
||||||
|
android:scaleType="centerCrop"/>
|
||||||
|
|
||||||
|
<LinearLayout
|
||||||
|
android:layout_width="0dp"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginLeft="8dp"
|
||||||
|
android:layout_weight="1"
|
||||||
|
android:orientation="vertical" >
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/backgroundSongName"
|
||||||
|
style="@android:style/TextAppearance.StatusBar.EventContent.Title"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:ellipsize="marquee"
|
||||||
|
android:singleLine="true"
|
||||||
|
android:text="title" />
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/backgroundArtist"
|
||||||
|
style="@android:style/TextAppearance.StatusBar.EventContent"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:ellipsize="marquee"
|
||||||
|
android:singleLine="true"
|
||||||
|
android:text="artist" />
|
||||||
|
</LinearLayout>
|
||||||
|
|
||||||
|
<ImageButton
|
||||||
|
android:id="@+id/backgroundPlayPause"
|
||||||
|
android:layout_width="40dp"
|
||||||
|
android:layout_height="40dp"
|
||||||
|
android:layout_margin="5dp"
|
||||||
|
android:background="#00ffffff"
|
||||||
|
android:clickable="true"
|
||||||
|
android:scaleType="fitXY"
|
||||||
|
android:src="@drawable/ic_play_arrow_white_48dp" />
|
||||||
|
|
||||||
|
<ImageButton
|
||||||
|
android:id="@+id/backgroundStop"
|
||||||
|
android:layout_width="40dp"
|
||||||
|
android:layout_height="40dp"
|
||||||
|
android:layout_margin="5dp"
|
||||||
|
android:background="#00ffffff"
|
||||||
|
android:clickable="true"
|
||||||
|
android:scaleType="fitXY"
|
||||||
|
android:src="@drawable/ic_close_white_24dp" />
|
||||||
|
|
||||||
|
</LinearLayout>
|
|
@ -0,0 +1,80 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
xmlns:tools="http://schemas.android.com/tools"
|
||||||
|
android:id="@+id/content"
|
||||||
|
android:layout_width="fill_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:clickable="true"
|
||||||
|
android:background="@color/background_notification_color"
|
||||||
|
tools:targetApi="jelly_bean" >
|
||||||
|
|
||||||
|
<ImageView
|
||||||
|
android:id="@+id/backgroundCover"
|
||||||
|
android:layout_width="128dp"
|
||||||
|
android:layout_height="128dp"
|
||||||
|
android:layout_marginRight="8dp"
|
||||||
|
android:src="@drawable/dummy_thumbnail"
|
||||||
|
android:scaleType="centerCrop"/>
|
||||||
|
|
||||||
|
<LinearLayout
|
||||||
|
android:layout_width="fill_parent"
|
||||||
|
android:layout_height="fill_parent"
|
||||||
|
android:layout_above="@+id/backgroundButtons"
|
||||||
|
android:layout_toRightOf="@+id/backgroundCover"
|
||||||
|
android:gravity="center_vertical"
|
||||||
|
android:orientation="vertical" >
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/backgroundSongName"
|
||||||
|
style="@android:style/TextAppearance.StatusBar.EventContent.Title"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginRight="40dp"
|
||||||
|
android:ellipsize="marquee"
|
||||||
|
android:singleLine="true"
|
||||||
|
android:text="title" />
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/backgroundArtist"
|
||||||
|
style="@android:style/TextAppearance.StatusBar.EventContent"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:ellipsize="marquee"
|
||||||
|
android:singleLine="true"
|
||||||
|
android:text="artist" />
|
||||||
|
</LinearLayout>
|
||||||
|
|
||||||
|
<ImageButton
|
||||||
|
android:id="@+id/backgroundStop"
|
||||||
|
android:layout_width="30dp"
|
||||||
|
android:layout_height="30dp"
|
||||||
|
android:layout_alignParentRight="true"
|
||||||
|
android:layout_margin="5dp"
|
||||||
|
android:background="#00ffffff"
|
||||||
|
android:clickable="true"
|
||||||
|
android:scaleType="fitXY"
|
||||||
|
android:src="@drawable/ic_close_white_24dp" />
|
||||||
|
|
||||||
|
<LinearLayout
|
||||||
|
android:id="@+id/backgroundButtons"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="40dp"
|
||||||
|
android:layout_alignBottom="@id/backgroundCover"
|
||||||
|
android:layout_alignParentRight="true"
|
||||||
|
android:layout_toRightOf="@+id/backgroundCover"
|
||||||
|
android:orientation="horizontal" >
|
||||||
|
|
||||||
|
<ImageButton
|
||||||
|
android:id="@+id/backgroundPlayPause"
|
||||||
|
android:layout_width="0dp"
|
||||||
|
android:layout_height="fill_parent"
|
||||||
|
android:layout_marginLeft="30dp"
|
||||||
|
android:layout_marginRight="30dp"
|
||||||
|
android:layout_weight="1"
|
||||||
|
android:background="#00ffffff"
|
||||||
|
android:clickable="true"
|
||||||
|
android:scaleType="centerInside"
|
||||||
|
android:src="@drawable/ic_play_arrow_white_48dp" />
|
||||||
|
</LinearLayout>
|
||||||
|
|
||||||
|
</RelativeLayout>
|
|
@ -49,4 +49,9 @@
|
||||||
<string name="detailUploaderThumbnailViewDescription">Avatar de l\'utilisateur</string>
|
<string name="detailUploaderThumbnailViewDescription">Avatar de l\'utilisateur</string>
|
||||||
<string name="useExternalVideoPlayerTitle">Utiliser un lecteur vidéo externe</string>
|
<string name="useExternalVideoPlayerTitle">Utiliser un lecteur vidéo externe</string>
|
||||||
<string name="useExternalAudioPlayerTitle">Utiliser un lecteur audio externe</string>
|
<string name="useExternalAudioPlayerTitle">Utiliser un lecteur audio externe</string>
|
||||||
|
<string name="backgroundPlayerStartPlayingToast">Lecture en arrière-plan</string>
|
||||||
|
<string name="background_player_name">Lecteur en arrière-plan NewPipe</string>
|
||||||
|
<string name="loading">Chargement</string>
|
||||||
|
<string name="play">Lecture</string>
|
||||||
|
|
||||||
</resources>
|
</resources>
|
||||||
|
|
|
@ -0,0 +1,10 @@
|
||||||
|
<?xml version='1.0' encoding='utf-8'?>
|
||||||
|
<resources><string name="viewCountText">%1$s צפיות</string>
|
||||||
|
<string name="uploadDateText">הועלה בתאריך %1$s</string>
|
||||||
|
<string name="share">שתף</string>
|
||||||
|
<string name="search">חפש</string>
|
||||||
|
<string name="nextVideoTitle">הבא</string>
|
||||||
|
<string name="download">הורדה</string>
|
||||||
|
<string name="settings">הגדרות</string>
|
||||||
|
<string name="title_activity_settings">הגדרות</string>
|
||||||
|
</resources>
|
|
@ -0,0 +1 @@
|
||||||
|
values-in
|
|
@ -0,0 +1,3 @@
|
||||||
|
<?xml version='1.0' encoding='utf-8'?>
|
||||||
|
<resources>
|
||||||
|
</resources>
|
|
@ -0,0 +1 @@
|
||||||
|
values-he
|
|
@ -50,4 +50,8 @@
|
||||||
<string name="useExternalAudioPlayerTitle">外部オーディオ プレイヤーを使用する</string>
|
<string name="useExternalAudioPlayerTitle">外部オーディオ プレイヤーを使用する</string>
|
||||||
<string name="backgroundPlayerStartPlayingToast">バックグラウンドで再生しています</string>
|
<string name="backgroundPlayerStartPlayingToast">バックグラウンドで再生しています</string>
|
||||||
|
|
||||||
|
<string name="background_player_name">NewPipe バックグラウンド プレーヤー</string>
|
||||||
|
<string name="loading">読み込み中</string>
|
||||||
|
<string name="play">再生</string>
|
||||||
|
|
||||||
</resources>
|
</resources>
|
||||||
|
|
|
@ -51,4 +51,7 @@
|
||||||
<string name="detailUploaderThumbnailViewDescription">Миниатюра аватара пользователся</string>
|
<string name="detailUploaderThumbnailViewDescription">Миниатюра аватара пользователся</string>
|
||||||
<string name="detailThumbsDownImgViewDescription">Дислайки</string>
|
<string name="detailThumbsDownImgViewDescription">Дислайки</string>
|
||||||
<string name="detailThumbsUpImgViewDescription">Лайки</string>
|
<string name="detailThumbsUpImgViewDescription">Лайки</string>
|
||||||
</resources>
|
<string name="useExternalVideoPlayerTitle">Использовать внешний проигрыватель для видео</string>
|
||||||
|
<string name="useExternalAudioPlayerTitle">Использовать внешний проигрыватель для аудио</string>
|
||||||
|
<string name="backgroundPlayerStartPlayingToast">Проигрывание в фоновом режиме</string>
|
||||||
|
</resources>
|
||||||
|
|
|
@ -47,4 +47,9 @@
|
||||||
|
|
||||||
<string name="detailThumbsUpImgViewDescription">Všeč mi je</string>
|
<string name="detailThumbsUpImgViewDescription">Všeč mi je</string>
|
||||||
<string name="detailThumbsDownImgViewDescription">Ni mi všeč</string>
|
<string name="detailThumbsDownImgViewDescription">Ni mi všeč</string>
|
||||||
|
<string name="background_player_name">Ozadnji predvajalnik NewPipe</string>
|
||||||
|
<string name="loading">Nalaganje ...</string>
|
||||||
|
<string name="backgroundPlayerStartPlayingToast">Predvajanje v ozadju</string>
|
||||||
|
<string name="play">Predvajaj</string>
|
||||||
|
|
||||||
</resources>
|
</resources>
|
||||||
|
|
|
@ -54,4 +54,10 @@
|
||||||
<string name="useExternalAudioPlayerTitle">Користи спољашњи аудио плејер</string>
|
<string name="useExternalAudioPlayerTitle">Користи спољашњи аудио плејер</string>
|
||||||
<string name="backgroundPlayerStartPlayingToast">Пуштам у позадини</string>
|
<string name="backgroundPlayerStartPlayingToast">Пуштам у позадини</string>
|
||||||
|
|
||||||
</resources>
|
<string name="background_player_name">Позадински плејер за Јутјуб цев</string>
|
||||||
|
<string name="loading">Учитавам</string>
|
||||||
|
<string name="play">Пусти</string>
|
||||||
|
|
||||||
|
<string name="useTor">Користи Тор</string>
|
||||||
|
<string name="useTorSummary">Принудно преусмерење саобраћаја кроз Тор за доданту приватност (токови још нису подржани)</string>
|
||||||
|
</resources>
|
||||||
|
|
|
@ -7,4 +7,5 @@
|
||||||
<color name="durationText">#efff</color>
|
<color name="durationText">#efff</color>
|
||||||
<color name="dark_overlay">#6000</color>
|
<color name="dark_overlay">#6000</color>
|
||||||
<color name="background_gray">#EEEEEE</color>
|
<color name="background_gray">#EEEEEE</color>
|
||||||
|
<color name="background_notification_color">#323232</color>
|
||||||
</resources>
|
</resources>
|
|
@ -71,6 +71,7 @@
|
||||||
<item>sl</item>
|
<item>sl</item>
|
||||||
<item>fi</item>
|
<item>fi</item>
|
||||||
<item>sv</item>
|
<item>sv</item>
|
||||||
|
<item>bo</item>
|
||||||
<item>vi</item>
|
<item>vi</item>
|
||||||
<item>tr</item>
|
<item>tr</item>
|
||||||
<item>bg</item>
|
<item>bg</item>
|
||||||
|
@ -149,6 +150,7 @@
|
||||||
<item>Slovenščina</item>
|
<item>Slovenščina</item>
|
||||||
<item>Suomi</item>
|
<item>Suomi</item>
|
||||||
<item>Svenska</item>
|
<item>Svenska</item>
|
||||||
|
<item>Tibetan བོད་སྐད།</item>
|
||||||
<item>Tiếng Việt</item>
|
<item>Tiếng Việt</item>
|
||||||
<item>Türkçe</item>
|
<item>Türkçe</item>
|
||||||
<item>Български</item>
|
<item>Български</item>
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
<?xml version='1.0' encoding='utf-8'?>
|
<?xml version='1.0' encoding='utf-8'?>
|
||||||
<resources>
|
<resources>
|
||||||
<string name="app_name" translatable="false">NewPipe</string>
|
<string name="app_name" translatable="false">NewPipe</string>
|
||||||
|
<string name="background_player_name">NewPipe Background Player</string>
|
||||||
<string name="title_videoitem_detail" translatable="false">NewPipe</string>
|
<string name="title_videoitem_detail" translatable="false">NewPipe</string>
|
||||||
<string name="viewCountText">%1$s views</string>
|
<string name="viewCountText">%1$s views</string>
|
||||||
<string name="uploadDateText">Uploaded on %1$s</string>
|
<string name="uploadDateText">Uploaded on %1$s</string>
|
||||||
|
@ -10,6 +11,7 @@
|
||||||
<string name="fdroidVLCurl" translatable="false">https://f-droid.org/repository/browse/?fdfilter=vlc&fdid=org.videolan.vlc</string>
|
<string name="fdroidVLCurl" translatable="false">https://f-droid.org/repository/browse/?fdfilter=vlc&fdid=org.videolan.vlc</string>
|
||||||
<string name="open_in_browser">Open in browser</string>
|
<string name="open_in_browser">Open in browser</string>
|
||||||
<string name="share">Share</string>
|
<string name="share">Share</string>
|
||||||
|
<string name="loading">Loading</string>
|
||||||
<string name="download">Download</string>
|
<string name="download">Download</string>
|
||||||
<string name="search">Search</string>
|
<string name="search">Search</string>
|
||||||
<string name="settings">Settings</string>
|
<string name="settings">Settings</string>
|
||||||
|
@ -53,6 +55,7 @@
|
||||||
<string name="backgroundPlayerTickerText" translatable="false">%1$s - NewPipe</string>
|
<string name="backgroundPlayerTickerText" translatable="false">%1$s - NewPipe</string>
|
||||||
<string name="backgroundPlayerStartPlayingToast">Playing in background</string>
|
<string name="backgroundPlayerStartPlayingToast">Playing in background</string>
|
||||||
<string name="c3sUrl" translatable="false">https://www.c3s.cc/</string>
|
<string name="c3sUrl" translatable="false">https://www.c3s.cc/</string>
|
||||||
|
<string name="play">Play</string>
|
||||||
|
|
||||||
<!-- Content descriptions (for better accessibility) -->
|
<!-- Content descriptions (for better accessibility) -->
|
||||||
<string name="itemThumbnailViewDescription">Video preview thumbnail</string>
|
<string name="itemThumbnailViewDescription">Video preview thumbnail</string>
|
||||||
|
@ -60,4 +63,6 @@
|
||||||
<string name="detailUploaderThumbnailViewDescription">Uploader thumbnail</string>
|
<string name="detailUploaderThumbnailViewDescription">Uploader thumbnail</string>
|
||||||
<string name="detailThumbsDownImgViewDescription">Dislikes</string>
|
<string name="detailThumbsDownImgViewDescription">Dislikes</string>
|
||||||
<string name="detailThumbsUpImgViewDescription">Likes</string>
|
<string name="detailThumbsUpImgViewDescription">Likes</string>
|
||||||
|
<string name="useTor">Use Tor</string>
|
||||||
|
<string name="useTorSummary">Force download traffic through Tor for increased privacy (streaming videos not yet supported)</string>
|
||||||
</resources>
|
</resources>
|
||||||
|
|
|
@ -64,8 +64,7 @@
|
||||||
android:key="@string/downloadPathPreference"
|
android:key="@string/downloadPathPreference"
|
||||||
android:title="@string/downloadLocation"
|
android:title="@string/downloadLocation"
|
||||||
android:summary="@string/downloadLocationSummary"
|
android:summary="@string/downloadLocationSummary"
|
||||||
android:dialogTitle="@string/downloadLocationDialogTitle"
|
android:dialogTitle="@string/downloadLocationDialogTitle" />
|
||||||
android:defaultValue=""/>
|
|
||||||
|
|
||||||
<CheckBoxPreference
|
<CheckBoxPreference
|
||||||
android:key="@string/autoPlayThroughIntent"
|
android:key="@string/autoPlayThroughIntent"
|
||||||
|
@ -73,5 +72,10 @@
|
||||||
android:summary="@string/autoPlayThroughIntentSummary"
|
android:summary="@string/autoPlayThroughIntentSummary"
|
||||||
android:defaultValue="false" />
|
android:defaultValue="false" />
|
||||||
|
|
||||||
|
<CheckBoxPreference
|
||||||
|
android:key="@string/useTor"
|
||||||
|
android:title="@string/useTor"
|
||||||
|
android:summary="@string/useTorSummary" />
|
||||||
|
|
||||||
</PreferenceCategory>
|
</PreferenceCategory>
|
||||||
</PreferenceScreen>
|
</PreferenceScreen>
|
||||||
|
|
Before Width: | Height: | Size: 67 KiB After Width: | Height: | Size: 62 KiB |
|
@ -1,18 +0,0 @@
|
||||||
# Project-wide Gradle settings.
|
|
||||||
|
|
||||||
# IDE (e.g. Android Studio) users:
|
|
||||||
# Gradle settings configured through the IDE *will override*
|
|
||||||
# any settings specified in this file.
|
|
||||||
|
|
||||||
# For more details on how to configure your build environment visit
|
|
||||||
# http://www.gradle.org/docs/current/userguide/build_environment.html
|
|
||||||
|
|
||||||
# Specifies the JVM arguments used for the daemon process.
|
|
||||||
# The setting is particularly useful for tweaking memory settings.
|
|
||||||
# Default value: -Xmx10248m -XX:MaxPermSize=256m
|
|
||||||
# org.gradle.jvmargs=-Xmx2048m -XX:MaxPermSize=512m -XX:+HeapDumpOnOutOfMemoryError -Dfile.encoding=UTF-8
|
|
||||||
|
|
||||||
# When configured, Gradle will run in incubating parallel mode.
|
|
||||||
# This option should only be used with decoupled projects. More details, visit
|
|
||||||
# http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects
|
|
||||||
# org.gradle.parallel=true
|
|