diff --git a/app/build.gradle b/app/build.gradle
index e548e70..2094f72 100644
--- a/app/build.gradle
+++ b/app/build.gradle
@@ -22,7 +22,6 @@ repositories {
android {
signingConfigs {
-
}
compileSdkVersion 28
buildToolsVersion '28.0.3'
@@ -30,16 +29,16 @@ android {
applicationId "app.exploitr.nsg.youp3"
minSdkVersion 19
targetSdkVersion 28
- versionCode 91020719
- versionName "1.1.0"
+ versionCode 91021030
+ versionName "1.1.2"
vectorDrawables.useSupportLibrary = true
multiDexEnabled true
}
buildTypes {
debug {
- /* minifyEnabled true
- shrinkResources true
- proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' */
+ minifyEnabled true
+ shrinkResources true
+ proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
signingConfig signingConfigs.config
}
release {
@@ -61,16 +60,16 @@ dependencies {
implementation('com.crashlytics.sdk.android:crashlytics:2.6.8@aar') {
transitive = true
}
- implementation 'androidx.appcompat:appcompat:1.0.2'
+ implementation 'androidx.appcompat:appcompat:1.1.0'
implementation 'com.google.android.material:material:1.0.0'
implementation 'androidx.annotation:annotation:1.1.0'
implementation 'androidx.constraintlayout:constraintlayout:1.1.3'
- implementation 'com.koushikdutta.ion:ion:2.2.1'
+ implementation 'com.koushikdutta.ion:ion:3.0.8'
implementation('com.github.wangjiegulu:rfab:2.0.0') {
exclude group: 'com.android.support'
}
- implementation 'com.github.HaarigerHarald:android-youtubeExtractor:v1.9.0'
+ implementation 'com.github.HaarigerHarald:android-youtubeExtractor:master-SNAPSHOT'
//noinspection GradleDependency
annotationProcessor 'com.google.auto.value:auto-value:1.1'
implementation('com.google.android.exoplayer:exoplayer:2.10.1') {
@@ -99,8 +98,9 @@ dependencies {
implementation 'io.reactivex.rxjava2:rxandroid:2.0.1'
implementation 'com.github.esafirm:rxdownloader:2.0.0'
implementation 'com.github.adrielcafe:AndroidAudioConverter:0.0.8'
- implementation ('com.obsez.android.lib.filechooser:filechooser:1.2.0'){
+ implementation('com.obsez.android.lib.filechooser:filechooser:1.2.0') {
exclude group: 'com.android.support'
}
+ implementation 'com.github.lzyzsd:circleprogress:1.2.1'
implementation 'org.greenrobot:eventbus:3.1.1'
}
diff --git a/app/fabric.properties b/app/fabric.properties
deleted file mode 100644
index 2b39b65..0000000
--- a/app/fabric.properties
+++ /dev/null
@@ -1,3 +0,0 @@
-#Contains API Secret used to validate your application. Commit to internal source control; avoid making secret public.
-#Wed Aug 23 16:41:43 IST 2017
-apiSecret=XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml
index d810d4b..7cc2f30 100644
--- a/app/src/main/AndroidManifest.xml
+++ b/app/src/main/AndroidManifest.xml
@@ -14,7 +14,7 @@
@@ -40,43 +40,43 @@
+ android:value="b531c330857e24f378d562b1176ce4574483c2be" />
diff --git a/app/src/main/java/app/exploitr/nsg/youp3/Book/BookMark.java b/app/src/main/java/app/exploitr/nsg/youp3/Book/BookMark.java
new file mode 100644
index 0000000..2b30a0a
--- /dev/null
+++ b/app/src/main/java/app/exploitr/nsg/youp3/Book/BookMark.java
@@ -0,0 +1,45 @@
+package app.exploitr.nsg.youp3.Book;
+
+import io.realm.RealmObject;
+import io.realm.annotations.PrimaryKey;
+
+public class BookMark extends RealmObject {
+
+ @PrimaryKey
+ private int id;
+ private String title;
+ private String url;
+ private String favicon;
+
+ public int getId() {
+ return id;
+ }
+
+ public void setId(int id) {
+ this.id = id;
+ }
+
+ public String getTitle() {
+ return title;
+ }
+
+ public void setTitle(String title) {
+ this.title = title;
+ }
+
+ public String getUrl() {
+ return url;
+ }
+
+ public void setUrl(String url) {
+ this.url = url;
+ }
+
+ public String getFavicon() {
+ return favicon;
+ }
+
+ public void setFavicon(String favicon) {
+ this.favicon = favicon;
+ }
+}
diff --git a/app/src/main/java/app/exploitr/nsg/youp3/Book/BookMarkAdapter.java b/app/src/main/java/app/exploitr/nsg/youp3/Book/BookMarkAdapter.java
new file mode 100644
index 0000000..ec8fedd
--- /dev/null
+++ b/app/src/main/java/app/exploitr/nsg/youp3/Book/BookMarkAdapter.java
@@ -0,0 +1,126 @@
+package app.exploitr.nsg.youp3.Book;
+
+import android.content.Context;
+import android.graphics.Bitmap;
+import android.graphics.BitmapFactory;
+import android.util.Base64;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.LinearLayout;
+import android.widget.TextView;
+
+import androidx.annotation.NonNull;
+import androidx.recyclerview.widget.RecyclerView;
+
+import com.mikhaellopez.circularimageview.CircularImageView;
+
+import java.util.List;
+
+import app.exploitr.nsg.youp3.R;
+
+
+
+/*
+ * Created by exploitr on 28-09-2017.
+ */
+
+public class BookMarkAdapter extends RecyclerView.Adapter {
+
+ private List mData;
+ private LayoutInflater mInflater;
+ private ItemClickListener mClickListener;
+ private ItemLongClickListener mLongClickListener;
+
+ public BookMarkAdapter(Context context, List data) {
+ this.mInflater = LayoutInflater.from(context);
+ this.mData = data;
+ }
+
+ public void notifyDataSetChangedCustom(List newdata) {
+ mData.clear();
+ mData.addAll(newdata);
+ this.notifyDataSetChanged();
+ }
+
+ @NonNull
+ @Override
+ public ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
+ View view = mInflater.inflate(R.layout.row_bookmarks_list_item, parent, false);
+ return new ViewHolder(view);
+ }
+
+ @Override
+ public void onBindViewHolder(@NonNull ViewHolder holder, int position) {
+ String[] x = mData.get(position).split(",");
+ holder.titleTextView.setText(x[1]);
+ holder.urlTextView.setText(x[2]);
+ holder.id = Integer.parseInt(x[0]);
+
+ byte[] decodedString = Base64.decode(x[3], Base64.DEFAULT);
+ Bitmap decodedByte = BitmapFactory.decodeByteArray(decodedString, 0, decodedString.length);
+
+ holder.favicon.setImageBitmap(decodedByte);
+ }
+
+ @Override
+ public int getItemCount() {
+ return mData.size();
+ }
+
+ public void setClickListener(ItemClickListener itemClickListener) {
+ this.mClickListener = itemClickListener;
+ }
+
+ public void setLongClickListener(ItemLongClickListener itemLongClickListener) {
+ this.mLongClickListener = itemLongClickListener;
+ }
+
+ public interface ItemClickListener {
+ void onOpenClick(String url);
+ }
+
+ public interface ItemLongClickListener {
+ void onDeleteClick(int id);
+ }
+
+ class ViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener, View.OnLongClickListener {
+ TextView urlTextView, titleTextView;
+ CircularImageView favicon;
+ LinearLayout clicker;
+ int id;
+
+ ViewHolder(View itemView) {
+ super(itemView);
+ id = 0;
+ urlTextView = itemView.findViewById(R.id.urlView);
+ titleTextView = itemView.findViewById(R.id.titleView);
+ favicon = itemView.findViewById(R.id.favicon);
+ clicker = itemView.findViewById(R.id.bookmarkClickable);
+
+ clicker.setOnClickListener(this);
+ clicker.setOnLongClickListener(this);
+ itemView.setOnClickListener(this);
+ }
+
+ @Override
+ public void onClick(View view) {
+ if (mClickListener != null) {
+ if (view.getId() == clicker.getId()) {
+ mClickListener.onOpenClick(urlTextView.getText().toString());
+ }
+ }
+ }
+
+ @Override
+ public boolean onLongClick(View view) {
+ if (mLongClickListener != null) {
+ if (view.getId() == clicker.getId()) {
+ mLongClickListener.onDeleteClick(id);
+ }
+ }
+ return true;
+ }
+ }
+
+}
diff --git a/app/src/main/java/app/exploitr/nsg/youp3/Book/BookMarkManager.java b/app/src/main/java/app/exploitr/nsg/youp3/Book/BookMarkManager.java
new file mode 100644
index 0000000..67df3df
--- /dev/null
+++ b/app/src/main/java/app/exploitr/nsg/youp3/Book/BookMarkManager.java
@@ -0,0 +1,50 @@
+package app.exploitr.nsg.youp3.Book;
+
+/*
+ * Created by exploitr on 25-09-2017.
+ *
+ * I've created a new instance for each getters.
+ * I don't know but think If the data is updated at the middle,
+ * an old instance wouldn't return the updated data
+ */
+
+import io.realm.Realm;
+
+public class BookMarkManager {
+
+ private Realm realm;
+
+ public BookMarkManager() {
+ realm = Realm.getDefaultInstance();
+ }
+
+ private BookRealmController getController() {
+ return new BookRealmController();
+ }
+
+ public void push(int id, String title, String url, String favicon) {
+ BookMark info = new BookMark();
+
+ info.setId(id);
+ info.setTitle(title);
+ info.setUrl(url);
+ info.setFavicon(favicon);
+
+ realm.beginTransaction();
+ realm.copyToRealmOrUpdate(info);
+ realm.commitTransaction();
+ }
+
+
+ public String getTitleById(int id) {
+ return getController().getBookMark(id).getTitle();
+ }
+
+ public int getTotalInfoCount() {
+ return getController().getBookMarks().size();
+ }
+
+ public void removeInfoById(int id) {
+ getController().deleteBookMark(id);
+ }
+}
diff --git a/app/src/main/java/app/exploitr/nsg/youp3/Book/BookRealmController.java b/app/src/main/java/app/exploitr/nsg/youp3/Book/BookRealmController.java
new file mode 100644
index 0000000..1868153
--- /dev/null
+++ b/app/src/main/java/app/exploitr/nsg/youp3/Book/BookRealmController.java
@@ -0,0 +1,48 @@
+package app.exploitr.nsg.youp3.Book;
+
+/*
+ * Created by exploitr on 27-09-2017.
+ */
+import com.crashlytics.android.Crashlytics;
+
+import java.util.Objects;
+
+import app.exploitr.nsg.youp3.ui_access.MainActivity;
+import io.realm.Realm;
+import io.realm.RealmResults;
+
+public class BookRealmController {
+
+ private final Realm realm;
+
+ public BookRealmController() {
+ realm = Realm.getDefaultInstance();
+ }
+
+ public Realm getRealm() {
+ return realm;
+ }
+
+ public RealmResults getBookMarks() {
+ return realm.where(BookMark.class).findAll();
+ }
+
+ BookMark getBookMark(int id) {
+ return realm.where(BookMark.class).equalTo("id", id).findFirst();
+ }
+
+ void deleteBookMark(int id) {
+ realm.beginTransaction();
+ try {
+ Objects.requireNonNull(realm.where(BookMark.class).equalTo("id", id).findFirst()).deleteFromRealm();
+ } catch (Exception ex) {
+ ex.printStackTrace();
+ if (MainActivity.isBuildFinal) {
+ Crashlytics.logException(ex);
+ }
+ }
+ realm.commitTransaction();
+ }
+
+}
+
diff --git a/app/src/main/java/app/exploitr/nsg/youp3/Book/Launcher.java b/app/src/main/java/app/exploitr/nsg/youp3/Book/Launcher.java
new file mode 100644
index 0000000..7cc3111
--- /dev/null
+++ b/app/src/main/java/app/exploitr/nsg/youp3/Book/Launcher.java
@@ -0,0 +1,35 @@
+package app.exploitr.nsg.youp3.Book;
+
+public class Launcher {
+ private static Launcher launcher;
+ private String url;
+ private boolean shouldLoad;
+
+ private Launcher() {
+ }
+
+ public static Launcher i() {
+ if (launcher != null) {
+ return launcher;
+ } else {
+ launcher = new Launcher();
+ return launcher;
+ }
+ }
+
+ public String getUrl() {
+ return url;
+ }
+
+ public void setUrl(String url) {
+ this.url = url;
+ }
+
+ public boolean isShouldLoad() {
+ return shouldLoad;
+ }
+
+ public void setShouldLoad(boolean shouldLoad) {
+ this.shouldLoad = shouldLoad;
+ }
+}
diff --git a/app/src/main/java/app/exploitr/nsg/youp3/Book/SimpleDivider.java b/app/src/main/java/app/exploitr/nsg/youp3/Book/SimpleDivider.java
new file mode 100644
index 0000000..56a0cd9
--- /dev/null
+++ b/app/src/main/java/app/exploitr/nsg/youp3/Book/SimpleDivider.java
@@ -0,0 +1,37 @@
+package app.exploitr.nsg.youp3.Book;
+
+import android.content.Context;
+import android.graphics.Canvas;
+import android.graphics.drawable.Drawable;
+import android.view.View;
+
+import androidx.recyclerview.widget.RecyclerView;
+
+import app.exploitr.nsg.youp3.R;
+
+public class SimpleDivider extends RecyclerView.ItemDecoration {
+ private Drawable mDivider;
+
+ public SimpleDivider(Context context) {
+ mDivider = context.getResources().getDrawable(R.drawable.line_divider);
+ }
+
+ @Override
+ public void onDrawOver(Canvas c, RecyclerView parent, RecyclerView.State state) {
+ int left = parent.getPaddingLeft();
+ int right = parent.getWidth() - parent.getPaddingRight();
+
+ int childCount = parent.getChildCount();
+ for (int i = 0; i < childCount; i++) {
+ View child = parent.getChildAt(i);
+
+ RecyclerView.LayoutParams params = (RecyclerView.LayoutParams) child.getLayoutParams();
+
+ int top = child.getBottom() + params.bottomMargin;
+ int bottom = top + mDivider.getIntrinsicHeight();
+
+ mDivider.setBounds(left, top, right, bottom);
+ mDivider.draw(c);
+ }
+ }
+}
diff --git a/app/src/main/java/app/exploitr/nsg/youp3/Book/VideoScreen.java b/app/src/main/java/app/exploitr/nsg/youp3/Book/VideoScreen.java
new file mode 100644
index 0000000..2c979bd
--- /dev/null
+++ b/app/src/main/java/app/exploitr/nsg/youp3/Book/VideoScreen.java
@@ -0,0 +1,66 @@
+package app.exploitr.nsg.youp3.Book;
+
+import android.annotation.SuppressLint;
+import android.content.Context;
+import android.graphics.Bitmap;
+import android.os.AsyncTask;
+import android.util.Base64;
+import android.util.SparseArray;
+
+import com.koushikdutta.ion.Ion;
+
+import java.io.ByteArrayOutputStream;
+import java.util.concurrent.ExecutionException;
+
+import at.huber.youtubeExtractor.VideoMeta;
+import at.huber.youtubeExtractor.YouTubeExtractor;
+import at.huber.youtubeExtractor.YtFile;
+
+public class VideoScreen {
+
+ private static VideoScreen screen;
+ private completeListener listener;
+ private String bow = "data:image/jpeg;base64,R0lGODlhAQABAIAAAAUEBAAAACwAAAAAAQABAAACAkQBADs=";
+ private String url;
+
+ private VideoScreen(String urlZero) {
+ this.url = urlZero;
+ }
+
+ public static VideoScreen load(String urlOne) {
+ screen = new VideoScreen(urlOne);
+ return screen;
+ }
+
+ @SuppressLint("StaticFieldLeak")
+ public VideoScreen start(final Context context) {
+ new YouTubeExtractor(context) {
+ @Override
+ public void onExtractionComplete(SparseArray ytFiles, VideoMeta vMeta) {
+ AsyncTask.execute(() -> {
+ try {
+ Bitmap bacterial = Ion.with(context).load(vMeta.getThumbUrl()).asBitmap().get();
+ ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
+ bacterial.compress(Bitmap.CompressFormat.JPEG, 100, byteArrayOutputStream);
+ byte[] byteArray = byteArrayOutputStream.toByteArray();
+ bow = Base64.encodeToString(byteArray, Base64.DEFAULT);
+ listener.onComplete(bow);
+ } catch (InterruptedException | ExecutionException e) {
+ e.printStackTrace();
+ listener.onComplete(bow);
+ }
+ });
+ }
+ }.extract(url, false, false);
+ screen.url = null;
+ return this;
+ }
+
+ public void setOnCompleteListener(completeListener completeListener) {
+ this.listener = completeListener;
+ }
+
+ public interface completeListener {
+ void onComplete(String what);
+ }
+}
diff --git a/app/src/main/java/app/exploitr/nsg/youp3/ui_access/AboutActivity.java b/app/src/main/java/app/exploitr/nsg/youp3/ui_access/AboutActivity.java
new file mode 100644
index 0000000..50c0b71
--- /dev/null
+++ b/app/src/main/java/app/exploitr/nsg/youp3/ui_access/AboutActivity.java
@@ -0,0 +1,107 @@
+package app.exploitr.nsg.youp3.ui_access;
+
+
+import android.content.Intent;
+import android.net.Uri;
+import android.os.Bundle;
+
+import androidx.appcompat.app.AppCompatActivity;
+
+import java.util.Objects;
+
+import app.exploitr.nsg.youp3.R;
+import de.psdev.licensesdialog.LicensesDialog;
+import de.psdev.licensesdialog.licenses.ApacheSoftwareLicense20;
+import de.psdev.licensesdialog.licenses.GnuGeneralPublicLicense30;
+import de.psdev.licensesdialog.licenses.MITLicense;
+import de.psdev.licensesdialog.model.Notice;
+import de.psdev.licensesdialog.model.Notices;
+
+public class AboutActivity extends AppCompatActivity {
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ setContentView(R.layout.activity_about);
+
+ Objects.requireNonNull(getSupportActionBar()).setTitle("About");
+
+ findViewById(R.id.OK).setOnClickListener(v -> finish());
+
+ findViewById(R.id.url).setOnClickListener(v -> {
+ Intent intent = new Intent(Intent.ACTION_VIEW, Uri.parse("https://exploitrme.wordpress.com/"));
+ intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+ startActivity(intent);
+ });
+
+ findViewById(R.id.giturl).setOnClickListener(v -> {
+ Intent intent = new Intent(Intent.ACTION_VIEW, Uri.parse("https://github.com/exploitr/youp3"));
+ intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+ startActivity(intent);
+ });
+
+ findViewById(R.id.osl).setOnClickListener(v -> {
+ Notices notices = new Notices();
+ notices.addNotice(new Notice("Apache Commons IO",
+ "https://commons.apache.org/proper/commons-io/",
+ "Apache.org",
+ new ApacheSoftwareLicense20()));
+ notices.addNotice(new Notice("Android Support Libraries",
+ "https://developer.android.com/topic/libraries/support-library/packages",
+ "Google",
+ new ApacheSoftwareLicense20()));
+ notices.addNotice(new Notice("Ion",
+ "https://github.com/koush/ion/",
+ "Koushik Dutta",
+ new ApacheSoftwareLicense20()));
+ notices.addNotice(new Notice("RapidFloatingActionButton",
+ "https://github.com/wangjiegulu/RapidFloatingActionButton",
+ "Wang Jie",
+ new ApacheSoftwareLicense20()));
+ notices.addNotice(new Notice("Android-Youtube-Extractor",
+ "https://github.com/HaarigerHarald/android-youtubeExtractor",
+ " Benjamin Huber",
+ new MITLicense()));
+ notices.addNotice(new Notice("Exoplayer",
+ "https://github.com/google/ExoPlayer",
+ "Google",
+ new ApacheSoftwareLicense20()));
+ notices.addNotice(new Notice("Android-Toggle-Switch",
+ "https://github.com/daisho-wakazashi/android-toggle-switch",
+ " Copyright (c) 2017 Lorenzo Rigato", new MITLicense()));
+ notices.addNotice(new Notice("CircularImageView",
+ "https://github.com/lopspower/CircularImageView",
+ "Lopez Mikhael", new ApacheSoftwareLicense20()));
+ notices.addNotice(new Notice("ffmpeg-android-java",
+ "https://github.com/WritingMinds/ffmpeg-android-java",
+ "WritingMinds", new GnuGeneralPublicLicense30()));
+ notices.addNotice(new Notice("Android-DirectoryChooser",
+ "https://github.com/passy/Android-DirectoryChooser",
+ "Copyright 2013-2016 Pascal Hartig", new ApacheSoftwareLicense20()));
+ notices.addNotice(new Notice("material-intro-screen",
+ "https://github.com/DreierF/material-intro-screen",
+ "Florian Dreier", new MITLicense()));
+ notices.addNotice(new Notice("TapTargetView",
+ "https://github.com/KeepSafe/TapTargetView",
+ "Copyright 2016 Keepsafe Software Inc.", new ApacheSoftwareLicense20()));
+ notices.addNotice(new Notice("EventBus",
+ "https://github.com/greenrobot/EventBus",
+ "Markus Junginger", new ApacheSoftwareLicense20()));
+
+
+ new LicensesDialog.Builder(AboutActivity.this)
+ .setNotices(notices)
+ .setIncludeOwnLicense(true)
+ .build()
+ .show();
+ });
+
+ }
+
+ @Override
+ public void finish() {
+ super.finish();
+ overridePendingTransition(0, R.anim.enter);
+ }
+}
+
diff --git a/app/src/main/java/app/exploitr/nsg/youp3/ui_access/AudioConverter.java b/app/src/main/java/app/exploitr/nsg/youp3/ui_access/AudioConverter.java
new file mode 100644
index 0000000..a84e130
--- /dev/null
+++ b/app/src/main/java/app/exploitr/nsg/youp3/ui_access/AudioConverter.java
@@ -0,0 +1,189 @@
+package app.exploitr.nsg.youp3.ui_access;
+
+import android.content.Intent;
+import android.os.Build;
+import android.os.Bundle;
+import android.os.Handler;
+import android.os.Looper;
+import android.widget.EditText;
+import android.widget.ImageButton;
+import android.widget.RadioButton;
+import android.widget.RadioGroup;
+import android.widget.Toast;
+
+import androidx.appcompat.app.AlertDialog;
+import androidx.appcompat.app.AppCompatActivity;
+
+import com.google.android.material.floatingactionbutton.FloatingActionButton;
+import com.obsez.android.lib.filechooser.ChooserDialog;
+
+import java.io.File;
+
+import app.exploitr.nsg.youp3.R;
+import cafe.adriel.androidaudioconverter.AndroidAudioConverter;
+import cafe.adriel.androidaudioconverter.callback.ILoadCallback;
+import converter.utils.ConverterService;
+import utils.DataStore;
+import utils.YouWorker;
+
+public class AudioConverter extends AppCompatActivity {
+
+ public static final String INPUT_ = "input";
+ public static final String OUTPUT_ = "output";
+ public static final String ID_ = "id";
+ public static boolean isConversionRunning = false;
+ AlertDialog alertDialog, convDialog;
+ RadioGroup radioGroup;
+ EditText input, output;
+ ImageButton inputAddr, outputAddr;
+ FloatingActionButton go_convert;
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ setContentView(R.layout.activity_audio_converter);
+
+ alertDialog = dialog();
+ convDialog = converter_dialog();
+
+ radioGroup = findViewById(R.id.r_group);
+ input = findViewById(R.id.inputAddr);
+ output = findViewById(R.id.outputAddr);
+ inputAddr = findViewById(R.id.inputAddrEditor);
+ outputAddr = findViewById(R.id.outputAddrEditor);
+ go_convert = findViewById(R.id.conv_go);
+
+ radioGroup.check(R.id.mp3);
+ radioGroup.setOnCheckedChangeListener((group, checkedId) -> Toast.makeText(this, ((RadioButton) findViewById(checkedId)).getText(), Toast.LENGTH_SHORT).show());
+
+ if (getSupportActionBar() != null) {
+ getSupportActionBar().setTitle("Audio Converter (Beta)");
+ }
+
+ new Handler(Looper.getMainLooper()).postDelayed(() -> {
+ if (!YouWorker.IS_CONVERSION_SUPPORTED && !AudioConverter.this.isFinishing()) {
+ alertDialog.show();
+ checkSupportForConversion();
+ }
+ }, 300);
+
+
+ inputAddr.setOnClickListener(v -> new ChooserDialog(AudioConverter.this)
+ .withStartFile(DataStore.getInstance(getBaseContext()).getPathDownload())
+ .withChosenListener((path, pathFile) -> input.setText(path))
+ .withOnCancelListener(dialog -> {
+ Toast.makeText(this, "Nothing Selected :-(", Toast.LENGTH_SHORT).show();
+ dialog.cancel(); // MUST have
+ })
+ .build()
+ .show());
+
+ outputAddr.setOnClickListener(v -> new ChooserDialog(AudioConverter.this)
+ .withFilter(true, false)
+ .withStartFile(DataStore.getInstance(getBaseContext()).getPathDownload())
+ .withChosenListener((path, pathFile) -> output.setText(path))
+ .build()
+ .show());
+
+ go_convert.setOnClickListener(v -> {
+ if (YouWorker.IS_CONVERSION_SUPPORTED) {
+ if (!isConversionRunning) {
+ if (new File(input.getText().toString()).exists() && new File(input.getText().toString()).canRead()) {
+ if (new File(output.getText().toString()).canWrite()) {
+ Intent con_Int = new Intent(AudioConverter.this, ConverterService.class)
+ .putExtra(INPUT_, input.getText().toString())
+ .putExtra(OUTPUT_, output.getText().toString())
+ .putExtra(ID_, radioGroup.getCheckedRadioButtonId());
+ AudioConverter.isConversionRunning = true;
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
+ startForegroundService(con_Int);
+ } else {
+ startService(con_Int);
+ }
+ } else {
+ Toast.makeText(this, "Can't Write Output Directory", Toast.LENGTH_SHORT).show();
+ }
+ } else {
+ Toast.makeText(this, "Invalid input file", Toast.LENGTH_SHORT).show();
+ }
+ } else {
+ Toast.makeText(this, "Pending Conversion.. Wait For Finish", Toast.LENGTH_SHORT).show();
+ }
+ } else {
+ Toast.makeText(this, "Conversion not supported on this device", Toast.LENGTH_SHORT).show();
+ }
+ });
+ }
+
+ @Override
+ protected void onResume() {
+ startChecking();
+ super.onResume();
+ }
+
+ @Override
+ protected void onPause() {
+ alertDialog.dismiss();
+ convDialog.dismiss();
+ super.onPause();
+ }
+
+ private void startChecking() {
+ Handler handler = new Handler();
+ new Handler().post(new Runnable() {
+ @Override
+ public void run() {
+ if (convDialog.isShowing() && !AudioConverter.isConversionRunning) {
+ convDialog.dismiss();
+ }
+ if (!convDialog.isShowing() && AudioConverter.isConversionRunning) {
+ convDialog.show();
+ }
+ handler.postDelayed(this, 250);
+ }
+ });
+ }
+
+ private void checkSupportForConversion() {
+ AndroidAudioConverter.load(this, new ILoadCallback() {
+ @Override
+ public void onSuccess() {
+ if (alertDialog.isShowing())
+ alertDialog.dismiss();
+ YouWorker.IS_CONVERSION_SUPPORTED = true;
+ }
+
+ @Override
+ public void onFailure(Exception error) {
+ if (alertDialog.isShowing())
+ alertDialog.dismiss();
+ YouWorker.IS_CONVERSION_SUPPORTED = false;
+ AlertDialog localDialog = new AlertDialog.Builder(AudioConverter.this)
+ .setTitle("Error")
+ .setMessage("This device currently doesn't support Audio Conversion.")
+ .setCancelable(false)
+ .setPositiveButton("Ok", (dialog, which) -> finish())
+ .create();
+ if (!AudioConverter.this.isFinishing()) {
+ localDialog.show();
+ }
+ }
+ });
+ }
+
+
+ private AlertDialog converter_dialog() {
+ return new AlertDialog.Builder(this)
+ .setView(R.layout.convert_progress)
+ .setCancelable(false)
+ .create();
+ }
+
+ private AlertDialog dialog() {
+ return new AlertDialog.Builder(this)
+ .setView(R.layout.dialog_progress)
+ .setCancelable(false)
+ .create();
+ }
+
+}
diff --git a/app/src/main/java/app/exploitr/nsg/youp3/ui_access/BASwitcher.java b/app/src/main/java/app/exploitr/nsg/youp3/ui_access/BASwitcher.java
new file mode 100644
index 0000000..73cc9ce
--- /dev/null
+++ b/app/src/main/java/app/exploitr/nsg/youp3/ui_access/BASwitcher.java
@@ -0,0 +1,66 @@
+package app.exploitr.nsg.youp3.ui_access;
+
+
+import android.content.Intent;
+import android.os.Bundle;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+
+import androidx.annotation.Nullable;
+
+import com.llollox.androidtoggleswitch.widgets.ToggleSwitch;
+
+import org.jetbrains.annotations.NotNull;
+
+import app.exploitr.nsg.youp3.R;
+import app.exploitr.nsg.youp3.ui_access.MainActivity;
+import io.github.dreierf.materialintroscreen.SlideFragment;
+import utils.DataStore;
+
+public class BASwitcher extends SlideFragment {
+ private boolean ok = false;
+
+ @Nullable
+ @Override
+ public View onCreateView(@NotNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
+ final View view = inflater.inflate(R.layout.slide_for_bas, container, false);
+ ((ToggleSwitch) view.findViewById(R.id.basicAdv_switch)).setOnChangeListener(position -> {
+ DataStore.getInstance(view.getContext()).setAdvancedDownloadMode(position == 1);
+ ok = true;
+ });
+ return view;
+ }
+
+ @Override
+ public int backgroundColor() {
+ return android.R.color.white;
+ }
+
+ @Override
+ public int buttonsColor() {
+ return android.R.color.black;
+ }
+
+ @Override
+ public boolean canMoveFurther() {
+ return ok;
+ }
+
+ @Override
+ public void onDestroyView() {
+ DataStore.getInstance(getContext()).setNewUserNoMoreForSPLASH();
+ startActivity(new Intent(getActivity(), MainActivity.class));
+ super.onDestroyView();
+ }
+
+ @Override
+ public String cantMoveFurtherErrorMessage() {
+ return "Please Select One Default Mode";
+ }
+
+ @Override
+ public void onDestroy() {
+ super.onDestroy();
+ }
+}
diff --git a/app/src/main/java/app/exploitr/nsg/youp3/ui_access/BookMarkActivity.java b/app/src/main/java/app/exploitr/nsg/youp3/ui_access/BookMarkActivity.java
new file mode 100644
index 0000000..92db37e
--- /dev/null
+++ b/app/src/main/java/app/exploitr/nsg/youp3/ui_access/BookMarkActivity.java
@@ -0,0 +1,152 @@
+package app.exploitr.nsg.youp3.ui_access;
+
+
+import android.content.Context;
+import android.os.Build;
+import android.os.Bundle;
+import android.os.Handler;
+import android.os.Looper;
+import android.os.VibrationEffect;
+import android.os.Vibrator;
+import android.view.Menu;
+import android.view.MenuItem;
+import android.view.View;
+import android.widget.TextView;
+
+import androidx.appcompat.app.AlertDialog;
+import androidx.appcompat.app.AppCompatActivity;
+import androidx.core.content.ContextCompat;
+import androidx.recyclerview.widget.LinearLayoutManager;
+import androidx.recyclerview.widget.RecyclerView;
+
+import com.google.android.material.snackbar.Snackbar;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import app.exploitr.nsg.youp3.Book.BookMark;
+import app.exploitr.nsg.youp3.Book.BookMarkAdapter;
+import app.exploitr.nsg.youp3.Book.BookMarkManager;
+import app.exploitr.nsg.youp3.Book.BookRealmController;
+import app.exploitr.nsg.youp3.Book.Launcher;
+import app.exploitr.nsg.youp3.Book.SimpleDivider;
+import app.exploitr.nsg.youp3.R;
+import utils.DataStore;
+
+public class BookMarkActivity extends AppCompatActivity {
+
+ TextView noBook;
+ RecyclerView books;
+ BookMarkAdapter adapter;
+ Handler handler;
+ Runnable runnable;
+ Snackbar bar;
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ setContentView(R.layout.activity_book_mark);
+
+ books = findViewById(R.id.bookedItems);
+ noBook = findViewById(R.id.noBookText);
+
+ books.setLayoutManager(new LinearLayoutManager(BookMarkActivity.this));
+ books.addItemDecoration(new SimpleDivider(BookMarkActivity.this));
+
+ List dex = getInfoInArrayList();
+ adapter = new BookMarkAdapter(BookMarkActivity.this, dex);
+
+ adapter.setClickListener(url -> {
+ Launcher.i().setUrl(url);
+ Launcher.i().setShouldLoad(true);
+ finish();
+ });
+
+ adapter.setLongClickListener(id -> {
+ Vibrator v = (Vibrator) getSystemService(Context.VIBRATOR_SERVICE);
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
+ if (v != null) {
+ v.vibrate(VibrationEffect.createOneShot(500, VibrationEffect.DEFAULT_AMPLITUDE));
+ }
+ } else {
+ if (v != null) {
+ v.vibrate(500);
+ }
+ }
+ final String book = new BookMarkManager().getTitleById(id);
+ new AlertDialog.Builder(BookMarkActivity.this)
+ .setTitle("Remove BookMark")
+ .setMessage("Remove " + book + "?")
+ .setNegativeButton("Nope", null)
+ .setPositiveButton("Ya", (dialog, which) -> {
+ new BookMarkManager().removeInfoById(id);
+ adapter.notifyDataSetChangedCustom(getInfoInArrayList());
+ }).show();
+ });
+
+ books.setAdapter(adapter);
+ adapter.notifyDataSetChanged();
+
+ handler = new Handler(Looper.getMainLooper());
+ runnable = () -> {
+ if (getSupportActionBar() != null) {
+ getSupportActionBar().setTitle("BookMarks (" + new BookMarkManager().getTotalInfoCount() + ")");
+ }
+
+ if (new BookMarkManager().getTotalInfoCount() == 0) {
+ books.setVisibility(View.GONE);
+ noBook.setVisibility(View.VISIBLE);
+ } else {
+ books.setVisibility(View.VISIBLE);
+ noBook.setVisibility(View.GONE);
+ }
+ handler.postDelayed(runnable, 100);
+ };
+ handler.post(runnable);
+
+ if (DataStore.getInstance(getBaseContext()).isNewUserForBOOKMARK()) {
+ bar = Snackbar.make(getWindow().getDecorView(), "Single Press To Open , Long Press To Remove", Snackbar.LENGTH_INDEFINITE)
+ .setActionTextColor(ContextCompat.getColor(getApplicationContext(), R.color.themeDef_dark))
+ .setAction("Understand", v -> bar.dismiss());
+ bar.show();
+ DataStore.getInstance(getBaseContext()).setNewUserNoMoreForBOOKMARK();
+ }
+ }
+
+ private ArrayList getInfoInArrayList() {
+ ArrayList all = new ArrayList<>();
+ for (BookMark info : new BookRealmController().getBookMarks()) {
+ all.add(info.getId() + "," + info.getTitle() + "," + info.getUrl() + "," + info.getFavicon());
+ }
+ return all;
+ }
+
+ @Override
+ public boolean onCreateOptionsMenu(Menu menu) {
+ getMenuInflater().inflate(R.menu.clear_one,menu);
+ return super.onCreateOptionsMenu(menu);
+ }
+
+ @Override
+ public boolean onOptionsItemSelected(MenuItem item) {
+ new AlertDialog.Builder(BookMarkActivity.this)
+ .setTitle("Check!")
+ .setMessage("Are you sure to clear all downloads? It will also remove current downloads.")
+ .setPositiveButton("Ok", (dialog, which) -> {
+ for (String x : getInfoInArrayList()) {
+ String[] y = x.split(",");
+ new BookMarkManager().removeInfoById(Integer.parseInt(y[0]));
+ }
+ adapter.notifyDataSetChangedCustom(getInfoInArrayList());
+ }).setNegativeButton("nope", null)
+ .show();
+ return super.onOptionsItemSelected(item);
+ }
+
+ @Override
+ protected void onDestroy() {
+ handler.removeCallbacks(runnable);
+ super.onDestroy();
+ }
+
+}
diff --git a/app/src/main/java/app/exploitr/nsg/youp3/ui_access/BottomSheetFragment.java b/app/src/main/java/app/exploitr/nsg/youp3/ui_access/BottomSheetFragment.java
new file mode 100644
index 0000000..d725483
--- /dev/null
+++ b/app/src/main/java/app/exploitr/nsg/youp3/ui_access/BottomSheetFragment.java
@@ -0,0 +1,265 @@
+package app.exploitr.nsg.youp3.ui_access;
+
+
+import android.os.Bundle;
+import android.text.Editable;
+import android.text.TextWatcher;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.Button;
+import android.widget.EditText;
+import android.widget.Toast;
+
+import androidx.annotation.NonNull;
+import androidx.appcompat.app.AlertDialog;
+
+import com.google.android.material.bottomsheet.BottomSheetDialogFragment;
+
+import java.security.SecureRandom;
+import java.util.Locale;
+import java.util.concurrent.TimeUnit;
+
+import app.exploitr.nsg.youp3.R;
+import at.huber.youtubeExtractor.VideoMeta;
+import at.huber.youtubeExtractor.YtFile;
+import downloader.utils.Queue;
+import downloader.utils.QueueObject;
+import downloads.FileHolder;
+import downloads.HolderObject;
+import utils.Helper;
+
+@SuppressWarnings("ConstantConditions")
+public class BottomSheetFragment extends BottomSheetDialogFragment {
+
+ private FileHolder holder;
+ private VideoMeta videoMeta;
+ private String youtubeUrl;
+
+ public BottomSheetFragment() {
+ // Required empty public constructor
+ }
+
+ @Override
+ public void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ }
+
+ public BottomSheetFragment prepare(VideoMeta meta, String youUrl) {
+ holder = new FileHolder();
+ videoMeta = meta;
+ youtubeUrl = youUrl;
+ return this;
+ }
+
+ public void setupDialogData(YtFile file, int type) {
+ holder.add(new HolderObject().setFile(file).setType(type));
+ }
+
+ @Override
+ public int getTheme() {
+ return R.style.BottomSheetDialogTheme;
+ }
+
+ @Override
+ public View onCreateView(@NonNull LayoutInflater inflater, ViewGroup container,
+ Bundle savedInstanceState) {
+ View download_sheet = inflater.inflate(R.layout.advanced_download_item, container, false);
+
+ Button aud_64k = download_sheet.findViewById(R.id._64);
+ Button aud_96k = download_sheet.findViewById(R.id._96);
+ Button aud_128k = download_sheet.findViewById(R.id._128);
+ Button aud_160k = download_sheet.findViewById(R.id._160);
+ Button aud_192k = download_sheet.findViewById(R.id._192);
+
+ Button vid_144p = download_sheet.findViewById(R.id._144p);
+ Button vid_240p = download_sheet.findViewById(R.id._240p);
+ Button vid_320p = download_sheet.findViewById(R.id._360p);
+ Button vid_480p = download_sheet.findViewById(R.id._480p);
+ Button vid_720p = download_sheet.findViewById(R.id._720p);
+ Button vid_1080p = download_sheet.findViewById(R.id._1080p);
+ Button vid_1440p = download_sheet.findViewById(R.id._1440p);
+ Button vid_2160p = download_sheet.findViewById(R.id._2160p);
+
+ Button vid_144p_silent = download_sheet.findViewById(R.id._144p_silent);
+ Button vid_240p_silent = download_sheet.findViewById(R.id._240p_silent);
+ Button vid_320p_silent = download_sheet.findViewById(R.id._360p_silent);
+ Button vid_480p_silent = download_sheet.findViewById(R.id._480p_silent);
+ Button vid_720p_silent = download_sheet.findViewById(R.id._720p_silent);
+ Button vid_1080p_silent = download_sheet.findViewById(R.id._1080p_silent);
+ Button vid_1440p_silent = download_sheet.findViewById(R.id._1440p_silent);
+ Button vid_2160p_silent = download_sheet.findViewById(R.id._2160p_silent);
+
+ for (HolderObject object : holder) {
+
+ //
+ final View.OnClickListener onClickListener = v -> ready(object.getYtFile(), object.getType());
+ if (object.getType() == FileHolder.TYPE_AUDIO) {
+ if (object.getYtFile().getFormat().getAudioBitrate() == 64) {
+ aud_64k.setEnabled(true);
+ aud_64k.setOnClickListener(onClickListener);
+ } else if (object.getYtFile().getFormat().getAudioBitrate() == 96) {
+ aud_96k.setEnabled(true);
+ aud_96k.setOnClickListener(onClickListener);
+ } else if (object.getYtFile().getFormat().getAudioBitrate() == 128) {
+ aud_128k.setEnabled(true);
+ aud_128k.setOnClickListener(onClickListener);
+ } else if (object.getYtFile().getFormat().getAudioBitrate() == 160) {
+ aud_160k.setEnabled(true);
+ aud_160k.setOnClickListener(onClickListener);
+ } else if (object.getYtFile().getFormat().getAudioBitrate() == 192) {
+ aud_192k.setEnabled(true);
+ aud_192k.setOnClickListener(onClickListener);
+ }
+ }
+ //
+
+ //
+ if (object.getType() == FileHolder.TYPE_VIDEO) {
+ if (object.getYtFile().getFormat().getHeight() == 144) {
+ vid_144p.setEnabled(true);
+ vid_144p.setOnClickListener(onClickListener);
+ } else if (object.getYtFile().getFormat().getHeight() == 240) {
+ vid_240p.setEnabled(true);
+ vid_240p.setOnClickListener(onClickListener);
+ } else if (object.getYtFile().getFormat().getHeight() == 360) {
+ vid_320p.setEnabled(true);
+ vid_320p.setOnClickListener(onClickListener);
+ } else if (object.getYtFile().getFormat().getHeight() == 480) {
+ vid_480p.setEnabled(true);
+ vid_480p.setOnClickListener(onClickListener);
+ } else if (object.getYtFile().getFormat().getHeight() == 720) {
+ vid_720p.setEnabled(true);
+ vid_720p.setOnClickListener(onClickListener);
+ } else if (object.getYtFile().getFormat().getHeight() == 1080) {
+ vid_1080p.setEnabled(true);
+ vid_1080p.setOnClickListener(onClickListener);
+ } else if (object.getYtFile().getFormat().getHeight() == 1440) {
+ vid_1440p.setEnabled(true);
+ vid_1440p.setOnClickListener(onClickListener);
+ } else if (object.getYtFile().getFormat().getHeight() == 2160) {
+ vid_2160p.setEnabled(true);
+ vid_2160p.setOnClickListener(onClickListener);
+ }
+ }
+ //
+
+ //
+ if (object.getType() == FileHolder.TYPE_VIDEO_SILENT) {
+ if (object.getYtFile().getFormat().getHeight() == 144) {
+ vid_144p_silent.setEnabled(true);
+ vid_144p_silent.setOnClickListener(onClickListener);
+ } else if (object.getYtFile().getFormat().getHeight() == 240) {
+ vid_240p_silent.setEnabled(true);
+ vid_240p_silent.setOnClickListener(onClickListener);
+ } else if (object.getYtFile().getFormat().getHeight() == 360) {
+ vid_320p_silent.setEnabled(true);
+ vid_320p_silent.setOnClickListener(onClickListener);
+ } else if (object.getYtFile().getFormat().getHeight() == 480) {
+ vid_480p_silent.setEnabled(true);
+ vid_480p_silent.setOnClickListener(onClickListener);
+ } else if (object.getYtFile().getFormat().getHeight() == 720) {
+ vid_720p_silent.setEnabled(true);
+ vid_720p_silent.setOnClickListener(onClickListener);
+ } else if (object.getYtFile().getFormat().getHeight() == 1080) {
+ vid_1080p_silent.setEnabled(true);
+ vid_1080p_silent.setOnClickListener(onClickListener);
+ } else if (object.getYtFile().getFormat().getHeight() == 1440) {
+ vid_1440p_silent.setEnabled(true);
+ vid_1440p_silent.setOnClickListener(onClickListener);
+ } else if (object.getYtFile().getFormat().getHeight() == 2160) {
+ vid_2160p_silent.setEnabled(true);
+ vid_2160p_silent.setOnClickListener(onClickListener);
+ }
+ }
+ //ī
+ }
+ return download_sheet;
+ }
+
+
+ private void ready(YtFile ytFile, int type) {
+ new AlertDialog.Builder(getActivity())
+ .setTitle("Download Information")
+ .setCancelable(false)
+ .setMessage(displayed(type, videoMeta))
+ .setPositiveButton("Download", (dialog, which) -> {
+
+ View fileName = getLayoutInflater().inflate(R.layout._download_filename, null);
+
+ EditText file = fileName.findViewById(R.id.fileName);
+ file.setText(Helper.getFilenameFromString(videoMeta.getTitle()));
+ file.addTextChangedListener(watcher(fileName.findViewById(R.id.in_val_ch)));
+
+ new AlertDialog.Builder(getActivity())
+ .setView(fileName)
+ .setPositiveButton("Ok", (dialog1, which1) -> download(file.getText().toString(), ytFile))
+ .setNegativeButton("Cancel", (dialog12, which12) -> Toast.makeText(getContext(), "Download Cancelled", Toast.LENGTH_SHORT).show())
+ .show();
+ })
+ .setNegativeButton("Cancel", (v, x) -> v.dismiss())
+ .show();
+ }
+
+
+ /* Converts milli time to conventional format */
+ private static String getTimeStamp(long value) {
+ return String.format(Locale.US, "%d hours,%d min, %d sec", TimeUnit.SECONDS.toHours(value),
+ TimeUnit.SECONDS.toMinutes(value - TimeUnit.HOURS.toSeconds(TimeUnit.SECONDS.toHours(value))),
+ value - (TimeUnit.MINUTES.toSeconds(
+ TimeUnit.SECONDS.toMinutes(value - TimeUnit.HOURS.toSeconds(TimeUnit.SECONDS.toHours(value)))
+ ) + TimeUnit.HOURS.toSeconds(TimeUnit.SECONDS.toHours(value)))
+ );
+ }
+
+
+ /* Warns if there is a illegal character in filename */
+ private static TextWatcher watcher(View validView) {
+ return new TextWatcher() {
+ @Override
+ public void beforeTextChanged(CharSequence s, int start, int count, int after) {
+
+ }
+
+ @Override
+ public void onTextChanged(CharSequence s, int start, int before, int count) {
+
+ }
+
+ @Override
+ public void afterTextChanged(Editable s) {
+ if (!Helper.fileNameReady(s.toString())) {
+ validView.setVisibility(View.VISIBLE);
+ } else {
+ validView.setVisibility(View.INVISIBLE);
+ }
+ }
+ };
+ }
+
+ private static String displayed(int type, VideoMeta videoMeta) {
+ return "Download : " + videoMeta.getTitle() + "\n\n"
+ + "Author : " + videoMeta.getAuthor() + "\n"
+ + "Length : " + getTimeStamp(videoMeta.getVideoLength()) + "\n\n"
+ + "Type : " + (type == FileHolder.TYPE_AUDIO ? "Audio" : "Video") +
+ (type == FileHolder.TYPE_VIDEO_SILENT ? " | Silent" : "");
+ }
+
+ /* Proceed To Download */
+ private void download(String fileName, YtFile ytFile) {
+ if (Helper.fileNameReady(fileName)) {
+ QueueObject object = new QueueObject();
+ object.setId(new SecureRandom().nextInt(1024));
+ object.setName(fileName);
+ object.setUrl(ytFile.getUrl());
+ object.setExt(ytFile.getFormat().getExt());
+ object.setYtUrl(youtubeUrl);
+
+ Queue.getInstance().add(object);
+ this.dismiss();
+ } else {
+ Toast.makeText(getContext(), "Invalid Filename, Dont use special characters", Toast.LENGTH_SHORT).show();
+ }
+ }
+
+}
diff --git a/app/src/main/java/app/exploitr/nsg/youp3/ui_access/DownloadsActivity.java b/app/src/main/java/app/exploitr/nsg/youp3/ui_access/DownloadsActivity.java
new file mode 100644
index 0000000..34d1eec
--- /dev/null
+++ b/app/src/main/java/app/exploitr/nsg/youp3/ui_access/DownloadsActivity.java
@@ -0,0 +1,255 @@
+package app.exploitr.nsg.youp3.ui_access;
+
+
+import android.annotation.SuppressLint;
+import android.content.Intent;
+import android.content.res.Configuration;
+import android.net.Uri;
+import android.os.Bundle;
+import android.os.Handler;
+import android.view.Menu;
+import android.view.MenuItem;
+import android.view.View;
+import android.widget.TextView;
+
+import androidx.appcompat.app.AlertDialog;
+import androidx.appcompat.app.AppCompatActivity;
+import androidx.appcompat.widget.SwitchCompat;
+import androidx.core.content.ContextCompat;
+import androidx.recyclerview.widget.LinearLayoutManager;
+import androidx.recyclerview.widget.RecyclerView;
+
+import com.esafirm.rxdownloader.RxDownloader;
+import com.google.android.material.snackbar.Snackbar;
+
+import org.apache.commons.io.FilenameUtils;
+import org.greenrobot.eventbus.EventBus;
+import org.greenrobot.eventbus.Subscribe;
+import org.greenrobot.eventbus.ThreadMode;
+
+import java.io.File;
+import java.util.ArrayList;
+
+import utils.MediaPlayer;
+import app.exploitr.nsg.youp3.R;
+import downloads.DownloadHistoryManager;
+import downloads.DownloadsAdapter;
+import downloads.RealmController;
+import downloads.VideoInfo;
+import utils.Helper;
+import utils.IPC;
+
+@SuppressLint("InflateParams")
+public class DownloadsActivity extends AppCompatActivity {
+
+ private static boolean isRunning = false;
+ private Handler mHandler;
+ private Runnable mHandlerTask;
+ private DownloadsAdapter adapter;
+ private Configuration configuration;
+ private RecyclerView recyclerView;
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ setContentView(R.layout.activity_downloads);
+
+ mHandler = new Handler();
+
+ configuration = new Configuration();
+ configuration.orientation = getResources().getConfiguration().orientation;
+
+ if (getSupportActionBar() != null) {
+ getSupportActionBar().setTitle("Downloads (" + new DownloadHistoryManager().getTotalInfoCount() + ")");
+ }
+
+ recyclerView = findViewById(R.id.downloadedItems);
+
+ if (new DownloadHistoryManager().getTotalInfoCount() == 0) {
+ recyclerView.setVisibility(View.GONE);
+ findViewById(R.id.noDownloadsText).setVisibility(View.VISIBLE);
+ } else {
+ recyclerView.setVisibility(View.VISIBLE);
+ findViewById(R.id.noDownloadsText).setVisibility(View.GONE);
+ }
+
+ recyclerView.setLayoutManager(new LinearLayoutManager(DownloadsActivity.this));
+
+ adapter = new DownloadsAdapter(this, getInfoInArrayList());
+
+ adapter.setClickListener(new DownloadsAdapter.ItemClickListener() {
+ @Override
+ public void onCancelClick(final int id, int position, String name, final String path) {
+ View topZa = getLayoutInflater().inflate(R.layout.downloads_opt_layout, null);
+ ((TextView) (topZa.findViewById(R.id._file_del_name))).setText("Delete Entry For " + FilenameUtils.getBaseName(path) + " ?");
+ SwitchCompat compat = topZa.findViewById(R.id.prompt_del_file);
+ new AlertDialog.Builder(DownloadsActivity.this)
+ .setView(topZa)
+ .setPositiveButton("Okay", (dialog, which) -> {
+ if (compat.isChecked()) {
+ if (new File(path).canWrite() && new RealmController().getVideoInfo(id).isCompleted()) {
+ if (new File(path).delete()) {
+ new DownloadHistoryManager().removeInfoById(id);
+ adapter.notifyItemRemoved(position);
+ adapter.notifyDataSetChangedCustom(getInfoInArrayList());
+ } else {
+ Snackbar.make(getWindow().getDecorView(),
+ "Can't delete, can't access file",
+ Snackbar.LENGTH_INDEFINITE)
+ .setAction("Remove Entry", v -> {
+ new DownloadHistoryManager().removeInfoById(id);
+ adapter.notifyItemRemoved(position);
+ adapter.notifyDataSetChangedCustom(getInfoInArrayList());
+ }).show();
+ }
+ } else {
+ Snackbar.make(getWindow().getDecorView(),
+ "Can't delete, maybe previously deleted!",
+ Snackbar.LENGTH_INDEFINITE)
+ .setAction("Remove Entry", v -> {
+ new DownloadHistoryManager().removeInfoById(id);
+ adapter.notifyItemRemoved(position);
+ adapter.notifyDataSetChangedCustom(getInfoInArrayList());
+ })
+ .setActionTextColor(ContextCompat.getColor(getBaseContext(),
+ android.R.color.holo_blue_bright))
+ .show();
+ }
+ } else {
+ new DownloadHistoryManager().removeInfoById(id);
+ adapter.notifyItemRemoved(position);
+ adapter.notifyDataSetChangedCustom(getInfoInArrayList());
+ }
+ }).show();
+ }
+
+ @Override
+ public void onOpenClick(final int id, int position, String path) {
+ Helper.verb(id + "/" + path);
+ File xyz = new File(path);
+ if (xyz.exists()) {
+ Intent superPlayer = new Intent(DownloadsActivity.this, MediaPlayer.class)
+ .setFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK | Intent.FLAG_ACTIVITY_NEW_TASK)
+ .setData(Uri.fromFile(xyz));
+ startActivity(superPlayer);
+ } else {
+ Snackbar.make(getWindow().getDecorView(), "File doesn't exists!", Snackbar.LENGTH_LONG)
+ .setAction("Remove", v -> {
+ new DownloadHistoryManager().removeInfoById(id);
+ adapter.notifyItemRemoved(position);
+ adapter.notifyDataSetChangedCustom(getInfoInArrayList());
+ }).show();
+ }
+ }
+
+ @Override
+ public void onReDownloadClick(int id, String ytUrl) {
+ Intent criticism = new Intent(DownloadsActivity.this, MainActivity.class)
+ .setAction(MainActivity.reDownloadAction)
+ .setData(Uri.parse(ytUrl));
+ startActivity(criticism);
+ DownloadsActivity.this.finish();
+ }
+ });
+
+ adapter.setLongClickListener(new DownloadsAdapter.ItemLongClickListener() {
+ @Override
+ public void onOpenClick() {
+ new AlertDialog.Builder(DownloadsActivity.this)
+ .setTitle("Open File")
+ .setMessage("\nClicking button will open the file\n")
+ .show();
+ }
+
+ @Override
+ public void onReDownloadClick() {
+ new AlertDialog.Builder(DownloadsActivity.this)
+ .setTitle("Open Youtube Page")
+ .setMessage("\nOpens youtube page from where the download was captured\n")
+ .show();
+ }
+
+ @Override
+ public void onCancelClick() {
+ new AlertDialog.Builder(DownloadsActivity.this)
+ .setTitle("Delete File/Cancel Download")
+ .setMessage("\nClicking button will delete this file from disk!!\n")
+ .show();
+ }
+ });
+
+ recyclerView.setAdapter(adapter);
+ adapter.notifyDataSetChangedCustom(getInfoInArrayList());
+
+ mHandlerTask = () -> {
+ if (getSupportActionBar() != null)
+ getSupportActionBar().setTitle("Downloads (" + new DownloadHistoryManager().getTotalInfoCount() + ")");
+ mHandler.postDelayed(mHandlerTask, 200); // decreasing anymore will make ui laggy
+ };
+ mHandlerTask.run();
+
+ }
+
+ @Override
+ protected void onDestroy() {
+ mHandler.removeCallbacks(mHandlerTask);
+ super.onDestroy();
+ }
+
+ private ArrayList getInfoInArrayList() {
+ return new ArrayList<>(new RealmController().getVideoInfos());
+ }
+
+ @Override
+ public boolean onCreateOptionsMenu(Menu menu) {
+ getMenuInflater().inflate(R.menu.clear_one, menu);
+ return super.onCreateOptionsMenu(menu);
+ }
+
+ @Override
+ public boolean onOptionsItemSelected(MenuItem item) {
+ new AlertDialog.Builder(DownloadsActivity.this)
+ .setTitle("Check!")
+ .setMessage("Are you sure to clear all downloads? It will also remove current downloads.")
+ .setPositiveButton("Ok", (dialog, which) -> {
+ for (VideoInfo x : getInfoInArrayList()) {
+ new DownloadHistoryManager().removeInfoById(x.getId());
+ }
+ adapter.notifyDataSetChangedCustom(getInfoInArrayList());
+ }).setNegativeButton("nope", null)
+ .show();
+ return super.onOptionsItemSelected(item);
+ }
+
+ @Override
+ public void onConfigurationChanged(Configuration newConfig) {
+ if (newConfig.orientation != configuration.orientation) {
+ configuration.orientation = newConfig.orientation;
+ }
+ super.onConfigurationChanged(newConfig);
+ }
+
+ @Override
+ protected void onResume() {
+ super.onResume();
+ isRunning = true;
+ EventBus.getDefault().register(this);
+ }
+
+ @Override
+ protected void onPause() {
+ super.onPause();
+ isRunning = false;
+ EventBus.getDefault().unregister(this);
+ }
+
+ @Subscribe(threadMode = ThreadMode.MAIN)
+ public void onMessageEvent(IPC ignored) {
+ if (isRunning) {
+ recyclerView.post(() -> {
+ recyclerView.setAdapter(adapter);
+ adapter.notifyDataSetChangedCustom(getInfoInArrayList());
+ });
+ }
+ }
+}
diff --git a/app/src/main/java/app/exploitr/nsg/youp3/ui_access/IntroActivity.java b/app/src/main/java/app/exploitr/nsg/youp3/ui_access/IntroActivity.java
new file mode 100644
index 0000000..baff942
--- /dev/null
+++ b/app/src/main/java/app/exploitr/nsg/youp3/ui_access/IntroActivity.java
@@ -0,0 +1,78 @@
+package app.exploitr.nsg.youp3.ui_access;
+
+import android.Manifest;
+import android.os.Build;
+import android.os.Bundle;
+import android.view.View;
+
+import androidx.annotation.RequiresApi;
+
+import app.exploitr.nsg.youp3.R;
+import io.github.dreierf.materialintroscreen.MaterialIntroActivity;
+import io.github.dreierf.materialintroscreen.MessageButtonBehaviour;
+import io.github.dreierf.materialintroscreen.SlideFragmentBuilder;
+
+public class IntroActivity extends MaterialIntroActivity {
+
+ private String[] perms = new String[]{
+ Manifest.permission.INTERNET,
+ Manifest.permission.READ_EXTERNAL_STORAGE,
+ Manifest.permission.WRITE_EXTERNAL_STORAGE,
+ Manifest.permission.ACCESS_NETWORK_STATE,
+ };
+
+ @RequiresApi(api = Build.VERSION_CODES.P) /*Fix Foreground Permission For Pi*/
+ private String[] permsforPi = new String[]{
+ Manifest.permission.INTERNET,
+ Manifest.permission.READ_EXTERNAL_STORAGE,
+ Manifest.permission.WRITE_EXTERNAL_STORAGE,
+ Manifest.permission.ACCESS_NETWORK_STATE,
+ Manifest.permission.FOREGROUND_SERVICE
+ };
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+
+ enableLastSlideAlphaExitTransition(true);
+
+ getBackButtonTranslationWrapper().setEnterTranslation(View::setAlpha);
+
+ addSlide(new SlideFragmentBuilder()
+ .backgroundColor(R.color.themeDef_primary)
+ .buttonsColor(android.R.color.background_dark)
+ .image(R.drawable.ic_launcher_web)
+ .title("Download Content With Ease")
+ .description("Let's have a try!")
+ .build());
+
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) {
+ addSlide(new SlideFragmentBuilder()
+ .backgroundColor(R.color.themeDef_AboutActivity_primary)
+ .buttonsColor(R.color.themeDef_BookmarkActivity_accent)
+ .image(R.drawable.ic_perm_lock)
+ .possiblePermissions(permsforPi)
+ .neededPermissions(permsforPi)
+ .title("Give me permissions")
+ .description("I can't work without them")
+ .build(),
+ new MessageButtonBehaviour(v -> showMessage("Thanks! You are already done!"), "Grant Permissions"));
+ } else {
+ addSlide(new SlideFragmentBuilder()
+ .backgroundColor(R.color.themeDef_AboutActivity_primary)
+ .buttonsColor(R.color.themeDef_BookmarkActivity_accent)
+ .image(R.drawable.ic_perm_lock)
+ .possiblePermissions(perms)
+ .neededPermissions(perms)
+ .title("Give me permissions")
+ .description("I can't work without them")
+ .build(),
+ new MessageButtonBehaviour(v -> showMessage("Thanks! You are already done!"), "Grant Permissions"));
+ }
+
+ addSlide(new Tos());
+ addSlide(new BASwitcher());
+
+ }
+
+}
diff --git a/app/src/main/java/app/exploitr/nsg/youp3/ui_access/MainActivity.java b/app/src/main/java/app/exploitr/nsg/youp3/ui_access/MainActivity.java
new file mode 100644
index 0000000..a37ec77
--- /dev/null
+++ b/app/src/main/java/app/exploitr/nsg/youp3/ui_access/MainActivity.java
@@ -0,0 +1,980 @@
+package app.exploitr.nsg.youp3.ui_access;
+
+
+import android.annotation.TargetApi;
+import android.content.Intent;
+import android.content.pm.PackageInfo;
+import android.content.res.Configuration;
+import android.graphics.Bitmap;
+import android.graphics.Color;
+import android.graphics.PorterDuff;
+import android.graphics.drawable.Drawable;
+import android.net.Uri;
+import android.net.http.SslError;
+import android.os.Build;
+import android.os.Bundle;
+import android.os.Environment;
+import android.os.Handler;
+import android.os.Looper;
+import android.provider.Settings;
+import android.view.Menu;
+import android.view.MenuItem;
+import android.view.View;
+import android.view.ViewTreeObserver;
+import android.view.WindowManager;
+import android.webkit.SslErrorHandler;
+import android.webkit.WebChromeClient;
+import android.webkit.WebResourceError;
+import android.webkit.WebResourceRequest;
+import android.webkit.WebResourceResponse;
+import android.webkit.WebSettings;
+import android.webkit.WebView;
+import android.webkit.WebViewClient;
+import android.widget.AdapterView;
+import android.widget.ArrayAdapter;
+import android.widget.ProgressBar;
+import android.widget.Spinner;
+import android.widget.Toast;
+
+import androidx.annotation.NonNull;
+import androidx.appcompat.app.ActionBarDrawerToggle;
+import androidx.appcompat.app.AlertDialog;
+import androidx.appcompat.app.AppCompatActivity;
+import androidx.appcompat.widget.SearchView;
+import androidx.appcompat.widget.Toolbar;
+import androidx.constraintlayout.widget.ConstraintLayout;
+import androidx.core.app.NotificationManagerCompat;
+import androidx.core.graphics.drawable.DrawableCompat;
+import androidx.core.view.GravityCompat;
+import androidx.drawerlayout.widget.DrawerLayout;
+
+import com.crashlytics.android.answers.Answers;
+import com.crashlytics.android.answers.ContentViewEvent;
+import com.getkeepsafe.taptargetview.TapTarget;
+import com.getkeepsafe.taptargetview.TapTargetSequence;
+import com.google.android.material.navigation.NavigationView;
+import com.google.android.material.snackbar.Snackbar;
+import com.wangjie.rapidfloatingactionbutton.RapidFloatingActionButton;
+import com.wangjie.rapidfloatingactionbutton.RapidFloatingActionHelper;
+import com.wangjie.rapidfloatingactionbutton.RapidFloatingActionLayout;
+import com.wangjie.rapidfloatingactionbutton.contentimpl.labellist.RFACLabelItem;
+import com.wangjie.rapidfloatingactionbutton.contentimpl.labellist.RapidFloatingActionContentLabelList;
+
+import org.greenrobot.eventbus.EventBus;
+import org.greenrobot.eventbus.Subscribe;
+import org.greenrobot.eventbus.ThreadMode;
+
+import java.io.File;
+import java.net.URLEncoder;
+import java.security.SecureRandom;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Objects;
+
+import app.exploitr.nsg.youp3.Book.BookMark;
+import app.exploitr.nsg.youp3.Book.BookMarkManager;
+import app.exploitr.nsg.youp3.Book.BookRealmController;
+import app.exploitr.nsg.youp3.Book.Launcher;
+import app.exploitr.nsg.youp3.Book.VideoScreen;
+import app.exploitr.nsg.youp3.R;
+import downloader.utils.DownloadExecutorService;
+import downloader.utils.DownloadManager;
+import utils.DataStore;
+import utils.Helper;
+import utils.IPC;
+
+import static utils.Helper.verb;
+
+@SuppressWarnings("FieldCanBeLocal")
+public class MainActivity extends AppCompatActivity implements NavigationView.OnNavigationItemSelectedListener,
+ RapidFloatingActionContentLabelList.OnRapidFloatingActionContentLabelListListener {
+
+ public static final boolean isBuildFinal = true;
+ public static final String reDownloadAction = "_redownload_action";
+ public static final String broadCastIntent = "_broad_cast";
+ public static final String broadCastIntentFullScreen = "_broad_cast_full";
+ public static final String broadCastIntentToolbar = "_broad_cast_tool";
+ public static final long CURRENT_TEST_CHROME_VERSION = 353808052L;
+ private static final int REQUEST_CODE_PERMISSION = 120;
+ private static final String ERROR_HTML = "file:///android_asset/index.html";
+ public static boolean isActive = false;
+ private boolean canceled = false;
+ private WebView mainView;
+ private DrawerLayout drawer;
+ private ProgressBar indicator;
+ private String urlAll = "", urlTitle = "";
+ //
+ private String[] urlYtPages = new String[]{
+ "https://www.youtube.com/feed/trending",
+ "https://www.youtube.com/channel/UC1vGae2Q3oT5MkhhfW8lwjg",
+ "https://www.youtube.com/channel/UC-9-kyTW8ZkZNDHQJ6FgpwQ",
+ "https://www.youtube.com/channel/UCEgdi0XIXXZ-qJOFPf4JSKw",
+ "https://www.youtube.com/channel/UCOpNcN46UbXVtpKMrmU4Abg",
+ "https://www.youtube.com/channel/UClgRkhTL3_hImCAmdLfDE4g",
+ "https://www.youtube.com/channel/UCYfdidRxbB8Qhf0Nx7ioOYw",
+ "https://www.youtube.com/channel/UC4R8DWoMoI7CAwX8_LjQHig",
+ "https://www.youtube.com/channel/UCzuqhhs6NWbgTzMuM09WKDQ"
+ };
+ //
+ private RapidFloatingActionLayout rfaLayout;
+ private RapidFloatingActionButton rfaBtn;
+ private RapidFloatingActionHelper rabHelper;
+ private RapidFloatingActionContentLabelList rfaContent;
+ private Spinner pageSpinner;
+
+ @Override
+ protected void onCreate(Bundle bundle) {
+ super.onCreate(bundle);
+ setContentView(R.layout.activity_main);
+
+ DataStore.getInstance(getBaseContext()).setNewUserNoMoreForSERVICE_STARTER();
+
+ if (DataStore.getInstance(getBaseContext()).isNewUserForSPLASH()) {
+ startActivity(new Intent(this, IntroActivity.class));
+ finish();
+ }
+
+ final Toolbar toolbar = findViewById(R.id.toolbar);
+ setSupportActionBar(toolbar);
+ toolbar.inflateMenu(R.menu.mux_menu);
+
+ mainView = new WebView(MainActivity.this);
+
+ ConstraintLayout mx = findViewById(R.id.main);
+ ViewTreeObserver vto = mx.getViewTreeObserver();
+ vto.addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
+ @Override
+ public void onGlobalLayout() {
+ int width = mx.getMeasuredWidth();
+ int height = mx.getMeasuredHeight();
+ mx.removeView(mainView);
+ mx.addView(mainView, 0, new ConstraintLayout.LayoutParams(width, height));
+ mx.getViewTreeObserver().removeOnGlobalLayoutListener(this);
+ }
+ });
+ //Init Done
+ if (DataStore.getInstance(getBaseContext()).isFullScreen()) {
+ getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, WindowManager.LayoutParams.FLAG_FULLSCREEN);
+ }
+
+ if (DataStore.getInstance(getBaseContext()).isRemoveToolbar()) {
+ if (getSupportActionBar() != null) getSupportActionBar().hide();
+ } else {
+ if (getSupportActionBar() != null) getSupportActionBar().show();
+ }
+
+ indicator = findViewById(R.id.indicator);
+ if (Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP) {
+ Drawable drawableProgress = DrawableCompat.wrap(indicator.getIndeterminateDrawable());
+ DrawableCompat.setTint(drawableProgress, Color.WHITE);
+ indicator.setIndeterminateDrawable(DrawableCompat.unwrap(drawableProgress));
+ } else {
+ indicator.getIndeterminateDrawable().setColorFilter(Color.WHITE, PorterDuff.Mode.SRC_IN);
+ }
+
+ rfaLayout = findViewById(R.id.activity_main_rfal);
+ rfaBtn = findViewById(R.id.activity_main_rfab);
+ rfaContent = new RapidFloatingActionContentLabelList(MainActivity.this);
+ rfaContent.setOnRapidFloatingActionContentLabelListListener(this);
+ List items = new ArrayList<>();
+ items.add(new RFACLabelItem()
+ .setLabel("Share Link Of This Video")
+ .setResId(R.drawable.ic_share_video)
+ .setIconNormalColor(0xffd84315)
+ .setIconPressedColor(0xffbf360c)
+ .setWrapper(0)
+ );
+ items.add(new RFACLabelItem()
+ .setLabel("Fetch Downloadable File(s) Details")
+ .setResId(R.drawable.ic_file_download)
+ .setIconNormalColor(0xff4e342e)
+ .setIconPressedColor(0xff3e2723)
+ .setWrapper(1)
+ );
+ rfaContent.setItems(items);
+ rabHelper = new RapidFloatingActionHelper(
+ MainActivity.this,
+ rfaLayout,
+ rfaBtn,
+ rfaContent
+ );
+ rabHelper.build();
+
+ checkFilePermsOkay();
+
+ drawer = findViewById(R.id.drawer_layout);
+ ActionBarDrawerToggle toggle = new ActionBarDrawerToggle(this, drawer, toolbar,
+ R.string.navigation_drawer_open, R.string.navigation_drawer_close);
+ drawer.addDrawerListener(toggle);
+ toggle.syncState();
+
+ final NavigationView navigationView = findViewById(R.id.nav_view);
+ navigationView.setNavigationItemSelectedListener(this);
+
+ mainView.setScrollBarStyle(View.SCROLLBARS_INSIDE_OVERLAY);
+
+ WebSettings settings = mainView.getSettings();
+ settings.setJavaScriptEnabled(true);
+ settings.setCacheMode(WebSettings.LOAD_DEFAULT);
+ settings.setAppCacheEnabled(false);
+ settings.setLayoutAlgorithm(WebSettings.LayoutAlgorithm.NARROW_COLUMNS);
+ settings.setDisplayZoomControls(true);
+ settings.setMediaPlaybackRequiresUserGesture(true);
+
+ mainView.setWebChromeClient(new WebChromeClient() {
+ @Override
+ public void onReceivedTitle(WebView view, String pageTitle) {
+ if (!pageTitle.equals("YouTube") && DataStore.getInstance(getBaseContext()).isDeskModeEnabled()) {
+ toolbar.setSubtitle(pageTitle);
+ } else {
+ toolbar.setSubtitle("");
+ }
+ }
+ });
+
+ mainView.setWebViewClient(new WebViewClient() {
+ @Override
+ public void onPageFinished(WebView view, String url) {
+ mainView.setVisibility(View.VISIBLE);
+ indicator.setVisibility(View.INVISIBLE);
+ rfaLayout.setVisibility(View.VISIBLE);
+ try {
+ for (int i = 0; i < urlYtPages.length; i++) {
+ if ((url.split("channel")[1])
+ .equals(urlYtPages[i].split("channel")[1])) {
+ pageSpinner.setSelection(i, true);
+ break;
+ }
+ }
+ } catch (Exception ignored) {
+ }
+ verb(url);
+ }
+
+ @Override
+ public void onPageStarted(WebView view, String url, Bitmap favicon) {
+ indicator.setVisibility(View.VISIBLE);
+ mainView.setVisibility(View.INVISIBLE);
+ rfaLayout.setVisibility(View.INVISIBLE);
+ if (url.contains("m.youtube") && DataStore.getInstance(getBaseContext()).isDeskModeEnabled()) {
+ String[] cow1 = url.split("m.");
+ url = "https://www." + cow1[1];
+ mainView.loadUrl(url);
+ }
+ if (url.contains("account")) {
+ getWindow().setFlags(WindowManager.LayoutParams.FLAG_SECURE, WindowManager.LayoutParams.FLAG_SECURE);
+ } else {
+ getWindow().clearFlags(WindowManager.LayoutParams.FLAG_SECURE);
+ }
+ }
+
+ @Override
+ public void onReceivedError(WebView view, int errorCode, String description, String failingUrl) {
+ if (errorCode == WebViewClient.ERROR_PROXY_AUTHENTICATION || errorCode == WebViewClient.ERROR_CONNECT) {
+ mainView.loadUrl(ERROR_HTML);
+ }
+ }
+
+ @TargetApi(android.os.Build.VERSION_CODES.M)
+ @Override
+ public void onReceivedError(WebView view, WebResourceRequest req, WebResourceError err) {
+ if (err.getErrorCode() == WebViewClient.ERROR_PROXY_AUTHENTICATION ||
+ err.getErrorCode() == WebViewClient.ERROR_CONNECT) {
+ mainView.loadUrl(ERROR_HTML);
+ }
+ }
+
+ @Override
+ public void onReceivedSslError(WebView view, SslErrorHandler handler, SslError error) {
+ handler.proceed();
+ }
+
+ @TargetApi(Build.VERSION_CODES.LOLLIPOP)
+ @Override
+ public boolean shouldOverrideUrlLoading(WebView view, final WebResourceRequest request) {
+ if ((!(request.getUrl().toString().contains("youtube") | request.getUrl().toString().contains("google")))) {
+ new AlertDialog.Builder(MainActivity.this)
+ .setMessage("YouP3 will forward external urls to browser.")
+ .setCancelable(false)
+ .setPositiveButton("Ok", (dialog, which) -> {
+ Intent intent = new Intent(Intent.ACTION_VIEW);
+ intent.setData(request.getUrl());
+ startActivity(intent);
+ })
+ .setNegativeButton("Back", (dialog, which) -> {
+ if (mainView.canGoBack()) {
+ mainView.goBack();
+ }
+ }).show();
+ }
+ return super.shouldOverrideUrlLoading(view, request);
+ }
+
+ @Override
+ public boolean shouldOverrideUrlLoading(WebView view, final String url) {
+ if ((!(url.contains("youtube") | url.contains("google")))) {
+ new AlertDialog.Builder(MainActivity.this)
+ .setMessage("YouP3 will forward external urls to browser?!?")
+ .setCancelable(false)
+ .setPositiveButton("Ok", (dialog, which) -> {
+ Intent intent = new Intent(Intent.ACTION_VIEW);
+ intent.setData(Uri.parse(url));
+ startActivity(intent);
+ })
+ .setNegativeButton("Back", (dialog, which) -> {
+ if (mainView.canGoBack()) {
+ mainView.goBack();
+ }
+ }).show();
+ }
+ return super.shouldOverrideUrlLoading(view, url);
+ }
+
+ @TargetApi(Build.VERSION_CODES.LOLLIPOP)
+ @Override
+ public WebResourceResponse shouldInterceptRequest(WebView view, final WebResourceRequest request) {
+ if (request.getUrl().toString().matches(".*googlevideo.com/videoplayback.*")) {
+ new Handler(Looper.getMainLooper()).post(() -> {
+ String urlBob = request.getUrl().toString().replaceAll("&range=[\\d-]*&", "&");
+ if (urlBob.contains("mime=audio") && urlBob.contains("buf=0")) {
+ urlAll = urlBob;
+ urlTitle = mainView.getUrl();
+ }
+ });
+ }
+ return super.shouldInterceptRequest(view, request);
+ }
+
+ @Override
+ public WebResourceResponse shouldInterceptRequest(WebView view, final String url) {
+ if (url.matches(".*googlevideo.com/videoplayback.*")) {
+ new Handler(Looper.getMainLooper()).post(() -> {
+ String urlBob = url.replaceAll("&range=[\\d-]*&", "&");
+ if (urlBob.contains("mime=audio") && urlBob.contains("buf=0")) {
+ urlAll = urlBob;
+ urlTitle = mainView.getUrl();
+ }
+ });
+ }
+ return super.shouldInterceptRequest(view, url);
+ }
+
+ });
+
+ if (DataStore.getInstance(getBaseContext()).isNewUserForIntro()) {
+
+ TapTargetSequence sequence = new TapTargetSequence(this);
+ //
+ sequence.targets(
+ TapTarget.forToolbarMenuItem(toolbar,
+ R.id.action_search,
+ "That's the Search Bar!",
+ "Search the most you love from what you don't!")
+ .outerCircleColor(android.R.color.background_dark).id(1996),
+ TapTarget.forToolbarMenuItem(toolbar,
+ R.id.action_bookmark,
+ "That's the Bookmark button!",
+ "Make bookmarks on one single click!")
+ .outerCircleColor(android.R.color.background_dark).id(1995),
+ TapTarget.forToolbarMenuItem(toolbar,
+ R.id.action_show_bookmarks,
+ "That's the Bookmark Home!",
+ "Find all of your bookmarks here!")
+ .outerCircleColor(android.R.color.background_dark).id(1994),
+ TapTarget.forView(rfaBtn,
+ "Here comes the main action part!",
+ "Download & Share your favourite youtube content!")
+ .outerCircleColor(android.R.color.background_dark)
+ .tintTarget(false)
+ .id(1992),
+ TapTarget.forView(navigationView.getMenu().findItem(R.id.go_all).getActionView(),
+ "Here is a pre-made categories list!",
+ "Enjoy!")
+ .tintTarget(false).id(1993)
+
+ );
+ //
+ sequence.listener(new TapTargetSequence.Listener() {
+ @Override
+ public void onSequenceFinish() {
+ DataStore.getInstance(getBaseContext()).setNewUserNoMoreForINTRO();
+ drawer.closeDrawer(GravityCompat.START);
+ new AlertDialog.Builder(MainActivity.this)
+ .setTitle("Sign-In?")
+ .setMessage("Would you like to sign in into YouTube for a personalized experience ?")
+ .setNeutralButton("Privacy Policy", (dialog, which) -> startActivity(new Intent(Intent.ACTION_VIEW,
+ Uri.parse("https://github.com/ExploiTR/YouP3/blob/master/privacy.md"))))
+ .setNegativeButton("No", null)
+ .setOnDismissListener(dialog -> startService(new Intent(MainActivity.this, DownloadExecutorService.class)))
+ .setPositiveButton("Why not?", (dialog, which) -> mainView.loadUrl(
+ "https://accounts.google.com/" +
+ "signin/v2/identifier?passive=true" +
+ "&service=youtube&hl=en&uilel=3" +
+ "&continue=https%3A%2F%2Fwww.youtube.com" +
+ "%2Fsignin%3Faction_handle_signin%3Dtrue%26app%3Dmobile" +
+ "%26next%3D%252F%26hl%3Den&flowName=GlifWebSignIn" +
+ "&flowEntry=ServiceLogin"
+ ))
+ .show();
+ }
+
+ @Override
+ public void onSequenceStep(TapTarget lastTarget, boolean targetClicked) {
+ if (lastTarget.id() == 1992 && targetClicked) {
+ drawer.openDrawer(GravityCompat.START);
+ }
+ }
+
+ @Override
+ public void onSequenceCanceled(TapTarget lastTarget) {
+ }
+ });
+
+ new AlertDialog.Builder(MainActivity.this)
+ .setTitle("Hi!")
+ .setMessage("Mate, looks like you're first time here. Have a tour?")
+ .setPositiveButton("Yas", (dialog, which) -> sequence.start())
+ .setNegativeButton("Leave me", (dialogs, x) -> {
+ DataStore.getInstance(getBaseContext()).setNewUserNoMoreForINTRO();
+ drawer.closeDrawer(GravityCompat.START);
+ new AlertDialog.Builder(MainActivity.this)
+ .setTitle("Sign-In?")
+ .setMessage("Would you like to sign in into YouTube for a personalized experience ?")
+ .setNeutralButton("Privacy Policy", (dialog, which) -> startActivity(new Intent(Intent.ACTION_VIEW,
+ Uri.parse("https://github.com/ExploiTR/YouP3/blob/master/privacy.md"))))
+ .setNegativeButton("No", null)
+ .setOnDismissListener(dialog -> startService(new Intent(MainActivity.this, DownloadExecutorService.class)))
+ .setPositiveButton("Why not?", (dialog, which) -> mainView.loadUrl(
+ "https://accounts.google.com/" +
+ "signin/v2/identifier?passive=true" +
+ "&service=youtube&hl=en&uilel=3" +
+ "&continue=https%3A%2F%2Fwww.youtube.com" +
+ "%2Fsignin%3Faction_handle_signin%3Dtrue%26app%3Dmobile" +
+ "%26next%3D%252F%26hl%3Den&flowName=GlifWebSignIn" +
+ "&flowEntry=ServiceLogin"
+ ))
+ .show();
+ })
+ .show();
+ }
+
+
+ //
+ pageSpinner = (Spinner) navigationView.getMenu().findItem(R.id.go_all).getActionView();
+ pageSpinner.setAdapter(new ArrayAdapter<>(this, android.R.layout.simple_spinner_dropdown_item, new String[]{
+ "Select",
+ "Trending",
+ "Life-Style",
+ "Music",
+ "Sports",
+ "Gaming",
+ "Movies",
+ "News",
+ "Live",
+ "VR"
+ }));
+ //
+
+ pageSpinner.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
+ @Override
+ public void onItemSelected(AdapterView> parent, View view, int position, long id) {
+ if (position == 1) { //I REALLY DON'T TRUST SWITCH CLAUSES
+ mainView.loadUrl(urlYtPages[0]);
+ } else if (position == 2) {
+ mainView.loadUrl(urlYtPages[1]);
+ } else if (position == 3) {
+ mainView.loadUrl(urlYtPages[2]);
+ } else if (position == 4) {
+ mainView.loadUrl(urlYtPages[3]);
+ } else if (position == 5) {
+ mainView.loadUrl(urlYtPages[4]);
+ } else if (position == 6) {
+ mainView.loadUrl(urlYtPages[5]);
+ } else if (position == 7) {
+ mainView.loadUrl(urlYtPages[6]);
+ } else if (position == 8) {
+ mainView.loadUrl(urlYtPages[7]);
+ } else if (position == 9) {
+ mainView.loadUrl(urlYtPages[8]);
+ }
+ drawer.closeDrawers();
+ }
+
+ @Override
+ public void onNothingSelected(AdapterView> parent) {
+ }
+ });
+
+ setBookMarkListener(mainView);
+
+ if (!Helper.isNetworkAvailable(MainActivity.this)) {
+ new AlertDialog.Builder(MainActivity.this)
+ .setTitle("Network Error :")
+ .setMessage("\nCan't Connect To Server")
+ .setPositiveButton("Ok", null).show();
+ mainView.loadUrl(ERROR_HTML);
+ } else {
+ mainView.loadUrl("https://www.youtube.com/");
+ }
+
+ if (Objects.equals(getIntent().getAction(), reDownloadAction)) {
+ String localLink = getIntent().getDataString();
+ if (localLink != null) {
+ if (localLink.contains("youtu.be")) {
+ mainView.loadUrl("https://www.youtube.com/watch?v=" + localLink.split("be/")[1]);
+ } else {
+ mainView.loadUrl(localLink);
+ }
+ } else {
+ mainView.loadUrl(ERROR_HTML);
+ Toast.makeText(this, "Invalid Url", Toast.LENGTH_SHORT).show();
+ }
+ Snackbar.make(rfaLayout, "Loading Given YouTube URL", Snackbar.LENGTH_SHORT).show();
+ }
+
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
+ checkWebViewVersionO();
+ } else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
+ checkWebViewVersionN();
+ } else {
+ checkWebViewHard();
+ }
+
+
+ if (!Helper.isMyServiceRunning(DownloadExecutorService.class, getBaseContext()) && !DataStore.getInstance(getBaseContext()).isNewUserForSERVICE_STARTER()) {
+ startService(new Intent(getBaseContext(), DownloadExecutorService.class));
+ }
+ }
+
+ private void checkWebViewVersionN() {
+ try {
+ PackageInfo pf = getPackageManager().getPackageInfo("com.android.chrome", 0);
+ if (isBuildFinal) {
+ Answers.getInstance().logContentView(new ContentViewEvent()
+ .putContentName("WebView Impl")
+ .putCustomAttribute("SDK", Build.VERSION.SDK_INT)
+ .putCustomAttribute("PackageName", pf.packageName));
+ } else {
+ verb(pf.packageName + "\n" + pf.versionCode);
+ }
+ //will just check chrome
+ if (pf.versionCode < CURRENT_TEST_CHROME_VERSION) {
+ //old
+ new AlertDialog.Builder(MainActivity.this)
+ .setTitle("WebClient is outdated")
+ .setMessage("Your Chrome is a little bit outdated and thus you can experince problems." +
+ " Consider updating your Chrome from Google Play")
+ .setPositiveButton("Take me there", (dialog, which) -> startActivity(new Intent(
+ Intent.ACTION_VIEW,
+ Uri.parse("https://play.google.com/store/apps/details?id=com.android.chrome")
+ ).addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)))
+ .setNegativeButton("I'll do it", null).show();
+ }
+
+ } catch (Exception ignored) {
+ }
+ }
+
+ @TargetApi(Build.VERSION_CODES.O)
+ private void checkWebViewVersionO() {
+ PackageInfo pf = WebView.getCurrentWebViewPackage();
+
+ if (isBuildFinal) {
+ if (pf != null) {
+ Answers.getInstance().logContentView(new ContentViewEvent()
+ .putContentName("WebView Impl")
+ .putCustomAttribute("SDK", Build.VERSION.SDK_INT)
+ .putCustomAttribute("PackageName", pf.packageName));
+ }
+ } else {
+ if (pf != null)
+ verb(pf.packageName + "\n" + pf.versionCode);
+ }
+ if (pf != null)
+ if (pf.packageName.equals("com.android.chrome")) {
+ //will just check chrome
+ if (pf.versionCode < CURRENT_TEST_CHROME_VERSION) {
+ //old
+ new AlertDialog.Builder(MainActivity.this)
+ .setTitle("WebClient is outdated")
+ .setMessage("Your Chrome is a little bit outdated and thus you can experince problems." +
+ " Consider updating your Chrome from Google Play")
+ .setPositiveButton("Take me there", (dialog, which) -> startActivity(new Intent(
+ Intent.ACTION_VIEW,
+ Uri.parse("https://play.google.com/store/apps/details?id=com.android.chrome")
+ ).addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)))
+ .setNegativeButton("I'll do it", null).show();
+ }
+ }
+ }
+
+ private void checkWebViewHard() {
+ try {
+ PackageInfo pf = getPackageManager().getPackageInfo("com.google.android.webview", 0);
+ if (isBuildFinal) {
+ Answers.getInstance().logContentView(new ContentViewEvent()
+ .putContentName("WebView Impl")
+ .putCustomAttribute("SDK", Build.VERSION.SDK_INT)
+ .putCustomAttribute("PackageName", pf.packageName));
+ } else {
+ verb(pf.packageName + "\n" + pf.versionCode);
+ }
+
+ if (pf.versionCode < CURRENT_TEST_CHROME_VERSION) {
+ //old
+ new AlertDialog.Builder(MainActivity.this)
+ .setTitle("WebClient is outdated")
+ .setMessage("Your Chrome is a little bit outdated and thus you can experince problems." +
+ " Consider updating your Chrome from Google Play")
+ .setPositiveButton("Take me there", (dialog, which) -> startActivity(new Intent(
+ Intent.ACTION_VIEW,
+ Uri.parse("https://play.google.com/store/apps/details?id=com.google.android.webview")
+ ).addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)))
+ .setNegativeButton("I'll do it", null).show();
+ }
+
+ } catch (Exception ignored) {
+ }
+ }
+
+ private void setBookMarkListener(final WebView mainView) {
+ final Handler handler = new Handler();
+ if (mainView != null) {
+ handler.post(new Runnable() {
+ @Override
+ public void run() {
+ if (Launcher.i().isShouldLoad()) {
+ mainView.loadUrl(Launcher.i().getUrl());
+ Launcher.i().setShouldLoad(false);
+ }
+ handler.postDelayed(this, 100);
+ }
+ });
+ }
+ }
+
+
+ private void setDeskTopMode(WebSettings webSettings, final boolean enabled) {
+ final String newUserAgent;
+ if (enabled) {
+ newUserAgent = webSettings.getUserAgentString().replace("Mobile", "eliboM").replace("Android", "diordnA");
+ } else {
+ newUserAgent = webSettings.getUserAgentString().replace("eliboM", "Mobile").replace("diordnA", "Android");
+ }
+ webSettings.setUserAgentString(newUserAgent);
+ webSettings.setUseWideViewPort(enabled);
+ webSettings.setLoadWithOverviewMode(enabled);
+ webSettings.setSupportZoom(enabled);
+ webSettings.setBuiltInZoomControls(enabled);
+ mainView.reload();
+ }
+
+
+ private void checkFilePermsOkay() {
+ new Handler().postDelayed(() -> {
+ File dirFile = new File(Environment.getExternalStorageDirectory().getPath() + "/YouP3");
+ if (!dirFile.exists()) {
+ if (!dirFile.mkdir() && MainActivity.isActive && !MainActivity.this.isFinishing()) {
+ new AlertDialog.Builder(MainActivity.this)
+ .setTitle("Error Accessing Storage")
+ .setMessage("YouP3 can't access your storage. Check if everything is okay in settings")
+ .setCancelable(true)
+ .setPositiveButton("Exit", (dialog, which) -> {
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
+ finishAndRemoveTask();
+ } else {
+ finish();
+ }
+ })
+ .setNeutralButton("Settings", (dialog, which) -> startActivity(new Intent(Settings.ACTION_SETTINGS)))
+ .show();
+ }
+ }
+ }, 10000);
+ }
+
+ @Override
+ protected void onPause() {
+ mainView.onPause();
+ isActive = false;
+ EventBus.getDefault().unregister(this);
+ super.onPause();
+ }
+
+ @Override
+ protected void onResume() {
+ super.onResume();
+ mainView.onResume();
+ setDeskTopMode(mainView.getSettings(), DataStore.getInstance(getBaseContext()).isDeskModeEnabled());
+ isActive = true;
+ EventBus.getDefault().register(this);
+ }
+
+ @Override
+ public void onBackPressed() {
+ if (mainView.canGoBack()) {
+ mainView.goBack();
+ } else {
+ AlertDialog.Builder alertDialog = new AlertDialog.Builder(MainActivity.this);
+ alertDialog.setTitle("Exit");
+ alertDialog.setMessage("Close App?");
+ alertDialog.setPositiveButton("Yes", (dialog, which) -> {
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
+ finishAndRemoveTask();
+ } else finish();
+ });
+ alertDialog.setNegativeButton("Nope", (dialog, which) -> dialog.dismiss());
+ AlertDialog dialog = alertDialog.create();
+ dialog.show();
+ }
+ }
+
+ @Override
+ protected void onDestroy() {
+ Helper.clearCache(mainView);
+ if (Helper.isDownloadInActive()) {
+ stopService(new Intent(MainActivity.this, DownloadExecutorService.class));
+ NotificationManagerCompat.from(getApplicationContext()).cancelAll();
+ }
+ super.onDestroy();
+ }
+
+ @Override
+ public boolean onNavigationItemSelected(@NonNull MenuItem item) {
+ int id = item.getItemId();
+ if (id == R.id.go_home) {
+ mainView.loadUrl("https://www.youtube.com");
+ }
+ if (id == R.id.go_me) {
+ startActivity(new Intent(MainActivity.this, AboutActivity.class));
+ }
+ if (id == R.id.downloads) {
+
+ startActivity(new Intent(MainActivity.this, DownloadsActivity.class));
+ }
+ if (id == R.id.settings) {
+ startActivity(new Intent(MainActivity.this, SettingsActivity.class));
+ }
+ if (id == R.id.go_exit) {
+ System.exit(0);
+ }
+ if (id == R.id.do_bug_report) {
+ startActivityForResult(Intent.createChooser(new Intent(Intent.ACTION_SEND)
+ .setType("text/plain")
+ .putExtra(Intent.EXTRA_EMAIL, new String[]{getString(R.string.dev_mail)})
+ .putExtra(Intent.EXTRA_TEXT, mainView.getUrl() + "\n\n Write Below \n\n")
+ .putExtra(Intent.EXTRA_SUBJECT, "BUG_REPORT_" + getPackageName()),
+ "Choose Your Mail Client"), 1001);
+ }
+ if (id == R.id.convert_) {
+ startActivity(new Intent(this, AudioConverter.class));
+ }
+ drawer.closeDrawer(GravityCompat.START);
+ return true;
+ }
+
+
+ @Override
+ public boolean onCreateOptionsMenu(Menu menu) {
+ getMenuInflater().inflate(R.menu.mux_menu, menu);
+ MenuItem myActionMenuItem = menu.findItem(R.id.action_search);
+ SearchView searchView = (SearchView) myActionMenuItem.getActionView();
+ searchView.setQueryHint("How to make stuffs like....");
+ searchView.setOnQueryTextListener(new SearchView.OnQueryTextListener() {
+ @Override
+ public boolean onQueryTextSubmit(String query) {
+ if (!query.equals("")) {
+ try {
+ mainView.loadUrl("https:www.youtube.com/results?search_query=" +
+ URLEncoder.encode(query, "UTF-8"));
+ } catch (Exception e) {
+ e.printStackTrace();
+ e.getSuppressed();
+ }
+ } else {
+ Toast.makeText(getApplicationContext(), "Please enter some text to search.",
+ Toast.LENGTH_SHORT).show();
+ }
+ searchView.clearFocus();
+ findViewById(R.id.main).requestFocus();
+ return true;
+ }
+
+ @Override
+ public boolean onQueryTextChange(String newText) {
+ return false;
+ }
+ });
+ return true;
+ }
+
+ @Override
+ public boolean onOptionsItemSelected(MenuItem item) {
+ if (item.getOrder() == 1) {
+ if (mainView.getUrl().contains("v=")) {
+ /*Because it doesn't work*/
+ String url = mainView.getUrl();
+ String urlFinal = "";
+ if (url.contains("youtu.be")) {
+ urlFinal = "https://www.youtube.com/watch?v=" + url.split("be/")[1];
+ } else if (url.contains("m.youtube")) {
+ urlFinal = "https://www.youtube.com/watch?v=" + url.split("v=")[1];
+ } else if (url.contains("&list=")) {
+ urlFinal = "https://www.youtube.com/watch?v=" +
+ url.split("v=")[1].split("&list=")[0];
+ }
+
+ String finalUrl = urlFinal;
+ VideoScreen.load(mainView.getUrl())
+ .start(MainActivity.this)
+ .setOnCompleteListener(what -> runOnUiThread(() -> {
+ for (final BookMark mark : new BookRealmController().getBookMarks()) {
+ if (mainView.getUrl().equals(mark.getUrl())) {
+ canceled = true;
+ new AlertDialog.Builder(MainActivity.this)
+ .setTitle("Oops!")
+ .setMessage("BookMark Already Exists!")
+ .setPositiveButton("Update", (dialog, which) -> {
+ new BookMarkManager().push(
+ mark.getId(),
+ Helper.getTitle(getBaseContext(), finalUrl),
+ mainView.getUrl(),
+ what
+ );
+ Toast.makeText(getBaseContext(), "Page Got Bookmarked!", Toast.LENGTH_SHORT).show();
+ }).setNegativeButton("Cancel", null).show();
+ }
+ }
+ if (!canceled) {
+ if (mainView.getFavicon() != null) {
+ new BookMarkManager().push(
+ new SecureRandom().nextInt(Integer.MAX_VALUE),
+ Helper.getTitle(getBaseContext(), finalUrl),
+ mainView.getUrl(),
+ what
+ );
+ }
+ Toast.makeText(getBaseContext(), "Page Got Bookmarked!", Toast.LENGTH_SHORT).show();
+ }
+ }));
+ } else {
+ Toast.makeText(getBaseContext(), "Only Videos Can Be Added To BookMarks :-)", Toast.LENGTH_SHORT).show();
+ }
+ } else if (item.getOrder() == 2) {
+ startActivity(new Intent(MainActivity.this, BookMarkActivity.class));
+ }
+ return true;
+ }
+
+ @Override
+ protected void onActivityResult(int requestCode, int resultCode, Intent data) {
+ if (requestCode == REQUEST_CODE_PERMISSION) {
+ if (resultCode != RESULT_OK) {
+ Toast.makeText(MainActivity.this, "Can't work without permission", Toast.LENGTH_SHORT).show();
+ finish();
+ }
+ }
+ super.onActivityResult(requestCode, resultCode, data);
+ }
+
+ @Override
+ public void onConfigurationChanged(Configuration newConfig) {
+ ConstraintLayout mx = findViewById(R.id.main);
+ ViewTreeObserver vto = mx.getViewTreeObserver();
+ vto.addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
+ @Override
+ public void onGlobalLayout() {
+ int width = mx.getMeasuredWidth();
+ int height = mx.getMeasuredHeight();
+ mx.removeView(mainView);
+ mx.addView(mainView, 0, new ConstraintLayout.LayoutParams(width, height));
+ mx.getViewTreeObserver().removeOnGlobalLayoutListener(this);
+ }
+ });
+ super.onConfigurationChanged(newConfig);
+ }
+
+ @Override
+ public void onRFACItemLabelClick(int position, RFACLabelItem item) {
+ switch (position) {
+ case 0:
+ Toast.makeText(getApplicationContext(), "Share Current Video", Toast.LENGTH_SHORT).show();
+ case 1:
+ Toast.makeText(getApplicationContext(),
+ DataStore.getInstance(getBaseContext()).isAdvancedDownloadMode() ?
+ "Show Audio/Video Formats To Download" : "Show Audio Format To Download", Toast.LENGTH_SHORT).show();
+ }
+ }
+
+ @Override
+ public void onRFACItemIconClick(int position, RFACLabelItem item) {
+ if (position == 0) {
+ Intent i = new Intent(Intent.ACTION_SEND)
+ .setType("text/plain")
+ .putExtra(Intent.EXTRA_TEXT, mainView.getUrl());
+ startActivity(Intent.createChooser(i, "Share Link"));
+ } else if (position == 1) {
+ if (mainView.getUrl().contains("watch?")) {
+ if (urlAll != null) {
+ String url = mainView.getUrl();
+ String linkLocal;
+
+ /*https://www.youtube.com/watch?v=J8Ma7V33Ju0
+ https://m.youtube.com/watch?v=J8Ma7V33Ju0
+ https://www.youtube.com/watch?v=aJOTlE1K90k&list=PLx0sYbCqOb8TBPRdmBHs5Iftvv9TPboYG*/
+
+ if (mainView.getUrl().contains("&list=")) {
+ linkLocal = "https://www.youtube.com/watch?v=" +
+ url.split("v=")[1].split("&list=")[0];
+ } else {
+ linkLocal = "https://www.youtube.com/watch?v=" +
+ url.split("v=")[1];
+ }
+
+ /* Mode Switch */
+ if (DataStore.getInstance(getBaseContext()).isAdvancedDownloadMode()) {
+ if (linkLocal.equals("")) {
+ Toast.makeText(MainActivity.this, "Error processing url - Please retry", Toast.LENGTH_SHORT).show();
+ return;
+ }
+ new DownloadManager().startAdvanceDownloadProcess(linkLocal, this, getSupportFragmentManager());
+ } else {
+ if (urlAll.equals("")) {
+ Snackbar.make(rfaLayout, "Please Wait,Loading Urls \n Try After Some Time", Snackbar.LENGTH_LONG).show();
+ } else {
+ new DownloadManager().startBasicDownloadProcess(MainActivity.this, urlAll, urlTitle, mainView.getUrl());
+ }
+ }
+
+ } else {
+ Snackbar.make(rfaLayout, "Empty Url", Snackbar.LENGTH_LONG).show();
+ }
+ } else {
+ Snackbar.make(rfaLayout, "Please Select A Valid Youtube Video ", Snackbar.LENGTH_SHORT).show();
+ }
+ }
+ }
+
+ @Subscribe(threadMode = ThreadMode.MAIN)
+ public void onMessageEvent(IPC ignored) {
+ if (isActive) {
+ if (Objects.equals(ignored.getMessage(), broadCastIntent) && mainView != null) {
+ Helper.clearCookies(mainView, false);
+ setDeskTopMode(mainView.getSettings(), DataStore.getInstance(getBaseContext()).isDeskModeEnabled());
+ } else if (Objects.equals(ignored.getMessage(), broadCastIntentFullScreen)) {
+ if (DataStore.getInstance(getBaseContext()).isFullScreen()) {
+ getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,
+ WindowManager.LayoutParams.FLAG_FULLSCREEN);
+ } else {
+ getWindow().clearFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN);
+ }
+ } else if (Objects.equals(ignored.getMessage(), broadCastIntentToolbar) && getSupportActionBar() != null) {
+ if (DataStore.getInstance(getBaseContext()).isRemoveToolbar()) {
+ getSupportActionBar().hide();
+ } else {
+ getSupportActionBar().show();
+ }
+ }
+ }
+ }
+}
diff --git a/app/src/main/java/app/exploitr/nsg/youp3/ui_access/SettingsActivity.java b/app/src/main/java/app/exploitr/nsg/youp3/ui_access/SettingsActivity.java
new file mode 100644
index 0000000..21e74da
--- /dev/null
+++ b/app/src/main/java/app/exploitr/nsg/youp3/ui_access/SettingsActivity.java
@@ -0,0 +1,143 @@
+package app.exploitr.nsg.youp3.ui_access;
+
+import android.content.Intent;
+import android.net.Uri;
+import android.os.Bundle;
+import android.text.Editable;
+import android.text.TextWatcher;
+import android.view.View;
+import android.widget.ImageButton;
+import android.widget.TextView;
+import android.widget.Toast;
+
+import androidx.appcompat.app.AppCompatActivity;
+import androidx.appcompat.widget.AppCompatEditText;
+import androidx.appcompat.widget.SwitchCompat;
+
+import com.llollox.androidtoggleswitch.widgets.ToggleSwitch;
+import com.obsez.android.lib.filechooser.ChooserDialog;
+
+import org.greenrobot.eventbus.EventBus;
+
+import java.io.File;
+import java.util.Objects;
+
+import app.exploitr.nsg.youp3.R;
+import utils.DataStore;
+import utils.IPC;
+
+public class SettingsActivity extends AppCompatActivity {
+
+ private static boolean edited = false;
+ SwitchCompat screenFull, remBar, deskTop;
+ ToggleSwitch basicAdv;
+ AppCompatEditText destination;
+ ImageButton browse_file;
+ TextView wrongText;
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ setContentView(R.layout.activity_settings);
+
+ Objects.requireNonNull(getSupportActionBar()).setTitle("Settings");
+
+ screenFull = findViewById(R.id.fullScr);
+ remBar = findViewById(R.id.remBar);
+ deskTop = findViewById(R.id.deskMode);
+ basicAdv = findViewById(R.id.basicAdv);
+ destination = findViewById(R.id.destin);
+ browse_file = findViewById(R.id.browse_directory);
+ wrongText = findViewById(R.id.wrongText);
+
+ screenFull.setChecked(DataStore.getInstance(getBaseContext()).isFullScreen());
+ remBar.setChecked(DataStore.getInstance(getBaseContext()).isRemoveToolbar());
+ deskTop.setChecked(DataStore.getInstance(getBaseContext()).isDeskModeEnabled());
+ basicAdv.setCheckedPosition(DataStore.getInstance(getBaseContext()).isAdvancedDownloadMode() ? 1 : 0); //1 adv 0 basic
+
+ screenFull.setOnCheckedChangeListener((buttonView, isChecked) -> {
+ EventBus.getDefault().post(new IPC().setMessage(MainActivity.broadCastIntentFullScreen));
+ DataStore.getInstance(getBaseContext()).setFullScreen(isChecked);
+ finish();
+ });
+
+ deskTop.setOnCheckedChangeListener((buttonView, isChecked) -> {
+ EventBus.getDefault().post(new IPC().setMessage(MainActivity.broadCastIntent));
+ DataStore.getInstance(getBaseContext()).setDeskModeEnabled(isChecked);
+ finish();
+ });
+
+ remBar.setOnCheckedChangeListener((buttonView, isChecked) -> {
+ EventBus.getDefault().post(new IPC().setMessage(MainActivity.broadCastIntentToolbar));
+ DataStore.getInstance(getBaseContext()).setRemoveToolbar(isChecked);
+ finish();
+ });
+
+ basicAdv.setOnChangeListener(position -> {
+ Toast.makeText(getApplicationContext(), position == 0 ? "Basic Mode" : "Advanced Mode", Toast.LENGTH_SHORT).show();
+ DataStore.getInstance(getBaseContext()).setAdvancedDownloadMode(position == 1);
+ });
+
+ findViewById(R.id.report).setOnClickListener(v -> {
+ Intent x = new Intent(Intent.ACTION_VIEW, Uri.parse("https://github.com/ExploiTR/YouP3/issues"));
+ x.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+ startActivity(x);
+ });
+
+ findViewById(R.id.okay).setOnClickListener(v -> {
+ if (checkFile(Objects.requireNonNull(destination.getText()).toString())) {
+ DataStore.getInstance(getBaseContext()).setPathDownload(destination.getText().toString());
+ if (edited) {
+ Toast.makeText(this, "Changed Download Directory to : " + destination.getText().toString()
+ , Toast.LENGTH_SHORT).show();
+ }
+ finish();
+ } else {
+ Toast.makeText(this, "Download Directory Selected Is Invalid", Toast.LENGTH_SHORT).show();
+ }
+ });
+
+
+ destination.setText(DataStore.getInstance(getBaseContext()).getPathDownload());
+ destination.addTextChangedListener(new TextWatcher() {
+ @Override
+ public void beforeTextChanged(CharSequence s, int start, int count, int after) {
+
+ }
+
+ @Override
+ public void onTextChanged(CharSequence s, int start, int before, int count) {
+
+ }
+
+ @Override
+ public void afterTextChanged(Editable s) {
+ edited = true;
+ checkFile(s.toString());
+ }
+ });
+ checkFile(Objects.requireNonNull(destination.getText()).toString());
+
+ browse_file.setOnClickListener(v -> new ChooserDialog(SettingsActivity.this)
+ .withStartFile(DataStore.getInstance(getBaseContext()).getPathDownload())
+ .withChosenListener((path, pathFile) -> destination.setText(path))
+ .withOnCancelListener(dialog -> {
+ Toast.makeText(this, "Nothing Selected :-(", Toast.LENGTH_SHORT).show();
+ dialog.cancel(); // MUST have
+ })
+ .build()
+ .show());
+ }
+
+ private boolean checkFile(String text) {
+ File newFile = new File(text);
+ if (newFile.exists() && newFile.canWrite() && newFile.canRead() && newFile.canExecute()) {
+ wrongText.setVisibility(View.GONE);
+ return true;
+ } else {
+ wrongText.setVisibility(View.VISIBLE);
+ return false;
+ }
+ }
+
+}
diff --git a/app/src/main/java/app/exploitr/nsg/youp3/ui_access/SuperIntentReceiver.java b/app/src/main/java/app/exploitr/nsg/youp3/ui_access/SuperIntentReceiver.java
new file mode 100644
index 0000000..f63d0ea
--- /dev/null
+++ b/app/src/main/java/app/exploitr/nsg/youp3/ui_access/SuperIntentReceiver.java
@@ -0,0 +1,29 @@
+package app.exploitr.nsg.youp3.ui_access;
+
+import android.content.Intent;
+import android.net.Uri;
+import android.os.Bundle;
+
+import androidx.annotation.Nullable;
+import androidx.appcompat.app.AppCompatActivity;
+
+import java.util.Objects;
+
+public class SuperIntentReceiver extends AppCompatActivity {
+ private String localLink = null; //nullification required for not passing null check
+
+ @Override
+ protected void onCreate(@Nullable Bundle savedInstanceState) {
+ if (Objects.equals(getIntent().getAction(), Intent.ACTION_SEND)) {
+ localLink = getIntent().getStringExtra(Intent.EXTRA_TEXT);
+ } else if (Objects.equals(getIntent().getAction(), Intent.ACTION_VIEW)) {
+ localLink = getIntent().getDataString();
+ }
+ startActivity(new Intent(SuperIntentReceiver.this, MainActivity.class)
+ .setAction(MainActivity.reDownloadAction)
+ .setFlags(Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED | Intent.FLAG_ACTIVITY_NEW_TASK)
+ .setData(Uri.parse(localLink)));
+ finish();
+ super.onCreate(savedInstanceState);
+ }
+}
diff --git a/app/src/main/java/app/exploitr/nsg/youp3/ui_access/Tos.java b/app/src/main/java/app/exploitr/nsg/youp3/ui_access/Tos.java
new file mode 100644
index 0000000..cc4d9a7
--- /dev/null
+++ b/app/src/main/java/app/exploitr/nsg/youp3/ui_access/Tos.java
@@ -0,0 +1,106 @@
+package app.exploitr.nsg.youp3.ui_access;
+
+import android.annotation.SuppressLint;
+import android.os.Bundle;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.CheckBox;
+import android.widget.TextView;
+
+import androidx.annotation.Nullable;
+
+import org.jetbrains.annotations.NotNull;
+
+import app.exploitr.nsg.youp3.R;
+import io.github.dreierf.materialintroscreen.SlideFragment;
+
+public class Tos extends SlideFragment {
+ private CheckBox checkBox;
+
+ @SuppressLint("SetTextI18n")
+ @Nullable
+ @Override
+ public View onCreateView(@NotNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
+ final View view = inflater.inflate(R.layout.slide_for_tos, container, false);
+ //
+ ((TextView) view.findViewById(R.id.pvp_text)).setText(
+ "Pratim Majumder built the YouP3 app as an Open Source app. This SERVICE is provided by Pratim Majumder at no cost and is intended for use as is.\n" +
+ "\n" +
+ "This page is used to inform visitors regarding my policies with the collection, use, and disclosure of Personal Information if anyone decided to use my Service.\n" +
+ "\n" +
+ "If you choose to use my Service, then you agree to the collection and use of information in relation to this policy. The Personal Information that I collect is used for providing and improving the Service. I will not use or share your information with anyone except as described in this Privacy Policy.\n" +
+ "\n" +
+ "The terms used in this Privacy Policy have the same meanings as in our Terms and Conditions, which is accessible at YouP3 unless otherwise defined in this Privacy Policy.\n" +
+ "\n" +
+ "Information Collection and Use\n" +
+ "\n" +
+ "For a better experience, while using our Service, I may require you to provide us with certain personally identifiable information. The information that I request will be retained on your device and is not collected by me in any way.\n" +
+ "\n" +
+ "The app does use third party services that may collect information used to identify you.\n" +
+ "\n" +
+ "Link to privacy policy of third party service providers used by the app\n" +
+ "\n" +
+ "* Firebase Analytics \n" +
+ "* Fabric \n" +
+ "* Crashlytics \n" +
+ "* Log Data\n" +
+ "\n" +
+ "I want to inform you that whenever you use my Service, in a case of an error in the app I collect data and information (through third party products) on your phone called Log Data. This Log Data may include information such as your device Internet Protocol (“IP”) address, device name, operating system version, the configuration of the app when utilizing my Service, the time and date of your use of the Service, and other statistics.\n" +
+ "\n" +
+ "Cookies\n" +
+ "\n" +
+ "Cookies are files with a small amount of data that are commonly used as anonymous unique identifiers. These are sent to your browser from the websites that you visit and are stored on your device's internal memory.\n" +
+ "\n" +
+ "This Service does not use these “cookies” explicitly. However, the app may use third party code and libraries that use “cookies” to collect information and improve their services. You have the option to either accept or refuse these cookies and know when a cookie is being sent to your device. If you choose to refuse our cookies, you may not be able to use some portions of this Service.\n" +
+ "\n" +
+ "Service Providers\n" +
+ "\n" +
+ "I may employ third-party companies and individuals due to the following reasons:\n" +
+ "\n" +
+ "To facilitate our Service;\n" +
+ "To provide the Service on our behalf;\n" +
+ "To perform Service-related services; or\n" +
+ "To assist us in analyzing how our Service is used.\n" +
+ "I want to inform users of this Service that these third parties have access to your Personal Information. The reason is to perform the tasks assigned to them on our behalf. However, they are obligated not to disclose or use the information for any other purpose.\n" +
+ "\n" +
+ "Security\n" +
+ "\n" +
+ "I value your trust in providing us your Personal Information, thus we are striving to use commercially acceptable means of protecting it. But remember that no method of transmission over the internet, or method of electronic storage is 100% secure and reliable, and I cannot guarantee its absolute security.\n" +
+ "\n" +
+ "Links to Other Sites\n" +
+ "\n" +
+ "This Service may contain links to other sites. If you click on a third-party link, you will be directed to that site. Note that these external sites are not operated by me. Therefore, I strongly advise you to review the Privacy Policy of these websites. I have no control over and assume no responsibility for the content, privacy policies, or practices of any third-party sites or services.\n" +
+ "\n" +
+ "Children’s Privacy\n" +
+ "\n" +
+ "These Services do not address anyone under the age of 13. I do not knowingly collect personally identifiable information from children under 13. In the case I discover that a child under 13 has provided me with personal information, I immediately delete this from our servers. If you are a parent or guardian and you are aware that your child has provided us with personal information, please contact me so that I will be able to do necessary actions.\n" +
+ "\n" +
+ "Changes to This Privacy Policy\n" +
+ "\n" +
+ "I may update our Privacy Policy from time to time. Thus, you are advised to review this page periodically for any changes. I will notify you of any changes by posting the new Privacy Policy on this page. These changes are effective immediately after they are posted on this page.");
+ //
+ checkBox = view.findViewById(R.id.checkBox);
+ return view;
+ }
+
+ @Override
+ public int backgroundColor() {
+ return R.color.themeDef_SettingsActivity_primary;
+ }
+
+ @Override
+ public int buttonsColor() {
+ return R.color.themeDef_Intro_purple_orchid;
+ }
+
+ @Override
+ public boolean canMoveFurther() {
+ return checkBox.isChecked();
+ }
+
+ @Override
+ public String cantMoveFurtherErrorMessage() {
+ return "Please Accept Usage Criteria(s)";
+ }
+}
diff --git a/app/src/main/java/converter/utils/ConverterService.java b/app/src/main/java/converter/utils/ConverterService.java
index 45b244d..597c357 100644
--- a/app/src/main/java/converter/utils/ConverterService.java
+++ b/app/src/main/java/converter/utils/ConverterService.java
@@ -21,8 +21,8 @@
import java.io.File;
import java.io.IOException;
-import app.exploitr.nsg.youp3.AudioConverter;
import app.exploitr.nsg.youp3.R;
+import app.exploitr.nsg.youp3.ui_access.AudioConverter;
import cafe.adriel.androidaudioconverter.AndroidAudioConverter;
import cafe.adriel.androidaudioconverter.callback.IConvertCallback;
import cafe.adriel.androidaudioconverter.model.AudioFormat;
diff --git a/app/src/main/java/downloader/utils/DownloadExecutorService.java b/app/src/main/java/downloader/utils/DownloadExecutorService.java
index 5b36d9a..1021201 100644
--- a/app/src/main/java/downloader/utils/DownloadExecutorService.java
+++ b/app/src/main/java/downloader/utils/DownloadExecutorService.java
@@ -15,10 +15,9 @@
import androidx.annotation.Nullable;
import androidx.core.app.NotificationManagerCompat;
-import app.exploitr.nsg.youp3.DownloadsActivity;
-import app.exploitr.nsg.youp3.MainActivity;
+import app.exploitr.nsg.youp3.ui_access.DownloadsActivity;
+import app.exploitr.nsg.youp3.ui_access.MainActivity;
import app.exploitr.nsg.youp3.R;
-import io.realm.Realm;
import utils.Helper;
public class DownloadExecutorService extends Service {
diff --git a/app/src/main/java/downloader/utils/DownloadManager.java b/app/src/main/java/downloader/utils/DownloadManager.java
index efb4ec8..bd2ca07 100644
--- a/app/src/main/java/downloader/utils/DownloadManager.java
+++ b/app/src/main/java/downloader/utils/DownloadManager.java
@@ -16,7 +16,7 @@
import java.util.Arrays;
import java.util.List;
-import app.exploitr.nsg.youp3.BottomSheetFragment;
+import app.exploitr.nsg.youp3.ui_access.BottomSheetFragment;
import app.exploitr.nsg.youp3.R;
import at.huber.youtubeExtractor.Format;
import at.huber.youtubeExtractor.VideoMeta;
diff --git a/app/src/main/java/downloader/utils/Downloader.java b/app/src/main/java/downloader/utils/Downloader.java
index b16d4ec..1726129 100644
--- a/app/src/main/java/downloader/utils/Downloader.java
+++ b/app/src/main/java/downloader/utils/Downloader.java
@@ -15,7 +15,6 @@
import java.io.File;
import java.util.Locale;
-import app.exploitr.nsg.youp3.DownloadsActivity;
import downloads.DownloadHistoryManager;
import downloads.RealmController;
import io.reactivex.Observer;
@@ -49,7 +48,7 @@ public void onSubscribe(Disposable d) {
.push(FINAL_ID,
"Downloading Now.",
object.getName(),
- "0 MB",
+ 0,
false,
object.getYtUrl()
);
@@ -64,7 +63,7 @@ public void onNext(String finalFilePath) {
.push(FINAL_ID,
content.getAbsolutePath(),
object.getName(),
- String.format(Locale.US, "%.2f", Helper.fileLen(content, 2)) + "MB",
+ Helper.fileLen(content),
true,
object.getYtUrl()
);
diff --git a/app/src/main/java/downloads/DownloadHistoryManager.java b/app/src/main/java/downloads/DownloadHistoryManager.java
index 05ba544..6db0d03 100644
--- a/app/src/main/java/downloads/DownloadHistoryManager.java
+++ b/app/src/main/java/downloads/DownloadHistoryManager.java
@@ -23,7 +23,7 @@ private RealmController getController() {
return new RealmController();
}
- public void push(int id, String path, String name, String sizeWithUnit, boolean complete, String ytUrl) {
+ public void push(int id, String path, String name, double sizeMb, boolean complete, String ytUrl) {
VideoInfo info = new VideoInfo();
@@ -31,7 +31,7 @@ public void push(int id, String path, String name, String sizeWithUnit, boolean
/*IDK but link would be the same*/
info.setPath(path);
info.setName(name);
- info.setSize(sizeWithUnit);
+ info.setSize(sizeMb);
info.setCompleted(complete);
info.setYtUrl(ytUrl);
diff --git a/app/src/main/java/downloads/DownloadsAdapter.java b/app/src/main/java/downloads/DownloadsAdapter.java
index 82f93d7..a386f37 100644
--- a/app/src/main/java/downloads/DownloadsAdapter.java
+++ b/app/src/main/java/downloads/DownloadsAdapter.java
@@ -1,6 +1,7 @@
package downloads;
import android.content.Context;
+import android.os.Environment;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
@@ -10,6 +11,9 @@
import androidx.annotation.NonNull;
import androidx.recyclerview.widget.RecyclerView;
+import com.github.lzyzsd.circleprogress.DonutProgress;
+
+import java.text.DecimalFormat;
import java.util.List;
import app.exploitr.nsg.youp3.R;
@@ -24,9 +28,11 @@ public class DownloadsAdapter extends RecyclerView.Adapter data) {
this.mInflater = LayoutInflater.from(context);
+ SIZE_TOTAL = Environment.getExternalStorageDirectory().getTotalSpace() / (1024 * 1024);
this.mData = data;
}
@@ -42,15 +48,14 @@ public ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
View view = mInflater.inflate(R.layout.row_downloads_list_item, parent, false);
return new ViewHolder(view);
}
-
-
+
@Override
public void onBindViewHolder(@NonNull final ViewHolder holder, int position) {
final VideoInfo vInfo = mData.get(position);
- holder.nameTextView.setText(vInfo.getName());
+ holder.nameTextView.setText(vInfo.getName().substring(0, 40) + ".....");
holder.pathTextView.setText(vInfo.getPath());
- holder.sizeTextView.setText(vInfo.getSize());
- holder.urlTextView.setText(vInfo.getYtUrl());
+ holder.sizeView.setProgress(Float.parseFloat(new DecimalFormat("##.##")
+ .format((vInfo.getSize() / SIZE_TOTAL) * 100)));
if (new RealmController().getVideoInfo(vInfo.getId()) != null) {
if (new RealmController().getVideoInfo(vInfo.getId()).isCompleted()) {
@@ -62,7 +67,6 @@ public void onBindViewHolder(@NonNull final ViewHolder holder, int position) {
}
-
@Override
public int getItemCount() {
return mData.size();
@@ -93,15 +97,15 @@ public interface ItemLongClickListener {
}
class ViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener, View.OnLongClickListener {
- TextView nameTextView, pathTextView, sizeTextView, urlTextView;
+ TextView nameTextView, pathTextView;
+ DonutProgress sizeView;
ImageButton cancelButton, openButton, reDownload;
ViewHolder(View itemView) {
super(itemView);
nameTextView = itemView.findViewById(R.id.file_downloads_name);
pathTextView = itemView.findViewById(R.id.file_downloads_path);
- sizeTextView = itemView.findViewById(R.id.file_size);
- urlTextView = itemView.findViewById(R.id.file_downloads_url);
+ sizeView = itemView.findViewById(R.id.file_size);
cancelButton = itemView.findViewById(R.id.cancel_download);
openButton = itemView.findViewById(R.id.open_file);
@@ -125,19 +129,19 @@ public void onClick(View view) {
mClickListener.onCancelClick(
mData.get(this.getLayoutPosition()).getId(),
this.getLayoutPosition(),
- nameTextView.getText().toString(),
- pathTextView.getText().toString()
+ mData.get(this.getLayoutPosition()).getName(),
+ mData.get(this.getLayoutPosition()).getPath()
);
} else if (view.getId() == openButton.getId()) {
mClickListener.onOpenClick(
mData.get(this.getLayoutPosition()).getId(),
this.getLayoutPosition(),
- pathTextView.getText().toString()
+ mData.get(this.getLayoutPosition()).getPath()
);
} else if (view.getId() == reDownload.getId()) {
mClickListener.onReDownloadClick(
mData.get(this.getLayoutPosition()).getId(),
- urlTextView.getText().toString());
+ mData.get(this.getLayoutPosition()).getYtUrl());
}
}
}
diff --git a/app/src/main/java/downloads/RealmController.java b/app/src/main/java/downloads/RealmController.java
index 431c73c..e383560 100644
--- a/app/src/main/java/downloads/RealmController.java
+++ b/app/src/main/java/downloads/RealmController.java
@@ -8,7 +8,7 @@
import java.util.Objects;
-import app.exploitr.nsg.youp3.MainActivity;
+import app.exploitr.nsg.youp3.ui_access.MainActivity;
import io.realm.Realm;
import io.realm.RealmResults;
diff --git a/app/src/main/java/downloads/VideoInfo.java b/app/src/main/java/downloads/VideoInfo.java
index 6ae5657..90685ef 100644
--- a/app/src/main/java/downloads/VideoInfo.java
+++ b/app/src/main/java/downloads/VideoInfo.java
@@ -13,7 +13,7 @@ public class VideoInfo extends RealmObject {
private int id;
private String path;
private String name;
- private String size;
+ private double size;
private String url;
private String ytUrl;
private boolean completed;
@@ -42,11 +42,11 @@ public void setName(String name) {
this.name = name;
}
- public String getSize() {
+ public double getSize() {
return size;
}
- public void setSize(String size) {
+ public void setSize(double size) {
this.size = size;
}
diff --git a/app/src/main/java/utils/Helper.java b/app/src/main/java/utils/Helper.java
index 729c2c1..87882c2 100644
--- a/app/src/main/java/utils/Helper.java
+++ b/app/src/main/java/utils/Helper.java
@@ -52,10 +52,8 @@ public static void verb(String tag, @NonNull Object what) {
* Expecting byte-returns
* So, for mb, 2 -> 1024/1024 -> kb/mb
* */
- public static double fileLen(File path, int multiplier) {
- verb(path.length());
- verb(Math.pow(1024, multiplier));
- return path.length() / Math.pow(1024, multiplier);
+ public static double fileLen(File path) {
+ return path.length() / (1024*1024);
}
public static String getTitle(Context context, String url) {
diff --git a/app/src/main/java/utils/MediaPlayer.java b/app/src/main/java/utils/MediaPlayer.java
new file mode 100644
index 0000000..ce6b318
--- /dev/null
+++ b/app/src/main/java/utils/MediaPlayer.java
@@ -0,0 +1,144 @@
+package utils;
+
+import android.app.PictureInPictureParams;
+import android.content.pm.ActivityInfo;
+import android.content.pm.PackageManager;
+import android.content.res.Configuration;
+import android.net.Uri;
+import android.os.Build;
+import android.os.Bundle;
+import android.util.Rational;
+import android.view.WindowManager;
+
+import androidx.annotation.Nullable;
+import androidx.appcompat.app.AppCompatActivity;
+
+import com.google.android.exoplayer2.DefaultLoadControl;
+import com.google.android.exoplayer2.DefaultRenderersFactory;
+import com.google.android.exoplayer2.ExoPlayerFactory;
+import com.google.android.exoplayer2.LoadControl;
+import com.google.android.exoplayer2.RenderersFactory;
+import com.google.android.exoplayer2.SimpleExoPlayer;
+import com.google.android.exoplayer2.extractor.DefaultExtractorsFactory;
+import com.google.android.exoplayer2.extractor.ExtractorsFactory;
+import com.google.android.exoplayer2.source.LoopingMediaSource;
+import com.google.android.exoplayer2.source.MediaSource;
+import com.google.android.exoplayer2.source.ProgressiveMediaSource;
+import com.google.android.exoplayer2.trackselection.AdaptiveTrackSelection;
+import com.google.android.exoplayer2.trackselection.DefaultTrackSelector;
+import com.google.android.exoplayer2.trackselection.TrackSelection;
+import com.google.android.exoplayer2.trackselection.TrackSelector;
+import com.google.android.exoplayer2.ui.PlayerView;
+import com.google.android.exoplayer2.upstream.DefaultBandwidthMeter;
+import com.google.android.exoplayer2.upstream.DefaultDataSourceFactory;
+import com.google.android.exoplayer2.util.Util;
+
+import app.exploitr.nsg.youp3.R;
+
+public class MediaPlayer extends AppCompatActivity {
+
+ private SimpleExoPlayer player;
+ private PlayerView playerView;
+ private boolean lock = true;
+
+ @Override
+ public void onCreate(@Nullable Bundle savedInstanceState) {
+ setContentView(R.layout.media_player);
+ if (getIntent() != null) {
+ if (getIntent().getDataString() != null) {
+ playerView = findViewById(R.id.exoPlayer);
+ play(Uri.parse(getIntent().getDataString()));
+
+ if (getWindow() != null) {
+ getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,
+ WindowManager.LayoutParams.FLAG_FULLSCREEN);
+ }
+
+ setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);
+
+ } else {
+ superFinish();
+ }
+ } else {
+ superFinish();
+ }
+ super.onCreate(savedInstanceState);
+ }
+
+ /*Handled both finish() types*/
+ private void superFinish() {
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
+ finishAndRemoveTask();
+ } else {
+ finish();
+ }
+ }
+
+ void play(Uri fileUri) {
+ DefaultBandwidthMeter bandwidthMeter = new DefaultBandwidthMeter.Builder(playerView.getContext()).build();
+ TrackSelection.Factory videoTrackSelectionFactory = new AdaptiveTrackSelection.Factory();
+ TrackSelector trackSelector = new DefaultTrackSelector(videoTrackSelectionFactory);
+
+ LoadControl loadControl = new DefaultLoadControl();
+ RenderersFactory renderersFactory = new DefaultRenderersFactory(getApplicationContext());
+ player = ExoPlayerFactory.newSimpleInstance(playerView.getContext(), renderersFactory, trackSelector, loadControl);
+
+ playerView.setUseController(true);
+ playerView.requestFocus();
+ playerView.setControllerHideOnTouch(true);
+ playerView.setPlayer(player);
+
+ DefaultDataSourceFactory dataSourceFactory = new DefaultDataSourceFactory(MediaPlayer.this,
+ Util.getUserAgent(MediaPlayer.this,
+ "YouP3 Player"), bandwidthMeter);
+ ExtractorsFactory extractorsFactory = new DefaultExtractorsFactory();
+
+ MediaSource videoSource = new ProgressiveMediaSource.Factory(dataSourceFactory, extractorsFactory)
+ .createMediaSource(fileUri);
+ LoopingMediaSource loopingSource = new LoopingMediaSource(videoSource);
+ player.prepare(loopingSource);
+ player.setPlayWhenReady(true);
+
+ }
+
+ @Override
+ protected void onStop() {
+ player.setPlayWhenReady(false);
+ player.stop();
+ player.release();
+ player = null;
+ super.onStop();
+ }
+
+ @Override
+ public void onPictureInPictureModeChanged(boolean isInPictureInPictureMode, Configuration newConfig) {
+ if (isInPictureInPictureMode) {
+ setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
+ } else {
+ setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);
+ }
+ if (lock) {
+ lock = false;
+ } else {
+ superFinish();
+ }
+ }
+
+ @Override
+ public void onBackPressed() {
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N
+ && getPackageManager().hasSystemFeature(PackageManager.FEATURE_PICTURE_IN_PICTURE)) {
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
+ PictureInPictureParams params = new PictureInPictureParams
+ .Builder()
+ .setAspectRatio(new Rational(16, 9))
+ .build();
+ enterPictureInPictureMode(params);
+ } else {
+ enterPictureInPictureMode();
+ }
+ } else {
+ superFinish();
+ }
+ }
+}
diff --git a/app/src/main/java/utils/YouWorker.java b/app/src/main/java/utils/YouWorker.java
new file mode 100644
index 0000000..67bb7d3
--- /dev/null
+++ b/app/src/main/java/utils/YouWorker.java
@@ -0,0 +1,41 @@
+package utils;
+
+import android.os.Build;
+import android.os.Environment;
+import android.os.StatFs;
+
+import androidx.multidex.MultiDexApplication;
+
+import com.crashlytics.android.Crashlytics;
+
+import app.exploitr.nsg.youp3.ui_access.MainActivity;
+import io.fabric.sdk.android.Fabric;
+import io.realm.Realm;
+
+public class YouWorker extends MultiDexApplication {
+
+ public static boolean IS_CONVERSION_SUPPORTED = false;
+ @Override
+ public void onCreate() {
+
+ if (MainActivity.isBuildFinal) {
+ Fabric.with(this, new Crashlytics());
+ setUserForLogging();
+ }
+
+ /*Initializing Realm*/
+ Realm.init(this);
+ super.onCreate();
+
+ Thread.setDefaultUncaughtExceptionHandler((t, e) -> {
+ e.printStackTrace();
+ });
+ }
+
+ private void setUserForLogging() {
+ Crashlytics.setUserName(Build.DEVICE);
+ Crashlytics.setUserIdentifier(Build.FINGERPRINT);
+ }
+
+
+}
diff --git a/app/src/main/res/layout/activity_audio_converter.xml b/app/src/main/res/layout/activity_audio_converter.xml
index 04eca2c..1acc561 100644
--- a/app/src/main/res/layout/activity_audio_converter.xml
+++ b/app/src/main/res/layout/activity_audio_converter.xml
@@ -4,7 +4,7 @@
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
- tools:context=".AudioConverter">
+ tools:context=".ui_access.AudioConverter">
+ tools:context=".ui_access.BookMarkActivity">
+ tools:context="app.exploitr.nsg.youp3.ui_access.DownloadsActivity">
+
+
+
+
+
+
diff --git a/app/src/main/res/layout/row_downloads_list_item.xml b/app/src/main/res/layout/row_downloads_list_item.xml
index 8537254..e0d08fe 100644
--- a/app/src/main/res/layout/row_downloads_list_item.xml
+++ b/app/src/main/res/layout/row_downloads_list_item.xml
@@ -5,9 +5,9 @@
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginLeft="5dp"
- app:cardCornerRadius="10dp"
android:layout_marginTop="5dp"
- android:layout_marginRight="5dp">
+ android:layout_marginRight="5dp"
+ app:cardCornerRadius="10dp">
-
-
-
-
-
+ android:layout_height="match_parent"
+ android:orientation="horizontal">
-
+
-
+
-
+
+
+
+
+
+
- false
- true
+ - true
diff --git a/build.gradle b/build.gradle
index a01c4cb..1925682 100644
--- a/build.gradle
+++ b/build.gradle
@@ -1,4 +1,3 @@
-//noinspection GradleDependency
// Top-level build file where you can add configuration options common to all sub-projects/modules.
buildscript {
@@ -7,18 +6,18 @@ buildscript {
jcenter()
}
dependencies {
- //noinspection GradleDependency
- classpath 'com.android.tools.build:gradle:3.4.1'
- classpath "io.realm:realm-gradle-plugin:3.7.2"
- classpath 'com.google.gms:google-services:4.2.0'
+ classpath 'com.android.tools.build:gradle:3.5.1'
+ classpath "io.realm:realm-gradle-plugin:5.12.0"
+ classpath 'com.google.gms:google-services:4.3.0'
}
}
allprojects {
repositories {
+ mavenCentral()
+ maven { url 'https://jitpack.io' }
google()
jcenter()
- maven { url 'https://jitpack.io' }
maven { url 'http://guardian.github.com/maven/repo-releases' }
}
}