Merge branch 'dev' into trending
1
.github/CONTRIBUTING.md
vendored
@ -13,6 +13,7 @@ Do not report crashes in the GitHub issue tracker. NewPipe has an automated cras
|
||||
* Check whether your issue/feature is already fixed/implemented
|
||||
* If you are an Android/Java developer, you are always welcome to fix/implement an issue/a feature yourself. PRs welcome!
|
||||
* We use English for development. Issues in other languages will be closed and ignored.
|
||||
* Please only add *one* issue at a time. Do not put multiple issues into one thread.
|
||||
|
||||
## Bug Fixing
|
||||
* If you want to help NewPipe to become free of bugs (this is our utopic goal for NewPipe), you can send us an email to tnp@newpipe.schabi.org to let me know that you intend to help. We'll send you further instructions. You may, on request, register at our [Sentry](https://sentry.schabi.org) instance (see section "Crash reporting" for more information.
|
||||
|
@ -10,9 +10,6 @@ android:
|
||||
# The SDK version used to compile NewPipe
|
||||
- android-26
|
||||
|
||||
# Additional components
|
||||
- extra-android-m2repository
|
||||
|
||||
script: ./gradlew -Dorg.gradle.jvmargs=-Xmx1536m assembleDebug lintDebug testDebugUnitTest
|
||||
|
||||
licenses:
|
||||
|
84
README.md
@ -1,34 +1,32 @@
|
||||
<p align="center"><a href="https://newpipe.schabi.org"><img src="assets/new_pipe_icon_5.png" width="150"/></a></p>
|
||||
<h2 align="center"><b>NewPipe</b></h2>
|
||||
<h4 align="center">A free lightweight YouTube frontend for Android.</h4>
|
||||
<p align="center"><a href="https://f-droid.org/packages/org.schabi.newpipe/"><img src="https://f-droid.org/wiki/images/0/06/F-Droid-button_get-it-on.png"/></a></p>
|
||||
|
||||
<p align="center">
|
||||
<a href="https://github.com/TeamNewPipe/NewPipe" alt="GitHub release"><img src="https://img.shields.io/github/release/TeamNewPipe/NewPipe.svg" /></a>
|
||||
<a href="https://www.gnu.org/licenses/gpl-3.0" alt="License: GPL v3"><img src="https://img.shields.io/badge/License-GPL%20v3-blue.svg" /></a>
|
||||
<a href="https://travis-ci.org/TeamNewPipe/NewPipe" alt="Build Status"><img src="https://travis-ci.org/TeamNewPipe/NewPipe.svg" /></a>
|
||||
<a href="https://hosted.weblate.org/engage/NewPipe/" alt="Translation Status"><img src="https://hosted.weblate.org/widgets/NewPipe/-/svg-badge.svg" /></a>
|
||||
<a href="http://webchat.freenode.net/?channels=%23newpipe" alt="IRC channel: #newpipe"><img src="https://img.shields.io/badge/IRC%20chat-%23newpipe-brightgreen.svg" /></a>
|
||||
</p>
|
||||
<hr />
|
||||
<p align="center"><a href="#screenshots">Screenshots</a> • <a href="#description">Description</a> • <a href="#features">Features</a> • <a href="#contribution">Contribution</a> • <a href="#donate">Donate</a> • <a href="#license">License</a></p>
|
||||
<hr />
|
||||
WARNING: PUTTING NEWPIPE OR ANY FORK OF IT INTO GOOGLE PLAYSTORE VIOLATES THEIR TERMS OF CONDITIONS.
|
||||
|
||||
# NewPipe
|
||||
NewPipe: A free lightweight YouTube frontend for Android.
|
||||
|
||||
[![NewPipe](app/src/main/res/mipmap-xhdpi/ic_launcher.png)](https://newpipe.schabi.org)
|
||||
[![F-Droid](https://f-droid.org/wiki/images/0/06/F-Droid-button_get-it-on.png)](https://f-droid.org/packages/org.schabi.newpipe/)
|
||||
|
||||
|
||||
Project status:
|
||||
[![Translation Status](https://hosted.weblate.org/widgets/NewPipe/-/svg-badge.svg)](https://hosted.weblate.org/engage/NewPipe/)
|
||||
[![Build Status](https://travis-ci.org/TeamNewPipe/NewPipe.svg)](https://travis-ci.org/TeamNewPipe/NewPipe)
|
||||
|
||||
## Donate
|
||||
![Bitcoin](https://bitcoin.org/img/icons/logotop.svg)
|
||||
![BitcoinQR](assets/16A9J59ahMRqkLSZjhYj33n9j3fMztFxnh.png)
|
||||
|
||||
`16A9J59ahMRqkLSZjhYj33n9j3fMztFxnh`
|
||||
|
||||
## Screenshots
|
||||
|
||||
[<img src="screenshots/screenshot_1.png" width=160>](screenshots/screenshot_1.png)
|
||||
[<img src="screenshots/screenshot_2.png" width=160>](screenshots/screenshot_2.png)
|
||||
[<img src="screenshots/screenshot_3.png" width=160>](screenshots/screenshot_3.png)
|
||||
[<img src="screenshots/screenshot_4.png" width=160>](screenshots/screenshot_4.png)
|
||||
[<img src="screenshots/screenshot_5.png" width=160>](screenshots/screenshot_5.png)
|
||||
[<img src="screenshots/screenshot_6.png" width=160>](screenshots/screenshot_6.png)
|
||||
[<img src="screenshots/screenshot_7.png" width=160>](screenshots/screenshot_7.png)
|
||||
[<img src="screenshots/screenshot_8.png" width=160>](screenshots/screenshot_8.png)
|
||||
[<img src="screenshots/screenshot_9.png" width=160>](screenshots/screenshot_9.png)
|
||||
|
||||
[<img src="screenshots/shot_1.png" width=160>](screenshots/shot_1.png)
|
||||
[<img src="screenshots/shot_2.png" width=160>](screenshots/shot_2.png)
|
||||
[<img src="screenshots/shot_3.png" width=160>](screenshots/shot_3.png)
|
||||
[<img src="screenshots/shot_4.png" width=160>](screenshots/shot_4.png)
|
||||
[<img src="screenshots/shot_5.png" width=160>](screenshots/shot_5.png)
|
||||
[<img src="screenshots/shot_6.png" width=160>](screenshots/shot_6.png)
|
||||
[<img src="screenshots/shot_7.png" width=160>](screenshots/shot_7.png)
|
||||
[<img src="screenshots/shot_8.png" width=160>](screenshots/shot_8.png)
|
||||
[<img src="screenshots/shot_9.png" width=160>](screenshots/shot_9.png)
|
||||
[<img src="screenshots/shot_10.png" width=160>](screenshots/shot_10.png)
|
||||
|
||||
## Description
|
||||
|
||||
@ -39,7 +37,7 @@ NewPipe does not use any Google framework libraries, or the YouTube API. It only
|
||||
* Search videos
|
||||
* Display general information about a video
|
||||
* Watch YouTube videos
|
||||
* Listen to YouTube videos (experimental)
|
||||
* Listen to YouTube videos
|
||||
* Popup mode (floating player)
|
||||
* Select the streaming player to watch the video with
|
||||
* Download videos
|
||||
@ -47,21 +45,23 @@ NewPipe does not use any Google framework libraries, or the YouTube API. It only
|
||||
* Open a video in Kodi
|
||||
* Show Next/Related videos
|
||||
* Search YouTube in a specific language
|
||||
* Watch age restricted material
|
||||
* Watch/Block age restricted material
|
||||
* Display general information about channels
|
||||
* Search channels
|
||||
* Watch videos from a channel
|
||||
* Orbot/Tor support (not yet directly)
|
||||
* 1080p/2k/4k support
|
||||
* View history
|
||||
* Subscribe to channels
|
||||
* Search history
|
||||
* Search/Watch Playlists
|
||||
|
||||
### Coming Features
|
||||
|
||||
* Multiservice support (eg. SoundCloud)
|
||||
* Bookmarks
|
||||
* View history
|
||||
* Search history
|
||||
* Subscribe to channels
|
||||
* Search/Watch Playlists
|
||||
* Queeing videos
|
||||
* Watch as queues Playlists
|
||||
* Queuing videos
|
||||
* Subtitles support
|
||||
* livestream support
|
||||
* ... and many more
|
||||
@ -75,6 +75,22 @@ The more is done the better it gets!
|
||||
|
||||
If you'd like to get involved, check our [contribution notes](.github/CONTRIBUTING.md).
|
||||
|
||||
## Donate
|
||||
If you like NewPipe we'd be happy about a donation. You can either donate via Bitcoin or BountySource. For further information about donating to NewPipe, please visit our [website](https://newpipe.schabi.org/donate/).
|
||||
|
||||
<table>
|
||||
<tr>
|
||||
<td><img src="https://bitcoin.org/img/icons/logotop.svg" alt="Bitcoin" /></td>
|
||||
<td><img src="assets/bitcoin_qr_code.png" alt="Bitcoin QR Code" width="100px"/></td>
|
||||
<td><samp>16A9J59ahMRqkLSZjhYj33n9j3fMztFxnh</samp></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><a href="https://www.bountysource.com/teams/newpipe"><img src="https://upload.wikimedia.org/wikipedia/commons/thumb/2/22/Bountysource.png/320px-Bountysource.png" alz="Bountysource" width="190px" /></a></td>
|
||||
<td><a href="https://www.bountysource.com/teams/newpipe"><img src="assets/bountysource_qr_code.png" alt="Visit NewPipe at bountysource.com" width="100px"/></a></td>
|
||||
<td><a href="https://www.bountysource.com/teams/newpipe/issues"><img src="https://img.shields.io/bountysource/team/newpipe/activity.svg?colorB=cd201f" height="30px" alt="Check out how many bounties you can earn." /></a></td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
## License
|
||||
[![GNU GPLv3 Image](https://www.gnu.org/graphics/gplv3-127x51.png)](http://www.gnu.org/licenses/gpl-3.0.en.html)
|
||||
|
||||
|
@ -26,6 +26,9 @@ android {
|
||||
debuggable true
|
||||
applicationIdSuffix ".debug"
|
||||
}
|
||||
beta {
|
||||
applicationIdSuffix ".beta"
|
||||
}
|
||||
}
|
||||
|
||||
lintOptions {
|
||||
@ -44,7 +47,7 @@ dependencies {
|
||||
androidTestCompile('com.android.support.test.espresso:espresso-core:2.2.2') {
|
||||
exclude module: 'support-annotations'
|
||||
}
|
||||
|
||||
|
||||
compile 'com.github.TeamNewPipe:NewPipeExtractor:7fffef5'
|
||||
|
||||
testCompile 'junit:junit:4.12'
|
||||
@ -62,7 +65,7 @@ dependencies {
|
||||
compile 'com.nostra13.universalimageloader:universal-image-loader:1.9.5'
|
||||
compile 'de.hdodenhof:circleimageview:2.1.0'
|
||||
compile 'com.github.nirhart:parallaxscroll:1.0'
|
||||
compile 'com.nononsenseapps:filepicker:3.0.0'
|
||||
compile 'com.nononsenseapps:filepicker:3.0.1'
|
||||
compile 'com.google.android.exoplayer:exoplayer:r2.5.1'
|
||||
|
||||
debugCompile 'com.facebook.stetho:stetho:1.5.0'
|
||||
|
10
app/src/beta/AndroidManifest.xml
Normal file
@ -0,0 +1,10 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:tools="http://schemas.android.com/tools">
|
||||
|
||||
<application
|
||||
android:label="NewPipe Beta"
|
||||
tools:replace="android:label">
|
||||
</application>
|
||||
|
||||
</manifest>
|
BIN
app/src/beta/res/mipmap-hdpi/ic_launcher.png
Normal file
After Width: | Height: | Size: 5.8 KiB |
BIN
app/src/beta/res/mipmap-mdpi/ic_launcher.png
Normal file
After Width: | Height: | Size: 3.0 KiB |
BIN
app/src/beta/res/mipmap-xhdpi/ic_launcher.png
Normal file
After Width: | Height: | Size: 8.1 KiB |
BIN
app/src/beta/res/mipmap-xxhdpi/ic_launcher.png
Normal file
After Width: | Height: | Size: 13 KiB |
BIN
app/src/beta/res/mipmap-xxxhdpi/ic_launcher.png
Normal file
After Width: | Height: | Size: 19 KiB |
@ -88,10 +88,14 @@
|
||||
<service android:name="us.shandian.giga.service.DownloadManagerService"/>
|
||||
|
||||
<activity
|
||||
android:name="com.nononsenseapps.filepicker.FilePickerActivity"
|
||||
android:name=".util.FilePickerActivityHelper"
|
||||
android:label="@string/app_name"
|
||||
android:launchMode="singleTop"
|
||||
android:theme="@style/FilePickerTheme"/>
|
||||
android:theme="@style/FilePickerThemeDark">
|
||||
<intent-filter>
|
||||
<action android:name="android.intent.action.GET_CONTENT" />
|
||||
<category android:name="android.intent.category.DEFAULT" />
|
||||
</intent-filter>
|
||||
</activity>
|
||||
|
||||
<activity
|
||||
android:name=".ReCaptchaActivity"
|
||||
|
@ -43,9 +43,8 @@ public class RouterActivity extends AppCompatActivity {
|
||||
}
|
||||
|
||||
protected void handleUrl(String url) {
|
||||
try {
|
||||
NavigationHelper.openByLink(this, url);
|
||||
} catch (Exception e) {
|
||||
boolean success = NavigationHelper.openByLink(this, url);
|
||||
if (!success) {
|
||||
Toast.makeText(this, R.string.url_not_supported_toast, Toast.LENGTH_LONG).show();
|
||||
}
|
||||
|
||||
|
@ -34,6 +34,7 @@ import org.schabi.newpipe.ReCaptchaActivity;
|
||||
import org.schabi.newpipe.extractor.InfoItem;
|
||||
import org.schabi.newpipe.extractor.ListExtractor;
|
||||
import org.schabi.newpipe.extractor.NewPipe;
|
||||
import org.schabi.newpipe.extractor.StreamingService;
|
||||
import org.schabi.newpipe.extractor.exceptions.ParsingException;
|
||||
import org.schabi.newpipe.extractor.search.SearchEngine;
|
||||
import org.schabi.newpipe.extractor.search.SearchResult;
|
||||
@ -47,12 +48,14 @@ import org.schabi.newpipe.util.StateSaver;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Queue;
|
||||
import java.util.concurrent.Callable;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import icepick.State;
|
||||
import io.reactivex.Notification;
|
||||
import io.reactivex.Observable;
|
||||
import io.reactivex.android.schedulers.AndroidSchedulers;
|
||||
import io.reactivex.disposables.CompositeDisposable;
|
||||
import io.reactivex.disposables.Disposable;
|
||||
import io.reactivex.functions.Consumer;
|
||||
import io.reactivex.functions.Function;
|
||||
@ -97,6 +100,7 @@ public class SearchFragment extends BaseListFragment<SearchResult, ListExtractor
|
||||
private PublishSubject<String> suggestionPublisher = PublishSubject.create();
|
||||
private Disposable searchDisposable;
|
||||
private Disposable suggestionWorkerDisposable;
|
||||
private CompositeDisposable disposables = new CompositeDisposable();
|
||||
|
||||
private SuggestionListAdapter suggestionListAdapter;
|
||||
|
||||
@ -149,6 +153,7 @@ public class SearchFragment extends BaseListFragment<SearchResult, ListExtractor
|
||||
|
||||
if (searchDisposable != null) searchDisposable.dispose();
|
||||
if (suggestionWorkerDisposable != null) suggestionWorkerDisposable.dispose();
|
||||
if (disposables != null) disposables.clear();
|
||||
hideSoftKeyboard(searchEditText);
|
||||
}
|
||||
|
||||
@ -192,6 +197,7 @@ public class SearchFragment extends BaseListFragment<SearchResult, ListExtractor
|
||||
|
||||
if (searchDisposable != null) searchDisposable.dispose();
|
||||
if (suggestionWorkerDisposable != null) suggestionWorkerDisposable.dispose();
|
||||
if (disposables != null) disposables.clear();
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -514,6 +520,38 @@ public class SearchFragment extends BaseListFragment<SearchResult, ListExtractor
|
||||
private void search(final String query) {
|
||||
if (DEBUG) Log.d(TAG, "search() called with: query = [" + query + "]");
|
||||
|
||||
try {
|
||||
final StreamingService service = NewPipe.getServiceByUrl(query);
|
||||
if (service != null) {
|
||||
showLoading();
|
||||
disposables.add(Observable
|
||||
.fromCallable(new Callable<Intent>() {
|
||||
@Override
|
||||
public Intent call() throws Exception {
|
||||
return NavigationHelper.getIntentByLink(activity, service, query);
|
||||
}
|
||||
})
|
||||
.subscribeOn(Schedulers.io())
|
||||
.observeOn(AndroidSchedulers.mainThread())
|
||||
.subscribe(new Consumer<Intent>() {
|
||||
@Override
|
||||
public void accept(Intent intent) throws Exception {
|
||||
getFragmentManager().popBackStackImmediate();
|
||||
activity.startActivity(intent);
|
||||
}
|
||||
}, new Consumer<Throwable>() {
|
||||
@Override
|
||||
public void accept(Throwable throwable) throws Exception {
|
||||
showError(getString(R.string.url_not_supported_toast), false);
|
||||
hideLoading();
|
||||
}
|
||||
}));
|
||||
return;
|
||||
}
|
||||
} catch (Exception e) {
|
||||
// Exception occurred, it's not a url
|
||||
}
|
||||
|
||||
hideSoftKeyboard(searchEditText);
|
||||
this.searchQuery = query;
|
||||
this.currentPage = 0;
|
||||
@ -532,6 +570,7 @@ public class SearchFragment extends BaseListFragment<SearchResult, ListExtractor
|
||||
@Override
|
||||
public void startLoading(boolean forceLoad) {
|
||||
super.startLoading(forceLoad);
|
||||
if (disposables != null) disposables.clear();
|
||||
if (searchDisposable != null) searchDisposable.dispose();
|
||||
searchDisposable = ExtractorHelper.searchFor(serviceId, searchQuery, currentPage, searchLanguage, filter)
|
||||
.subscribeOn(Schedulers.io())
|
||||
|
@ -7,9 +7,8 @@ import android.support.annotation.Nullable;
|
||||
import android.support.v7.preference.Preference;
|
||||
import android.util.Log;
|
||||
|
||||
import com.nononsenseapps.filepicker.FilePickerActivity;
|
||||
|
||||
import org.schabi.newpipe.R;
|
||||
import org.schabi.newpipe.util.FilePickerActivityHelper;
|
||||
|
||||
public class DownloadSettingsFragment extends BasePreferenceFragment {
|
||||
private static final int REQUEST_DOWNLOAD_PATH = 0x1235;
|
||||
@ -48,10 +47,10 @@ public class DownloadSettingsFragment extends BasePreferenceFragment {
|
||||
}
|
||||
|
||||
if (preference.getKey().equals(DOWNLOAD_PATH_PREFERENCE) || preference.getKey().equals(DOWNLOAD_PATH_AUDIO_PREFERENCE)) {
|
||||
Intent i = new Intent(getActivity(), FilePickerActivity.class)
|
||||
.putExtra(FilePickerActivity.EXTRA_ALLOW_MULTIPLE, false)
|
||||
.putExtra(FilePickerActivity.EXTRA_ALLOW_CREATE_DIR, true)
|
||||
.putExtra(FilePickerActivity.EXTRA_MODE, FilePickerActivity.MODE_DIR);
|
||||
Intent i = new Intent(getActivity(), FilePickerActivityHelper.class)
|
||||
.putExtra(FilePickerActivityHelper.EXTRA_ALLOW_MULTIPLE, false)
|
||||
.putExtra(FilePickerActivityHelper.EXTRA_ALLOW_CREATE_DIR, true)
|
||||
.putExtra(FilePickerActivityHelper.EXTRA_MODE, FilePickerActivityHelper.MODE_DIR);
|
||||
if (preference.getKey().equals(DOWNLOAD_PATH_PREFERENCE)) {
|
||||
startActivityForResult(i, REQUEST_DOWNLOAD_PATH);
|
||||
} else if (preference.getKey().equals(DOWNLOAD_PATH_AUDIO_PREFERENCE)) {
|
||||
|
@ -0,0 +1,17 @@
|
||||
package org.schabi.newpipe.util;
|
||||
|
||||
import android.os.Bundle;
|
||||
import org.schabi.newpipe.R;
|
||||
|
||||
public class FilePickerActivityHelper extends com.nononsenseapps.filepicker.FilePickerActivity {
|
||||
|
||||
@Override
|
||||
public void onCreate(Bundle savedInstanceState) {
|
||||
if(ThemeHelper.isLightThemeSelected(this)) {
|
||||
this.setTheme(R.style.FilePickerThemeLight);
|
||||
} else {
|
||||
this.setTheme(R.style.FilePickerThemeDark);
|
||||
}
|
||||
super.onCreate(savedInstanceState);
|
||||
}
|
||||
}
|
@ -14,7 +14,9 @@ import org.schabi.newpipe.R;
|
||||
import org.schabi.newpipe.about.AboutActivity;
|
||||
import org.schabi.newpipe.download.DownloadActivity;
|
||||
import org.schabi.newpipe.extractor.NewPipe;
|
||||
import org.schabi.newpipe.extractor.ServiceList;
|
||||
import org.schabi.newpipe.extractor.StreamingService;
|
||||
import org.schabi.newpipe.extractor.exceptions.ExtractionException;
|
||||
import org.schabi.newpipe.extractor.stream.AudioStream;
|
||||
import org.schabi.newpipe.extractor.stream.StreamInfo;
|
||||
import org.schabi.newpipe.fragments.MainFragment;
|
||||
@ -228,13 +230,17 @@ public class NavigationHelper {
|
||||
// Link handling
|
||||
//////////////////////////////////////////////////////////////////////////*/
|
||||
|
||||
public static void openByLink(Context context, String url) throws Exception {
|
||||
Intent intentByLink = getIntentByLink(context, url);
|
||||
if (intentByLink == null)
|
||||
throw new NullPointerException("getIntentByLink(context = [" + context + "], url = [" + url + "]) returned null");
|
||||
public static boolean openByLink(Context context, String url) {
|
||||
Intent intentByLink;
|
||||
try {
|
||||
intentByLink = getIntentByLink(context, url);
|
||||
} catch (ExtractionException e) {
|
||||
return false;
|
||||
}
|
||||
intentByLink.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
|
||||
intentByLink.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK);
|
||||
context.startActivity(intentByLink);
|
||||
return true;
|
||||
}
|
||||
|
||||
private static Intent getOpenIntent(Context context, String url, int serviceId, StreamingService.LinkType type) {
|
||||
@ -245,14 +251,20 @@ public class NavigationHelper {
|
||||
return mIntent;
|
||||
}
|
||||
|
||||
private static Intent getIntentByLink(Context context, String url) throws Exception {
|
||||
StreamingService service = NewPipe.getServiceByUrl(url);
|
||||
public static Intent getIntentByLink(Context context, String url) throws ExtractionException {
|
||||
return getIntentByLink(context, NewPipe.getServiceByUrl(url), url);
|
||||
}
|
||||
|
||||
public static Intent getIntentByLink(Context context, StreamingService service, String url) throws ExtractionException {
|
||||
if (service != ServiceList.YouTube.getService()) {
|
||||
throw new ExtractionException("Service not supported at the moment");
|
||||
}
|
||||
|
||||
int serviceId = service.getServiceId();
|
||||
StreamingService.LinkType linkType = service.getLinkTypeByUrl(url);
|
||||
|
||||
if (linkType == StreamingService.LinkType.NONE) {
|
||||
throw new Exception("Url not known to service. service=" + serviceId + " url=" + url);
|
||||
throw new ExtractionException("Url not known to service. service=" + serviceId + " url=" + url);
|
||||
}
|
||||
|
||||
url = getCleanUrl(service, url, linkType);
|
||||
@ -268,7 +280,7 @@ public class NavigationHelper {
|
||||
return rIntent;
|
||||
}
|
||||
|
||||
private static String getCleanUrl(StreamingService service, String dirtyUrl, StreamingService.LinkType linkType) throws Exception {
|
||||
private static String getCleanUrl(StreamingService service, String dirtyUrl, StreamingService.LinkType linkType) throws ExtractionException {
|
||||
switch (linkType) {
|
||||
case STREAM:
|
||||
return service.getStreamUrlIdHandler().cleanUrl(dirtyUrl);
|
||||
|
@ -101,6 +101,18 @@ public class DownloadManagerImpl implements DownloadManager {
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Sort a list of mission by its timestamp. Oldest first
|
||||
* @param missions the missions to sort
|
||||
*/
|
||||
static void sortByTimestamp(List<DownloadMission> missions) {
|
||||
Collections.sort(missions, new Comparator<DownloadMission>() {
|
||||
@Override
|
||||
public int compare(DownloadMission o1, DownloadMission o2) {
|
||||
return Long.valueOf(o1.timestamp).compareTo(o2.timestamp);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Loads finished missions from the data source
|
||||
@ -111,12 +123,8 @@ public class DownloadManagerImpl implements DownloadManager {
|
||||
finishedMissions = new ArrayList<>();
|
||||
}
|
||||
// Ensure its sorted
|
||||
Collections.sort(finishedMissions, new Comparator<DownloadMission>() {
|
||||
@Override
|
||||
public int compare(DownloadMission o1, DownloadMission o2) {
|
||||
return (int) (o1.timestamp - o2.timestamp);
|
||||
}
|
||||
});
|
||||
sortByTimestamp(finishedMissions);
|
||||
|
||||
mMissions.ensureCapacity(mMissions.size() + finishedMissions.size());
|
||||
for (DownloadMission mission : finishedMissions) {
|
||||
File downloadedFile = mission.getDownloadedFile();
|
||||
|
5
app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml
Normal file
@ -0,0 +1,5 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<background android:drawable="@color/ic_launcher_background"/>
|
||||
<foreground android:drawable="@mipmap/ic_launcher_foreground"/>
|
||||
</adaptive-icon>
|
BIN
app/src/main/res/mipmap-hdpi/ic_launcher_foreground.png
Normal file
After Width: | Height: | Size: 1.3 KiB |
BIN
app/src/main/res/mipmap-mdpi/ic_launcher_foreground.png
Normal file
After Width: | Height: | Size: 788 B |
BIN
app/src/main/res/mipmap-xhdpi/ic_launcher_foreground.png
Normal file
After Width: | Height: | Size: 1.8 KiB |
BIN
app/src/main/res/mipmap-xxhdpi/ic_launcher_foreground.png
Normal file
After Width: | Height: | Size: 3.6 KiB |
BIN
app/src/main/res/mipmap-xxxhdpi/ic_launcher_foreground.png
Normal file
After Width: | Height: | Size: 4.9 KiB |
4
app/src/main/res/values/ic_launcher_background.xml
Normal file
@ -0,0 +1,4 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources>
|
||||
<color name="ic_launcher_background">#CD201F</color>
|
||||
</resources>
|
@ -51,7 +51,7 @@
|
||||
<string-array name="video_format_description_list" translatable="false">
|
||||
<item>MPEG-4</item>
|
||||
<item>WebM</item>
|
||||
<item>3GPP</item>
|
||||
<item>3GP</item>
|
||||
</string-array>
|
||||
<string-array name="video_format_values_list" translatable="false">
|
||||
<item>@string/video_mp4_key</item>
|
||||
|
@ -109,23 +109,47 @@
|
||||
<item name="background">@color/video_overlay_color</item>
|
||||
</style>
|
||||
|
||||
<!-- You can also inherit from NNF_BaseTheme.Light -->
|
||||
<style name="FilePickerTheme" parent="NNF_BaseTheme.Light">
|
||||
<!-- Set these to match your theme -->
|
||||
<style name="FilePickerThemeLight" parent="NNF_BaseTheme.Light">
|
||||
<item name="colorPrimary">@color/light_youtube_primary_color</item>
|
||||
<item name="colorPrimaryDark">@color/light_youtube_dark_color</item>
|
||||
<item name="colorAccent">@color/light_youtube_accent_color</item>
|
||||
<item name="android:background">@color/light_background_color</item>
|
||||
<item name="nnf_separator_color">@color/light_separator_color</item>
|
||||
|
||||
<!-- Need to set this also to style create folder dialog -->
|
||||
<item name="alertDialogTheme">@style/FilePickerAlertDialogTheme</item>
|
||||
|
||||
<!-- If you want to set a specific toolbar theme, do it here -->
|
||||
<!-- <item name="nnf_toolbarTheme">@style/ThemeOverlay.AppCompat.Dark.ActionBar</item> -->
|
||||
<item name="alertDialogTheme">@style/FilePickerAlertDialogThemeLight</item>
|
||||
<item name="nnf_toolbarTheme">@style/FilePickerToolbarLight</item>
|
||||
</style>
|
||||
|
||||
<style name="FilePickerAlertDialogTheme" parent="Theme.AppCompat.Dialog.Alert">
|
||||
<style name="FilePickerAlertDialogThemeLight" parent="Theme.AppCompat.Dialog.Alert">
|
||||
<item name="colorPrimary">@color/light_youtube_primary_color</item>
|
||||
<item name="colorPrimaryDark">@color/light_youtube_dark_color</item>
|
||||
<item name="colorAccent">@color/light_youtube_accent_color</item>
|
||||
</style>
|
||||
|
||||
<style name="FilePickerToolbarLight" parent="ThemeOverlay.AppCompat.Dark.ActionBar">
|
||||
<item name="android:background">@color/light_youtube_primary_color</item>
|
||||
</style>
|
||||
|
||||
<style name="FilePickerThemeDark" parent="FilePickerThemeLight">
|
||||
<item name="colorPrimary">@color/dark_youtube_primary_color</item>
|
||||
<item name="colorPrimaryDark">@color/dark_youtube_dark_color</item>
|
||||
<item name="colorAccent">@color/dark_youtube_accent_color</item>
|
||||
<item name="android:background">@color/dark_background_color</item>
|
||||
<item name="android:textColorPrimary">@color/dark_youtube_accent_color</item>
|
||||
<item name="nnf_separator_color">@color/black_separator_color</item>
|
||||
|
||||
<item name="alertDialogTheme">@style/FilePickerAlertDialogThemeDark</item>
|
||||
<item name="nnf_toolbarTheme">@style/FilePickerToolbarDark</item>
|
||||
</style>
|
||||
|
||||
<style name="FilePickerAlertDialogThemeDark" parent="Theme.AppCompat.Dialog.Alert">
|
||||
<item name="colorPrimary">@color/dark_youtube_primary_color</item>
|
||||
<item name="colorPrimaryDark">@color/dark_youtube_dark_color</item>
|
||||
<item name="colorAccent">@color/dark_youtube_accent_color</item>
|
||||
</style>
|
||||
|
||||
<style name="FilePickerToolbarDark" parent="ThemeOverlay.AppCompat.Dark.ActionBar">
|
||||
<item name="android:background">@color/dark_youtube_primary_color</item>
|
||||
</style>
|
||||
|
||||
</resources>
|
||||
|
@ -1,4 +1,4 @@
|
||||
package us.shandian.giga.get.get;
|
||||
package us.shandian.giga.get;
|
||||
|
||||
import org.junit.Ignore;
|
||||
import org.junit.Test;
|
||||
@ -153,4 +153,34 @@ public class DownloadManagerImplTest {
|
||||
assertSame(missions.get(1), downloadManager.getMission(1));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void sortByTimestamp() throws Exception {
|
||||
ArrayList<DownloadMission> downloadMissions = new ArrayList<>();
|
||||
DownloadMission mission = new DownloadMission();
|
||||
mission.timestamp = 0;
|
||||
|
||||
DownloadMission mission1 = new DownloadMission();
|
||||
mission1.timestamp = Integer.MAX_VALUE + 1L;
|
||||
|
||||
DownloadMission mission2 = new DownloadMission();
|
||||
mission2.timestamp = 2L * Integer.MAX_VALUE ;
|
||||
|
||||
DownloadMission mission3 = new DownloadMission();
|
||||
mission3.timestamp = 2L * Integer.MAX_VALUE + 5L;
|
||||
|
||||
|
||||
downloadMissions.add(mission3);
|
||||
downloadMissions.add(mission1);
|
||||
downloadMissions.add(mission2);
|
||||
downloadMissions.add(mission);
|
||||
|
||||
|
||||
DownloadManagerImpl.sortByTimestamp(downloadMissions);
|
||||
|
||||
assertEquals(mission, downloadMissions.get(0));
|
||||
assertEquals(mission1, downloadMissions.get(1));
|
||||
assertEquals(mission2, downloadMissions.get(2));
|
||||
assertEquals(mission3, downloadMissions.get(3));
|
||||
}
|
||||
|
||||
}
|
546
assets/BETA_new_pipe_icon_5.svg
Normal file
@ -0,0 +1,546 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<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:xlink="http://www.w3.org/1999/xlink"
|
||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||
version="1.1"
|
||||
id="svg2"
|
||||
viewBox="0 0 192 192"
|
||||
height="204.8"
|
||||
width="204.8"
|
||||
inkscape:version="0.91 r13725"
|
||||
sodipodi:docname="BETA_new_pipe_icon_5.svg"
|
||||
inkscape:export-filename="/home/the-scrabi/Projects/NewPipe/assets/new_pipe_icon_5.png"
|
||||
inkscape:export-xdpi="120"
|
||||
inkscape:export-ydpi="120">
|
||||
<sodipodi:namedview
|
||||
pagecolor="#ffffff"
|
||||
bordercolor="#666666"
|
||||
borderopacity="1"
|
||||
objecttolerance="10"
|
||||
gridtolerance="10"
|
||||
guidetolerance="10"
|
||||
inkscape:pageopacity="0"
|
||||
inkscape:pageshadow="2"
|
||||
inkscape:window-width="1366"
|
||||
inkscape:window-height="713"
|
||||
id="namedview4149"
|
||||
showgrid="false"
|
||||
inkscape:zoom="2.5673112"
|
||||
inkscape:cx="105.05076"
|
||||
inkscape:cy="98.81914"
|
||||
inkscape:window-x="0"
|
||||
inkscape:window-y="0"
|
||||
inkscape:window-maximized="1"
|
||||
inkscape:current-layer="svg2" />
|
||||
<defs
|
||||
id="defs4">
|
||||
<linearGradient
|
||||
inkscape:collect="always"
|
||||
id="linearGradient4447">
|
||||
<stop
|
||||
style="stop-color:#ffffff;stop-opacity:0.1"
|
||||
offset="0"
|
||||
id="stop4449" />
|
||||
<stop
|
||||
style="stop-color:#ffffff;stop-opacity:0"
|
||||
offset="1"
|
||||
id="stop4451" />
|
||||
</linearGradient>
|
||||
<filter
|
||||
style="color-interpolation-filters:sRGB"
|
||||
inkscape:label="Drop Shadow"
|
||||
id="filter4454"
|
||||
width="1.4"
|
||||
height="1.4"
|
||||
x="-0.2"
|
||||
y="-0.2">
|
||||
<feFlood
|
||||
flood-opacity="0.427451"
|
||||
flood-color="rgb(0,0,0)"
|
||||
result="flood"
|
||||
id="feFlood4456" />
|
||||
<feComposite
|
||||
in="flood"
|
||||
in2="SourceGraphic"
|
||||
operator="in"
|
||||
result="composite1"
|
||||
id="feComposite4458" />
|
||||
<feGaussianBlur
|
||||
in="composite1"
|
||||
stdDeviation="10.9"
|
||||
result="blur"
|
||||
id="feGaussianBlur4460" />
|
||||
<feOffset
|
||||
dx="0"
|
||||
dy="7"
|
||||
result="offset"
|
||||
id="feOffset4462" />
|
||||
<feComposite
|
||||
in="SourceGraphic"
|
||||
in2="offset"
|
||||
operator="over"
|
||||
result="composite2"
|
||||
id="feComposite4464" />
|
||||
</filter>
|
||||
<filter
|
||||
style="color-interpolation-filters:sRGB"
|
||||
inkscape:label="Drop Shadow"
|
||||
id="filter4777">
|
||||
<feFlood
|
||||
flood-opacity="0.498039"
|
||||
flood-color="rgb(0,0,0)"
|
||||
result="flood"
|
||||
id="feFlood4779" />
|
||||
<feComposite
|
||||
in="flood"
|
||||
in2="SourceGraphic"
|
||||
operator="in"
|
||||
result="composite1"
|
||||
id="feComposite4781" />
|
||||
<feGaussianBlur
|
||||
in="composite1"
|
||||
stdDeviation="5.82011"
|
||||
result="blur"
|
||||
id="feGaussianBlur4783" />
|
||||
<feOffset
|
||||
dx="0"
|
||||
dy="5.6"
|
||||
result="offset"
|
||||
id="feOffset4785" />
|
||||
<feComposite
|
||||
in="SourceGraphic"
|
||||
in2="offset"
|
||||
operator="over"
|
||||
result="fbSourceGraphic"
|
||||
id="feComposite4787" />
|
||||
<feColorMatrix
|
||||
result="fbSourceGraphicAlpha"
|
||||
in="fbSourceGraphic"
|
||||
values="0 0 0 -1 0 0 0 0 -1 0 0 0 0 -1 0 0 0 0 1 0"
|
||||
id="feColorMatrix4789" />
|
||||
<feFlood
|
||||
id="feFlood4791"
|
||||
flood-opacity="0.498039"
|
||||
flood-color="rgb(0,0,0)"
|
||||
result="flood"
|
||||
in="fbSourceGraphic" />
|
||||
<feComposite
|
||||
id="feComposite4793"
|
||||
in2="fbSourceGraphic"
|
||||
in="flood"
|
||||
operator="in"
|
||||
result="composite1" />
|
||||
<feGaussianBlur
|
||||
id="feGaussianBlur4795"
|
||||
in="composite1"
|
||||
stdDeviation="5.8"
|
||||
result="blur" />
|
||||
<feOffset
|
||||
id="feOffset4797"
|
||||
dx="0"
|
||||
dy="5.6"
|
||||
result="offset" />
|
||||
<feComposite
|
||||
id="feComposite4799"
|
||||
in2="offset"
|
||||
in="fbSourceGraphic"
|
||||
operator="over"
|
||||
result="composite2" />
|
||||
</filter>
|
||||
<filter
|
||||
style="color-interpolation-filters:sRGB"
|
||||
inkscape:label="Drop Shadow"
|
||||
id="filter4885">
|
||||
<feFlood
|
||||
flood-opacity="0.498039"
|
||||
flood-color="rgb(0,0,0)"
|
||||
result="flood"
|
||||
id="feFlood4887" />
|
||||
<feComposite
|
||||
in="flood"
|
||||
in2="SourceGraphic"
|
||||
operator="in"
|
||||
result="composite1"
|
||||
id="feComposite4889" />
|
||||
<feGaussianBlur
|
||||
in="composite1"
|
||||
stdDeviation="7.9"
|
||||
result="blur"
|
||||
id="feGaussianBlur4891" />
|
||||
<feOffset
|
||||
dx="0"
|
||||
dy="2.54709"
|
||||
result="offset"
|
||||
id="feOffset4893" />
|
||||
<feComposite
|
||||
in="SourceGraphic"
|
||||
in2="offset"
|
||||
operator="over"
|
||||
result="fbSourceGraphic"
|
||||
id="feComposite4895" />
|
||||
<feColorMatrix
|
||||
result="fbSourceGraphicAlpha"
|
||||
in="fbSourceGraphic"
|
||||
values="0 0 0 -1 0 0 0 0 -1 0 0 0 0 -1 0 0 0 0 1 0"
|
||||
id="feColorMatrix4897" />
|
||||
<feFlood
|
||||
id="feFlood4899"
|
||||
flood-opacity="0.498039"
|
||||
flood-color="rgb(0,0,0)"
|
||||
result="flood"
|
||||
in="fbSourceGraphic" />
|
||||
<feComposite
|
||||
id="feComposite4901"
|
||||
in2="fbSourceGraphic"
|
||||
in="flood"
|
||||
operator="in"
|
||||
result="composite1" />
|
||||
<feGaussianBlur
|
||||
id="feGaussianBlur4903"
|
||||
in="composite1"
|
||||
stdDeviation="7.9"
|
||||
result="blur" />
|
||||
<feOffset
|
||||
id="feOffset4905"
|
||||
dx="0"
|
||||
dy="2.5"
|
||||
result="offset" />
|
||||
<feComposite
|
||||
id="feComposite4907"
|
||||
in2="offset"
|
||||
in="fbSourceGraphic"
|
||||
operator="over"
|
||||
result="composite2" />
|
||||
</filter>
|
||||
<filter
|
||||
style="color-interpolation-filters:sRGB"
|
||||
inkscape:label="Drop Shadow"
|
||||
id="filter4257">
|
||||
<feFlood
|
||||
flood-opacity="0.498039"
|
||||
flood-color="rgb(0,0,0)"
|
||||
result="flood"
|
||||
id="feFlood4259" />
|
||||
<feComposite
|
||||
in="flood"
|
||||
in2="SourceGraphic"
|
||||
operator="in"
|
||||
result="composite1"
|
||||
id="feComposite4261" />
|
||||
<feGaussianBlur
|
||||
in="composite1"
|
||||
stdDeviation="7.9"
|
||||
result="blur"
|
||||
id="feGaussianBlur4263" />
|
||||
<feOffset
|
||||
dx="0"
|
||||
dy="5.02645"
|
||||
result="offset"
|
||||
id="feOffset4265" />
|
||||
<feComposite
|
||||
in="SourceGraphic"
|
||||
in2="offset"
|
||||
operator="over"
|
||||
result="fbSourceGraphic"
|
||||
id="feComposite4267" />
|
||||
<feColorMatrix
|
||||
result="fbSourceGraphicAlpha"
|
||||
in="fbSourceGraphic"
|
||||
values="0 0 0 -1 0 0 0 0 -1 0 0 0 0 -1 0 0 0 0 1 0"
|
||||
id="feColorMatrix4269" />
|
||||
<feFlood
|
||||
id="feFlood4271"
|
||||
flood-opacity="0.498039"
|
||||
flood-color="rgb(0,0,0)"
|
||||
result="flood"
|
||||
in="fbSourceGraphic" />
|
||||
<feComposite
|
||||
id="feComposite4273"
|
||||
in2="fbSourceGraphic"
|
||||
in="flood"
|
||||
operator="in"
|
||||
result="composite1" />
|
||||
<feGaussianBlur
|
||||
id="feGaussianBlur4275"
|
||||
in="composite1"
|
||||
stdDeviation="7.9"
|
||||
result="blur" />
|
||||
<feOffset
|
||||
id="feOffset4277"
|
||||
dx="0"
|
||||
dy="5"
|
||||
result="offset" />
|
||||
<feComposite
|
||||
id="feComposite4279"
|
||||
in2="offset"
|
||||
in="fbSourceGraphic"
|
||||
operator="over"
|
||||
result="composite2" />
|
||||
</filter>
|
||||
<filter
|
||||
style="color-interpolation-filters:sRGB"
|
||||
inkscape:label="Drop Shadow"
|
||||
id="filter4192">
|
||||
<feFlood
|
||||
flood-opacity="0.498039"
|
||||
flood-color="rgb(0,0,0)"
|
||||
result="flood"
|
||||
id="feFlood4194" />
|
||||
<feComposite
|
||||
in="flood"
|
||||
in2="SourceGraphic"
|
||||
operator="in"
|
||||
result="composite1"
|
||||
id="feComposite4196" />
|
||||
<feGaussianBlur
|
||||
in="composite1"
|
||||
stdDeviation="7.7"
|
||||
result="blur"
|
||||
id="feGaussianBlur4198" />
|
||||
<feOffset
|
||||
dx="0"
|
||||
dy="5"
|
||||
result="offset"
|
||||
id="feOffset4200" />
|
||||
<feComposite
|
||||
in="SourceGraphic"
|
||||
in2="offset"
|
||||
operator="over"
|
||||
result="composite2"
|
||||
id="feComposite4202" />
|
||||
</filter>
|
||||
<filter
|
||||
style="color-interpolation-filters:sRGB"
|
||||
inkscape:label="Drop Shadow"
|
||||
id="filter4349">
|
||||
<feFlood
|
||||
flood-opacity="0.498039"
|
||||
flood-color="rgb(0,0,0)"
|
||||
result="flood"
|
||||
id="feFlood4351" />
|
||||
<feComposite
|
||||
in="flood"
|
||||
in2="SourceGraphic"
|
||||
operator="in"
|
||||
result="composite1"
|
||||
id="feComposite4353" />
|
||||
<feGaussianBlur
|
||||
in="composite1"
|
||||
stdDeviation="7.2"
|
||||
result="blur"
|
||||
id="feGaussianBlur4355" />
|
||||
<feOffset
|
||||
dx="0"
|
||||
dy="5"
|
||||
result="offset"
|
||||
id="feOffset4357" />
|
||||
<feComposite
|
||||
in="SourceGraphic"
|
||||
in2="offset"
|
||||
operator="over"
|
||||
result="composite2"
|
||||
id="feComposite4359" />
|
||||
</filter>
|
||||
<filter
|
||||
style="color-interpolation-filters:sRGB"
|
||||
inkscape:label="Drop Shadow"
|
||||
id="filter4361">
|
||||
<feFlood
|
||||
flood-opacity="0.498039"
|
||||
flood-color="rgb(0,0,0)"
|
||||
result="flood"
|
||||
id="feFlood4363" />
|
||||
<feComposite
|
||||
in="flood"
|
||||
in2="SourceGraphic"
|
||||
operator="in"
|
||||
result="composite1"
|
||||
id="feComposite4365" />
|
||||
<feGaussianBlur
|
||||
in="composite1"
|
||||
stdDeviation="5.3"
|
||||
result="blur"
|
||||
id="feGaussianBlur4367" />
|
||||
<feOffset
|
||||
dx="0"
|
||||
dy="5"
|
||||
result="offset"
|
||||
id="feOffset4369" />
|
||||
<feComposite
|
||||
in="SourceGraphic"
|
||||
in2="offset"
|
||||
operator="over"
|
||||
result="composite2"
|
||||
id="feComposite4371" />
|
||||
</filter>
|
||||
<filter
|
||||
style="color-interpolation-filters:sRGB"
|
||||
inkscape:label="Drop Shadow"
|
||||
id="filter4481">
|
||||
<feFlood
|
||||
flood-opacity="0.498039"
|
||||
flood-color="rgb(0,0,0)"
|
||||
result="flood"
|
||||
id="feFlood4483" />
|
||||
<feComposite
|
||||
in="flood"
|
||||
in2="SourceGraphic"
|
||||
operator="in"
|
||||
result="composite1"
|
||||
id="feComposite4485" />
|
||||
<feGaussianBlur
|
||||
in="composite1"
|
||||
stdDeviation="5"
|
||||
result="blur"
|
||||
id="feGaussianBlur4487" />
|
||||
<feOffset
|
||||
dx="0"
|
||||
dy="5"
|
||||
result="offset"
|
||||
id="feOffset4489" />
|
||||
<feComposite
|
||||
in="SourceGraphic"
|
||||
in2="offset"
|
||||
operator="over"
|
||||
result="composite2"
|
||||
id="feComposite4491" />
|
||||
</filter>
|
||||
<filter
|
||||
style="color-interpolation-filters:sRGB"
|
||||
inkscape:label="Drop Shadow"
|
||||
id="filter4433">
|
||||
<feFlood
|
||||
flood-opacity="0.2"
|
||||
flood-color="rgb(0,0,0)"
|
||||
result="flood"
|
||||
id="feFlood4435" />
|
||||
<feComposite
|
||||
in="flood"
|
||||
in2="SourceGraphic"
|
||||
operator="in"
|
||||
result="composite1"
|
||||
id="feComposite4437" />
|
||||
<feGaussianBlur
|
||||
in="composite1"
|
||||
stdDeviation="4"
|
||||
result="blur"
|
||||
id="feGaussianBlur4439" />
|
||||
<feOffset
|
||||
dx="0"
|
||||
dy="4"
|
||||
result="offset"
|
||||
id="feOffset4441" />
|
||||
<feComposite
|
||||
in="SourceGraphic"
|
||||
in2="offset"
|
||||
operator="over"
|
||||
result="composite2"
|
||||
id="feComposite4443" />
|
||||
</filter>
|
||||
<radialGradient
|
||||
inkscape:collect="always"
|
||||
xlink:href="#linearGradient4447"
|
||||
id="radialGradient4453"
|
||||
cx="0.56012386"
|
||||
cy="0.35701406"
|
||||
fx="0.56012386"
|
||||
fy="0.35701406"
|
||||
r="88"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
gradientTransform="matrix(0.00132321,2.1587518,-2.1815784,0.00133718,1.1131155,-0.39216099)" />
|
||||
</defs>
|
||||
<metadata
|
||||
id="metadata7">
|
||||
<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 />
|
||||
</cc:Work>
|
||||
</rdf:RDF>
|
||||
</metadata>
|
||||
<path
|
||||
style="opacity:1;fill:#ff7575;fill-opacity:1;stroke:none;stroke-width:17.10300064;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
|
||||
id="path4144-9"
|
||||
r="88"
|
||||
cy="104"
|
||||
cx="88"
|
||||
d=""
|
||||
inkscape:connector-curvature="0" />
|
||||
<circle
|
||||
style="fill:#ff5252;fill-opacity:1;stroke:none;stroke-width:17.10300064;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
|
||||
id="path4144-6"
|
||||
cx="88"
|
||||
cy="104"
|
||||
r="0" />
|
||||
<circle
|
||||
style="opacity:1;fill:#ff7575;fill-opacity:1;stroke:none;stroke-width:17.10300064;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;filter:url(#filter4433)"
|
||||
id="path4144-67"
|
||||
cx="96"
|
||||
cy="96"
|
||||
r="88" />
|
||||
<path
|
||||
style="opacity:1;fill:#cc4242;fill-opacity:1;stroke:none;stroke-width:17.10300064;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;filter:url(#filter4433)"
|
||||
id="path4144-5"
|
||||
sodipodi:type="arc"
|
||||
sodipodi:cx="96"
|
||||
sodipodi:cy="96"
|
||||
sodipodi:rx="88"
|
||||
sodipodi:ry="88"
|
||||
sodipodi:start="0"
|
||||
sodipodi:end="3.1387981"
|
||||
sodipodi:open="true"
|
||||
d="M 184,96 A 88,88 0 0 1 96.12296,183.99991 88,88 0 0 1 8.0003436,96.24592" />
|
||||
<ellipse
|
||||
style="fill:#cd201f;fill-opacity:1;stroke:none;stroke-width:17.10300064;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;filter:url(#filter4433)"
|
||||
id="path4144"
|
||||
cx="96"
|
||||
cy="96"
|
||||
rx="88"
|
||||
ry="87" />
|
||||
<path
|
||||
style="fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;filter:url(#filter4433)"
|
||||
d="M 62.03771,154.84774 79.885207,143.47161 80.258503,68.06594 126.18321,95.333 92.950545,114.49592 v 21.92836 L 161.9848,95.333 61.944386,36.538494 Z"
|
||||
id="path4234"
|
||||
inkscape:connector-curvature="0"
|
||||
sodipodi:nodetypes="ccccccccc" />
|
||||
<path
|
||||
style="opacity:1;fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:3.5;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
|
||||
id="path4445-5"
|
||||
sodipodi:type="arc"
|
||||
sodipodi:cx="96.001564"
|
||||
sodipodi:cy="96.021866"
|
||||
sodipodi:rx="88"
|
||||
sodipodi:ry="88"
|
||||
sodipodi:start="0.082013054"
|
||||
sodipodi:end="1.9854818"
|
||||
sodipodi:open="true"
|
||||
d="m 183.70578,103.23093 a 88,88 0 0 1 -42.68319,68.40249 88,88 0 0 1 -80.476409,4.92984" />
|
||||
<text
|
||||
xml:space="preserve"
|
||||
style="font-style:normal;font-weight:normal;font-size:37.49999619px;line-height:125%;font-family:sans-serif;letter-spacing:0px;word-spacing:0px;fill:#cd201f;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
|
||||
x="-4.6590595"
|
||||
y="208.67332"
|
||||
id="text3415"
|
||||
sodipodi:linespacing="125%"
|
||||
transform="matrix(0.86357335,-0.50422323,0.50422323,0.86357335,0,0)"><tspan
|
||||
sodipodi:role="line"
|
||||
id="tspan3417"
|
||||
x="-4.6590595"
|
||||
y="208.67332"
|
||||
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:29.29687309px;font-family:sans-serif;-inkscape-font-specification:sans-serif;fill:#cd201f;fill-opacity:1">BETA</tspan></text>
|
||||
<circle
|
||||
style="opacity:1;fill:url(#radialGradient4453);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:3.5;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
|
||||
id="path4445"
|
||||
cx="95.978127"
|
||||
cy="96.021866"
|
||||
r="88" />
|
||||
</svg>
|
After Width: | Height: | Size: 16 KiB |
Before Width: | Height: | Size: 346 B After Width: | Height: | Size: 346 B |
BIN
assets/bountysource_qr_code.png
Normal file
After Width: | Height: | Size: 1.2 KiB |
@ -3,6 +3,7 @@
|
||||
buildscript {
|
||||
repositories {
|
||||
jcenter()
|
||||
google()
|
||||
}
|
||||
dependencies {
|
||||
classpath 'com.android.tools.build:gradle:2.3.3'
|
||||
@ -16,7 +17,7 @@ allprojects {
|
||||
repositories {
|
||||
jcenter()
|
||||
maven { url 'https://jitpack.io' }
|
||||
maven { url 'https://maven.google.com' }
|
||||
google()
|
||||
maven { url 'https://clojars.org/repo' }
|
||||
}
|
||||
}
|
||||
|
Before Width: | Height: | Size: 302 KiB |
Before Width: | Height: | Size: 324 KiB |
Before Width: | Height: | Size: 399 KiB |
Before Width: | Height: | Size: 185 KiB |
Before Width: | Height: | Size: 241 KiB |
Before Width: | Height: | Size: 1.0 MiB |
Before Width: | Height: | Size: 865 KiB |
Before Width: | Height: | Size: 134 KiB |
Before Width: | Height: | Size: 476 KiB |
BIN
screenshots/shot_1.png
Normal file
After Width: | Height: | Size: 112 KiB |
BIN
screenshots/shot_10.png
Normal file
After Width: | Height: | Size: 40 KiB |
BIN
screenshots/shot_2.png
Normal file
After Width: | Height: | Size: 110 KiB |
BIN
screenshots/shot_3.png
Normal file
After Width: | Height: | Size: 263 KiB |
BIN
screenshots/shot_4.png
Normal file
After Width: | Height: | Size: 101 KiB |
BIN
screenshots/shot_5.png
Normal file
After Width: | Height: | Size: 122 KiB |
BIN
screenshots/shot_6.png
Normal file
After Width: | Height: | Size: 50 KiB |
BIN
screenshots/shot_7.png
Normal file
After Width: | Height: | Size: 88 KiB |
BIN
screenshots/shot_8.png
Normal file
After Width: | Height: | Size: 44 KiB |
BIN
screenshots/shot_9.png
Normal file
After Width: | Height: | Size: 74 KiB |