Merge remote-tracking branch 'origin/master'

This commit is contained in:
Weblate 2017-03-01 12:45:58 +01:00
commit 8ed86261ef
47 changed files with 1606 additions and 858 deletions

View File

@ -8,8 +8,8 @@ android {
applicationId "org.schabi.newpipe"
minSdkVersion 15
targetSdkVersion 25
versionCode 24
versionName "0.8.10"
versionCode 25
versionName "0.8.11"
}
buildTypes {
release {
@ -32,10 +32,10 @@ android {
dependencies {
testCompile 'junit:junit:4.12'
compile 'com.android.support:appcompat-v7:25.1.1'
compile 'com.android.support:support-v4:25.1.1'
compile 'com.android.support:design:25.1.1'
compile 'com.android.support:recyclerview-v7:25.1.1'
compile 'com.android.support:appcompat-v7:25.2.0'
compile 'com.android.support:support-v4:25.2.0'
compile 'com.android.support:design:25.2.0'
compile 'com.android.support:recyclerview-v7:25.2.0'
compile 'org.jsoup:jsoup:1.8.3'
compile 'org.mozilla:rhino:1.7.7'
compile 'info.guardianproject.netcipher:netcipher:1.2'

View File

@ -16,7 +16,6 @@
android:logo="@mipmap/ic_launcher"
android:theme="@style/AppTheme"
tools:ignore="AllowBackup">
<activity
android:name=".MainActivity"
android:label="@string/app_name">
@ -34,53 +33,6 @@
<meta-data
android:name="android.support.PARENT_ACTIVITY"
android:value=".MainActivity" />
<intent-filter>
<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.BROWSABLE" />
<data android:scheme="http" />
<data android:scheme="https" />
<data android:host="youtube.com" />
<data android:host="m.youtube.com" />
<data android:host="www.youtube.com" />
<data android:pathPrefix="/v/" />
<data android:pathPrefix="/watch" />
<data android:pathPrefix="/attribution_link" />
</intent-filter>
<intent-filter>
<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.BROWSABLE" />
<data android:scheme="http" />
<data android:scheme="https" />
<data android:host="youtu.be" />
<data android:pathPrefix="/" />
</intent-filter>
<intent-filter>
<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.BROWSABLE" />
<data android:scheme="vnd.youtube" />
<data android:scheme="vnd.youtube.launch" />
</intent-filter>
<intent-filter>
<action android:name="android.intent.action.SEND" />
<category android:name="android.intent.category.DEFAULT" />
<data android:mimeType="text/plain" />
</intent-filter>
</activity>
<activity
android:name=".player.PlayVideoActivity"
@ -149,16 +101,11 @@
<activity
android:name="com.nononsenseapps.filepicker.FilePickerActivity"
android:label="@string/app_name"
android:theme="@style/FilePickerTheme"
android:launchMode="singleTop">
</activity>
android:launchMode="singleTop"
android:theme="@style/FilePickerTheme"/>
<activity
android:name=".ChannelActivity"
android:label="@string/title_activity_channel"
android:launchMode="singleTask"
android:theme="@style/AppTheme.NoActionBar" />
android:launchMode="singleTask" />
<activity
android:name=".ReCaptchaActivity"
android:label="@string/reCaptchaActivity" />
@ -170,8 +117,64 @@
android:grantUriPermissions="true">
<meta-data
android:name="android.support.FILE_PROVIDER_PATHS"
android:resource="@xml/provider_paths"/>
android:resource="@xml/provider_paths" />
</provider>
<activity android:name=".RouterActivity"
android:theme="@android:style/Theme.NoDisplay">
<intent-filter>
<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.BROWSABLE" />
<data android:scheme="http" />
<data android:scheme="https" />
<data android:host="youtube.com" />
<data android:host="m.youtube.com" />
<data android:host="www.youtube.com" />
<!-- video prefix -->
<data android:pathPrefix="/v/" />
<data android:pathPrefix="/watch" />
<data android:pathPrefix="/attribution_link" />
<!-- channel prefix -->
<data android:pathPrefix="/channel/"/>
<data android:pathPrefix="/user/"/>
</intent-filter>
<intent-filter>
<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.BROWSABLE" />
<data android:scheme="http" />
<data android:scheme="https" />
<data android:host="youtu.be" />
<data android:pathPrefix="/" />
</intent-filter>
<intent-filter>
<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.BROWSABLE" />
<data android:scheme="vnd.youtube" />
<data android:scheme="vnd.youtube.launch" />
</intent-filter>
<intent-filter>
<action android:name="android.intent.action.SEND" />
<category android:name="android.intent.category.DEFAULT" />
<data android:mimeType="text/plain" />
</intent-filter>
</activity>
</application>
</manifest>

View File

@ -1,31 +1,24 @@
package org.schabi.newpipe;
import android.annotation.TargetApi;
import android.content.Context;
import android.content.Intent;
import android.net.Uri;
import android.os.Build;
import android.os.Bundle;
import android.os.Handler;
import android.preference.PreferenceManager;
import android.support.design.widget.CollapsingToolbarLayout;
import android.support.design.widget.FloatingActionButton;
import android.support.v4.content.ContextCompat;
import android.support.v7.app.AppCompatActivity;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.support.v7.widget.Toolbar;
import android.util.Log;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.view.Window;
import android.view.WindowManager;
import android.widget.Button;
import android.widget.ImageView;
import android.widget.ProgressBar;
import android.widget.TextView;
import android.widget.Toast;
import com.nostra13.universalimageloader.core.ImageLoader;
import org.schabi.newpipe.detail.VideoItemDetailActivity;
import org.schabi.newpipe.detail.VideoItemDetailFragment;
import org.schabi.newpipe.extractor.NewPipe;
import org.schabi.newpipe.extractor.StreamingService;
@ -36,13 +29,12 @@ import org.schabi.newpipe.extractor.exceptions.ParsingException;
import org.schabi.newpipe.info_list.InfoItemBuilder;
import org.schabi.newpipe.info_list.InfoListAdapter;
import org.schabi.newpipe.report.ErrorActivity;
import org.schabi.newpipe.settings.SettingsActivity;
import org.schabi.newpipe.util.NavStack;
import java.io.IOException;
import java.util.Objects;
import static android.os.Build.VERSION.SDK;
import static android.os.Build.VERSION.SDK_INT;
import org.schabi.newpipe.util.ThemeHelper;
/**
* Copyright (C) Christian Schabesberger 2016 <chris.schabesberger@mailbox.org>
@ -75,38 +67,36 @@ public class ChannelActivity extends AppCompatActivity {
private ImageLoader imageLoader = ImageLoader.getInstance();
private InfoListAdapter infoListAdapter = null;
private String subS = "";
ProgressBar progressBar = null;
ImageView channelBanner = null;
ImageView avatarView = null;
TextView titleView = null;
TextView subscirberView = null;
Button subscriberButton = null;
View subscriberLayout = null;
View header = null;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
//since we set themeing we have to set translucent statusBar by hand
if (PreferenceManager.getDefaultSharedPreferences(this)
.getString("theme", getResources().getString(R.string.light_theme_title)).
equals(getResources().getString(R.string.dark_theme_title))) {
setTheme(R.style.DarkTheme_NoActionBar);
}
setTranslucentStatusBar(getWindow());
ThemeHelper.setTheme(this, true);
setContentView(R.layout.activity_channel);
Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
rootView = findViewById(R.id.rootView);
setSupportActionBar(toolbar);
if(savedInstanceState == null) {
Intent i = getIntent();
channelUrl = i.getStringExtra(NavStack.URL);
serviceId = i.getIntExtra(NavStack.SERVICE_ID, -1);
} else {
channelUrl = savedInstanceState.getString(NavStack.URL);
serviceId = savedInstanceState.getInt(NavStack.SERVICE_ID);
NavStack.getInstance()
.restoreSavedInstanceState(savedInstanceState);
}
rootView = findViewById(android.R.id.content);
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
getSupportActionBar().setDisplayShowTitleEnabled(true);
infoListAdapter = new InfoListAdapter(this, rootView);
RecyclerView recyclerView = (RecyclerView) findViewById(R.id.channel_streams_view);
final LinearLayoutManager layoutManager = new LinearLayoutManager(this);
recyclerView.setLayoutManager(layoutManager);
header = getLayoutInflater().inflate(R.layout.channel_header, recyclerView, false);
infoListAdapter.setHeader(header);
infoListAdapter.setFooter(
getLayoutInflater().inflate(R.layout.pignate_footer, recyclerView, false));
recyclerView.setAdapter(infoListAdapter);
infoListAdapter.setOnStreamInfoItemSelectedListener(
new InfoItemBuilder.OnInfoItemSelectedListener() {
@ -140,6 +130,36 @@ public class ChannelActivity extends AppCompatActivity {
}
});
subS = getString(R.string.subscriber);
progressBar = (ProgressBar) findViewById(R.id.progressBar);
channelBanner = (ImageView) header.findViewById(R.id.channel_banner_image);
avatarView = (ImageView) header.findViewById(R.id.channel_avatar_view);
titleView = (TextView) header.findViewById(R.id.channel_title_view);
subscirberView = (TextView) header.findViewById(R.id.channel_subscriber_view);
subscriberButton = (Button) header.findViewById(R.id.channel_subscribe_button);
subscriberLayout = header.findViewById(R.id.channel_subscriber_layout);
if(savedInstanceState == null) {
handleIntent(getIntent());
} else {
channelUrl = savedInstanceState.getString(NavStack.URL);
serviceId = savedInstanceState.getInt(NavStack.SERVICE_ID);
NavStack.getInstance()
.restoreSavedInstanceState(savedInstanceState);
}
}
@Override
public void onNewIntent(Intent intent) {
super.onNewIntent(intent);
handleIntent(intent);
}
private void handleIntent(Intent i) {
channelUrl = i.getStringExtra(NavStack.URL);
serviceId = i.getIntExtra(NavStack.SERVICE_ID, -1);
requestData(false);
}
@ -153,33 +173,36 @@ public class ChannelActivity extends AppCompatActivity {
}
private void updateUi(final ChannelInfo info) {
CollapsingToolbarLayout ctl = (CollapsingToolbarLayout) findViewById(R.id.channel_toolbar_layout);
ProgressBar progressBar = (ProgressBar) findViewById(R.id.progressBar);
ImageView channelBanner = (ImageView) findViewById(R.id.channel_banner_image);
final FloatingActionButton feedButton = (FloatingActionButton) findViewById(R.id.channel_rss_fab);
ImageView avatarView = (ImageView) findViewById(R.id.channel_avatar_view);
ImageView haloView = (ImageView) findViewById(R.id.channel_avatar_halo);
findViewById(R.id.channel_header_layout).setVisibility(View.VISIBLE);
progressBar.setVisibility(View.GONE);
if(info.channel_name != null && !info.channel_name.isEmpty()) {
ctl.setTitle(info.channel_name);
getSupportActionBar().setTitle(info.channel_name);
titleView.setText(info.channel_name);
}
if(info.banner_url != null && !info.banner_url.isEmpty()) {
imageLoader.displayImage(info.banner_url, channelBanner,
new ImageErrorLoadingListener(this, rootView ,info.service_id));
new ImageErrorLoadingListener(this, rootView ,info.service_id));
}
if(info.avatar_url != null && !info.avatar_url.isEmpty()) {
avatarView.setVisibility(View.VISIBLE);
haloView.setVisibility(View.VISIBLE);
imageLoader.displayImage(info.avatar_url, avatarView,
new ImageErrorLoadingListener(this, rootView ,info.service_id));
}
if(info.subscriberCount != -1) {
subscirberView.setText(buildSubscriberString(info.subscriberCount));
}
if((info.feed_url != null && !info.feed_url.isEmpty()) ||
(info.subscriberCount != -1)) {
subscriberLayout.setVisibility(View.VISIBLE);
}
if(info.feed_url != null && !info.feed_url.isEmpty()) {
feedButton.setOnClickListener(new View.OnClickListener() {
subscriberButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
Log.d(TAG, info.feed_url);
@ -188,8 +211,9 @@ public class ChannelActivity extends AppCompatActivity {
}
});
} else {
feedButton.setVisibility(View.GONE);
subscriberButton.setVisibility(View.INVISIBLE);
}
}
private void addVideos(final ChannelInfo info) {
@ -209,6 +233,22 @@ public class ChannelActivity extends AppCompatActivity {
private void requestData(final boolean onlyVideos) {
// start processing
isLoading = true;
if(!onlyVideos) {
//delete already displayed content
progressBar.setVisibility(View.VISIBLE);
infoListAdapter.clearSteamItemList();
pageNumber = 0;
subscriberLayout.setVisibility(View.GONE);
titleView.setText("");
getSupportActionBar().setTitle("");
if (SDK_INT >= 21) {
channelBanner.setImageDrawable(getDrawable(R.drawable.channel_banner));
avatarView.setImageDrawable(getDrawable(R.drawable.buddy));
}
infoListAdapter.showFooter(false);
}
Thread channelExtractorThread = new Thread(new Runnable() {
Handler h = new Handler();
@ -229,8 +269,12 @@ public class ChannelActivity extends AppCompatActivity {
isLoading = false;
if(!onlyVideos) {
updateUi(info);
infoListAdapter.showFooter(true);
}
hasNextPage = info.hasNextPage;
if(!hasNextPage) {
infoListAdapter.showFooter(false);
}
addVideos(info);
}
});
@ -297,30 +341,6 @@ public class ChannelActivity extends AppCompatActivity {
channelExtractorThread.start();
}
// fix transparent statusbar fuckup (fuck google why can't they just leave something that worked
// as it is, and everyone gets happy)
public static void setTranslucentStatusBar(Window window) {
if (window == null) return;
int sdkInt = Build.VERSION.SDK_INT;
if (sdkInt >= Build.VERSION_CODES.LOLLIPOP) {
setTranslucentStatusBarLollipop(window);
} else if (sdkInt >= Build.VERSION_CODES.KITKAT) {
setTranslucentStatusBarKiKat(window);
}
}
@TargetApi(Build.VERSION_CODES.LOLLIPOP)
private static void setTranslucentStatusBarLollipop(Window window) {
window.setStatusBarColor(
ContextCompat.getColor(window.getContext(), android.R.color.transparent));
}
@TargetApi(Build.VERSION_CODES.KITKAT)
private static void setTranslucentStatusBarKiKat(Window window) {
window.addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);
}
@Override
public void onBackPressed() {
try {
@ -331,4 +351,54 @@ public class ChannelActivity extends AppCompatActivity {
}
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
super.onCreateOptionsMenu(menu);
getMenuInflater().inflate(R.menu.menu_channel, menu);
return true;
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
super.onOptionsItemSelected(item);
switch(item.getItemId()) {
case R.id.action_settings: {
Intent intent = new Intent(this, SettingsActivity.class);
startActivity(intent);
return true;
}
case R.id.menu_item_openInBrowser: {
Intent intent = new Intent();
intent.setAction(Intent.ACTION_VIEW);
intent.setData(Uri.parse(channelUrl));
startActivity(Intent.createChooser(intent, getString(R.string.choose_browser)));
}
case R.id.menu_item_share:
Intent intent = new Intent();
intent.setAction(Intent.ACTION_SEND);
intent.putExtra(Intent.EXTRA_TEXT, channelUrl);
intent.setType("text/plain");
startActivity(Intent.createChooser(intent, getString(R.string.share_dialog_title)));
case android.R.id.home:
NavStack.getInstance().openMainActivity(this);
default:
return super.onOptionsItemSelected(item);
}
}
private String buildSubscriberString(long count) {
String out = "";
if(count >= 1000000000){
out += Long.toString((count/1000000000)%1000)+".";
}
if(count>=1000000){
out += Long.toString((count/1000000)%1000) + ".";
}
if(count>=1000){
out += Long.toString((count/1000)%1000)+".";
}
out += Long.toString(count%1000) + " " + subS;
return out;
}
}

View File

@ -2,19 +2,17 @@ package org.schabi.newpipe;
import android.content.Intent;
import android.media.AudioManager;
import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.support.v4.app.NavUtils;
import android.os.Bundle;
import android.util.Log;
import android.support.v7.app.AppCompatActivity;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.View;
import android.widget.AdapterView;
import org.schabi.newpipe.download.DownloadActivity;
import org.schabi.newpipe.settings.SettingsActivity;
import org.schabi.newpipe.util.PermissionHelper;
import org.schabi.newpipe.util.ThemeHelper;
/**
* Created by Christian Schabesberger on 02.08.16.
@ -36,13 +34,15 @@ import org.schabi.newpipe.util.PermissionHelper;
* along with NewPipe. If not, see <http://www.gnu.org/licenses/>.
*/
public class MainActivity extends ThemableActivity {
public class MainActivity extends AppCompatActivity {
private Fragment mainFragment = null;
private static final String TAG = MainActivity.class.toString();
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
ThemeHelper.setTheme(this, true);
setContentView(R.layout.activity_main);
setVolumeControlStream(AudioManager.STREAM_MUSIC);
mainFragment = getSupportFragmentManager()
@ -53,7 +53,6 @@ public class MainActivity extends ThemableActivity {
public boolean onCreateOptionsMenu(Menu menu) {
super.onCreateOptionsMenu(menu);
MenuInflater inflater = getMenuInflater();
inflater.inflate(R.menu.main_menu, menu);
return true;
}

View File

@ -0,0 +1,158 @@
package org.schabi.newpipe;
import android.app.Activity;
import android.content.Intent;
import android.preference.PreferenceManager;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.util.Log;
import android.widget.Toast;
import org.schabi.newpipe.detail.VideoItemDetailActivity;
import org.schabi.newpipe.detail.VideoItemDetailFragment;
import org.schabi.newpipe.extractor.NewPipe;
import org.schabi.newpipe.extractor.StreamingService;
import org.schabi.newpipe.util.NavStack;
import java.util.Collection;
import java.util.HashSet;
/**
* Copyright (C) Christian Schabesberger 2017 <chris.schabesberger@mailbox.org>
* RouterActivity .java is part of NewPipe.
*
* OpenHitboxStreams is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* OpenHitboxStreams is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with OpenHitboxStreams. If not, see <http://www.gnu.org/licenses/>.
*/
/**
* This Acitivty is designed to route share/open intents to the specified service, and
* to the part of the service which can handle the url.
*/
public class RouterActivity extends Activity {
private static final String TAG = RouterActivity.class.toString();
/**
* Removes invisible separators (\p{Z}) and punctuation characters including
* brackets (\p{P}). See http://www.regular-expressions.info/unicode.html for
* more details.
*/
private final static String REGEX_REMOVE_FROM_URL = "[\\p{Z}\\p{P}]";
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
handleIntent(getIntent());
finish();
}
private static String removeHeadingGibberish(final String input) {
int start = 0;
for (int i = input.indexOf("://") - 1; i >= 0; i--) {
if (!input.substring(i, i + 1).matches("\\p{L}")) {
start = i + 1;
break;
}
}
return input.substring(start, input.length());
}
private static String trim(final String input) {
if (input == null || input.length() < 1) {
return input;
} else {
String output = input;
while (output.length() > 0 && output.substring(0, 1).matches(REGEX_REMOVE_FROM_URL)) {
output = output.substring(1);
}
while (output.length() > 0
&& output.substring(output.length() - 1, output.length()).matches(REGEX_REMOVE_FROM_URL)) {
output = output.substring(0, output.length() - 1);
}
return output;
}
}
/**
* Retrieves all Strings which look remotely like URLs from a text.
* Used if NewPipe was called through share menu.
*
* @param sharedText text to scan for URLs.
* @return potential URLs
*/
private String[] getUris(final String sharedText) {
final Collection<String> result = new HashSet<>();
if (sharedText != null) {
final String[] array = sharedText.split("\\p{Space}");
for (String s : array) {
s = trim(s);
if (s.length() != 0) {
if (s.matches(".+://.+")) {
result.add(removeHeadingGibberish(s));
} else if (s.matches(".+\\..+")) {
result.add("http://" + s);
}
}
}
}
return result.toArray(new String[result.size()]);
}
private void handleIntent(Intent intent) {
String videoUrl = "";
StreamingService service = null;
// first gather data and find service
if (intent.getData() != null) {
// this means the video was called though another app
videoUrl = intent.getData().toString();
} else if(intent.getStringExtra(Intent.EXTRA_TEXT) != null) {
//this means that vidoe was called through share menu
String extraText = intent.getStringExtra(Intent.EXTRA_TEXT);
videoUrl = getUris(extraText)[0];
}
service = NewPipe.getServiceByUrl(videoUrl);
if(service == null) {
Toast.makeText(this, R.string.url_not_supported_toast, Toast.LENGTH_LONG)
.show();
return;
} else {
Intent callIntent = new Intent();
switch(service.getLinkTypeByUrl(videoUrl)) {
case CHANNEL:
callIntent.setClass(this, ChannelActivity.class);
break;
case STREAM:
callIntent.setClass(this, VideoItemDetailActivity.class);
callIntent.putExtra(VideoItemDetailFragment.AUTO_PLAY,
PreferenceManager.getDefaultSharedPreferences(this)
.getBoolean(
getString(R.string.autoplay_through_intent_key), false));
break;
case PLAYLIST:
Log.e(TAG, "NOT YET DEFINED");
break;
default:
Toast.makeText(this, R.string.url_not_supported_toast, Toast.LENGTH_LONG)
.show();
return;
}
callIntent.putExtra(NavStack.URL, videoUrl);
callIntent.putExtra(NavStack.SERVICE_ID, service.getServiceId());
startActivity(callIntent);
}
}
}

View File

@ -1,29 +1,17 @@
package org.schabi.newpipe.detail;
import android.content.Context;
import android.content.Intent;
import android.media.AudioManager;
import android.os.Bundle;
import android.preference.PreferenceManager;
import android.support.v4.app.NavUtils;
import android.support.v7.app.AppCompatActivity;
import android.util.Log;
import android.view.Menu;
import android.view.MenuItem;
import android.widget.Toast;
import org.schabi.newpipe.App;
import org.schabi.newpipe.MainActivity;
import org.schabi.newpipe.R;
import org.schabi.newpipe.ThemableActivity;
import org.schabi.newpipe.extractor.NewPipe;
import org.schabi.newpipe.extractor.StreamingService;
import org.schabi.newpipe.report.ErrorActivity;
import org.schabi.newpipe.util.NavStack;
import java.util.Collection;
import java.util.HashSet;
import static android.os.Build.VERSION.SDK_INT;
import org.schabi.newpipe.util.ThemeHelper;
/**
@ -44,15 +32,7 @@ import static android.os.Build.VERSION.SDK_INT;
* along with NewPipe. If not, see <http://www.gnu.org/licenses/>.
*/
public class VideoItemDetailActivity extends ThemableActivity {
/**
* Removes invisible separators (\p{Z}) and punctuation characters including
* brackets (\p{P}). See http://www.regular-expressions.info/unicode.html for
* more details.
*/
private final static String REGEX_REMOVE_FROM_URL = "[\\p{Z}\\p{P}]";
public class VideoItemDetailActivity extends AppCompatActivity {
private static final String TAG = VideoItemDetailActivity.class.toString();
private VideoItemDetailFragment fragment;
@ -62,6 +42,7 @@ public class VideoItemDetailActivity extends ThemableActivity {
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
ThemeHelper.setTheme(this, true);
setContentView(R.layout.activity_videoitem_detail);
setVolumeControlStream(AudioManager.STREAM_MUSIC);
// Show the Up button in the action bar.
@ -104,27 +85,13 @@ public class VideoItemDetailActivity extends ThemableActivity {
private void handleIntent(Intent intent) {
Bundle arguments = new Bundle();
boolean autoplay = false;
if (intent.getData() != null) {
// this means the video was called though another app
videoUrl = intent.getData().toString();
currentStreamingService = getServiceIdByUrl(videoUrl);
if(currentStreamingService == -1) {
Toast.makeText(this, R.string.url_not_supported_toast, Toast.LENGTH_LONG)
.show();
}
autoplay = PreferenceManager.getDefaultSharedPreferences(this)
.getBoolean(getString(R.string.autoplay_through_intent_key), false);
} else if(intent.getStringExtra(Intent.EXTRA_TEXT) != null) {
//this means that vidoe was called through share menu
String extraText = intent.getStringExtra(Intent.EXTRA_TEXT);
videoUrl = getUris(extraText)[0];
currentStreamingService = getServiceIdByUrl(videoUrl);
} else {
//this is if the video was called through another NewPipe activity
videoUrl = intent.getStringExtra(NavStack.URL);
currentStreamingService = intent.getIntExtra(NavStack.SERVICE_ID, -1);
videoUrl = intent.getStringExtra(NavStack.URL);
currentStreamingService = intent.getIntExtra(NavStack.SERVICE_ID, -1);
if(intent.hasExtra(VideoItemDetailFragment.AUTO_PLAY)) {
arguments.putBoolean(VideoItemDetailFragment.AUTO_PLAY,
intent.getBooleanExtra(VideoItemDetailFragment.AUTO_PLAY, false));
}
arguments.putBoolean(VideoItemDetailFragment.AUTO_PLAY, autoplay);
arguments.putString(NavStack.URL, videoUrl);
arguments.putInt(NavStack.SERVICE_ID, currentStreamingService);
addFragment(arguments);
@ -185,69 +152,4 @@ public class VideoItemDetailActivity extends ThemableActivity {
ErrorActivity.reportUiError(this, e);
}
}
/**
* Retrieves all Strings which look remotely like URLs from a text.
* Used if NewPipe was called through share menu.
*
* @param sharedText text to scan for URLs.
* @return potential URLs
*/
private String[] getUris(final String sharedText) {
final Collection<String> result = new HashSet<>();
if (sharedText != null) {
final String[] array = sharedText.split("\\p{Space}");
for (String s : array) {
s = trim(s);
if (s.length() != 0) {
if (s.matches(".+://.+")) {
result.add(removeHeadingGibberish(s));
} else if (s.matches(".+\\..+")) {
result.add("http://" + s);
}
}
}
}
return result.toArray(new String[result.size()]);
}
private static String removeHeadingGibberish(final String input) {
int start = 0;
for (int i = input.indexOf("://") - 1; i >= 0; i--) {
if (!input.substring(i, i + 1).matches("\\p{L}")) {
start = i + 1;
break;
}
}
return input.substring(start, input.length());
}
private static String trim(final String input) {
if (input == null || input.length() < 1) {
return input;
} else {
String output = input;
while (output.length() > 0 && output.substring(0, 1).matches(REGEX_REMOVE_FROM_URL)) {
output = output.substring(1);
}
while (output.length() > 0
&& output.substring(output.length() - 1, output.length()).matches(REGEX_REMOVE_FROM_URL)) {
output = output.substring(0, output.length() - 1);
}
return output;
}
}
private int getServiceIdByUrl(String url) {
StreamingService[] serviceList = NewPipe.getServices();
int service = -1;
for (int i = 0; i < serviceList.length; i++) {
if (serviceList[i].getStreamUrlIdHandlerInstance().acceptUrl(videoUrl)) {
service = i;
//videoExtractor = ServiceList.getService(i).getExtractorInstance();
break;
}
}
return service;
}
}

View File

@ -33,6 +33,7 @@ import android.widget.RelativeLayout;
import android.widget.TextView;
import android.widget.Toast;
import com.google.android.exoplayer.util.Util;
import com.nostra13.universalimageloader.core.DisplayImageOptions;
import com.nostra13.universalimageloader.core.ImageLoader;
@ -797,8 +798,11 @@ public class VideoItemDetailFragment extends Fragment {
@Override
public boolean onOptionsItemSelected(MenuItem item) {
super.onOptionsItemSelected(item);
return actionBarHandler.onItemSelected(item);
if(!actionBarHandler.onItemSelected(item)) {
return super.onOptionsItemSelected(item);
} else {
return true;
}
}
public void setOnInvokeCreateOptionsMenuListener(OnInvokeCreateOptionsMenuListener listener) {

View File

@ -3,18 +3,15 @@ package org.schabi.newpipe.download;
import android.annotation.TargetApi;
import android.app.AlertDialog;
import android.app.FragmentTransaction;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.ServiceConnection;
import android.content.SharedPreferences;
import android.os.Bundle;
import android.os.IBinder;
import android.preference.PreferenceManager;
import android.support.v4.app.NavUtils;
import android.support.v7.app.ActionBar;
import android.support.v7.app.AppCompatActivity;
import android.support.v7.widget.Toolbar;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuInflater;
@ -28,32 +25,28 @@ import android.widget.SeekBar;
import android.widget.TextView;
import android.widget.Toast;
import org.schabi.newpipe.ThemableActivity;
import org.schabi.newpipe.report.ErrorActivity;
import org.schabi.newpipe.R;
import org.schabi.newpipe.report.ErrorActivity;
import org.schabi.newpipe.settings.NewPipeSettings;
import org.schabi.newpipe.settings.SettingsActivity;
import org.schabi.newpipe.util.ThemeHelper;
import java.io.File;
import java.util.Vector;
import us.shandian.giga.get.DownloadManager;
import us.shandian.giga.service.DownloadManagerService;
import us.shandian.giga.ui.fragment.AllMissionsFragment;
import us.shandian.giga.ui.fragment.MissionsFragment;
import us.shandian.giga.util.CrashHandler;
import us.shandian.giga.util.Utility;
public class DownloadActivity extends ThemableActivity implements AdapterView.OnItemClickListener{
public class DownloadActivity extends AppCompatActivity implements AdapterView.OnItemClickListener {
public static final String INTENT_DOWNLOAD = "us.shandian.giga.intent.DOWNLOAD";
public static final String INTENT_LIST = "us.shandian.giga.intent.LIST";
private static final String TAG = DownloadActivity.class.toString();
public static final String THREADS = "threads";
private static final String TAG = DownloadActivity.class.toString();
private MissionsFragment mFragment;
@ -72,9 +65,9 @@ public class DownloadActivity extends ThemableActivity implements AdapterView.On
startService(i);
super.onCreate(savedInstanceState);
ThemeHelper.setTheme(this, true);
setContentView(R.layout.activity_downloader);
//noinspection ConstantConditions
// its ok if this fails, we will catch that error later, and send it as report

View File

@ -54,6 +54,7 @@ public abstract class ChannelExtractor {
public abstract String getBannerUrl() throws ParsingException;
public abstract String getFeedUrl() throws ParsingException;
public abstract StreamInfoItemCollector getStreams() throws ParsingException;
public abstract long getSubscriberCount() throws ParsingException;
public abstract boolean hasNextPage() throws ParsingException;
public int getServiceId() {
return serviceId;

View File

@ -29,8 +29,6 @@ import java.util.Vector;
*/
public class ChannelInfo {
public void addException(Exception e) {
errors.add(e);
}
@ -66,6 +64,11 @@ public class ChannelInfo {
} catch(Exception e) {
info.errors.add(e);
}
try {
info.subscriberCount = extractor.getSubscriberCount();
} catch (Exception e) {
info.errors.add(e);
}
return info;
}
@ -76,6 +79,7 @@ public class ChannelInfo {
public String banner_url = "";
public String feed_url = "";
public List<InfoItem> related_streams = null;
public long subscriberCount = -1;
public boolean hasNextPage = false;
public List<Throwable> errors = new Vector<>();

View File

@ -55,6 +55,7 @@ public class YoutubeChannelExtractor extends ChannelExtractor {
private static String avatarUrl = "";
private static String bannerUrl = "";
private static String feedUrl = "";
private static long subscriberCount = -1;
// the fist page is html all other pages are ajax. Every new page can be requested by sending
// this request url.
private static String nextPageUrl = "";
@ -153,7 +154,7 @@ public class YoutubeChannelExtractor extends ChannelExtractor {
@Override
public StreamInfoItemCollector getStreams() throws ParsingException {
StreamInfoItemCollector collector = getStreamPreviewInfoCollector();
Element ul = null;
Element ul;
if(isAjaxPage) {
ul = doc.select("body").first();
} else {
@ -168,6 +169,15 @@ public class YoutubeChannelExtractor extends ChannelExtractor {
return AbstractStreamInfo.StreamType.VIDEO_STREAM;
}
@Override
public boolean isAd() throws ParsingException {
if(!li.select("span[class*=\"icon-not-available\"]").isEmpty()) {
return true;
} else {
return false;
}
}
@Override
public String getWebPageUrl() throws ParsingException {
try {
@ -213,9 +223,14 @@ public class YoutubeChannelExtractor extends ChannelExtractor {
@Override
public String getUploadDate() throws ParsingException {
try {
return li.select("div[class=\"yt-lockup-meta\"]").first()
.select("li").first()
.text();
Element meta = li.select("div[class=\"yt-lockup-meta\"]").first();
Element li = meta.select("li").first();
if (li == null && meta != null) {
//this means we have a youtube red video
return "";
}else {
return li.text();
}
} catch(Exception e) {
throw new ParsingException("Could not get uplaod date", e);
}
@ -230,13 +245,7 @@ public class YoutubeChannelExtractor extends ChannelExtractor {
.select("li").get(1)
.text();
} catch (IndexOutOfBoundsException e) {
if(isLiveStream(li)) {
// -1 for no view count
return -1;
} else {
throw new ParsingException(
"Could not parse yt-lockup-meta although available: " + getTitle(), e);
}
return -1;
}
output = Parser.matchGroup1("([0-9,\\. ]*)", input)
@ -294,6 +303,18 @@ public class YoutubeChannelExtractor extends ChannelExtractor {
return collector;
}
@Override
public long getSubscriberCount() throws ParsingException {
Element el = doc.select("span[class*=\"yt-subscription-button-subscriber-count\"]")
.first();
if(el != null) {
subscriberCount = Long.parseLong(el.text().replaceAll("\\D+",""));
} else if(el == null && subscriberCount == -1) {
throw new ParsingException("Could not get subscriber count");
}
return subscriberCount;
}
@Override
public String getFeedUrl() throws ParsingException {
try {

View File

@ -10,6 +10,7 @@ import org.mozilla.javascript.Function;
import org.mozilla.javascript.ScriptableObject;
import org.schabi.newpipe.extractor.AbstractStreamInfo;
import org.schabi.newpipe.extractor.exceptions.ExtractionException;
import org.schabi.newpipe.extractor.exceptions.FoundAdException;
import org.schabi.newpipe.extractor.exceptions.ParsingException;
import org.schabi.newpipe.extractor.exceptions.ReCaptchaException;
import org.schabi.newpipe.extractor.stream_info.AudioStream;
@ -420,9 +421,15 @@ public class YoutubeStreamExtractor extends StreamExtractor {
@Override
public String getDashMpdUrl() throws ParsingException {
/*
try {
String dashManifestUrl = videoInfoPage.get("dashmpd");
String dashManifestUrl = "";
if(videoInfoPage != null && videoInfoPage.containsKey("dashmpd")) {
dashManifestUrl = videoInfoPage.get("dashmpd");
} else if (playerArgs.has("dashmpd")) {
dashManifestUrl = playerArgs.getString("dashmpd");
} else {
return "";
}
if(!dashManifestUrl.contains("/signature/")) {
String encryptedSig = Parser.matchGroup1("/s/([a-fA-F0-9\\.]+)", dashManifestUrl);
String decryptedSig;
@ -435,8 +442,6 @@ public class YoutubeStreamExtractor extends StreamExtractor {
throw new ParsingException(
"Could not get \"dashmpd\" maybe VideoInfoPage is broken.", e);
}
*/
return "";
}
@ -447,9 +452,17 @@ public class YoutubeStreamExtractor extends StreamExtractor {
String encodedUrlMap;
// playerArgs could be null if the video is age restricted
if (playerArgs == null) {
encodedUrlMap = videoInfoPage.get("adaptive_fmts");
if(videoInfoPage.containsKey("adaptive_fmts")) {
encodedUrlMap = videoInfoPage.get("adaptive_fmts");
} else {
return null;
}
} else {
encodedUrlMap = playerArgs.getString("adaptive_fmts");
if(playerArgs.has("adaptive_fmts")) {
encodedUrlMap = playerArgs.getString("adaptive_fmts");
} else {
return null;
}
}
for(String url_data_str : encodedUrlMap.split(",")) {
// This loop iterates through multiple streams, therefor tags
@ -713,7 +726,16 @@ public class YoutubeStreamExtractor extends StreamExtractor {
return new StreamInfoItemExtractor() {
@Override
public AbstractStreamInfo.StreamType getStreamType() throws ParsingException {
return null;
return AbstractStreamInfo.StreamType.VIDEO_STREAM;
}
@Override
public boolean isAd() throws ParsingException {
if(!li.select("span[class*=\"icon-not-available\"]").isEmpty()) {
return true;
} else {
return false;
}
}
@Override

View File

@ -3,6 +3,7 @@ package org.schabi.newpipe.extractor.services.youtube;
import org.jsoup.nodes.Element;
import org.schabi.newpipe.extractor.AbstractStreamInfo;
import org.schabi.newpipe.extractor.Parser;
import org.schabi.newpipe.extractor.exceptions.FoundAdException;
import org.schabi.newpipe.extractor.exceptions.ParsingException;
import org.schabi.newpipe.extractor.stream_info.StreamInfoItemExtractor;
@ -28,7 +29,7 @@ public class YoutubeStreamInfoItemExtractor implements StreamInfoItemExtractor {
private final Element item;
public YoutubeStreamInfoItemExtractor(Element item) {
public YoutubeStreamInfoItemExtractor(Element item) throws FoundAdException {
this.item = item;
}
@ -161,6 +162,15 @@ public class YoutubeStreamInfoItemExtractor implements StreamInfoItemExtractor {
}
}
@Override
public boolean isAd() throws ParsingException {
if(!item.select("span[class*=\"icon-not-available\"]").isEmpty()) {
return true;
} else {
return false;
}
}
private boolean isLiveStream(Element item) {
Element bla = item.select("span[class*=\"yt-badge-live\"]").first();

View File

@ -15,7 +15,6 @@ import java.io.UnsupportedEncodingException;
import java.net.URI;
import java.net.URISyntaxException;
import java.net.URLDecoder;
import java.util.regex.Matcher;
/**
* Created by Christian Schabesberger on 02.02.16.
@ -149,9 +148,9 @@ public class YoutubeStreamUrlIdHandler implements UrlIdHandler {
@Override
public boolean acceptUrl(String videoUrl) {
videoUrl = videoUrl.toLowerCase();
if(videoUrl.contains("youtube") ||
videoUrl.contains("youtu.be")) {
String lowercaseUrl = videoUrl.toLowerCase();
if(lowercaseUrl.contains("youtube") ||
lowercaseUrl.contains("youtu.be")) {
// bad programming I know
try {
getId(videoUrl);

View File

@ -43,6 +43,9 @@ public class StreamInfoItemCollector extends InfoItemCollector {
}
public StreamInfoItem extract(StreamInfoItemExtractor extractor) throws Exception {
if(extractor.isAd()) {
throw new FoundAdException("Found ad");
}
StreamInfoItem resultItem = new StreamInfoItem();
// importand information
@ -91,7 +94,7 @@ public class StreamInfoItemCollector extends InfoItemCollector {
try {
addItem(extract(extractor));
} catch(FoundAdException ae) {
System.out.println("AD_WARNING: " + ae.getMessage());
//System.out.println("AD_WARNING: " + ae.getMessage());
} catch (Exception e) {
addError(e);
}

View File

@ -32,4 +32,5 @@ public interface StreamInfoItemExtractor {
String getUploadDate() throws ParsingException;
long getViewCount() throws ParsingException;
String getThumbnailUrl() throws ParsingException;
boolean isAd() throws ParsingException;
}

View File

@ -105,7 +105,7 @@ public class InfoItemBuilder {
switch(info.infoType()) {
case STREAM:
itemView = LayoutInflater.from(parent.getContext())
.inflate(R.layout.stream_item, parent, false);
.inflate(R.layout.stream_item, parent, false);
holder = new StreamInfoItemHolder(itemView);
break;
case CHANNEL:
@ -202,15 +202,15 @@ public class InfoItemBuilder {
}
}
public String shortSubscriber(Long viewCount){
if(viewCount >= 1000000000){
return Long.toString(viewCount/1000000000)+ billion + " " + subsS;
}else if(viewCount>=1000000){
return Long.toString(viewCount/1000000)+ million + " " + subsS;
}else if(viewCount>=1000){
return Long.toString(viewCount/1000)+ thousand + " " + subsS;
public String shortSubscriber(Long count){
if(count >= 1000000000){
return Long.toString(count/1000000000)+ billion + " " + subsS;
}else if(count>=1000000){
return Long.toString(count/1000000)+ million + " " + subsS;
}else if(count>=1000){
return Long.toString(count/1000)+ thousand + " " + subsS;
}else {
return Long.toString(viewCount)+ " " + subsS;
return Long.toString(count)+ " " + subsS;
}
}

View File

@ -33,11 +33,27 @@ import java.util.Vector;
* along with NewPipe. If not, see <http://www.gnu.org/licenses/>.
*/
public class InfoListAdapter extends RecyclerView.Adapter<InfoItemHolder> {
public class InfoListAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {
private static final String TAG = InfoListAdapter.class.toString();
private final InfoItemBuilder infoItemBuilder;
private final List<InfoItem> infoItemList;
private boolean showFooter = false;
private View header = null;
private View footer = null;
public class HFHolder extends RecyclerView.ViewHolder {
public HFHolder(View v) {
super(v);
view = v;
}
public View view;
}
public void showFooter(boolean show) {
showFooter = show;
notifyDataSetChanged();
}
public InfoListAdapter(Activity a, View rootView) {
infoItemBuilder = new InfoItemBuilder(a, rootView);
@ -54,9 +70,9 @@ public class InfoListAdapter extends RecyclerView.Adapter<InfoItemHolder> {
infoItemBuilder.setOnChannelInfoItemSelectedListener(listener);
}
public void addInfoItemList(List<InfoItem> videos) {
if(videos!= null) {
infoItemList.addAll(videos);
public void addInfoItemList(List<InfoItem> data) {
if(data != null) {
infoItemList.addAll(data);
notifyDataSetChanged();
}
}
@ -66,21 +82,42 @@ public class InfoListAdapter extends RecyclerView.Adapter<InfoItemHolder> {
notifyDataSetChanged();
}
public void setHeader(View header) {
this.header = header;
notifyDataSetChanged();
}
public void setFooter(View view) {
this.footer = view;
notifyDataSetChanged();
}
@Override
public int getItemCount() {
return infoItemList.size();
int cound = infoItemList.size();
if(header != null) cound++;
if(footer != null && showFooter) cound++;
return cound;
}
// don't ask why we have to do that this way... it's android accept it -.-
@Override
public int getItemViewType(int position) {
if(header != null && position == 0) {
return 0;
} else if(header != null) {
position--;
}
if(footer != null && position == infoItemList.size() && showFooter) {
return 1;
}
switch(infoItemList.get(position).infoType()) {
case STREAM:
return 0;
case CHANNEL:
return 1;
case PLAYLIST:
return 2;
case CHANNEL:
return 3;
case PLAYLIST:
return 4;
default:
Log.e(TAG, "Trollolo");
return -1;
@ -88,15 +125,19 @@ public class InfoListAdapter extends RecyclerView.Adapter<InfoItemHolder> {
}
@Override
public InfoItemHolder onCreateViewHolder(ViewGroup parent, int type) {
public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int type) {
switch(type) {
case 0:
return new HFHolder(header);
case 1:
return new HFHolder(footer);
case 2:
return new StreamInfoItemHolder(LayoutInflater.from(parent.getContext())
.inflate(R.layout.stream_item, parent, false));
case 1:
case 3:
return new ChannelInfoItemHolder(LayoutInflater.from(parent.getContext())
.inflate(R.layout.channel_item, parent, false));
case 2:
case 4:
Log.e(TAG, "Playlist is not yet implemented");
return null;
default:
@ -106,7 +147,17 @@ public class InfoListAdapter extends RecyclerView.Adapter<InfoItemHolder> {
}
@Override
public void onBindViewHolder(InfoItemHolder holder, int i) {
infoItemBuilder.buildByHolder(holder, infoItemList.get(i));
public void onBindViewHolder(RecyclerView.ViewHolder holder, int i) {
//god damen f*** ANDROID SH**
if(holder instanceof InfoItemHolder) {
if(header != null) {
i--;
}
infoItemBuilder.buildByHolder((InfoItemHolder) holder, infoItemList.get(i));
} else if(holder instanceof HFHolder && i == 0 && header != null) {
((HFHolder) holder).view = header;
} else if(holder instanceof HFHolder && i == infoItemList.size() && footer != null && showFooter) {
((HFHolder) holder).view = footer;
}
}
}

View File

@ -1,5 +1,3 @@
package org.schabi.newpipe.report;
import android.app.Activity;
@ -8,14 +6,14 @@ import android.content.Intent;
import android.graphics.Color;
import android.net.Uri;
import android.os.Build;
import android.os.Bundle;
import android.os.Handler;
import android.os.Parcel;
import android.os.Parcelable;
import android.preference.PreferenceManager;
import android.support.design.widget.Snackbar;
import android.support.v4.app.NavUtils;
import android.support.v7.app.ActionBar;
import android.os.Bundle;
import android.os.Handler;
import android.support.v7.app.AppCompatActivity;
import android.util.Log;
import android.view.Menu;
@ -35,8 +33,8 @@ import org.schabi.newpipe.BuildConfig;
import org.schabi.newpipe.Downloader;
import org.schabi.newpipe.MainActivity;
import org.schabi.newpipe.R;
import org.schabi.newpipe.ThemableActivity;
import org.schabi.newpipe.extractor.Parser;
import org.schabi.newpipe.util.ThemeHelper;
import java.io.PrintWriter;
import java.io.StringWriter;
@ -66,65 +64,12 @@ import java.util.Vector;
* along with NewPipe. If not, see <http://www.gnu.org/licenses/>.
*/
public class ErrorActivity extends ThemableActivity {
public static class ErrorInfo implements Parcelable {
public int userAction;
public String request;
public String serviceName;
public int message;
public static ErrorInfo make(int userAction, String serviceName, String request, int message) {
ErrorInfo info = new ErrorInfo();
info.userAction = userAction;
info.serviceName = serviceName;
info.request = request;
info.message = message;
return info;
}
@Override
public int describeContents() {
return 0;
}
@Override
public void writeToParcel(Parcel dest, int flags) {
dest.writeInt(this.userAction);
dest.writeString(this.request);
dest.writeString(this.serviceName);
dest.writeInt(this.message);
}
public ErrorInfo() {
}
protected ErrorInfo(Parcel in) {
this.userAction = in.readInt();
this.request = in.readString();
this.serviceName = in.readString();
this.message = in.readInt();
}
public static final Parcelable.Creator<ErrorInfo> CREATOR = new Parcelable.Creator<ErrorInfo>() {
@Override
public ErrorInfo createFromParcel(Parcel source) {
return new ErrorInfo(source);
}
@Override
public ErrorInfo[] newArray(int size) {
return new ErrorInfo[size];
}
};
}
public class ErrorActivity extends AppCompatActivity {
// LOG TAGS
public static final String TAG = ErrorActivity.class.toString();
// BUNDLE TAGS
public static final String ERROR_INFO = "error_info";
public static final String ERROR_LIST = "error_list";
// MESSAGE ID
public static final int SEARCHED = 0;
public static final int REQUESTED_STREAM = 1;
@ -134,7 +79,6 @@ public class ErrorActivity extends ThemableActivity {
public static final int LOAD_IMAGE = 5;
public static final int UI_ERROR = 6;
public static final int REQUESTED_CHANNEL = 7;
// MESSAGE STRING
public static final String SEARCHED_STRING = "searched";
public static final String REQUESTED_STREAM_STRING = "requested stream";
@ -144,17 +88,14 @@ public class ErrorActivity extends ThemableActivity {
public static final String LOAD_IMAGE_STRING = "load image";
public static final String UI_ERROR_STRING = "ui error";
public static final String REQUESTED_CHANNEL_STRING = "requested channel";
public static final String ERROR_EMAIL_ADDRESS = "crashreport@newpipe.schabi.org";
public static final String ERROR_EMAIL_SUBJECT = "Exception in NewPipe " + BuildConfig.VERSION_NAME;
Thread globIpRangeThread;
private String[] errorList;
private ErrorInfo errorInfo;
private Class returnActivity;
private String currentTimeStamp;
private String globIpRange;
Thread globIpRangeThread;
// views
private TextView errorView;
private EditText userCommentBox;
@ -243,9 +184,26 @@ public class ErrorActivity extends ThemableActivity {
context.startActivity(intent);
}
private static String getStackTrace(final Throwable throwable) {
final StringWriter sw = new StringWriter();
final PrintWriter pw = new PrintWriter(sw, true);
throwable.printStackTrace(pw);
return sw.getBuffer().toString();
}
// errorList to StringList
private static String[] elToSl(List<Throwable> stackTraces) {
String[] out = new String[stackTraces.size()];
for (int i = 0; i < stackTraces.size(); i++) {
out[i] = getStackTrace(stackTraces.get(i));
}
return out;
}
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
ThemeHelper.setTheme(this, true);
setContentView(R.layout.activity_error);
Intent intent = getIntent();
@ -335,13 +293,6 @@ public class ErrorActivity extends ThemableActivity {
return false;
}
private static String getStackTrace(final Throwable throwable) {
final StringWriter sw = new StringWriter();
final PrintWriter pw = new PrintWriter(sw, true);
throwable.printStackTrace(pw);
return sw.getBuffer().toString();
}
private String formErrorText(String[] el) {
String text = "";
if(el != null) {
@ -478,6 +429,56 @@ public class ErrorActivity extends ThemableActivity {
return df.format(new Date());
}
public static class ErrorInfo implements Parcelable {
public static final Parcelable.Creator<ErrorInfo> CREATOR = new Parcelable.Creator<ErrorInfo>() {
@Override
public ErrorInfo createFromParcel(Parcel source) {
return new ErrorInfo(source);
}
@Override
public ErrorInfo[] newArray(int size) {
return new ErrorInfo[size];
}
};
public int userAction;
public String request;
public String serviceName;
public int message;
public ErrorInfo() {
}
protected ErrorInfo(Parcel in) {
this.userAction = in.readInt();
this.request = in.readString();
this.serviceName = in.readString();
this.message = in.readInt();
}
public static ErrorInfo make(int userAction, String serviceName, String request, int message) {
ErrorInfo info = new ErrorInfo();
info.userAction = userAction;
info.serviceName = serviceName;
info.request = request;
info.message = message;
return info;
}
@Override
public int describeContents() {
return 0;
}
@Override
public void writeToParcel(Parcel dest, int flags) {
dest.writeInt(this.userAction);
dest.writeString(this.request);
dest.writeString(this.serviceName);
dest.writeInt(this.message);
}
}
private class IpRagneRequester implements Runnable {
Handler h = new Handler();
public void run() {
@ -497,8 +498,6 @@ public class ErrorActivity extends ThemableActivity {
}
}
private class IpRageReturnRunnable implements Runnable {
String ipRange;
public IpRageReturnRunnable(String ipRange) {
@ -514,13 +513,4 @@ public class ErrorActivity extends ThemableActivity {
}
}
}
// errorList to StringList
private static String[] elToSl(List<Throwable> stackTraces) {
String[] out = new String[stackTraces.size()];
for(int i = 0; i < stackTraces.size(); i++) {
out[i] = getStackTrace(stackTraces.get(i));
}
return out;
}
}

View File

@ -205,7 +205,6 @@ public class SearchInfoItemFragment extends Fragment {
RECAPTCHA_REQUEST);
}
});
}
@Override
@ -221,6 +220,8 @@ public class SearchInfoItemFragment extends Fragment {
infoListAdapter = new InfoListAdapter(getActivity(),
getActivity().findViewById(android.R.id.content));
infoListAdapter.setFooter(inflater.inflate(R.layout.pignate_footer, recyclerView, false));
infoListAdapter.showFooter(false);
infoListAdapter.setOnStreamInfoItemSelectedListener(
new InfoItemBuilder.OnInfoItemSelectedListener() {
@Override
@ -324,6 +325,7 @@ public class SearchInfoItemFragment extends Fragment {
private void search(String query) {
infoListAdapter.clearSteamItemList();
infoListAdapter.showFooter(false);
pageNumber = 0;
searchQuery = query;
search(query, pageNumber);
@ -344,6 +346,7 @@ public class SearchInfoItemFragment extends Fragment {
private void setDoneLoading() {
this.isLoading = false;
loadingIndicator.setVisibility(View.GONE);
infoListAdapter.showFooter(true);
}
/**

View File

@ -5,7 +5,6 @@ import android.content.Intent;
import android.content.res.Configuration;
import android.os.Bundle;
import android.preference.PreferenceActivity;
import android.preference.PreferenceManager;
import android.support.annotation.LayoutRes;
import android.support.annotation.NonNull;
import android.support.v7.app.ActionBar;
@ -16,8 +15,7 @@ import android.view.View;
import android.view.ViewGroup;
import org.schabi.newpipe.R;
import java.util.Objects;
import org.schabi.newpipe.util.ThemeHelper;
/**
@ -41,16 +39,16 @@ import java.util.Objects;
*/
public class SettingsActivity extends PreferenceActivity {
private AppCompatDelegate mDelegate = null;
SettingsFragment f = new SettingsFragment();
private AppCompatDelegate mDelegate = null;
public static void initSettings(Context context) {
NewPipeSettings.initSettings(context);
}
@Override
protected void onCreate(Bundle savedInstanceBundle) {
if (PreferenceManager.getDefaultSharedPreferences(this)
.getString("theme", getResources().getString(R.string.light_theme_title)).
equals(getResources().getString(R.string.dark_theme_title))) {
setTheme(R.style.DarkTheme);
}
ThemeHelper.setTheme(this, true);
getDelegate().installViewFactory();
getDelegate().onCreate(savedInstanceBundle);
super.onCreate(savedInstanceBundle);
@ -156,8 +154,4 @@ public class SettingsActivity extends PreferenceActivity {
}
return true;
}
public static void initSettings(Context context) {
NewPipeSettings.initSettings(context);
}
}

View File

@ -1,27 +1,27 @@
package org.schabi.newpipe.settings;
import android.app.Activity;
import android.app.ListActivity;
import android.content.ClipData;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.SharedPreferences;
import android.net.Uri;
import android.os.Build;
import android.os.Bundle;
import android.preference.CheckBoxPreference;
import android.preference.ListPreference;
import android.preference.Preference;
import android.preference.PreferenceFragment;
import android.preference.PreferenceManager;
import android.preference.PreferenceScreen;
import android.support.v7.app.AlertDialog;
import com.nononsenseapps.filepicker.FilePickerActivity;
import org.schabi.newpipe.App;
import org.schabi.newpipe.MainActivity;
import org.schabi.newpipe.R;
import java.util.ArrayList;
import java.util.Objects;
import info.guardianproject.netcipher.proxy.OrbotHelper;
@ -48,8 +48,8 @@ import info.guardianproject.netcipher.proxy.OrbotHelper;
public class SettingsFragment extends PreferenceFragment
implements SharedPreferences.OnSharedPreferenceChangeListener
{
public static final int REQUEST_INSTALL_ORBOT = 0x1234;
SharedPreferences.OnSharedPreferenceChangeListener prefListener;
// get keys
String DEFAULT_RESOLUTION_PREFERENCE;
String DEFAULT_AUDIO_FORMAT_PREFERENCE;
@ -58,9 +58,6 @@ public class SettingsFragment extends PreferenceFragment
String DOWNLOAD_PATH_AUDIO_PREFERENCE;
String USE_TOR_KEY;
String THEME;
public static final int REQUEST_INSTALL_ORBOT = 0x1234;
private ListPreference defaultResolutionPreference;
private ListPreference defaultAudioFormatPreference;
private ListPreference searchLanguagePreference;
@ -98,6 +95,8 @@ public class SettingsFragment extends PreferenceFragment
downloadPathAudioPreference = findPreference(DOWNLOAD_PATH_AUDIO_PREFERENCE);
themePreference = findPreference(THEME);
final String currentTheme = defaultPreferences.getString(THEME, "Light");
prefListener = new SharedPreferences.OnSharedPreferenceChangeListener() {
@Override
public void onSharedPreferenceChanged(SharedPreferences sharedPreferences,
@ -139,8 +138,27 @@ public class SettingsFragment extends PreferenceFragment
}
else if (key == THEME)
{
String theme = sharedPreferences.getString(THEME, "Light");
themePreference.setSummary(theme);
String selectedTheme = sharedPreferences.getString(THEME, "Light");
themePreference.setSummary(selectedTheme);
if(!selectedTheme.equals(currentTheme)) { // If it's not the current theme
new AlertDialog.Builder(activity)
.setTitle(R.string.restart_title)
.setMessage(R.string.msg_restart)
.setPositiveButton(R.string.yes, new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
Intent intentToMain = new Intent(activity, MainActivity.class);
intentToMain.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK);
activity.startActivity(intentToMain);
activity.finish();
Runtime.getRuntime().exit(0);
}
})
.setNegativeButton(R.string.later, null)
.create().show();
}
}
updateSummary();
}

View File

@ -0,0 +1,31 @@
package org.schabi.newpipe.util;
import android.content.Context;
import android.preference.PreferenceManager;
import org.schabi.newpipe.R;
public class ThemeHelper {
public static void setTheme(Context context, boolean mode) {
// mode is true for normal theme, false for no action bar theme.
String themeKey = context.getString(R.string.theme_key);
//String lightTheme = context.getResources().getString(R.string.light_theme_title);
String darkTheme = context.getResources().getString(R.string.dark_theme_title);
String blackTheme = context.getResources().getString(R.string.black_theme_title);
String sp = PreferenceManager.getDefaultSharedPreferences(context)
.getString(themeKey, context.getResources().getString(R.string.light_theme_title));
if (mode) {
if (sp.equals(darkTheme)) context.setTheme(R.style.DarkTheme);
else if (sp.equals(blackTheme)) context.setTheme(R.style.BlackTheme);
else context.setTheme(R.style.AppTheme);
} else {
if (sp.equals(darkTheme)) context.setTheme(R.style.DarkTheme_NoActionBar);
else if (sp.equals(blackTheme)) context.setTheme(R.style.BlackTheme_NoActionBar);
else context.setTheme(R.style.AppTheme_NoActionBar);
}
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 75 KiB

View File

@ -0,0 +1,12 @@
<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
<item
android:drawable="?android:windowBackground"/>
<item>
<bitmap
android:gravity="center"
android:src="@mipmap/ic_launcher"/>
</item>
</layer-list>

View File

@ -1,9 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
<item
android:drawable="?android:attr/windowBackground"/>
<item>
<bitmap
android:gravity="center"

View File

@ -0,0 +1,79 @@
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
android:id="@+id/channel_header_layout"
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<ImageView
android:id="@+id/channel_banner_image"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:fitsSystemWindows="true"
android:scaleType="center"
android:src="@drawable/channel_banner"
android:background="@android:color/black"
android:adjustViewBounds="true"/>
<RelativeLayout
android:id="@+id/channel_avatar_layout"
android:layout_alignTop="@id/channel_banner_image"
android:layout_width="@dimen/channel_avatar_halo_size"
android:layout_height="@dimen/channel_avatar_halo_size"
android:layout_marginLeft="20dp"
android:layout_marginStart="20dp"
android:layout_marginTop="60dp">
<ImageView
android:id="@+id/channel_avatar_halo"
android:layout_width="@dimen/channel_avatar_halo_size"
android:layout_height="@dimen/channel_avatar_halo_size"
android:layout_alignParentLeft="true"
android:layout_alignParentStart="true"
android:src="@drawable/white_circle" />
<de.hdodenhof.circleimageview.CircleImageView
android:id="@+id/channel_avatar_view"
android:layout_width="@dimen/channel_avatar_size"
android:layout_height="@dimen/channel_avatar_size"
android:src="@drawable/buddy"
android:layout_centerInParent="true"/>
</RelativeLayout>
<TextView
android:id="@+id/channel_title_view"
android:layout_below="@id/channel_banner_image"
android:layout_toEndOf="@id/channel_avatar_layout"
android:layout_toRightOf="@id/channel_avatar_layout"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="4dp"
android:layout_marginStart="4dp"
android:textSize="@dimen/video_item_detail_title_text_size"
android:textAppearance="?android:attr/textAppearanceLarge"/>
<LinearLayout
android:id="@+id/channel_subscriber_layout"
android:layout_below="@id/channel_banner_image"
android:layout_toEndOf="@id/channel_title_view"
android:layout_toRightOf="@id/channel_title_view"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="horizontal">
<Button
android:id="@+id/channel_subscribe_button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/subscribe"
android:layout_marginLeft="4dp"
android:layout_marginStart="4dp"/>
<TextView
android:id="@+id/channel_subscriber_view"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:gravity="center"/>
</LinearLayout>
</RelativeLayout>

View File

@ -1,81 +1,17 @@
<?xml version="1.0" encoding="utf-8"?>
<android.support.design.widget.CoordinatorLayout 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"
<RelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:fitsSystemWindows="true"
android:id="@+id/rootView"
tools:context="org.schabi.newpipe.ChannelActivity">
android:orientation="vertical"
android:title="Channel">
<android.support.design.widget.AppBarLayout
android:id="@+id/channel_app_bar"
<android.support.v7.widget.RecyclerView
android:id="@+id/channel_streams_view"
android:layout_width="match_parent"
android:layout_height="@dimen/app_bar_height"
android:fitsSystemWindows="true"
android:theme="@style/AppTheme.AppBarOverlay">
<android.support.design.widget.CollapsingToolbarLayout
android:id="@+id/channel_toolbar_layout"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:fitsSystemWindows="true"
app:contentScrim="@color/light_youtube_primary_color"
app:statusBarScrim="@color/light_youtube_dark_color"
app:layout_scrollFlags="scroll|exitUntilCollapsed">
<ImageView
android:id="@+id/channel_banner_image"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:fitsSystemWindows="true"
android:scaleType="centerCrop"
android:background="@color/light_youtube_dark_color"
app:layout_collapseMode="parallax" />
<ImageView
android:id="@+id/channel_avatar_halo"
android:visibility="gone"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="28dp"
android:layout_marginStart="28dp"
android:layout_marginTop="38dp"
android:layout_alignParentLeft="true"
android:layout_alignParentStart="true"
android:src="@drawable/white_circle"/>
<de.hdodenhof.circleimageview.CircleImageView
android:id="@+id/channel_avatar_view"
android:visibility="gone"
android:layout_width="@dimen/channel_avatar_size"
android:layout_height="@dimen/channel_avatar_size"
android:src="@drawable/buddy"
android:layout_marginLeft="30dp"
android:layout_marginStart="30dp"
android:layout_marginTop="40dp"
android:layout_alignParentLeft="true"
android:layout_alignParentStart="true"/>
<android.support.v7.widget.Toolbar
android:id="@+id/cannel_toolbar"
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
app:layout_collapseMode="pin"
app:popupTheme="@style/AppTheme.PopupOverlay" />
</android.support.design.widget.CollapsingToolbarLayout>
</android.support.design.widget.AppBarLayout>
<android.support.design.widget.FloatingActionButton
android:id="@+id/channel_rss_fab"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_margin="@dimen/fab_margin"
android:src="?attr/rss"
app:layout_anchor="@id/channel_app_bar"
app:layout_anchorGravity="bottom|end" />
android:layout_height="match_parent"
android:background="?android:windowBackground"
android:scrollbars="vertical"/>
<RelativeLayout
android:layout_width="match_parent"
@ -87,11 +23,4 @@
android:layout_centerInParent="true"
android:indeterminate="true"/>
</RelativeLayout>
<android.support.v7.widget.RecyclerView
android:id="@+id/channel_streams_view"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="?android:windowBackground"
app:layout_behavior="@string/appbar_scrolling_view_behavior"
android:scrollbars="vertical"/>
</android.support.design.widget.CoordinatorLayout>
</RelativeLayout>

View File

@ -0,0 +1,78 @@
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
android:id="@+id/channel_header_layout"
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<ImageView
android:id="@+id/channel_banner_image"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:fitsSystemWindows="true"
android:scaleType="center"
android:src="@drawable/channel_banner"
android:background="@android:color/black"
android:adjustViewBounds="true"/>
<RelativeLayout
android:id="@+id/channel_avatar_layout"
android:layout_alignTop="@id/channel_banner_image"
android:layout_width="@dimen/channel_avatar_halo_size"
android:layout_height="@dimen/channel_avatar_halo_size"
android:layout_marginLeft="20dp"
android:layout_marginStart="20dp"
android:layout_marginTop="30dp">
<ImageView
android:id="@+id/channel_avatar_halo"
android:layout_width="@dimen/channel_avatar_halo_size"
android:layout_height="@dimen/channel_avatar_halo_size"
android:layout_alignParentLeft="true"
android:layout_alignParentStart="true"
android:src="@drawable/white_circle" />
<de.hdodenhof.circleimageview.CircleImageView
android:id="@+id/channel_avatar_view"
android:layout_width="@dimen/channel_avatar_size"
android:layout_height="@dimen/channel_avatar_size"
android:src="@drawable/buddy"
android:layout_centerInParent="true"/>
</RelativeLayout>
<TextView
android:id="@+id/channel_title_view"
android:layout_below="@id/channel_banner_image"
android:layout_toEndOf="@id/channel_avatar_layout"
android:layout_toRightOf="@id/channel_avatar_layout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginLeft="4dp"
android:layout_marginStart="4dp"
android:textSize="@dimen/video_item_detail_title_text_size"
android:textAppearance="?android:attr/textAppearanceLarge"/>
<LinearLayout
android:id="@+id/channel_subscriber_layout"
android:visibility="gone"
android:layout_below="@id/channel_avatar_layout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal">
<Button
android:id="@+id/channel_subscribe_button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/subscribe"
android:layout_marginLeft="4dp"
android:layout_marginStart="4dp"/>
<TextView
android:id="@+id/channel_subscriber_view"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:gravity="center"/>
</LinearLayout>
</RelativeLayout>

View File

@ -0,0 +1,15 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center_horizontal"
android:orientation="vertical">
<ProgressBar
android:id="@+id/paginate_progress_bar"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:gravity="center"
android:paddingBottom="10dp"/>
</LinearLayout>

View File

@ -2,6 +2,16 @@
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
tools:context="org.schabi.newpipe.ChannelActivity">
<item android:id="@+id/menu_item_openInBrowser"
app:showAsAction="never"
android:title="@string/open_in_browser" />
<item android:id="@+id/menu_item_share"
android:title="@string/share"
app:showAsAction="ifRoom"
android:icon="?attr/share"/>
<item
android:id="@+id/action_settings"
android:orderInCategory="100"

View File

@ -175,16 +175,16 @@
A material metaphor is the unifying theory of a rationalized space and a system of motion.
The material is grounded in tactile reality, inspired by the study of paper and ink, yet
The material is grounded in tactile reality, inspired by the study of paper and ink, yet
technologically advanced and open to imagination and magic.
Surfaces and edges of the material provide visual cues that are grounded in reality. The
use of familiar tactile attributes helps users quickly understand affordances. Yet the
flexibility of the material creates new affordances that supercede those in the physical
Surfaces and edges of the material provide visual cues that are grounded in reality. The
use of familiar tactile attributes helps users quickly understand affordances. Yet the
flexibility of the material creates new affordances that supercede those in the physical
world, without breaking the rules of physics.
The fundamentals of light, surface, and movement are key to conveying how objects move,
interact, and exist in space and in relation to each other. Realistic lighting shows
The fundamentals of light, surface, and movement are key to conveying how objects move,
interact, and exist in space and in relation to each other. Realistic lighting shows
seams, divides space, and indicates moving parts.
@ -193,13 +193,13 @@
The foundational elements of print based design typography, grids, space, scale, color,
and use of imagery guide visual treatments. These elements do far more than please the
eye. They create hierarchy, meaning, and focus. Deliberate color choices, edge to edge
imagery, large scale typography, and intentional white space create a bold and graphic
The foundational elements of print based design typography, grids, space, scale, color,
and use of imagery guide visual treatments. These elements do far more than please the
eye. They create hierarchy, meaning, and focus. Deliberate color choices, edge to edge
imagery, large scale typography, and intentional white space create a bold and graphic
interface that immerse the user in the experience.
An emphasis on user actions makes core functionality immediately apparent and provides
An emphasis on user actions makes core functionality immediately apparent and provides
waypoints for the user.
@ -208,13 +208,13 @@
Motion respects and reinforces the user as the prime mover. Primary user actions are
Motion respects and reinforces the user as the prime mover. Primary user actions are
inflection points that initiate motion, transforming the whole design.
All action takes place in a single environment. Objects are presented to the user without
All action takes place in a single environment. Objects are presented to the user without
breaking the continuity of experience even as they transform and reorganize.
Motion is meaningful and appropriate, serving to focus attention and maintain continuity.
Motion is meaningful and appropriate, serving to focus attention and maintain continuity.
Feedback is subtle yet clear. Transitions are efficient yet coherent.
@ -223,12 +223,12 @@
The material environment is a 3D space, which means all objects have x, y, and z
dimensions. The z-axis is perpendicularly aligned to the plane of the display, with the
positive z-axis extending towards the viewer. Every sheet of material occupies a single
The material environment is a 3D space, which means all objects have x, y, and z
dimensions. The z-axis is perpendicularly aligned to the plane of the display, with the
positive z-axis extending towards the viewer. Every sheet of material occupies a single
position along the z-axis and has a standard 1dp thickness.
On the web, the z-axis is used for layering and not for perspective. The 3D world is
On the web, the z-axis is used for layering and not for perspective. The 3D world is
emulated by manipulating the y-axis.
@ -237,12 +237,12 @@
Within the material environment, virtual lights illuminate the scene. Key lights create
Within the material environment, virtual lights illuminate the scene. Key lights create
directional shadows, while ambient light creates soft shadows from all angles.
Shadows in the material environment are cast by these two light sources. In Android
development, shadows occur when light sources are blocked by sheets of material at
various positions along the z-axis. On the web, shadows are depicted by manipulating the
Shadows in the material environment are cast by these two light sources. In Android
development, shadows occur when light sources are blocked by sheets of material at
various positions along the z-axis. On the web, shadows are depicted by manipulating the
y-axis only. The following example shows the card with a height of 6dp.
@ -251,8 +251,8 @@
All material objects, regardless of size, have a resting elevation, or default elevation
that does not change. If an object changes elevation, it should return to its resting
All material objects, regardless of size, have a resting elevation, or default elevation
that does not change. If an object changes elevation, it should return to its resting
elevation as soon as possible.
@ -261,10 +261,10 @@
The resting elevation for a component type is consistent across apps (e.g., FAB elevation
The resting elevation for a component type is consistent across apps (e.g., FAB elevation
does not vary from 6dp in one app to 16dp in another app).
Components may have different resting elevations across platforms, depending on the depth
Components may have different resting elevations across platforms, depending on the depth
of the environment (e.g., TV has a greater depth than mobile or desktop).
@ -273,16 +273,16 @@
Some component types have responsive elevation, meaning they change elevation in response
to user input (e.g., normal, focused, and pressed) or system events. These elevation
Some component types have responsive elevation, meaning they change elevation in response
to user input (e.g., normal, focused, and pressed) or system events. These elevation
changes are consistently implemented using dynamic elevation offsets.
Dynamic elevation offsets are the goal elevation that a component moves towards, relative
to the components resting state. They ensure that elevation changes are consistent
across actions and component types. For example, all components that lift on press have
Dynamic elevation offsets are the goal elevation that a component moves towards, relative
to the components resting state. They ensure that elevation changes are consistent
across actions and component types. For example, all components that lift on press have
the same elevation change relative to their resting elevation.
Once the input event is completed or cancelled, the component will return to its resting
Once the input event is completed or cancelled, the component will return to its resting
elevation.
@ -291,17 +291,17 @@
Components with responsive elevations may encounter other components as they move between
their resting elevations and dynamic elevation offsets. Because material cannot pass
through other material, components avoid interfering with one another any number of ways,
Components with responsive elevations may encounter other components as they move between
their resting elevations and dynamic elevation offsets. Because material cannot pass
through other material, components avoid interfering with one another any number of ways,
whether on a per component basis or using the entire app layout.
On a component level, components can move or be removed before they cause interference.
For example, a floating action button (FAB) can disappear or move off screen before a
On a component level, components can move or be removed before they cause interference.
For example, a floating action button (FAB) can disappear or move off screen before a
user picks up a card, or it can move if a snackbar appears.
On the layout level, design your app layout to minimize opportunities for interference.
For example, position the FAB to one side of stream of a cards so the FAB wont interfere
On the layout level, design your app layout to minimize opportunities for interference.
For example, position the FAB to one side of stream of a cards so the FAB wont interfere
when a user tries to pick up one of cards.

View File

@ -165,16 +165,16 @@
A material metaphor is the unifying theory of a rationalized space and a system of motion.
The material is grounded in tactile reality, inspired by the study of paper and ink, yet
The material is grounded in tactile reality, inspired by the study of paper and ink, yet
technologically advanced and open to imagination and magic.
Surfaces and edges of the material provide visual cues that are grounded in reality. The
use of familiar tactile attributes helps users quickly understand affordances. Yet the
flexibility of the material creates new affordances that supercede those in the physical
Surfaces and edges of the material provide visual cues that are grounded in reality. The
use of familiar tactile attributes helps users quickly understand affordances. Yet the
flexibility of the material creates new affordances that supercede those in the physical
world, without breaking the rules of physics.
The fundamentals of light, surface, and movement are key to conveying how objects move,
interact, and exist in space and in relation to each other. Realistic lighting shows
The fundamentals of light, surface, and movement are key to conveying how objects move,
interact, and exist in space and in relation to each other. Realistic lighting shows
seams, divides space, and indicates moving parts.
@ -183,13 +183,13 @@
The foundational elements of print based design typography, grids, space, scale, color,
and use of imagery guide visual treatments. These elements do far more than please the
eye. They create hierarchy, meaning, and focus. Deliberate color choices, edge to edge
imagery, large scale typography, and intentional white space create a bold and graphic
The foundational elements of print based design typography, grids, space, scale, color,
and use of imagery guide visual treatments. These elements do far more than please the
eye. They create hierarchy, meaning, and focus. Deliberate color choices, edge to edge
imagery, large scale typography, and intentional white space create a bold and graphic
interface that immerse the user in the experience.
An emphasis on user actions makes core functionality immediately apparent and provides
An emphasis on user actions makes core functionality immediately apparent and provides
waypoints for the user.
@ -198,13 +198,13 @@
Motion respects and reinforces the user as the prime mover. Primary user actions are
Motion respects and reinforces the user as the prime mover. Primary user actions are
inflection points that initiate motion, transforming the whole design.
All action takes place in a single environment. Objects are presented to the user without
All action takes place in a single environment. Objects are presented to the user without
breaking the continuity of experience even as they transform and reorganize.
Motion is meaningful and appropriate, serving to focus attention and maintain continuity.
Motion is meaningful and appropriate, serving to focus attention and maintain continuity.
Feedback is subtle yet clear. Transitions are efficient yet coherent.
@ -213,12 +213,12 @@
The material environment is a 3D space, which means all objects have x, y, and z
dimensions. The z-axis is perpendicularly aligned to the plane of the display, with the
positive z-axis extending towards the viewer. Every sheet of material occupies a single
The material environment is a 3D space, which means all objects have x, y, and z
dimensions. The z-axis is perpendicularly aligned to the plane of the display, with the
positive z-axis extending towards the viewer. Every sheet of material occupies a single
position along the z-axis and has a standard 1dp thickness.
On the web, the z-axis is used for layering and not for perspective. The 3D world is
On the web, the z-axis is used for layering and not for perspective. The 3D world is
emulated by manipulating the y-axis.
@ -227,12 +227,12 @@
Within the material environment, virtual lights illuminate the scene. Key lights create
Within the material environment, virtual lights illuminate the scene. Key lights create
directional shadows, while ambient light creates soft shadows from all angles.
Shadows in the material environment are cast by these two light sources. In Android
development, shadows occur when light sources are blocked by sheets of material at
various positions along the z-axis. On the web, shadows are depicted by manipulating the
Shadows in the material environment are cast by these two light sources. In Android
development, shadows occur when light sources are blocked by sheets of material at
various positions along the z-axis. On the web, shadows are depicted by manipulating the
y-axis only. The following example shows the card with a height of 6dp.
@ -241,8 +241,8 @@
All material objects, regardless of size, have a resting elevation, or default elevation
that does not change. If an object changes elevation, it should return to its resting
All material objects, regardless of size, have a resting elevation, or default elevation
that does not change. If an object changes elevation, it should return to its resting
elevation as soon as possible.
@ -251,10 +251,10 @@
The resting elevation for a component type is consistent across apps (e.g., FAB elevation
The resting elevation for a component type is consistent across apps (e.g., FAB elevation
does not vary from 6dp in one app to 16dp in another app).
Components may have different resting elevations across platforms, depending on the depth
Components may have different resting elevations across platforms, depending on the depth
of the environment (e.g., TV has a greater depth than mobile or desktop).
@ -263,16 +263,16 @@
Some component types have responsive elevation, meaning they change elevation in response
to user input (e.g., normal, focused, and pressed) or system events. These elevation
Some component types have responsive elevation, meaning they change elevation in response
to user input (e.g., normal, focused, and pressed) or system events. These elevation
changes are consistently implemented using dynamic elevation offsets.
Dynamic elevation offsets are the goal elevation that a component moves towards, relative
to the components resting state. They ensure that elevation changes are consistent
across actions and component types. For example, all components that lift on press have
Dynamic elevation offsets are the goal elevation that a component moves towards, relative
to the components resting state. They ensure that elevation changes are consistent
across actions and component types. For example, all components that lift on press have
the same elevation change relative to their resting elevation.
Once the input event is completed or cancelled, the component will return to its resting
Once the input event is completed or cancelled, the component will return to its resting
elevation.
@ -281,17 +281,17 @@
Components with responsive elevations may encounter other components as they move between
their resting elevations and dynamic elevation offsets. Because material cannot pass
through other material, components avoid interfering with one another any number of ways,
Components with responsive elevations may encounter other components as they move between
their resting elevations and dynamic elevation offsets. Because material cannot pass
through other material, components avoid interfering with one another any number of ways,
whether on a per component basis or using the entire app layout.
On a component level, components can move or be removed before they cause interference.
For example, a floating action button (FAB) can disappear or move off screen before a
On a component level, components can move or be removed before they cause interference.
For example, a floating action button (FAB) can disappear or move off screen before a
user picks up a card, or it can move if a snackbar appears.
On the layout level, design your app layout to minimize opportunities for interference.
For example, position the FAB to one side of stream of a cards so the FAB wont interfere
On the layout level, design your app layout to minimize opportunities for interference.
For example, position the FAB to one side of stream of a cards so the FAB wont interfere
when a user tries to pick up one of cards.

View File

@ -157,16 +157,16 @@
A material metaphor is the unifying theory of a rationalized space and a system of motion.
The material is grounded in tactile reality, inspired by the study of paper and ink, yet
The material is grounded in tactile reality, inspired by the study of paper and ink, yet
technologically advanced and open to imagination and magic.
Surfaces and edges of the material provide visual cues that are grounded in reality. The
use of familiar tactile attributes helps users quickly understand affordances. Yet the
flexibility of the material creates new affordances that supercede those in the physical
Surfaces and edges of the material provide visual cues that are grounded in reality. The
use of familiar tactile attributes helps users quickly understand affordances. Yet the
flexibility of the material creates new affordances that supercede those in the physical
world, without breaking the rules of physics.
The fundamentals of light, surface, and movement are key to conveying how objects move,
interact, and exist in space and in relation to each other. Realistic lighting shows
The fundamentals of light, surface, and movement are key to conveying how objects move,
interact, and exist in space and in relation to each other. Realistic lighting shows
seams, divides space, and indicates moving parts.
@ -175,13 +175,13 @@
The foundational elements of print based design typography, grids, space, scale, color,
and use of imagery guide visual treatments. These elements do far more than please the
eye. They create hierarchy, meaning, and focus. Deliberate color choices, edge to edge
imagery, large scale typography, and intentional white space create a bold and graphic
The foundational elements of print based design typography, grids, space, scale, color,
and use of imagery guide visual treatments. These elements do far more than please the
eye. They create hierarchy, meaning, and focus. Deliberate color choices, edge to edge
imagery, large scale typography, and intentional white space create a bold and graphic
interface that immerse the user in the experience.
An emphasis on user actions makes core functionality immediately apparent and provides
An emphasis on user actions makes core functionality immediately apparent and provides
waypoints for the user.
@ -190,13 +190,13 @@
Motion respects and reinforces the user as the prime mover. Primary user actions are
Motion respects and reinforces the user as the prime mover. Primary user actions are
inflection points that initiate motion, transforming the whole design.
All action takes place in a single environment. Objects are presented to the user without
All action takes place in a single environment. Objects are presented to the user without
breaking the continuity of experience even as they transform and reorganize.
Motion is meaningful and appropriate, serving to focus attention and maintain continuity.
Motion is meaningful and appropriate, serving to focus attention and maintain continuity.
Feedback is subtle yet clear. Transitions are efficient yet coherent.
@ -205,12 +205,12 @@
The material environment is a 3D space, which means all objects have x, y, and z
dimensions. The z-axis is perpendicularly aligned to the plane of the display, with the
positive z-axis extending towards the viewer. Every sheet of material occupies a single
The material environment is a 3D space, which means all objects have x, y, and z
dimensions. The z-axis is perpendicularly aligned to the plane of the display, with the
positive z-axis extending towards the viewer. Every sheet of material occupies a single
position along the z-axis and has a standard 1dp thickness.
On the web, the z-axis is used for layering and not for perspective. The 3D world is
On the web, the z-axis is used for layering and not for perspective. The 3D world is
emulated by manipulating the y-axis.
@ -219,12 +219,12 @@
Within the material environment, virtual lights illuminate the scene. Key lights create
Within the material environment, virtual lights illuminate the scene. Key lights create
directional shadows, while ambient light creates soft shadows from all angles.
Shadows in the material environment are cast by these two light sources. In Android
development, shadows occur when light sources are blocked by sheets of material at
various positions along the z-axis. On the web, shadows are depicted by manipulating the
Shadows in the material environment are cast by these two light sources. In Android
development, shadows occur when light sources are blocked by sheets of material at
various positions along the z-axis. On the web, shadows are depicted by manipulating the
y-axis only. The following example shows the card with a height of 6dp.
@ -233,8 +233,8 @@
All material objects, regardless of size, have a resting elevation, or default elevation
that does not change. If an object changes elevation, it should return to its resting
All material objects, regardless of size, have a resting elevation, or default elevation
that does not change. If an object changes elevation, it should return to its resting
elevation as soon as possible.
@ -243,10 +243,10 @@
The resting elevation for a component type is consistent across apps (e.g., FAB elevation
The resting elevation for a component type is consistent across apps (e.g., FAB elevation
does not vary from 6dp in one app to 16dp in another app).
Components may have different resting elevations across platforms, depending on the depth
Components may have different resting elevations across platforms, depending on the depth
of the environment (e.g., TV has a greater depth than mobile or desktop).
@ -255,16 +255,16 @@
Some component types have responsive elevation, meaning they change elevation in response
to user input (e.g., normal, focused, and pressed) or system events. These elevation
Some component types have responsive elevation, meaning they change elevation in response
to user input (e.g., normal, focused, and pressed) or system events. These elevation
changes are consistently implemented using dynamic elevation offsets.
Dynamic elevation offsets are the goal elevation that a component moves towards, relative
to the components resting state. They ensure that elevation changes are consistent
across actions and component types. For example, all components that lift on press have
Dynamic elevation offsets are the goal elevation that a component moves towards, relative
to the components resting state. They ensure that elevation changes are consistent
across actions and component types. For example, all components that lift on press have
the same elevation change relative to their resting elevation.
Once the input event is completed or cancelled, the component will return to its resting
Once the input event is completed or cancelled, the component will return to its resting
elevation.
@ -273,17 +273,17 @@
Components with responsive elevations may encounter other components as they move between
their resting elevations and dynamic elevation offsets. Because material cannot pass
through other material, components avoid interfering with one another any number of ways,
Components with responsive elevations may encounter other components as they move between
their resting elevations and dynamic elevation offsets. Because material cannot pass
through other material, components avoid interfering with one another any number of ways,
whether on a per component basis or using the entire app layout.
On a component level, components can move or be removed before they cause interference.
For example, a floating action button (FAB) can disappear or move off screen before a
On a component level, components can move or be removed before they cause interference.
For example, a floating action button (FAB) can disappear or move off screen before a
user picks up a card, or it can move if a snackbar appears.
On the layout level, design your app layout to minimize opportunities for interference.
For example, position the FAB to one side of stream of a cards so the FAB wont interfere
On the layout level, design your app layout to minimize opportunities for interference.
For example, position the FAB to one side of stream of a cards so the FAB wont interfere
when a user tries to pick up one of cards.

View File

@ -170,16 +170,16 @@
A material metaphor is the unifying theory of a rationalized space and a system of motion.
The material is grounded in tactile reality, inspired by the study of paper and ink, yet
The material is grounded in tactile reality, inspired by the study of paper and ink, yet
technologically advanced and open to imagination and magic.
Surfaces and edges of the material provide visual cues that are grounded in reality. The
use of familiar tactile attributes helps users quickly understand affordances. Yet the
flexibility of the material creates new affordances that supercede those in the physical
Surfaces and edges of the material provide visual cues that are grounded in reality. The
use of familiar tactile attributes helps users quickly understand affordances. Yet the
flexibility of the material creates new affordances that supercede those in the physical
world, without breaking the rules of physics.
The fundamentals of light, surface, and movement are key to conveying how objects move,
interact, and exist in space and in relation to each other. Realistic lighting shows
The fundamentals of light, surface, and movement are key to conveying how objects move,
interact, and exist in space and in relation to each other. Realistic lighting shows
seams, divides space, and indicates moving parts.
@ -188,13 +188,13 @@
The foundational elements of print based design typography, grids, space, scale, color,
and use of imagery guide visual treatments. These elements do far more than please the
eye. They create hierarchy, meaning, and focus. Deliberate color choices, edge to edge
imagery, large scale typography, and intentional white space create a bold and graphic
The foundational elements of print based design typography, grids, space, scale, color,
and use of imagery guide visual treatments. These elements do far more than please the
eye. They create hierarchy, meaning, and focus. Deliberate color choices, edge to edge
imagery, large scale typography, and intentional white space create a bold and graphic
interface that immerse the user in the experience.
An emphasis on user actions makes core functionality immediately apparent and provides
An emphasis on user actions makes core functionality immediately apparent and provides
waypoints for the user.
@ -203,13 +203,13 @@
Motion respects and reinforces the user as the prime mover. Primary user actions are
Motion respects and reinforces the user as the prime mover. Primary user actions are
inflection points that initiate motion, transforming the whole design.
All action takes place in a single environment. Objects are presented to the user without
All action takes place in a single environment. Objects are presented to the user without
breaking the continuity of experience even as they transform and reorganize.
Motion is meaningful and appropriate, serving to focus attention and maintain continuity.
Motion is meaningful and appropriate, serving to focus attention and maintain continuity.
Feedback is subtle yet clear. Transitions are efficient yet coherent.
@ -218,12 +218,12 @@
The material environment is a 3D space, which means all objects have x, y, and z
dimensions. The z-axis is perpendicularly aligned to the plane of the display, with the
positive z-axis extending towards the viewer. Every sheet of material occupies a single
The material environment is a 3D space, which means all objects have x, y, and z
dimensions. The z-axis is perpendicularly aligned to the plane of the display, with the
positive z-axis extending towards the viewer. Every sheet of material occupies a single
position along the z-axis and has a standard 1dp thickness.
On the web, the z-axis is used for layering and not for perspective. The 3D world is
On the web, the z-axis is used for layering and not for perspective. The 3D world is
emulated by manipulating the y-axis.
@ -232,12 +232,12 @@
Within the material environment, virtual lights illuminate the scene. Key lights create
Within the material environment, virtual lights illuminate the scene. Key lights create
directional shadows, while ambient light creates soft shadows from all angles.
Shadows in the material environment are cast by these two light sources. In Android
development, shadows occur when light sources are blocked by sheets of material at
various positions along the z-axis. On the web, shadows are depicted by manipulating the
Shadows in the material environment are cast by these two light sources. In Android
development, shadows occur when light sources are blocked by sheets of material at
various positions along the z-axis. On the web, shadows are depicted by manipulating the
y-axis only. The following example shows the card with a height of 6dp.
@ -246,8 +246,8 @@
All material objects, regardless of size, have a resting elevation, or default elevation
that does not change. If an object changes elevation, it should return to its resting
All material objects, regardless of size, have a resting elevation, or default elevation
that does not change. If an object changes elevation, it should return to its resting
elevation as soon as possible.
@ -256,10 +256,10 @@
The resting elevation for a component type is consistent across apps (e.g., FAB elevation
The resting elevation for a component type is consistent across apps (e.g., FAB elevation
does not vary from 6dp in one app to 16dp in another app).
Components may have different resting elevations across platforms, depending on the depth
Components may have different resting elevations across platforms, depending on the depth
of the environment (e.g., TV has a greater depth than mobile or desktop).
@ -268,16 +268,16 @@
Some component types have responsive elevation, meaning they change elevation in response
to user input (e.g., normal, focused, and pressed) or system events. These elevation
Some component types have responsive elevation, meaning they change elevation in response
to user input (e.g., normal, focused, and pressed) or system events. These elevation
changes are consistently implemented using dynamic elevation offsets.
Dynamic elevation offsets are the goal elevation that a component moves towards, relative
to the components resting state. They ensure that elevation changes are consistent
across actions and component types. For example, all components that lift on press have
Dynamic elevation offsets are the goal elevation that a component moves towards, relative
to the components resting state. They ensure that elevation changes are consistent
across actions and component types. For example, all components that lift on press have
the same elevation change relative to their resting elevation.
Once the input event is completed or cancelled, the component will return to its resting
Once the input event is completed or cancelled, the component will return to its resting
elevation.
@ -286,17 +286,17 @@
Components with responsive elevations may encounter other components as they move between
their resting elevations and dynamic elevation offsets. Because material cannot pass
through other material, components avoid interfering with one another any number of ways,
Components with responsive elevations may encounter other components as they move between
their resting elevations and dynamic elevation offsets. Because material cannot pass
through other material, components avoid interfering with one another any number of ways,
whether on a per component basis or using the entire app layout.
On a component level, components can move or be removed before they cause interference.
For example, a floating action button (FAB) can disappear or move off screen before a
On a component level, components can move or be removed before they cause interference.
For example, a floating action button (FAB) can disappear or move off screen before a
user picks up a card, or it can move if a snackbar appears.
On the layout level, design your app layout to minimize opportunities for interference.
For example, position the FAB to one side of stream of a cards so the FAB wont interfere
On the layout level, design your app layout to minimize opportunities for interference.
For example, position the FAB to one side of stream of a cards so the FAB wont interfere
when a user tries to pick up one of cards.

View File

@ -168,16 +168,16 @@
A material metaphor is the unifying theory of a rationalized space and a system of motion.
The material is grounded in tactile reality, inspired by the study of paper and ink, yet
The material is grounded in tactile reality, inspired by the study of paper and ink, yet
technologically advanced and open to imagination and magic.
Surfaces and edges of the material provide visual cues that are grounded in reality. The
use of familiar tactile attributes helps users quickly understand affordances. Yet the
flexibility of the material creates new affordances that supercede those in the physical
Surfaces and edges of the material provide visual cues that are grounded in reality. The
use of familiar tactile attributes helps users quickly understand affordances. Yet the
flexibility of the material creates new affordances that supercede those in the physical
world, without breaking the rules of physics.
The fundamentals of light, surface, and movement are key to conveying how objects move,
interact, and exist in space and in relation to each other. Realistic lighting shows
The fundamentals of light, surface, and movement are key to conveying how objects move,
interact, and exist in space and in relation to each other. Realistic lighting shows
seams, divides space, and indicates moving parts.
@ -186,13 +186,13 @@
The foundational elements of print based design typography, grids, space, scale, color,
and use of imagery guide visual treatments. These elements do far more than please the
eye. They create hierarchy, meaning, and focus. Deliberate color choices, edge to edge
imagery, large scale typography, and intentional white space create a bold and graphic
The foundational elements of print based design typography, grids, space, scale, color,
and use of imagery guide visual treatments. These elements do far more than please the
eye. They create hierarchy, meaning, and focus. Deliberate color choices, edge to edge
imagery, large scale typography, and intentional white space create a bold and graphic
interface that immerse the user in the experience.
An emphasis on user actions makes core functionality immediately apparent and provides
An emphasis on user actions makes core functionality immediately apparent and provides
waypoints for the user.
@ -201,13 +201,13 @@
Motion respects and reinforces the user as the prime mover. Primary user actions are
Motion respects and reinforces the user as the prime mover. Primary user actions are
inflection points that initiate motion, transforming the whole design.
All action takes place in a single environment. Objects are presented to the user without
All action takes place in a single environment. Objects are presented to the user without
breaking the continuity of experience even as they transform and reorganize.
Motion is meaningful and appropriate, serving to focus attention and maintain continuity.
Motion is meaningful and appropriate, serving to focus attention and maintain continuity.
Feedback is subtle yet clear. Transitions are efficient yet coherent.
@ -216,12 +216,12 @@
The material environment is a 3D space, which means all objects have x, y, and z
dimensions. The z-axis is perpendicularly aligned to the plane of the display, with the
positive z-axis extending towards the viewer. Every sheet of material occupies a single
The material environment is a 3D space, which means all objects have x, y, and z
dimensions. The z-axis is perpendicularly aligned to the plane of the display, with the
positive z-axis extending towards the viewer. Every sheet of material occupies a single
position along the z-axis and has a standard 1dp thickness.
On the web, the z-axis is used for layering and not for perspective. The 3D world is
On the web, the z-axis is used for layering and not for perspective. The 3D world is
emulated by manipulating the y-axis.
@ -230,12 +230,12 @@
Within the material environment, virtual lights illuminate the scene. Key lights create
Within the material environment, virtual lights illuminate the scene. Key lights create
directional shadows, while ambient light creates soft shadows from all angles.
Shadows in the material environment are cast by these two light sources. In Android
development, shadows occur when light sources are blocked by sheets of material at
various positions along the z-axis. On the web, shadows are depicted by manipulating the
Shadows in the material environment are cast by these two light sources. In Android
development, shadows occur when light sources are blocked by sheets of material at
various positions along the z-axis. On the web, shadows are depicted by manipulating the
y-axis only. The following example shows the card with a height of 6dp.
@ -244,8 +244,8 @@
All material objects, regardless of size, have a resting elevation, or default elevation
that does not change. If an object changes elevation, it should return to its resting
All material objects, regardless of size, have a resting elevation, or default elevation
that does not change. If an object changes elevation, it should return to its resting
elevation as soon as possible.
@ -254,10 +254,10 @@
The resting elevation for a component type is consistent across apps (e.g., FAB elevation
The resting elevation for a component type is consistent across apps (e.g., FAB elevation
does not vary from 6dp in one app to 16dp in another app).
Components may have different resting elevations across platforms, depending on the depth
Components may have different resting elevations across platforms, depending on the depth
of the environment (e.g., TV has a greater depth than mobile or desktop).
@ -266,16 +266,16 @@
Some component types have responsive elevation, meaning they change elevation in response
to user input (e.g., normal, focused, and pressed) or system events. These elevation
Some component types have responsive elevation, meaning they change elevation in response
to user input (e.g., normal, focused, and pressed) or system events. These elevation
changes are consistently implemented using dynamic elevation offsets.
Dynamic elevation offsets are the goal elevation that a component moves towards, relative
to the components resting state. They ensure that elevation changes are consistent
across actions and component types. For example, all components that lift on press have
Dynamic elevation offsets are the goal elevation that a component moves towards, relative
to the components resting state. They ensure that elevation changes are consistent
across actions and component types. For example, all components that lift on press have
the same elevation change relative to their resting elevation.
Once the input event is completed or cancelled, the component will return to its resting
Once the input event is completed or cancelled, the component will return to its resting
elevation.
@ -284,17 +284,17 @@
Components with responsive elevations may encounter other components as they move between
their resting elevations and dynamic elevation offsets. Because material cannot pass
through other material, components avoid interfering with one another any number of ways,
Components with responsive elevations may encounter other components as they move between
their resting elevations and dynamic elevation offsets. Because material cannot pass
through other material, components avoid interfering with one another any number of ways,
whether on a per component basis or using the entire app layout.
On a component level, components can move or be removed before they cause interference.
For example, a floating action button (FAB) can disappear or move off screen before a
On a component level, components can move or be removed before they cause interference.
For example, a floating action button (FAB) can disappear or move off screen before a
user picks up a card, or it can move if a snackbar appears.
On the layout level, design your app layout to minimize opportunities for interference.
For example, position the FAB to one side of stream of a cards so the FAB wont interfere
On the layout level, design your app layout to minimize opportunities for interference.
For example, position the FAB to one side of stream of a cards so the FAB wont interfere
when a user tries to pick up one of cards.

View File

@ -163,16 +163,16 @@
A material metaphor is the unifying theory of a rationalized space and a system of motion.
The material is grounded in tactile reality, inspired by the study of paper and ink, yet
The material is grounded in tactile reality, inspired by the study of paper and ink, yet
technologically advanced and open to imagination and magic.
Surfaces and edges of the material provide visual cues that are grounded in reality. The
use of familiar tactile attributes helps users quickly understand affordances. Yet the
flexibility of the material creates new affordances that supercede those in the physical
Surfaces and edges of the material provide visual cues that are grounded in reality. The
use of familiar tactile attributes helps users quickly understand affordances. Yet the
flexibility of the material creates new affordances that supercede those in the physical
world, without breaking the rules of physics.
The fundamentals of light, surface, and movement are key to conveying how objects move,
interact, and exist in space and in relation to each other. Realistic lighting shows
The fundamentals of light, surface, and movement are key to conveying how objects move,
interact, and exist in space and in relation to each other. Realistic lighting shows
seams, divides space, and indicates moving parts.
@ -181,13 +181,13 @@
The foundational elements of print based design typography, grids, space, scale, color,
and use of imagery guide visual treatments. These elements do far more than please the
eye. They create hierarchy, meaning, and focus. Deliberate color choices, edge to edge
imagery, large scale typography, and intentional white space create a bold and graphic
The foundational elements of print based design typography, grids, space, scale, color,
and use of imagery guide visual treatments. These elements do far more than please the
eye. They create hierarchy, meaning, and focus. Deliberate color choices, edge to edge
imagery, large scale typography, and intentional white space create a bold and graphic
interface that immerse the user in the experience.
An emphasis on user actions makes core functionality immediately apparent and provides
An emphasis on user actions makes core functionality immediately apparent and provides
waypoints for the user.
@ -196,13 +196,13 @@
Motion respects and reinforces the user as the prime mover. Primary user actions are
Motion respects and reinforces the user as the prime mover. Primary user actions are
inflection points that initiate motion, transforming the whole design.
All action takes place in a single environment. Objects are presented to the user without
All action takes place in a single environment. Objects are presented to the user without
breaking the continuity of experience even as they transform and reorganize.
Motion is meaningful and appropriate, serving to focus attention and maintain continuity.
Motion is meaningful and appropriate, serving to focus attention and maintain continuity.
Feedback is subtle yet clear. Transitions are efficient yet coherent.
@ -211,12 +211,12 @@
The material environment is a 3D space, which means all objects have x, y, and z
dimensions. The z-axis is perpendicularly aligned to the plane of the display, with the
positive z-axis extending towards the viewer. Every sheet of material occupies a single
The material environment is a 3D space, which means all objects have x, y, and z
dimensions. The z-axis is perpendicularly aligned to the plane of the display, with the
positive z-axis extending towards the viewer. Every sheet of material occupies a single
position along the z-axis and has a standard 1dp thickness.
On the web, the z-axis is used for layering and not for perspective. The 3D world is
On the web, the z-axis is used for layering and not for perspective. The 3D world is
emulated by manipulating the y-axis.
@ -225,12 +225,12 @@
Within the material environment, virtual lights illuminate the scene. Key lights create
Within the material environment, virtual lights illuminate the scene. Key lights create
directional shadows, while ambient light creates soft shadows from all angles.
Shadows in the material environment are cast by these two light sources. In Android
development, shadows occur when light sources are blocked by sheets of material at
various positions along the z-axis. On the web, shadows are depicted by manipulating the
Shadows in the material environment are cast by these two light sources. In Android
development, shadows occur when light sources are blocked by sheets of material at
various positions along the z-axis. On the web, shadows are depicted by manipulating the
y-axis only. The following example shows the card with a height of 6dp.
@ -239,8 +239,8 @@
All material objects, regardless of size, have a resting elevation, or default elevation
that does not change. If an object changes elevation, it should return to its resting
All material objects, regardless of size, have a resting elevation, or default elevation
that does not change. If an object changes elevation, it should return to its resting
elevation as soon as possible.
@ -249,10 +249,10 @@
The resting elevation for a component type is consistent across apps (e.g., FAB elevation
The resting elevation for a component type is consistent across apps (e.g., FAB elevation
does not vary from 6dp in one app to 16dp in another app).
Components may have different resting elevations across platforms, depending on the depth
Components may have different resting elevations across platforms, depending on the depth
of the environment (e.g., TV has a greater depth than mobile or desktop).
@ -261,16 +261,16 @@
Some component types have responsive elevation, meaning they change elevation in response
to user input (e.g., normal, focused, and pressed) or system events. These elevation
Some component types have responsive elevation, meaning they change elevation in response
to user input (e.g., normal, focused, and pressed) or system events. These elevation
changes are consistently implemented using dynamic elevation offsets.
Dynamic elevation offsets are the goal elevation that a component moves towards, relative
to the components resting state. They ensure that elevation changes are consistent
across actions and component types. For example, all components that lift on press have
Dynamic elevation offsets are the goal elevation that a component moves towards, relative
to the components resting state. They ensure that elevation changes are consistent
across actions and component types. For example, all components that lift on press have
the same elevation change relative to their resting elevation.
Once the input event is completed or cancelled, the component will return to its resting
Once the input event is completed or cancelled, the component will return to its resting
elevation.
@ -279,17 +279,17 @@
Components with responsive elevations may encounter other components as they move between
their resting elevations and dynamic elevation offsets. Because material cannot pass
through other material, components avoid interfering with one another any number of ways,
Components with responsive elevations may encounter other components as they move between
their resting elevations and dynamic elevation offsets. Because material cannot pass
through other material, components avoid interfering with one another any number of ways,
whether on a per component basis or using the entire app layout.
On a component level, components can move or be removed before they cause interference.
For example, a floating action button (FAB) can disappear or move off screen before a
On a component level, components can move or be removed before they cause interference.
For example, a floating action button (FAB) can disappear or move off screen before a
user picks up a card, or it can move if a snackbar appears.
On the layout level, design your app layout to minimize opportunities for interference.
For example, position the FAB to one side of stream of a cards so the FAB wont interfere
On the layout level, design your app layout to minimize opportunities for interference.
For example, position the FAB to one side of stream of a cards so the FAB wont interfere
when a user tries to pick up one of cards.

View File

@ -164,16 +164,16 @@
A material metaphor is the unifying theory of a rationalized space and a system of motion.
The material is grounded in tactile reality, inspired by the study of paper and ink, yet
The material is grounded in tactile reality, inspired by the study of paper and ink, yet
technologically advanced and open to imagination and magic.
Surfaces and edges of the material provide visual cues that are grounded in reality. The
use of familiar tactile attributes helps users quickly understand affordances. Yet the
flexibility of the material creates new affordances that supercede those in the physical
Surfaces and edges of the material provide visual cues that are grounded in reality. The
use of familiar tactile attributes helps users quickly understand affordances. Yet the
flexibility of the material creates new affordances that supercede those in the physical
world, without breaking the rules of physics.
The fundamentals of light, surface, and movement are key to conveying how objects move,
interact, and exist in space and in relation to each other. Realistic lighting shows
The fundamentals of light, surface, and movement are key to conveying how objects move,
interact, and exist in space and in relation to each other. Realistic lighting shows
seams, divides space, and indicates moving parts.
@ -182,13 +182,13 @@
The foundational elements of print based design typography, grids, space, scale, color,
and use of imagery guide visual treatments. These elements do far more than please the
eye. They create hierarchy, meaning, and focus. Deliberate color choices, edge to edge
imagery, large scale typography, and intentional white space create a bold and graphic
The foundational elements of print based design typography, grids, space, scale, color,
and use of imagery guide visual treatments. These elements do far more than please the
eye. They create hierarchy, meaning, and focus. Deliberate color choices, edge to edge
imagery, large scale typography, and intentional white space create a bold and graphic
interface that immerse the user in the experience.
An emphasis on user actions makes core functionality immediately apparent and provides
An emphasis on user actions makes core functionality immediately apparent and provides
waypoints for the user.
@ -197,13 +197,13 @@
Motion respects and reinforces the user as the prime mover. Primary user actions are
Motion respects and reinforces the user as the prime mover. Primary user actions are
inflection points that initiate motion, transforming the whole design.
All action takes place in a single environment. Objects are presented to the user without
All action takes place in a single environment. Objects are presented to the user without
breaking the continuity of experience even as they transform and reorganize.
Motion is meaningful and appropriate, serving to focus attention and maintain continuity.
Motion is meaningful and appropriate, serving to focus attention and maintain continuity.
Feedback is subtle yet clear. Transitions are efficient yet coherent.
@ -212,12 +212,12 @@
The material environment is a 3D space, which means all objects have x, y, and z
dimensions. The z-axis is perpendicularly aligned to the plane of the display, with the
positive z-axis extending towards the viewer. Every sheet of material occupies a single
The material environment is a 3D space, which means all objects have x, y, and z
dimensions. The z-axis is perpendicularly aligned to the plane of the display, with the
positive z-axis extending towards the viewer. Every sheet of material occupies a single
position along the z-axis and has a standard 1dp thickness.
On the web, the z-axis is used for layering and not for perspective. The 3D world is
On the web, the z-axis is used for layering and not for perspective. The 3D world is
emulated by manipulating the y-axis.
@ -226,12 +226,12 @@
Within the material environment, virtual lights illuminate the scene. Key lights create
Within the material environment, virtual lights illuminate the scene. Key lights create
directional shadows, while ambient light creates soft shadows from all angles.
Shadows in the material environment are cast by these two light sources. In Android
development, shadows occur when light sources are blocked by sheets of material at
various positions along the z-axis. On the web, shadows are depicted by manipulating the
Shadows in the material environment are cast by these two light sources. In Android
development, shadows occur when light sources are blocked by sheets of material at
various positions along the z-axis. On the web, shadows are depicted by manipulating the
y-axis only. The following example shows the card with a height of 6dp.
@ -240,8 +240,8 @@
All material objects, regardless of size, have a resting elevation, or default elevation
that does not change. If an object changes elevation, it should return to its resting
All material objects, regardless of size, have a resting elevation, or default elevation
that does not change. If an object changes elevation, it should return to its resting
elevation as soon as possible.
@ -250,10 +250,10 @@
The resting elevation for a component type is consistent across apps (e.g., FAB elevation
The resting elevation for a component type is consistent across apps (e.g., FAB elevation
does not vary from 6dp in one app to 16dp in another app).
Components may have different resting elevations across platforms, depending on the depth
Components may have different resting elevations across platforms, depending on the depth
of the environment (e.g., TV has a greater depth than mobile or desktop).
@ -262,16 +262,16 @@
Some component types have responsive elevation, meaning they change elevation in response
to user input (e.g., normal, focused, and pressed) or system events. These elevation
Some component types have responsive elevation, meaning they change elevation in response
to user input (e.g., normal, focused, and pressed) or system events. These elevation
changes are consistently implemented using dynamic elevation offsets.
Dynamic elevation offsets are the goal elevation that a component moves towards, relative
to the components resting state. They ensure that elevation changes are consistent
across actions and component types. For example, all components that lift on press have
Dynamic elevation offsets are the goal elevation that a component moves towards, relative
to the components resting state. They ensure that elevation changes are consistent
across actions and component types. For example, all components that lift on press have
the same elevation change relative to their resting elevation.
Once the input event is completed or cancelled, the component will return to its resting
Once the input event is completed or cancelled, the component will return to its resting
elevation.
@ -280,17 +280,17 @@
Components with responsive elevations may encounter other components as they move between
their resting elevations and dynamic elevation offsets. Because material cannot pass
through other material, components avoid interfering with one another any number of ways,
Components with responsive elevations may encounter other components as they move between
their resting elevations and dynamic elevation offsets. Because material cannot pass
through other material, components avoid interfering with one another any number of ways,
whether on a per component basis or using the entire app layout.
On a component level, components can move or be removed before they cause interference.
For example, a floating action button (FAB) can disappear or move off screen before a
On a component level, components can move or be removed before they cause interference.
For example, a floating action button (FAB) can disappear or move off screen before a
user picks up a card, or it can move if a snackbar appears.
On the layout level, design your app layout to minimize opportunities for interference.
For example, position the FAB to one side of stream of a cards so the FAB wont interfere
On the layout level, design your app layout to minimize opportunities for interference.
For example, position the FAB to one side of stream of a cards so the FAB wont interfere
when a user tries to pick up one of cards.

View File

@ -161,16 +161,16 @@
Materiál metafora je zjednocujúci teórie racionálne priestoru a systém pohybu.
Materiál je zakotvená v taktilné skutočnosti, inšpirované štúdiom papiera a atramentu, ale napriek tomu
Materiál je zakotvená v taktilné skutočnosti, inšpirované štúdiom papiera a atramentu, ale napriek tomu
technologicky pokročilé a otvorené fantáziu a mágiu.
Povrchy a hrany materiálu poskytujú vizuálnu pokyny, ktoré sú zakotvené v realite.
Použitie známych hmatových vlastností, pomáha používateľom rýchlo pochopiť affordances. napriek tomu
Pružnosť materiálu vytvára nové affordances že nadradené tie fyzické
Povrchy a hrany materiálu poskytujú vizuálnu pokyny, ktoré sú zakotvené v realite.
Použitie známych hmatových vlastností, pomáha používateľom rýchlo pochopiť affordances. napriek tomu
Pružnosť materiálu vytvára nové affordances že nadradené tie fyzické
svet bez toho, aby porušenie pravidiel fyziky.
Základy svetla, povrchu a pohyb sú kľúčom k dopravovanie, ako sa objekty pohybovať,
komunikovať, a existujú v priestore a vo vzťahu k sebe navzájom. Realistické svetelné šou
Základy svetla, povrchu a pohyb sú kľúčom k dopravovanie, ako sa objekty pohybovať,
komunikovať, a existujú v priestore a vo vzťahu k sebe navzájom. Realistické svetelné šou
švy, rozdeľuje priestor, a indikuje pohyblivých častí.
@ -179,13 +179,13 @@
Foundational prvky tlače na dizajn typografie, rošty, priestor, mierka, farby,
a používanie metafor riadiť vizuálne procedúry. Tieto prvky robiť oveľa viac, než potešiť
oko. Vytvárajú hierarchie, zmysel a zameranie. výber farieb úmyselné, od okraja k okraju
snímok, rozsiahle typografie a úmyselné biely priestor vytvoriť tučný a grafický
Foundational prvky tlače na dizajn typografie, rošty, priestor, mierka, farby,
a používanie metafor riadiť vizuálne procedúry. Tieto prvky robiť oveľa viac, než potešiť
oko. Vytvárajú hierarchie, zmysel a zameranie. výber farieb úmyselné, od okraja k okraju
snímok, rozsiahle typografie a úmyselné biely priestor vytvoriť tučný a grafický
rozhranie, ktoré ponorí užívateľov v zážitku.
Dôraz na užívateľských akcií činí základné funkcie okamžite zrejmé a poskytuje
Dôraz na užívateľských akcií činí základné funkcie okamžite zrejmé a poskytuje
waypointy pre užívateľov.
@ -194,13 +194,13 @@
Návrh rešpektuje a posilňuje užívateľa ako hnacia sila. Primárne akcie užívateľa sú
Návrh rešpektuje a posilňuje užívateľa ako hnacia sila. Primárne akcie užívateľa sú
inflexné body, ktoré iniciujú pohyb, transformáciu celej konštrukcie.
Celá akcia prebieha v jedinom prostredí. Objekty sú prezentované užívateľovi bez toho,
Celá akcia prebieha v jedinom prostredí. Objekty sú prezentované užívateľovi bez toho,
prelomenie kontinuity skúseností, aj keď ich transformáciu a reorganizáciu.
Pohyb je zmysluplné a vhodné, slúžiace sústrediť pozornosť a zachovanie kontinuity.
Pohyb je zmysluplné a vhodné, slúžiace sústrediť pozornosť a zachovanie kontinuity.
Spätná väzba je jemné, ale napriek tomu jasné. Prechody sú ef fi točné ešte koherentné.
@ -209,12 +209,12 @@
Materiál prostredie je 3D priestore, čo znamená, že všetky objekty majú X, Y, a Z
rozmery. Os je kolmo zarovnaný k rovine zobrazenie, s
kladná os rozširuje smerom k divákovi. Každý list materiálu, umiestnené v jednom
Materiál prostredie je 3D priestore, čo znamená, že všetky objekty majú X, Y, a Z
rozmery. Os je kolmo zarovnaný k rovine zobrazenie, s
kladná os rozširuje smerom k divákovi. Každý list materiálu, umiestnené v jednom
poloha pozdĺž osi a má štandardnú hrúbku 1DP.
Na webe, os sa používa pre vrstvenie a nie pre perspektívy. 3D svet
Na webe, os sa používa pre vrstvenie a nie pre perspektívy. 3D svet
emuloval tým, že manipuluje os y.
@ -223,12 +223,12 @@
V hmotnom prostredí, virtuálne svetlá osvetľujú scénu. Kľúčové svetla vytvárajú
V hmotnom prostredí, virtuálne svetlá osvetľujú scénu. Kľúčové svetla vytvárajú
smerové tiene, zatiaľ čo okolité svetlo vytvára mäkké tiene zo všetkých strán.
Tiene v hmotnom prostredí sú obsadené týmito dvoma svetelnými zdrojmi. v Android
vývoj, dochádza tiene, keď sú svetelné zdroje blokované plechového materiálu, na
Rôzne pozície pozdĺž osi. Na webe tiene sú znázornené manipuláciou
Tiene v hmotnom prostredí sú obsadené týmito dvoma svetelnými zdrojmi. v Android
vývoj, dochádza tiene, keď sú svetelné zdroje blokované plechového materiálu, na
Rôzne pozície pozdĺž osi. Na webe tiene sú znázornené manipuláciou
Iba os y. Nasledujúci príklad ukazuje kartu s výškou 6dp.
@ -237,8 +237,8 @@
Všetky významné objekty, bez ohľadu na ich veľkosť, majú výšku odpočíva, alebo predvolené výšku
to nič nemení. V prípade, že objekt sa mení výšku, mal by sa vrátiť do svojej pokojovej
Všetky významné objekty, bez ohľadu na ich veľkosť, majú výšku odpočíva, alebo predvolené výšku
to nič nemení. V prípade, že objekt sa mení výšku, mal by sa vrátiť do svojej pokojovej
nadmorskej výšky čo najskôr.
@ -247,10 +247,10 @@
Pokojová nadmorská výška pre typ komponentu je konzistentné naprieč aplikáciami (napr FAB elevácie
Pokojová nadmorská výška pre typ komponentu je konzistentné naprieč aplikáciami (napr FAB elevácie
nelíši od 6dp v jednej aplikácii na 16dp v inej aplikácii).
Zložky môžu mať rôzne pokojovej výšky medzi platformami, v závislosti od hĺbky
Zložky môžu mať rôzne pokojovej výšky medzi platformami, v závislosti od hĺbky
životného prostredia (napr televízor má väčšiu hĺbku, ako mobilný telefón alebo plochy).
@ -259,16 +259,16 @@
Niektoré typy komponentov majú citlivejší výšku, čo znamená, že meniť výšku v odozve
na vstup používateľa (napríklad normálny priebeh, sa zameral, a lisované), alebo systémové udalosti. tieto elevácie
Niektoré typy komponentov majú citlivejší výšku, čo znamená, že meniť výšku v odozve
na vstup používateľa (napríklad normálny priebeh, sa zameral, a lisované), alebo systémové udalosti. tieto elevácie
Zmeny sa vykonávali dôsledne používať dynamické výškové posuny.
Dynamické výškové posuny sú cieľom nadmorská výška, ktorá zložka sa pohybuje smerom, relatívna
do pokojového stavu súčasti. Zaisťujú, že zmeny elevácie sú v súlade
naprieč akcií a typov komponentov. Napríklad všetky súčasti, ktoré vlek na lise majú
Dynamické výškové posuny sú cieľom nadmorská výška, ktorá zložka sa pohybuje smerom, relatívna
do pokojového stavu súčasti. Zaisťujú, že zmeny elevácie sú v súlade
naprieč akcií a typov komponentov. Napríklad všetky súčasti, ktoré vlek na lise majú
rovnaká zmena prevýšenie vo vzťahu k ich prevýšenie odpočinku.
Akonáhle je vstupná udalosť dokončenie alebo zrušená, bude zložka vráti do svojej pokojovej
Akonáhle je vstupná udalosť dokončenie alebo zrušená, bude zložka vráti do svojej pokojovej
nadmorská výška.
@ -277,17 +277,17 @@
Zložky s citlivými nadmorských výškach môže stretnúť s ďalšími komponentmi, ako sa pohybovať medzi
ich odpočinku vyvýšeniny a dynamické výškové odsadenie. Vzhľadom k tomu, materiál nemôže prejsť
prostredníctvom iného materiálu, komponenty nenarušovať spolu navzájom nejakom množstvo ciest,
Zložky s citlivými nadmorských výškach môže stretnúť s ďalšími komponentmi, ako sa pohybovať medzi
ich odpočinku vyvýšeniny a dynamické výškové odsadenie. Vzhľadom k tomu, materiál nemôže prejsť
prostredníctvom iného materiálu, komponenty nenarušovať spolu navzájom nejakom množstvo ciest,
či už na úrovni jednotlivých komponentov alebo s použitím kompletné rozloženie aplikácie.
Na úrovni komponentov môžu zložky presunúť alebo odstrániť skôr, než spôsobia rušenie.
Napríklad tlačidlo plávajúce akcie (FAB) môžu zmiznúť alebo presunúť mimo obrazovku pred
Na úrovni komponentov môžu zložky presunúť alebo odstrániť skôr, než spôsobia rušenie.
Napríklad tlačidlo plávajúce akcie (FAB) môžu zmiznúť alebo presunúť mimo obrazovku pred
Užívateľ zdvihne kartu, alebo sa môže pohybovať, ak sa objaví snackbar.
Na úrovni Usporiadanie, riešenie rozvrhnutie aplikácie, aby sa minimalizovalo príležitostí k rušeniu.
Napríklad, umiestnenie FAB na jednej strane prúdu niekoľkých kariet, takže FAB nebude zasahovať
Na úrovni Usporiadanie, riešenie rozvrhnutie aplikácie, aby sa minimalizovalo príležitostí k rušeniu.
Napríklad, umiestnenie FAB na jednej strane prúdu niekoľkých kariet, takže FAB nebude zasahovať
ak sa užívateľ pokúsi vyzdvihnúť jednu z kariet.

View File

@ -170,16 +170,16 @@
A material metaphor is the unifying theory of a rationalized space and a system of motion.
The material is grounded in tactile reality, inspired by the study of paper and ink, yet
The material is grounded in tactile reality, inspired by the study of paper and ink, yet
technologically advanced and open to imagination and magic.
Surfaces and edges of the material provide visual cues that are grounded in reality. The
use of familiar tactile attributes helps users quickly understand affordances. Yet the
flexibility of the material creates new affordances that supercede those in the physical
Surfaces and edges of the material provide visual cues that are grounded in reality. The
use of familiar tactile attributes helps users quickly understand affordances. Yet the
flexibility of the material creates new affordances that supercede those in the physical
world, without breaking the rules of physics.
The fundamentals of light, surface, and movement are key to conveying how objects move,
interact, and exist in space and in relation to each other. Realistic lighting shows
The fundamentals of light, surface, and movement are key to conveying how objects move,
interact, and exist in space and in relation to each other. Realistic lighting shows
seams, divides space, and indicates moving parts.
@ -188,13 +188,13 @@
The foundational elements of print based design typography, grids, space, scale, color,
and use of imagery guide visual treatments. These elements do far more than please the
eye. They create hierarchy, meaning, and focus. Deliberate color choices, edge to edge
imagery, large scale typography, and intentional white space create a bold and graphic
The foundational elements of print based design typography, grids, space, scale, color,
and use of imagery guide visual treatments. These elements do far more than please the
eye. They create hierarchy, meaning, and focus. Deliberate color choices, edge to edge
imagery, large scale typography, and intentional white space create a bold and graphic
interface that immerse the user in the experience.
An emphasis on user actions makes core functionality immediately apparent and provides
An emphasis on user actions makes core functionality immediately apparent and provides
waypoints for the user.
@ -203,13 +203,13 @@
Motion respects and reinforces the user as the prime mover. Primary user actions are
Motion respects and reinforces the user as the prime mover. Primary user actions are
inflection points that initiate motion, transforming the whole design.
All action takes place in a single environment. Objects are presented to the user without
All action takes place in a single environment. Objects are presented to the user without
breaking the continuity of experience even as they transform and reorganize.
Motion is meaningful and appropriate, serving to focus attention and maintain continuity.
Motion is meaningful and appropriate, serving to focus attention and maintain continuity.
Feedback is subtle yet clear. Transitions are efficient yet coherent.
@ -218,12 +218,12 @@
The material environment is a 3D space, which means all objects have x, y, and z
dimensions. The z-axis is perpendicularly aligned to the plane of the display, with the
positive z-axis extending towards the viewer. Every sheet of material occupies a single
The material environment is a 3D space, which means all objects have x, y, and z
dimensions. The z-axis is perpendicularly aligned to the plane of the display, with the
positive z-axis extending towards the viewer. Every sheet of material occupies a single
position along the z-axis and has a standard 1dp thickness.
On the web, the z-axis is used for layering and not for perspective. The 3D world is
On the web, the z-axis is used for layering and not for perspective. The 3D world is
emulated by manipulating the y-axis.
@ -232,12 +232,12 @@
Within the material environment, virtual lights illuminate the scene. Key lights create
Within the material environment, virtual lights illuminate the scene. Key lights create
directional shadows, while ambient light creates soft shadows from all angles.
Shadows in the material environment are cast by these two light sources. In Android
development, shadows occur when light sources are blocked by sheets of material at
various positions along the z-axis. On the web, shadows are depicted by manipulating the
Shadows in the material environment are cast by these two light sources. In Android
development, shadows occur when light sources are blocked by sheets of material at
various positions along the z-axis. On the web, shadows are depicted by manipulating the
y-axis only. The following example shows the card with a height of 6dp.
@ -246,8 +246,8 @@
All material objects, regardless of size, have a resting elevation, or default elevation
that does not change. If an object changes elevation, it should return to its resting
All material objects, regardless of size, have a resting elevation, or default elevation
that does not change. If an object changes elevation, it should return to its resting
elevation as soon as possible.
@ -256,10 +256,10 @@
The resting elevation for a component type is consistent across apps (e.g., FAB elevation
The resting elevation for a component type is consistent across apps (e.g., FAB elevation
does not vary from 6dp in one app to 16dp in another app).
Components may have different resting elevations across platforms, depending on the depth
Components may have different resting elevations across platforms, depending on the depth
of the environment (e.g., TV has a greater depth than mobile or desktop).
@ -268,16 +268,16 @@
Some component types have responsive elevation, meaning they change elevation in response
to user input (e.g., normal, focused, and pressed) or system events. These elevation
Some component types have responsive elevation, meaning they change elevation in response
to user input (e.g., normal, focused, and pressed) or system events. These elevation
changes are consistently implemented using dynamic elevation offsets.
Dynamic elevation offsets are the goal elevation that a component moves towards, relative
to the components resting state. They ensure that elevation changes are consistent
across actions and component types. For example, all components that lift on press have
Dynamic elevation offsets are the goal elevation that a component moves towards, relative
to the components resting state. They ensure that elevation changes are consistent
across actions and component types. For example, all components that lift on press have
the same elevation change relative to their resting elevation.
Once the input event is completed or cancelled, the component will return to its resting
Once the input event is completed or cancelled, the component will return to its resting
elevation.
@ -286,17 +286,17 @@
Components with responsive elevations may encounter other components as they move between
their resting elevations and dynamic elevation offsets. Because material cannot pass
through other material, components avoid interfering with one another any number of ways,
Components with responsive elevations may encounter other components as they move between
their resting elevations and dynamic elevation offsets. Because material cannot pass
through other material, components avoid interfering with one another any number of ways,
whether on a per component basis or using the entire app layout.
On a component level, components can move or be removed before they cause interference.
For example, a floating action button (FAB) can disappear or move off screen before a
On a component level, components can move or be removed before they cause interference.
For example, a floating action button (FAB) can disappear or move off screen before a
user picks up a card, or it can move if a snackbar appears.
On the layout level, design your app layout to minimize opportunities for interference.
For example, position the FAB to one side of stream of a cards so the FAB wont interfere
On the layout level, design your app layout to minimize opportunities for interference.
For example, position the FAB to one side of stream of a cards so the FAB wont interfere
when a user tries to pick up one of cards.

View File

@ -29,10 +29,12 @@
<string-array name="theme_description_list">
<item>@string/light_theme_title</item>
<item>@string/dark_theme_title</item>
<item>@string/black_theme_title</item>
</string-array>
<string-array name="theme_list">
<item>@string/light_theme_title</item>
<item>@string/dark_theme_title</item>
<item>@string/black_theme_title</item>
</string-array>
<string name="default_audio_format_key" translatable="false">default_audio_format</string>

View File

@ -86,6 +86,8 @@
<string name="error_report_title">Error report</string>
<string name="all">All</string>
<string name="channel">Channel</string>
<string name="yes">Yes</string>
<string name="later">Later</string>
<!-- error strings -->
<string name="general_error">Error</string>
@ -151,10 +153,12 @@
<string name="use_exoplayer_summary">Experimental</string>
<string name="videos">videos</string>
<string name="subscriber">subscriber</string>
<string name="subscribe">Subscribe</string>
<string name="views">views</string>
<string name="short_thousand">T</string>
<string name="short_thousand">K</string>
<string name="short_million">M</string>
<string name="short_billion">B</string>
<string name="restart_title">Restart</string>
<!-- Missions -->
<string name="start">Start</string>
@ -183,6 +187,7 @@
<string name="msg_wait">Please wait…</string>
<string name="msg_copied">Copied to clipboard.</string>
<string name="no_available_dir">Please select an available download directory.</string>
<string name="msg_restart">You have to restart the application to apply the theme.\n\nDo you want to restart now?</string>
<!-- Checksum types -->
<string name="md5" translatable="false">MD5</string>

View File

@ -49,6 +49,10 @@
<item name="rss">@drawable/ic_rss_feed_black_24dp</item>
</style>
<style name="BlackTheme" parent="DarkTheme">
<item name="android:windowBackground">@color/black</item>
</style>
<style name="NewPipeActionbarTheme" parent="Widget.AppCompat.Light.ActionBar.Solid">
<item name="android:displayOptions">showHome</item>
<item name="displayOptions">showHome</item>
@ -107,6 +111,11 @@
<item name="windowNoTitle">true</item>
</style>
<style name="BlackTheme.NoActionBar">
<item name="windowActionBar">false</item>
<item name="windowNoTitle">true</item>
</style>
<style name="AppTheme.AppBarOverlay" parent="ThemeOverlay.AppCompat.Dark.ActionBar" />
<style name="AppTheme.PopupOverlay" parent="ThemeOverlay.AppCompat.Light" />

View File

@ -87,6 +87,11 @@ public class YoutubeChannelExtractorTest {
assertTrue("no next page link found", extractor.hasNextPage());
}
@Test
public void testGetSubscriberCount() throws Exception {
assertTrue("wrong subscriber count", extractor.getSubscriberCount() >= 0);
}
@Test
public void testGetNextPage() throws Exception {
extractor = NewPipe.getService("Youtube")

View File

@ -111,9 +111,9 @@ public class YoutubeStreamUrlIdHandlerTest {
assertTrue(urlIdHandler.acceptUrl("vnd.youtube:jZViOEv90dI"));
String sharedId = "7JIArTByb3E";
String sharedId = "8A940MXKFmQ";
assertTrue(urlIdHandler.acceptUrl("vnd.youtube://www.youtube.com/shared?ci=" + sharedId + "&feature=twitter-deep-link"));
assertTrue(urlIdHandler.acceptUrl("vnd.youtube://www.youtube.com/shared?ci=" + sharedId ));
assertTrue(urlIdHandler.acceptUrl("https://www.youtube.com/shared?ci=7JIArTByb3E"));
assertTrue(urlIdHandler.acceptUrl("https://www.youtube.com/shared?ci=" + sharedId));
}
}

View File

@ -0,0 +1,186 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
width="2550"
height="427"
viewBox="0 0 674.68749 112.97708"
version="1.1"
id="svg8"
inkscape:version="0.92.1 r"
sodipodi:docname="channel_banner_desktop.svg"
inkscape:export-filename="/home/the-scrabi/channel_banner.png"
inkscape:export-xdpi="96"
inkscape:export-ydpi="96">
<defs
id="defs2" />
<sodipodi:namedview
id="base"
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1.0"
inkscape:pageopacity="0.0"
inkscape:pageshadow="2"
inkscape:zoom="0.1438037"
inkscape:cx="983.1312"
inkscape:cy="-254.76355"
inkscape:document-units="mm"
inkscape:current-layer="layer1"
showgrid="false"
units="px"
inkscape:window-width="1920"
inkscape:window-height="1012"
inkscape:window-x="0"
inkscape:window-y="32"
inkscape:window-maximized="1" />
<metadata
id="metadata5">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title></dc:title>
</cc:Work>
</rdf:RDF>
</metadata>
<g
inkscape:label="Ebene 1"
inkscape:groupmode="layer"
id="layer1"
transform="translate(0,-184.02291)">
<path
inkscape:connector-curvature="0"
style="color:#000000;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;fill:#6c6c6c;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:0.10828106;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate"
d="m 283.72686,296.99999 h 30.94953 l 81.58882,-112.97708 h -30.949 z"
id="path5067" />
<path
inkscape:connector-curvature="0"
style="color:#000000;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;fill:#6c6c6c;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:0.10828106;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate"
d="m 221.83555,296.99999 h 30.94902 L 334.3739,184.02291 h -30.94953 z"
id="path5063" />
<path
inkscape:connector-curvature="0"
style="color:#000000;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;fill:#6c6c6c;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:0.10828106;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate"
d="m 159.94424,296.99999 h 30.95005 L 272.4831,184.02291 h -30.95004 z"
id="path5059" />
<path
inkscape:connector-curvature="0"
style="color:#000000;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;fill:#6c6c6c;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:0.10828106;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate"
d="M 98.052928,296.99999 H 129.00246 L 210.59128,184.02291 H 179.64175 Z"
id="path5055" />
<path
inkscape:connector-curvature="0"
style="color:#000000;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;fill:#6c6c6c;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:0.10828106;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate"
d="M 36.161617,296.99999 H 67.111149 L 148.70048,184.02291 h -30.94953 z"
id="path5051" />
<path
inkscape:connector-curvature="0"
style="color:#000000;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;fill:#6c6c6c;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:0.10828106;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate"
d="m 0,261.37168 v 35.62831 H 5.2193195 L 86.808653,184.02291 H 55.859121 Z"
id="path5047" />
<path
inkscape:connector-curvature="0"
style="color:#000000;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;fill:#6c6c6c;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:0.10828106;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate"
d="M 24.917342,184.02291 H 0 v 34.50332 z"
id="path5045" />
<path
inkscape:connector-curvature="0"
style="color:#000000;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;fill:#999999;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:0.10828106;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate"
d="m 252.7794,296.99999 h 30.94952 l 81.58935,-112.97708 h -30.95005 z"
id="path5020" />
<path
inkscape:connector-curvature="0"
style="color:#000000;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;fill:#999999;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:0.10828106;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate"
d="m 190.88809,296.99999 h 30.94953 l 81.58932,-112.97708 h -30.94953 z"
id="path5016" />
<path
inkscape:connector-curvature="0"
style="color:#000000;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;fill:#999999;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:0.10828106;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate"
d="m 128.99678,296.99999 h 30.94953 l 81.58933,-112.97708 h -30.95005 z"
id="path5012" />
<path
inkscape:connector-curvature="0"
style="color:#000000;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;fill:#999999;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:0.10828106;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate"
d="M 67.105463,296.99999 H 98.054995 L 179.64381,184.02291 h -30.94953 z"
id="path5008" />
<path
inkscape:connector-curvature="0"
style="color:#000000;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;fill:#999999;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:0.10828106;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate"
d="M 5.2141519,296.99999 H 36.163168 L 117.7525,184.02291 H 86.80297 Z"
id="path5004" />
<path
inkscape:connector-curvature="0"
style="color:#000000;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;fill:#999999;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:0.10828106;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate"
d="M 55.861706,184.02291 H 24.912174 L 0,218.51848 v 42.8563 z"
id="path5000" />
<path
inkscape:connector-curvature="0"
style="color:#000000;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;fill:#6c6c6c;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:0.10828107;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate"
d="M 531.30347,297 H 562.253 l 81.58881,-112.97709 h -30.949 z"
id="path5067-3" />
<path
inkscape:connector-curvature="0"
style="color:#000000;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;fill:#6c6c6c;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:0.10828107;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate"
d="m 469.41216,297 h 30.94902 L 581.9505,184.02291 h -30.94952 z"
id="path5063-6" />
<path
inkscape:connector-curvature="0"
style="color:#000000;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;fill:#6c6c6c;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:0.10828107;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate"
d="M 407.52085,297 H 438.4709 L 520.05971,184.02291 H 489.10967 Z"
id="path5059-7" />
<path
inkscape:connector-curvature="0"
style="color:#000000;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;fill:#6c6c6c;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:0.10828107;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate"
d="m 345.62386,297 h 30.94953 l 81.58882,-112.97709 h -30.94953 z"
id="path5055-5" />
<path
inkscape:connector-curvature="0"
style="color:#000000;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;fill:#999999;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:0.10828107;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate"
d="m 500.35601,297 h 30.94952 l 81.58934,-112.97709 h -30.95003 z"
id="path5020-3" />
<path
inkscape:connector-curvature="0"
style="color:#000000;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;fill:#999999;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:0.10828107;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate"
d="m 438.4647,297 h 30.94953 l 81.58932,-112.97709 h -30.94953 z"
id="path5016-5" />
<path
inkscape:connector-curvature="0"
style="color:#000000;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;fill:#999999;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:0.10828107;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate"
d="m 376.57339,297 h 30.94953 L 489.11225,184.02291 H 458.1622 Z"
id="path5012-6" />
<path
inkscape:connector-curvature="0"
style="color:#000000;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;fill:#999999;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:0.10828107;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate"
d="m 314.67639,297 h 30.94953 l 81.58882,-112.97709 h -30.94953 z"
id="path5008-2" />
<path
style="color:#000000;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;fill:#6c6c6c;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:0.40925127;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate"
d="M 2475.9375 427 L 2550 427 L 2550 324.44531 L 2475.9375 427 z "
id="path5063-6-1"
transform="matrix(0.26458333,0,0,0.26458333,0,184.02291)" />
<path
style="color:#000000;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;fill:#6c6c6c;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:0.40925127;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate"
d="M 2242.0176 427 L 2358.9941 427 L 2550 162.51172 L 2550 0.53320312 L 2242.0176 427 z "
id="path5059-7-2"
transform="matrix(0.26458333,0,0,0.26458333,0,184.02291)" />
<path
style="color:#000000;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;fill:#999999;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:0.40925127;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate"
d="M 2358.9707 427 L 2475.9453 427 L 2550 324.45703 L 2550 162.48047 L 2358.9707 427 z "
id="path5016-5-0"
transform="matrix(0.26458333,0,0,0.26458333,0,184.02291)" />
<path
inkscape:connector-curvature="0"
style="color:#000000;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;fill:#999999;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:0.10828107;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate"
d="m 562.253,297 h 30.94953 l 81.58933,-112.97709 h -30.95005 z"
id="path5012-6-9" />
</g>
</svg>

After

Width:  |  Height:  |  Size: 16 KiB

View File

@ -0,0 +1,144 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
width="1540"
height="427"
viewBox="0 0 407.45833 112.97708"
version="1.1"
id="svg8"
inkscape:version="0.92.1 r"
sodipodi:docname="channel_banner.svg"
inkscape:export-filename="/home/the-scrabi/channel_banner.png"
inkscape:export-xdpi="96"
inkscape:export-ydpi="96">
<defs
id="defs2" />
<sodipodi:namedview
id="base"
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1.0"
inkscape:pageopacity="0.0"
inkscape:pageshadow="2"
inkscape:zoom="0.5"
inkscape:cx="803.85939"
inkscape:cy="182.74745"
inkscape:document-units="mm"
inkscape:current-layer="layer1"
showgrid="false"
units="px"
inkscape:window-width="1920"
inkscape:window-height="1012"
inkscape:window-x="0"
inkscape:window-y="32"
inkscape:window-maximized="1" />
<metadata
id="metadata5">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title></dc:title>
</cc:Work>
</rdf:RDF>
</metadata>
<g
inkscape:label="Ebene 1"
inkscape:groupmode="layer"
id="layer1"
transform="translate(0,-184.02291)">
<g
id="g5158">
<path
transform="matrix(0.26458333,0,0,0.26458333,0,184.02291)"
id="path5071"
d="M 1306.2734 427 L 1423.248 427 L 1540 265.33398 L 1540 103.35547 L 1306.2734 427 z "
style="color:#000000;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;fill:#6c6c6c;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:0.40925127;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate" />
<path
transform="matrix(0.26458333,0,0,0.26458333,0,184.02291)"
id="path5067"
d="M 1072.3535 427 L 1189.3281 427 L 1497.6953 0 L 1380.7227 0 L 1072.3535 427 z "
style="color:#000000;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;fill:#6c6c6c;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:0.40925127;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate" />
<path
transform="matrix(0.26458333,0,0,0.26458333,0,184.02291)"
id="path5063"
d="M 838.43359 427 L 955.40625 427 L 1263.7754 0 L 1146.8008 0 L 838.43359 427 z "
style="color:#000000;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;fill:#6c6c6c;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:0.40925127;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate" />
<path
transform="matrix(0.26458333,0,0,0.26458333,0,184.02291)"
id="path5059"
d="M 604.51367 427 L 721.49023 427 L 1029.8574 0 L 912.88086 0 L 604.51367 427 z "
style="color:#000000;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;fill:#6c6c6c;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:0.40925127;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate" />
<path
transform="matrix(0.26458333,0,0,0.26458333,0,184.02291)"
id="path5055"
d="M 370.59375 427 L 487.56836 427 L 795.93555 0 L 678.96094 0 L 370.59375 427 z "
style="color:#000000;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;fill:#6c6c6c;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:0.40925127;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate" />
<path
transform="matrix(0.26458333,0,0,0.26458333,0,184.02291)"
id="path5051"
d="M 136.67383 427 L 253.64844 427 L 562.01758 0 L 445.04297 0 L 136.67383 427 z "
style="color:#000000;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;fill:#6c6c6c;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:0.40925127;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate" />
<path
transform="matrix(0.26458333,0,0,0.26458333,0,184.02291)"
id="path5047"
d="M 0 292.3418 L 0 427 L 19.726562 427 L 328.0957 0 L 211.12109 0 L 0 292.3418 z "
style="color:#000000;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;fill:#6c6c6c;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:0.40925127;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate" />
<path
transform="matrix(0.26458333,0,0,0.26458333,0,184.02291)"
id="path5045"
d="M 94.175781 0 L 0 0 L 0 130.40625 L 94.175781 0 z "
style="color:#000000;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;fill:#6c6c6c;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:0.40925127;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate" />
<path
transform="matrix(0.26458333,0,0,0.26458333,0,184.02291)"
id="path5028"
d="M 1423.2266 427 L 1540 427 L 1540 265.30273 L 1423.2266 427 z "
style="color:#000000;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;fill:#999999;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:0.40925127;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate" />
<path
transform="matrix(0.26458333,0,0,0.26458333,0,184.02291)"
id="path5024"
d="M 1189.3066 427 L 1306.2812 427 L 1540 103.36719 L 1540 0 L 1497.6758 0 L 1189.3066 427 z "
style="color:#000000;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;fill:#999999;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:0.40925127;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate" />
<path
transform="matrix(0.26458333,0,0,0.26458333,0,184.02291)"
id="path5020"
d="M 955.38672 427 L 1072.3613 427 L 1380.7305 0 L 1263.7539 0 L 955.38672 427 z "
style="color:#000000;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;fill:#999999;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:0.40925127;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate" />
<path
transform="matrix(0.26458333,0,0,0.26458333,0,184.02291)"
id="path5016"
d="M 721.4668 427 L 838.44141 427 L 1146.8105 0 L 1029.8359 0 L 721.4668 427 z "
style="color:#000000;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;fill:#999999;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:0.40925127;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate" />
<path
transform="matrix(0.26458333,0,0,0.26458333,0,184.02291)"
id="path5012"
d="M 487.54688 427 L 604.52148 427 L 912.89062 0 L 795.91406 0 L 487.54688 427 z "
style="color:#000000;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;fill:#999999;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:0.40925127;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate" />
<path
transform="matrix(0.26458333,0,0,0.26458333,0,184.02291)"
id="path5008"
d="M 253.62695 427 L 370.60156 427 L 678.96875 0 L 561.99414 0 L 253.62695 427 z "
style="color:#000000;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;fill:#999999;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:0.40925127;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate" />
<path
transform="matrix(0.26458333,0,0,0.26458333,0,184.02291)"
id="path5004"
d="M 19.707031 427 L 136.67969 427 L 445.04883 0 L 328.07422 0 L 19.707031 427 z "
style="color:#000000;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;fill:#999999;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:0.40925127;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate" />
<path
transform="matrix(0.26458333,0,0,0.26458333,0,184.02291)"
id="path5000"
d="M 211.13086 0 L 94.15625 0 L 0 130.37695 L 0 292.35352 L 211.13086 0 z "
style="color:#000000;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;fill:#999999;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:0.40925127;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate" />
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 12 KiB