Compare commits
81 Commits
Author | SHA1 | Date | |
---|---|---|---|
![]() |
8b2599297b | ||
![]() |
a9a43538be | ||
![]() |
905e4f16e2 | ||
![]() |
008489361d | ||
![]() |
dfa7fb53b2 | ||
![]() |
dc6604bcda | ||
![]() |
63194ff292 | ||
![]() |
53a727955f | ||
![]() |
a8fca89045 | ||
![]() |
1eff727722 | ||
![]() |
faefe957b0 | ||
![]() |
2fb8467673 | ||
![]() |
401422deb3 | ||
![]() |
b52ed8e4c9 | ||
![]() |
45194061b3 | ||
![]() |
ea917c82b6 | ||
![]() |
65d5303765 | ||
![]() |
08d37a4bef | ||
![]() |
da2b059802 | ||
![]() |
62d934dd8e | ||
![]() |
96086b7733 | ||
![]() |
182fc104bb | ||
![]() |
06a897fba0 | ||
![]() |
ff4b13245c | ||
![]() |
00a8906128 | ||
![]() |
8b73d2d39f | ||
![]() |
e976b3e43e | ||
![]() |
1585ca7c85 | ||
![]() |
f7697007e5 | ||
![]() |
ba151a8b83 | ||
![]() |
a5153f5375 | ||
![]() |
4899f01d6e | ||
![]() |
e6b3107997 | ||
![]() |
053440c4a8 | ||
![]() |
249e9c0b52 | ||
![]() |
099d5570f4 | ||
![]() |
12bf409e10 | ||
![]() |
a01f1e64fe | ||
![]() |
5f549a8fc6 | ||
![]() |
eb144af0b9 | ||
![]() |
0d020d3a54 | ||
![]() |
e1042e326d | ||
![]() |
f085e7d362 | ||
![]() |
b995f39206 | ||
![]() |
0be78b1204 | ||
![]() |
0a67ecbc3a | ||
![]() |
c57b4ee965 | ||
![]() |
d4db7b3fc1 | ||
![]() |
e9db964a70 | ||
![]() |
90c8a714fc | ||
![]() |
d958c0c68a | ||
![]() |
377d02ab1a | ||
![]() |
2c0ad89a07 | ||
![]() |
101a8adbc2 | ||
![]() |
5009fa461c | ||
![]() |
f48f6ae5df | ||
![]() |
be504212d0 | ||
![]() |
0f075137c9 | ||
![]() |
8714664e00 | ||
![]() |
bfaf938543 | ||
![]() |
b605bc086c | ||
![]() |
e394b16335 | ||
![]() |
0457423498 | ||
![]() |
91d30dbb83 | ||
![]() |
63642a4d3e | ||
![]() |
1b64900c14 | ||
![]() |
2660178658 | ||
![]() |
3a0271cd4d | ||
![]() |
76e2a2f032 | ||
![]() |
932de969f0 | ||
![]() |
9082ab6ff7 | ||
![]() |
2461173e26 | ||
![]() |
48c2f8b91b | ||
![]() |
6766b25414 | ||
![]() |
aacaf1b3fe | ||
![]() |
4cc154cbe1 | ||
![]() |
ca030dd5ed | ||
![]() |
f000409a90 | ||
![]() |
697f0659e2 | ||
![]() |
5169ef1f00 | ||
![]() |
10faa45182 |
@@ -12,8 +12,8 @@ android {
|
||||
resValue "string", "app_name", "NewPipe"
|
||||
minSdkVersion 19
|
||||
targetSdkVersion 28
|
||||
versionCode 900
|
||||
versionName "0.19.0"
|
||||
versionCode 920
|
||||
versionName "0.19.2"
|
||||
|
||||
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
|
||||
vectorDrawables.useSupportLibrary = true
|
||||
@@ -46,6 +46,7 @@ android {
|
||||
} else {
|
||||
applicationIdSuffix ".debug." + normalizedWorkingBranch
|
||||
resValue "string", "app_name", "NewPipe " + workingBranch
|
||||
archivesBaseName = 'NewPipe_' + normalizedWorkingBranch
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -25,6 +25,9 @@ class AppDatabaseTest {
|
||||
private const val DEFAULT_DURATION = 480L
|
||||
private const val DEFAULT_UPLOADER_NAME = "Uploader Test"
|
||||
private const val DEFAULT_THUMBNAIL = "https://example.com/example.jpg"
|
||||
|
||||
private const val DEFAULT_SECOND_SERVICE_ID = 0
|
||||
private const val DEFAULT_SECOND_URL = "https://www.youtube.com/watch?v=ncQU6iBn5Fc"
|
||||
}
|
||||
|
||||
@get:Rule val testHelper = MigrationTestHelper(InstrumentationRegistry.getInstrumentation(),
|
||||
@@ -45,6 +48,26 @@ class AppDatabaseTest {
|
||||
put("uploader", DEFAULT_UPLOADER_NAME)
|
||||
put("thumbnail_url", DEFAULT_THUMBNAIL)
|
||||
})
|
||||
insert("streams", SQLiteDatabase.CONFLICT_FAIL, ContentValues().apply {
|
||||
// put("uid", null)
|
||||
put("service_id", DEFAULT_SECOND_SERVICE_ID)
|
||||
put("url", DEFAULT_SECOND_URL)
|
||||
// put("title", null)
|
||||
// put("stream_type", null)
|
||||
// put("duration", null)
|
||||
// put("uploader", null)
|
||||
// put("thumbnail_url", null)
|
||||
})
|
||||
insert("streams", SQLiteDatabase.CONFLICT_FAIL, ContentValues().apply {
|
||||
// put("uid", null)
|
||||
put("service_id", DEFAULT_SERVICE_ID)
|
||||
// put("url", null)
|
||||
// put("title", null)
|
||||
// put("stream_type", null)
|
||||
// put("duration", null)
|
||||
// put("uploader", null)
|
||||
// put("thumbnail_url", null)
|
||||
})
|
||||
close()
|
||||
}
|
||||
|
||||
@@ -53,9 +76,11 @@ class AppDatabaseTest {
|
||||
|
||||
val migratedDatabaseV3 = getMigratedDatabase()
|
||||
val listFromDB = migratedDatabaseV3.streamDAO().all.blockingFirst()
|
||||
assertEquals(1, listFromDB.size)
|
||||
|
||||
val streamFromMigratedDatabase = listFromDB.first()
|
||||
// Only expect 2, the one with the null url will be ignored
|
||||
assertEquals(2, listFromDB.size)
|
||||
|
||||
val streamFromMigratedDatabase = listFromDB[0]
|
||||
assertEquals(DEFAULT_SERVICE_ID, streamFromMigratedDatabase.serviceId)
|
||||
assertEquals(DEFAULT_URL, streamFromMigratedDatabase.url)
|
||||
assertEquals(DEFAULT_TITLE, streamFromMigratedDatabase.title)
|
||||
@@ -67,6 +92,20 @@ class AppDatabaseTest {
|
||||
assertNull(streamFromMigratedDatabase.textualUploadDate)
|
||||
assertNull(streamFromMigratedDatabase.uploadDate)
|
||||
assertNull(streamFromMigratedDatabase.isUploadDateApproximation)
|
||||
|
||||
val secondStreamFromMigratedDatabase = listFromDB[1]
|
||||
assertEquals(DEFAULT_SECOND_SERVICE_ID, secondStreamFromMigratedDatabase.serviceId)
|
||||
assertEquals(DEFAULT_SECOND_URL, secondStreamFromMigratedDatabase.url)
|
||||
assertEquals("", secondStreamFromMigratedDatabase.title)
|
||||
// Should fallback to VIDEO_STREAM
|
||||
assertEquals(StreamType.VIDEO_STREAM, secondStreamFromMigratedDatabase.streamType)
|
||||
assertEquals(0, secondStreamFromMigratedDatabase.duration)
|
||||
assertEquals("", secondStreamFromMigratedDatabase.uploader)
|
||||
assertEquals("", secondStreamFromMigratedDatabase.thumbnailUrl)
|
||||
assertNull(secondStreamFromMigratedDatabase.viewCount)
|
||||
assertNull(secondStreamFromMigratedDatabase.textualUploadDate)
|
||||
assertNull(secondStreamFromMigratedDatabase.uploadDate)
|
||||
assertNull(secondStreamFromMigratedDatabase.isUploadDateApproximation)
|
||||
}
|
||||
|
||||
private fun getMigratedDatabase(): AppDatabase {
|
||||
|
@@ -83,11 +83,12 @@ public class MainActivity extends AppCompatActivity {
|
||||
private static final String TAG = "MainActivity";
|
||||
public static final boolean DEBUG = !BuildConfig.BUILD_TYPE.equals("release");
|
||||
|
||||
private ActionBarDrawerToggle toggle = null;
|
||||
private DrawerLayout drawer = null;
|
||||
private NavigationView drawerItems = null;
|
||||
private TextView headerServiceView = null;
|
||||
private Button toggleServiceButton = null;
|
||||
private ActionBarDrawerToggle toggle;
|
||||
private DrawerLayout drawer;
|
||||
private NavigationView drawerItems;
|
||||
private ImageView headerServiceIcon;
|
||||
private TextView headerServiceView;
|
||||
private Button toggleServiceButton;
|
||||
|
||||
private boolean servicesShown = false;
|
||||
private ImageView serviceArrow;
|
||||
@@ -285,11 +286,10 @@ public class MainActivity extends AppCompatActivity {
|
||||
View hView = navigationView.getHeaderView(0);
|
||||
|
||||
serviceArrow = hView.findViewById(R.id.drawer_arrow);
|
||||
headerServiceIcon = hView.findViewById(R.id.drawer_header_service_icon);
|
||||
headerServiceView = hView.findViewById(R.id.drawer_header_service_view);
|
||||
toggleServiceButton = hView.findViewById(R.id.drawer_header_action_button);
|
||||
toggleServiceButton.setOnClickListener(view -> {
|
||||
toggleServices();
|
||||
});
|
||||
toggleServiceButton.setOnClickListener(view -> toggleServices());
|
||||
}
|
||||
|
||||
private void toggleServices() {
|
||||
@@ -299,7 +299,6 @@ public class MainActivity extends AppCompatActivity {
|
||||
drawerItems.getMenu().removeGroup(R.id.menu_tabs_group);
|
||||
drawerItems.getMenu().removeGroup(R.id.menu_options_about_group);
|
||||
|
||||
|
||||
if(servicesShown) {
|
||||
showServices();
|
||||
} else {
|
||||
@@ -312,7 +311,7 @@ public class MainActivity extends AppCompatActivity {
|
||||
}
|
||||
|
||||
private void showServices() {
|
||||
serviceArrow.setImageResource(R.drawable.ic_arrow_up_white);
|
||||
serviceArrow.setImageResource(R.drawable.ic_arrow_drop_up_white_24dp);
|
||||
|
||||
for(StreamingService s : NewPipe.getServices()) {
|
||||
final String title = s.getServiceInfo().getName() +
|
||||
@@ -370,7 +369,7 @@ public class MainActivity extends AppCompatActivity {
|
||||
}
|
||||
|
||||
private void showTabs() throws ExtractionException {
|
||||
serviceArrow.setImageResource(R.drawable.ic_arrow_down_white);
|
||||
serviceArrow.setImageResource(R.drawable.ic_arrow_drop_down_white_24dp);
|
||||
|
||||
//Tabs
|
||||
int currentServiceId = ServiceHelper.getSelectedServiceId(this);
|
||||
@@ -428,9 +427,11 @@ public class MainActivity extends AppCompatActivity {
|
||||
// when the user returns to MainActivity
|
||||
drawer.closeDrawer(GravityCompat.START, false);
|
||||
try {
|
||||
String selectedServiceName = NewPipe.getService(
|
||||
ServiceHelper.getSelectedServiceId(this)).getServiceInfo().getName();
|
||||
final int selectedServiceId = ServiceHelper.getSelectedServiceId(this);
|
||||
final String selectedServiceName = NewPipe.getService(selectedServiceId).getServiceInfo().getName();
|
||||
headerServiceView.setText(selectedServiceName);
|
||||
headerServiceIcon.setImageResource(ServiceHelper.getIcon(selectedServiceId));
|
||||
|
||||
headerServiceView.post(() -> headerServiceView.setSelected(true));
|
||||
toggleServiceButton.setContentDescription(
|
||||
getString(R.string.drawer_header_description) + selectedServiceName);
|
||||
|
@@ -81,8 +81,16 @@ public class Migrations {
|
||||
" duration INTEGER NOT NULL, uploader TEXT NOT NULL, thumbnail_url TEXT, view_count INTEGER, textual_upload_date TEXT, upload_date INTEGER," +
|
||||
" is_upload_date_approximation INTEGER)");
|
||||
|
||||
database.execSQL("INSERT INTO streams_new (uid, service_id, url, title, stream_type, duration, uploader, thumbnail_url, view_count, textual_upload_date, upload_date, is_upload_date_approximation)"+
|
||||
" SELECT uid, service_id, url, title, stream_type, duration, uploader, thumbnail_url, NULL, NULL, NULL, NULL FROM streams");
|
||||
database.execSQL("INSERT INTO streams_new (uid, service_id, url, title, stream_type," +
|
||||
"duration, uploader, thumbnail_url, view_count," +
|
||||
"textual_upload_date, upload_date, is_upload_date_approximation) " +
|
||||
|
||||
"SELECT uid, service_id, url, ifnull(title, ''), ifnull(stream_type, 'VIDEO_STREAM')," +
|
||||
"ifnull(duration, 0), ifnull(uploader, ''), ifnull(thumbnail_url, ''), NULL," +
|
||||
"NULL, NULL, NULL " +
|
||||
|
||||
"FROM streams " +
|
||||
"WHERE url IS NOT NULL");
|
||||
|
||||
database.execSQL("DROP TABLE streams");
|
||||
database.execSQL("ALTER TABLE streams_new RENAME TO streams");
|
||||
|
@@ -5,7 +5,7 @@ import android.view.ViewGroup;
|
||||
import org.schabi.newpipe.R;
|
||||
import org.schabi.newpipe.info_list.InfoItemBuilder;
|
||||
|
||||
public class StreamGridInfoItemHolder extends StreamMiniInfoItemHolder {
|
||||
public class StreamGridInfoItemHolder extends StreamInfoItemHolder {
|
||||
|
||||
public StreamGridInfoItemHolder(InfoItemBuilder infoItemBuilder, ViewGroup parent) {
|
||||
super(infoItemBuilder, R.layout.list_stream_grid_item, parent);
|
||||
|
@@ -40,7 +40,11 @@ public class StreamInfoItemHolder extends StreamMiniInfoItemHolder {
|
||||
public final TextView itemAdditionalDetails;
|
||||
|
||||
public StreamInfoItemHolder(InfoItemBuilder infoItemBuilder, ViewGroup parent) {
|
||||
super(infoItemBuilder, R.layout.list_stream_item, parent);
|
||||
this(infoItemBuilder, R.layout.list_stream_item, parent);
|
||||
}
|
||||
|
||||
public StreamInfoItemHolder(InfoItemBuilder infoItemBuilder, int layoutId, ViewGroup parent) {
|
||||
super(infoItemBuilder, layoutId, parent);
|
||||
itemAdditionalDetails = itemView.findViewById(R.id.itemAdditionalDetails);
|
||||
}
|
||||
|
||||
|
@@ -3,17 +3,9 @@ package org.schabi.newpipe.player;
|
||||
import android.content.ComponentName;
|
||||
import android.content.Intent;
|
||||
import android.content.ServiceConnection;
|
||||
import android.graphics.drawable.Drawable;
|
||||
import android.os.Bundle;
|
||||
import android.os.IBinder;
|
||||
import android.provider.Settings;
|
||||
|
||||
import androidx.appcompat.app.AppCompatActivity;
|
||||
import androidx.recyclerview.widget.LinearLayoutManager;
|
||||
import androidx.recyclerview.widget.RecyclerView;
|
||||
import androidx.appcompat.widget.Toolbar;
|
||||
import androidx.recyclerview.widget.ItemTouchHelper;
|
||||
|
||||
import android.util.Log;
|
||||
import android.view.Menu;
|
||||
import android.view.MenuItem;
|
||||
@@ -26,6 +18,12 @@ import android.widget.ProgressBar;
|
||||
import android.widget.SeekBar;
|
||||
import android.widget.TextView;
|
||||
|
||||
import androidx.appcompat.app.AppCompatActivity;
|
||||
import androidx.appcompat.widget.Toolbar;
|
||||
import androidx.recyclerview.widget.ItemTouchHelper;
|
||||
import androidx.recyclerview.widget.LinearLayoutManager;
|
||||
import androidx.recyclerview.widget.RecyclerView;
|
||||
|
||||
import com.google.android.exoplayer2.PlaybackParameters;
|
||||
import com.google.android.exoplayer2.Player;
|
||||
|
||||
@@ -698,13 +696,10 @@ public abstract class ServicePlayerActivity extends AppCompatActivity
|
||||
item.setTitle(player.isMuted() ? R.string.unmute : R.string.mute);
|
||||
|
||||
//2) Icon change accordingly to current App Theme
|
||||
item.setIcon(player.isMuted() ? getThemedDrawable(R.attr.volume_off) : getThemedDrawable(R.attr.volume_on));
|
||||
// using rootView.getContext() because getApplicationContext() didn't work
|
||||
item.setIcon(player.isMuted()
|
||||
? ThemeHelper.resolveResourceIdFromAttr(rootView.getContext(), R.attr.volume_off)
|
||||
: ThemeHelper.resolveResourceIdFromAttr(rootView.getContext(), R.attr.volume_on));
|
||||
}
|
||||
}
|
||||
|
||||
private Drawable getThemedDrawable(int attribute) {
|
||||
return getResources().getDrawable(
|
||||
getTheme().obtainStyledAttributes(R.style.Theme_AppCompat, new int[]{attribute})
|
||||
.getResourceId(0, 0));
|
||||
}
|
||||
}
|
||||
|
@@ -69,6 +69,11 @@ public class DataReader {
|
||||
return primitive[0] << 24 | primitive[1] << 16 | primitive[2] << 8 | primitive[3];
|
||||
}
|
||||
|
||||
public long readUnsignedInt() throws IOException {
|
||||
long value = readInt();
|
||||
return value & 0xffffffffL;
|
||||
}
|
||||
|
||||
public short readShort() throws IOException {
|
||||
primitiveRead(SHORT_SIZE);
|
||||
return (short) (primitive[0] << 8 | primitive[1]);
|
||||
|
@@ -294,10 +294,6 @@ public class Mp4DashReader {
|
||||
|
||||
|
||||
|
||||
private long readUint() throws IOException {
|
||||
return stream.readInt() & 0xffffffffL;
|
||||
}
|
||||
|
||||
public static boolean hasFlag(int flags, int mask) {
|
||||
return (flags & mask) == mask;
|
||||
}
|
||||
@@ -317,7 +313,7 @@ public class Mp4DashReader {
|
||||
private Box readBox() throws IOException {
|
||||
Box b = new Box();
|
||||
b.offset = stream.position();
|
||||
b.size = stream.readInt();
|
||||
b.size = stream.readUnsignedInt();
|
||||
b.type = stream.readInt();
|
||||
|
||||
if (b.size == 1) {
|
||||
@@ -478,7 +474,7 @@ public class Mp4DashReader {
|
||||
private long parse_tfdt() throws IOException {
|
||||
int version = stream.read();
|
||||
stream.skipBytes(3);// flags
|
||||
return version == 0 ? readUint() : stream.readLong();
|
||||
return version == 0 ? stream.readUnsignedInt() : stream.readLong();
|
||||
}
|
||||
|
||||
private Trun parse_trun() throws IOException {
|
||||
@@ -551,7 +547,7 @@ public class Mp4DashReader {
|
||||
stream.skipBytes(2 * (version == 0 ? 4 : 8));
|
||||
|
||||
Mvhd obj = new Mvhd();
|
||||
obj.timeScale = readUint();
|
||||
obj.timeScale = stream.readUnsignedInt();
|
||||
|
||||
// chunkDuration
|
||||
stream.skipBytes(version == 0 ? 4 : 8);
|
||||
@@ -563,7 +559,7 @@ public class Mp4DashReader {
|
||||
// predefined
|
||||
stream.skipBytes(76);
|
||||
|
||||
obj.nextTrackId = readUint();
|
||||
obj.nextTrackId = stream.readUnsignedInt();
|
||||
|
||||
return obj;
|
||||
}
|
||||
@@ -582,7 +578,7 @@ public class Mp4DashReader {
|
||||
|
||||
stream.skipBytes(4);// reserved
|
||||
|
||||
obj.duration = version == 0 ? readUint() : stream.readLong();
|
||||
obj.duration = version == 0 ? stream.readUnsignedInt() : stream.readLong();
|
||||
|
||||
stream.skipBytes(2 * 4);// reserved
|
||||
|
||||
|
@@ -46,7 +46,7 @@ public class Mp4FromDashWriter {
|
||||
|
||||
private int overrideMainBrand = 0x00;
|
||||
|
||||
private ArrayList<Integer> compatibleBrands = new ArrayList<>(5);
|
||||
private final ArrayList<Integer> compatibleBrands = new ArrayList<>(5);
|
||||
|
||||
public Mp4FromDashWriter(SharpStream... sources) throws IOException {
|
||||
for (SharpStream src : sources) {
|
||||
|
@@ -104,7 +104,7 @@ public class ChunkFileInputStream extends SharpStream {
|
||||
|
||||
@Override
|
||||
public long available() {
|
||||
return (int) (length - position);
|
||||
return length - position;
|
||||
}
|
||||
|
||||
@SuppressWarnings("EmptyCatchBlock")
|
||||
|
@@ -221,7 +221,7 @@ public class CircularFileWriter extends SharpStream {
|
||||
available = out.length - offsetOut;
|
||||
}
|
||||
|
||||
int length = Math.min(len, (int) available);
|
||||
int length = Math.min(len, (int) Math.min(Integer.MAX_VALUE, available));
|
||||
out.write(b, off, length);
|
||||
|
||||
len -= length;
|
||||
|
Before Width: | Height: | Size: 267 B |
Before Width: | Height: | Size: 261 B |
Before Width: | Height: | Size: 210 B |
Before Width: | Height: | Size: 201 B |
Before Width: | Height: | Size: 425 B |
Before Width: | Height: | Size: 415 B |
Before Width: | Height: | Size: 470 B |
Before Width: | Height: | Size: 458 B |
@@ -0,0 +1,7 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<shape xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<gradient
|
||||
android:angle="90"
|
||||
android:endColor="#00000000"
|
||||
android:startColor="#4D000000"/>
|
||||
</shape>
|
@@ -0,0 +1,9 @@
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="24dp"
|
||||
android:height="24dp"
|
||||
android:viewportWidth="24.0"
|
||||
android:viewportHeight="24.0">
|
||||
<path
|
||||
android:fillColor="#FFFFFFFF"
|
||||
android:pathData="M7,10l5,5 5,-5z" />
|
||||
</vector>
|
@@ -0,0 +1,9 @@
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="24dp"
|
||||
android:height="24dp"
|
||||
android:viewportWidth="24.0"
|
||||
android:viewportHeight="24.0">
|
||||
<path
|
||||
android:fillColor="#FFFFFFFF"
|
||||
android:pathData="M7,14l5,-5 5,5z" />
|
||||
</vector>
|
@@ -1,82 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="150dp"
|
||||
android:clickable="true"
|
||||
android:focusable="true">
|
||||
|
||||
<Button
|
||||
android:id="@+id/drawer_header_action_button"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:contentDescription="@string/drawer_header_description"
|
||||
android:background="?android:attr/selectableItemBackground" />
|
||||
|
||||
<ImageView
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:background="?attr/colorPrimary"
|
||||
android:scaleType="centerCrop"
|
||||
android:src="@drawable/background_header"
|
||||
android:contentDescription="TODO" />
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/drawer_header_np_nude_view"
|
||||
android:layout_width="70dp"
|
||||
android:layout_height="70dp"
|
||||
android:layout_marginLeft="30dp"
|
||||
|
||||
android:layout_marginStart="30dp"
|
||||
android:layout_marginTop="30dp"
|
||||
android:src="@drawable/np_logo_nude_shadow"
|
||||
android:contentDescription="TODO" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/drawer_header_np_text_view"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="0dp"
|
||||
android:layout_alignBottom="@id/drawer_header_np_nude_view"
|
||||
android:layout_alignTop="@id/drawer_header_np_nude_view"
|
||||
android:layout_toEndOf="@id/drawer_header_np_nude_view"
|
||||
android:layout_toRightOf="@id/drawer_header_np_nude_view"
|
||||
android:gravity="center"
|
||||
android:text="@string/app_name"
|
||||
android:textSize="30sp"
|
||||
android:textColor="@color/drawer_header_font_color"
|
||||
android:textStyle="bold|italic" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/drawer_header_service_view"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="100dp"
|
||||
android:layout_alignLeft="@id/drawer_header_np_text_view"
|
||||
android:layout_alignStart="@id/drawer_header_np_text_view"
|
||||
android:layout_below="@id/drawer_header_np_text_view"
|
||||
android:layout_toLeftOf="@id/drawer_arrow"
|
||||
android:layout_marginRight="5dp"
|
||||
android:text="YouTube"
|
||||
android:textSize="18sp"
|
||||
android:textColor="@color/drawer_header_font_color"
|
||||
android:textStyle="italic"
|
||||
android:ellipsize="marquee"
|
||||
android:fadingEdge="horizontal"
|
||||
android:marqueeRepeatLimit="marquee_forever"
|
||||
android:scrollHorizontally="true"
|
||||
android:singleLine="true" />
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/drawer_arrow"
|
||||
android:layout_width="30dp"
|
||||
android:layout_height="35dp"
|
||||
android:layout_alignParentBottom="true"
|
||||
android:layout_alignParentEnd="true"
|
||||
android:layout_alignParentRight="true"
|
||||
android:layout_gravity="bottom"
|
||||
android:layout_marginBottom="0dp"
|
||||
android:paddingBottom="20dp"
|
||||
android:paddingEnd="20dp"
|
||||
android:paddingRight="20dp"
|
||||
android:src="@drawable/ic_arrow_down_white"
|
||||
android:contentDescription="TODO" />
|
||||
|
||||
</RelativeLayout>
|
@@ -1,81 +1,122 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="150dp"
|
||||
android:clickable="true"
|
||||
android:focusable="true">
|
||||
<androidx.constraintlayout.widget.ConstraintLayout 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:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:background="?colorPrimary"
|
||||
android:nextFocusDown="@+id/drawer_header_action_button">
|
||||
|
||||
<ImageView
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="0dp"
|
||||
android:scaleType="centerCrop"
|
||||
android:src="@drawable/background_header"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
tools:ignore="ContentDescription" />
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="@dimen/drawer_header_padding_top"
|
||||
android:fitsSystemWindows="true"
|
||||
android:gravity="bottom"
|
||||
android:minHeight="@dimen/drawer_header_content_min_height"
|
||||
android:orientation="vertical"
|
||||
app:layout_constraintTop_toTopOf="parent">
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="72dp"
|
||||
android:layout_marginLeft="16dp"
|
||||
android:layout_marginRight="16dp"
|
||||
android:gravity="center"
|
||||
android:orientation="horizontal"
|
||||
tools:ignore="UseCompoundDrawables">
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/drawer_header_newpipe_icon"
|
||||
android:layout_width="@dimen/drawer_header_newpipe_icon_size"
|
||||
android:layout_height="@dimen/drawer_header_newpipe_icon_size"
|
||||
android:layout_marginEnd="@dimen/drawer_header_newpipe_icon_title_space"
|
||||
app:srcCompat="@drawable/splash_forground"
|
||||
tools:ignore="ContentDescription" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/drawer_header_newpipe_title"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_marginEnd="@dimen/drawer_header_newpipe_icon_title_space"
|
||||
android:ellipsize="end"
|
||||
android:gravity="start|center_vertical"
|
||||
android:hyphenationFrequency="full"
|
||||
android:maxWidth="@dimen/drawer_header_newpipe_title_max_width"
|
||||
android:maxLines="2"
|
||||
android:minWidth="@dimen/drawer_header_newpipe_title_min_width"
|
||||
android:text="@string/app_name"
|
||||
android:textColor="@color/drawer_header_font_color"
|
||||
android:textStyle="bold"
|
||||
app:autoSizeMaxTextSize="@dimen/drawer_header_newpipe_title_max_text_size"
|
||||
app:autoSizeMinTextSize="@dimen/drawer_header_newpipe_title_min_text_size"
|
||||
app:autoSizeTextType="uniform"
|
||||
tools:ignore="UnusedAttribute" />
|
||||
</LinearLayout>
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="12dp"
|
||||
android:background="@drawable/drawer_header_bottom_background"
|
||||
android:gravity="center"
|
||||
android:orientation="horizontal"
|
||||
android:paddingLeft="6dp"
|
||||
android:paddingRight="6dp">
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="32dp"
|
||||
android:layout_weight="1"
|
||||
android:gravity="center"
|
||||
android:orientation="horizontal">
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/drawer_header_service_icon"
|
||||
android:layout_width="@dimen/drawer_header_service_icon_size"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginLeft="6dp"
|
||||
android:layout_marginRight="6dp"
|
||||
android:scaleType="fitCenter"
|
||||
app:tint="@color/drawer_header_font_color"
|
||||
tools:ignore="ContentDescription"
|
||||
tools:srcCompat="@drawable/youtube" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/drawer_header_service_view"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:ellipsize="end"
|
||||
android:maxLines="1"
|
||||
android:textColor="@color/drawer_header_font_color"
|
||||
android:textSize="@dimen/drawer_header_service_title_text_size"
|
||||
tools:text="YouTube" />
|
||||
</LinearLayout>
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/drawer_arrow"
|
||||
android:layout_width="24dp"
|
||||
android:layout_height="24dp"
|
||||
android:layout_marginStart="4dp"
|
||||
app:srcCompat="@drawable/ic_arrow_drop_down_white_24dp"
|
||||
tools:ignore="ContentDescription" />
|
||||
</LinearLayout>
|
||||
</LinearLayout>
|
||||
|
||||
<Button
|
||||
android:id="@+id/drawer_header_action_button"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:background="?android:attr/selectableItemBackground"/>
|
||||
|
||||
<ImageView
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:background="?attr/colorPrimary"
|
||||
android:src="@drawable/background_header"
|
||||
android:scaleType="centerCrop"
|
||||
android:contentDescription="TODO" />
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/drawer_header_np_nude_view"
|
||||
android:layout_marginLeft="30dp"
|
||||
android:layout_marginStart="30dp"
|
||||
android:layout_marginTop="20dp"
|
||||
|
||||
android:layout_width="70dp"
|
||||
android:layout_height="70dp"
|
||||
android:src="@drawable/np_logo_nude_shadow"
|
||||
android:contentDescription="TODO" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/drawer_header_np_text_view"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="0dp"
|
||||
android:text="@string/app_name"
|
||||
android:layout_toRightOf="@id/drawer_header_np_nude_view"
|
||||
android:layout_toEndOf="@id/drawer_header_np_nude_view"
|
||||
android:layout_alignTop="@id/drawer_header_np_nude_view"
|
||||
android:layout_alignBottom="@id/drawer_header_np_nude_view"
|
||||
android:gravity="center"
|
||||
android:textSize="30sp"
|
||||
android:textColor="@color/drawer_header_font_color"
|
||||
android:textStyle="bold|italic"/>
|
||||
|
||||
<TextView
|
||||
android:id="@+id/drawer_header_service_view"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="100dp"
|
||||
android:text="YouTube"
|
||||
android:layout_below="@id/drawer_header_np_text_view"
|
||||
android:layout_alignLeft="@id/drawer_header_np_text_view"
|
||||
android:layout_alignStart="@id/drawer_header_np_text_view"
|
||||
android:layout_toLeftOf="@id/drawer_arrow"
|
||||
android:layout_marginRight="5dp"
|
||||
android:textSize="18sp"
|
||||
android:textColor="@color/drawer_header_font_color"
|
||||
android:textStyle="italic"
|
||||
android:ellipsize="marquee"
|
||||
android:fadingEdge="horizontal"
|
||||
android:marqueeRepeatLimit="marquee_forever"
|
||||
android:scrollHorizontally="true"
|
||||
android:singleLine="true" />
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/drawer_arrow"
|
||||
android:layout_width="30dp"
|
||||
android:layout_height="35dp"
|
||||
android:layout_alignParentBottom="true"
|
||||
android:layout_alignParentEnd="true"
|
||||
android:layout_alignParentRight="true"
|
||||
android:layout_gravity="bottom"
|
||||
android:layout_marginBottom="0dp"
|
||||
android:paddingBottom="20dp"
|
||||
android:paddingRight="20dp"
|
||||
android:src="@drawable/ic_arrow_down_white"
|
||||
android:paddingEnd="20dp"
|
||||
android:contentDescription="TODO" />
|
||||
|
||||
</RelativeLayout>
|
||||
android:background="?selectableItemBackground"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent" />
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
@@ -1,36 +1,10 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<com.google.android.material.navigation.NavigationView android:id="@+id/navigation_layout"
|
||||
android:orientation="vertical"
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_gravity="start"
|
||||
<com.google.android.material.navigation.NavigationView xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
android:clickable="true"
|
||||
android:focusable="true"
|
||||
>
|
||||
|
||||
<com.google.android.material.navigation.NavigationView
|
||||
android:id="@+id/navigation"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
app:elevation="0dp"
|
||||
android:background="?attr/android:windowBackground"
|
||||
app:headerLayout="@layout/drawer_header"
|
||||
android:theme="@style/NavViewTextStyle"/>
|
||||
<!-- app:menu="@menu/drawer_items" -->
|
||||
|
||||
<LinearLayout
|
||||
android:id="@+id/navigation_drawer_footer"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="60dp"
|
||||
android:orientation="horizontal"
|
||||
android:layout_alignLeft="@id/navigation"
|
||||
android:layout_alignRight="@id/navigation"
|
||||
android:layout_alignStart="@id/navigation"
|
||||
android:layout_alignEnd="@id/navigation"
|
||||
|
||||
android:layout_alignParentBottom="true">
|
||||
</LinearLayout>
|
||||
|
||||
</com.google.android.material.navigation.NavigationView>
|
||||
android:id="@+id/navigation"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_gravity="start"
|
||||
android:background="?android:attr/windowBackground"
|
||||
android:orientation="vertical"
|
||||
app:headerLayout="@layout/drawer_header" />
|
@@ -67,6 +67,19 @@
|
||||
android:textSize="@dimen/video_item_search_uploader_text_size"
|
||||
tools:text="Uploader"/>
|
||||
|
||||
<TextView
|
||||
android:id="@+id/itemAdditionalDetails"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_below="@id/itemUploaderView"
|
||||
android:layout_alignStart="@id/itemUploaderView"
|
||||
android:layout_alignEnd="@id/itemUploaderView"
|
||||
android:ellipsize="end"
|
||||
android:lines="1"
|
||||
android:textAppearance="?android:attr/textAppearanceSmall"
|
||||
android:textSize="@dimen/video_item_search_upload_date_text_size"
|
||||
tools:text="2 years ago • 10M views"/>
|
||||
|
||||
<org.schabi.newpipe.views.AnimatedProgressBar
|
||||
android:id="@+id/itemProgressView"
|
||||
style="@style/Widget.AppCompat.ProgressBar.Horizontal"
|
||||
|
@@ -456,7 +456,7 @@
|
||||
<string name="error_postprocessing_failed">后期处理失败</string>
|
||||
<string name="stop">停止</string>
|
||||
<string name="max_retry_msg">最大重试次数</string>
|
||||
<string name="max_retry_desc">取消下载前的最多重试着次数</string>
|
||||
<string name="max_retry_desc">取消下载前的最多重试次数</string>
|
||||
<string name="pause_downloads_on_mobile">在切换到移动流量网络时中断播放</string>
|
||||
<string name="pause_downloads_on_mobile_desc">切换至移动数据时可能有用,尽管一些下载无法被暂停</string>
|
||||
<string name="events">事件</string>
|
||||
@@ -551,7 +551,7 @@
|
||||
<plurals name="days">
|
||||
<item quantity="other">%d天</item>
|
||||
</plurals>
|
||||
<string name="feed_groups_header_title">Feed组</string>
|
||||
<string name="feed_groups_header_title">频道组</string>
|
||||
<string name="feed_oldest_subscription_update">最早订阅更新:%s</string>
|
||||
<string name="feed_subscription_not_loaded_count">未加载: %d</string>
|
||||
<string name="feed_notification_loading">正在加载feed…</string>
|
||||
@@ -565,7 +565,7 @@
|
||||
<string name="feed_group_dialog_name_input">名称</string>
|
||||
<string name="feed_group_dialog_delete_message">您要删除该组吗?</string>
|
||||
<string name="feed_create_new_group_button_title">新建</string>
|
||||
<string name="settings_category_feed_title">Feed</string>
|
||||
<string name="settings_category_feed_title">订阅</string>
|
||||
<string name="feed_update_threshold_title">Feed更新阈值</string>
|
||||
<string name="feed_update_threshold_summary">上次更新后,订阅被视为过时的时间-%s</string>
|
||||
<string name="feed_update_threshold_option_always_update">始终更新</string>
|
||||
|
@@ -557,8 +557,8 @@ otevření ve vyskakovacím okně</string>
|
||||
<item quantity="other">%d vteřin</item>
|
||||
</plurals>
|
||||
<string name="new_seek_duration_toast">Kvůli omezením ExoPlayer bylo prohledávání nastaveno na %d vteřin</string>
|
||||
<string name="mute">Umlčet</string>
|
||||
<string name="unmute">Odumlčet</string>
|
||||
<string name="mute">Ztišit</string>
|
||||
<string name="unmute">Obnovit hlasitost</string>
|
||||
<string name="help">Nápověda</string>
|
||||
<plurals name="minutes">
|
||||
<item quantity="one">%d minuta</item>
|
||||
|
@@ -572,7 +572,7 @@
|
||||
<string name="feed_group_dialog_delete_message">Möchtest du diese Gruppe löschen\?</string>
|
||||
<string name="feed_create_new_group_button_title">Neu</string>
|
||||
<string name="feed_update_threshold_option_always_update">Immer aktualisieren</string>
|
||||
<string name="feed_groups_header_title">Feed-Gruppen</string>
|
||||
<string name="feed_groups_header_title">Channel-Gruppen</string>
|
||||
<string name="feed_subscription_not_loaded_count">Nicht geladen: %d</string>
|
||||
<string name="feed_notification_loading">Feed laden…</string>
|
||||
<string name="feed_processing_message">Feed verarbeiten…</string>
|
||||
|
@@ -550,7 +550,7 @@
|
||||
<plurals name="days">
|
||||
<item quantity="other">%d hari</item>
|
||||
</plurals>
|
||||
<string name="feed_groups_header_title">Grup feed</string>
|
||||
<string name="feed_groups_header_title">Grup channel</string>
|
||||
<string name="feed_oldest_subscription_update">Pembaruan subscription terlama: %s</string>
|
||||
<string name="feed_subscription_not_loaded_count">Tidak dimuat: %d</string>
|
||||
<string name="feed_notification_loading">Memuat feed…</string>
|
||||
|
@@ -551,7 +551,7 @@
|
||||
<plurals name="days">
|
||||
<item quantity="other">%d 日</item>
|
||||
</plurals>
|
||||
<string name="feed_groups_header_title">フィード グループ</string>
|
||||
<string name="feed_groups_header_title">チャンネル グループ</string>
|
||||
<string name="feed_oldest_subscription_update">最も古い登録チャンネルの更新: %s</string>
|
||||
<string name="feed_subscription_not_loaded_count">読み込み失敗: %d</string>
|
||||
<string name="feed_notification_loading">フィードを読み込み中…</string>
|
||||
|