other new features
- check for updates when app launches - remove scrollview so that recyclerview can recycle. It wont hide the top bar but thats a sacrifice for the greater good. - remove download all mini card and made it into a floating action button - made video loading from playlists as fast as possible even if you have thousands of videos in a list. It adds videos in recyclerview in a form of pagination - fixed preferences when you just installed the app and you never opened the preference screen you can still download without erroring out
This commit is contained in:
parent
b81add6008
commit
709a3778a2
23 changed files with 505 additions and 488 deletions
|
|
@ -67,13 +67,13 @@
|
||||||
<entry key="..\:/Users/denis/Documents/GitHub/ytdlnis/app/src/main/res/layout/download_all_card.xml" value="0.25" />
|
<entry key="..\:/Users/denis/Documents/GitHub/ytdlnis/app/src/main/res/layout/download_all_card.xml" value="0.25" />
|
||||||
<entry key="..\:/Users/denis/Documents/GitHub/ytdlnis/app/src/main/res/layout/empty_history_hint.xml" value="0.2" />
|
<entry key="..\:/Users/denis/Documents/GitHub/ytdlnis/app/src/main/res/layout/empty_history_hint.xml" value="0.2" />
|
||||||
<entry key="..\:/Users/denis/Documents/GitHub/ytdlnis/app/src/main/res/layout/fragment_history.xml" value="0.2" />
|
<entry key="..\:/Users/denis/Documents/GitHub/ytdlnis/app/src/main/res/layout/fragment_history.xml" value="0.2" />
|
||||||
<entry key="..\:/Users/denis/Documents/GitHub/ytdlnis/app/src/main/res/layout/fragment_home.xml" value="0.25" />
|
<entry key="..\:/Users/denis/Documents/GitHub/ytdlnis/app/src/main/res/layout/fragment_home.xml" value="0.16" />
|
||||||
<entry key="..\:/Users/denis/Documents/GitHub/ytdlnis/app/src/main/res/layout/fragment_more.xml" value="0.33" />
|
<entry key="..\:/Users/denis/Documents/GitHub/ytdlnis/app/src/main/res/layout/fragment_more.xml" value="0.33" />
|
||||||
<entry key="..\:/Users/denis/Documents/GitHub/ytdlnis/app/src/main/res/layout/fragment_music_editor.xml" value="0.16875" />
|
<entry key="..\:/Users/denis/Documents/GitHub/ytdlnis/app/src/main/res/layout/fragment_music_editor.xml" value="0.16875" />
|
||||||
<entry key="..\:/Users/denis/Documents/GitHub/ytdlnis/app/src/main/res/layout/fragment_settings.xml" value="0.16875" />
|
<entry key="..\:/Users/denis/Documents/GitHub/ytdlnis/app/src/main/res/layout/fragment_settings.xml" value="0.16875" />
|
||||||
<entry key="..\:/Users/denis/Documents/GitHub/ytdlnis/app/src/main/res/layout/history_bottom_sheet.xml" value="0.16875" />
|
<entry key="..\:/Users/denis/Documents/GitHub/ytdlnis/app/src/main/res/layout/history_bottom_sheet.xml" value="0.16875" />
|
||||||
<entry key="..\:/Users/denis/Documents/GitHub/ytdlnis/app/src/main/res/layout/history_card.xml" value="0.1" />
|
<entry key="..\:/Users/denis/Documents/GitHub/ytdlnis/app/src/main/res/layout/history_card.xml" value="0.33" />
|
||||||
<entry key="..\:/Users/denis/Documents/GitHub/ytdlnis/app/src/main/res/layout/history_card_shimmer.xml" value="0.22" />
|
<entry key="..\:/Users/denis/Documents/GitHub/ytdlnis/app/src/main/res/layout/history_card_shimmer.xml" value="0.33" />
|
||||||
<entry key="..\:/Users/denis/Documents/GitHub/ytdlnis/app/src/main/res/layout/history_no_results.xml" value="0.21" />
|
<entry key="..\:/Users/denis/Documents/GitHub/ytdlnis/app/src/main/res/layout/history_no_results.xml" value="0.21" />
|
||||||
<entry key="..\:/Users/denis/Documents/GitHub/ytdlnis/app/src/main/res/layout/home_download_all_bottom_sheet.xml" value="0.33" />
|
<entry key="..\:/Users/denis/Documents/GitHub/ytdlnis/app/src/main/res/layout/home_download_all_bottom_sheet.xml" value="0.33" />
|
||||||
<entry key="..\:/Users/denis/Documents/GitHub/ytdlnis/app/src/main/res/layout/home_video_bottom_sheet.xml" value="0.1703125" />
|
<entry key="..\:/Users/denis/Documents/GitHub/ytdlnis/app/src/main/res/layout/home_video_bottom_sheet.xml" value="0.1703125" />
|
||||||
|
|
|
||||||
|
|
@ -21,6 +21,6 @@ public class ExampleInstrumentedTest {
|
||||||
// Context of the app under test.
|
// Context of the app under test.
|
||||||
Context appContext = InstrumentationRegistry.getInstrumentation().getTargetContext();
|
Context appContext = InstrumentationRegistry.getInstrumentation().getTargetContext();
|
||||||
|
|
||||||
assertEquals("com.yausername.youtubedl_android_example", appContext.getPackageName());
|
assertEquals("com.deniscerri.ytdl", appContext.getPackageName());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,15 +1,24 @@
|
||||||
package com.deniscerri.ytdl;
|
package com.deniscerri.ytdl;
|
||||||
|
|
||||||
import android.app.Application;
|
import android.app.Application;
|
||||||
|
import android.os.Environment;
|
||||||
|
import android.provider.ContactsContract;
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
import android.widget.Toast;
|
import android.widget.Toast;
|
||||||
|
|
||||||
|
import androidx.preference.PreferenceManager;
|
||||||
|
|
||||||
import com.deniscerri.ytdl.util.NotificationUtil;
|
import com.deniscerri.ytdl.util.NotificationUtil;
|
||||||
|
import com.deniscerri.ytdl.util.UpdateUtil;
|
||||||
import com.google.android.material.color.DynamicColors;
|
import com.google.android.material.color.DynamicColors;
|
||||||
import com.yausername.ffmpeg.FFmpeg;
|
import com.yausername.ffmpeg.FFmpeg;
|
||||||
import com.yausername.youtubedl_android.YoutubeDL;
|
import com.yausername.youtubedl_android.YoutubeDL;
|
||||||
import com.yausername.youtubedl_android.YoutubeDLException;
|
import com.yausername.youtubedl_android.YoutubeDLException;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
|
import java.nio.file.Files;
|
||||||
|
import java.nio.file.Paths;
|
||||||
|
|
||||||
import io.reactivex.Completable;
|
import io.reactivex.Completable;
|
||||||
import io.reactivex.android.schedulers.AndroidSchedulers;
|
import io.reactivex.android.schedulers.AndroidSchedulers;
|
||||||
import io.reactivex.exceptions.UndeliverableException;
|
import io.reactivex.exceptions.UndeliverableException;
|
||||||
|
|
@ -30,6 +39,7 @@ public class App extends Application {
|
||||||
notificationUtil = new NotificationUtil(this);
|
notificationUtil = new NotificationUtil(this);
|
||||||
createNotificationChannels();
|
createNotificationChannels();
|
||||||
|
|
||||||
|
PreferenceManager.setDefaultValues(this, "root_preferences", this.MODE_PRIVATE, R.xml.root_preferences, false);
|
||||||
configureRxJavaErrorHandler();
|
configureRxJavaErrorHandler();
|
||||||
Completable.fromAction(this::initLibraries).subscribeOn(Schedulers.io()).observeOn(AndroidSchedulers.mainThread()).subscribe(new DisposableCompletableObserver() {
|
Completable.fromAction(this::initLibraries).subscribeOn(Schedulers.io()).observeOn(AndroidSchedulers.mainThread()).subscribe(new DisposableCompletableObserver() {
|
||||||
@Override
|
@Override
|
||||||
|
|
|
||||||
|
|
@ -10,12 +10,15 @@ import android.util.Log;
|
||||||
import androidx.appcompat.app.AppCompatActivity;
|
import androidx.appcompat.app.AppCompatActivity;
|
||||||
import androidx.fragment.app.Fragment;
|
import androidx.fragment.app.Fragment;
|
||||||
import androidx.fragment.app.FragmentManager;
|
import androidx.fragment.app.FragmentManager;
|
||||||
|
import androidx.preference.PreferenceManager;
|
||||||
|
|
||||||
import com.deniscerri.ytdl.databinding.ActivityMainBinding;
|
import com.deniscerri.ytdl.databinding.ActivityMainBinding;
|
||||||
import com.deniscerri.ytdl.page.HistoryFragment;
|
import com.deniscerri.ytdl.page.HistoryFragment;
|
||||||
import com.deniscerri.ytdl.page.HomeFragment;
|
import com.deniscerri.ytdl.page.HomeFragment;
|
||||||
import com.deniscerri.ytdl.page.MoreFragment;
|
import com.deniscerri.ytdl.page.MoreFragment;
|
||||||
import com.deniscerri.ytdl.page.MusicEditorFragment;
|
|
||||||
import com.deniscerri.ytdl.page.settings.SettingsActivity;
|
import com.deniscerri.ytdl.page.settings.SettingsActivity;
|
||||||
|
import com.deniscerri.ytdl.page.settings.SettingsFragment;
|
||||||
|
import com.deniscerri.ytdl.util.UpdateUtil;
|
||||||
|
|
||||||
|
|
||||||
public class MainActivity extends AppCompatActivity{
|
public class MainActivity extends AppCompatActivity{
|
||||||
|
|
@ -27,7 +30,6 @@ public class MainActivity extends AppCompatActivity{
|
||||||
|
|
||||||
private HomeFragment homeFragment;
|
private HomeFragment homeFragment;
|
||||||
private HistoryFragment historyFragment;
|
private HistoryFragment historyFragment;
|
||||||
private MusicEditorFragment musicEditorFragment;
|
|
||||||
private MoreFragment moreFragment;
|
private MoreFragment moreFragment;
|
||||||
|
|
||||||
private Fragment lastFragment;
|
private Fragment lastFragment;
|
||||||
|
|
@ -58,15 +60,15 @@ public class MainActivity extends AppCompatActivity{
|
||||||
|
|
||||||
setContentView(R.layout.activity_main);
|
setContentView(R.layout.activity_main);
|
||||||
setContentView(binding.getRoot());
|
setContentView(binding.getRoot());
|
||||||
|
|
||||||
context = getBaseContext();
|
context = getBaseContext();
|
||||||
|
|
||||||
|
checkUpdate();
|
||||||
|
|
||||||
fm = getSupportFragmentManager();
|
fm = getSupportFragmentManager();
|
||||||
|
|
||||||
homeFragment = new HomeFragment();
|
homeFragment = new HomeFragment();
|
||||||
historyFragment = new HistoryFragment();
|
historyFragment = new HistoryFragment();
|
||||||
moreFragment = new MoreFragment();
|
moreFragment = new MoreFragment();
|
||||||
musicEditorFragment = new MusicEditorFragment();
|
|
||||||
|
|
||||||
initFragments();
|
initFragments();
|
||||||
|
|
||||||
|
|
@ -94,8 +96,6 @@ public class MainActivity extends AppCompatActivity{
|
||||||
this.setTitle(getString(R.string.more));
|
this.setTitle(getString(R.string.more));
|
||||||
}
|
}
|
||||||
replaceFragment(moreFragment);
|
replaceFragment(moreFragment);
|
||||||
}else if(id == R.id.music_editor){
|
|
||||||
replaceFragment(musicEditorFragment);
|
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
});
|
});
|
||||||
|
|
@ -114,9 +114,9 @@ public class MainActivity extends AppCompatActivity{
|
||||||
if(Intent.ACTION_SEND.equals(action)){
|
if(Intent.ACTION_SEND.equals(action)){
|
||||||
Log.e(TAG, action);
|
Log.e(TAG, action);
|
||||||
|
|
||||||
|
|
||||||
homeFragment = new HomeFragment();
|
homeFragment = new HomeFragment();
|
||||||
historyFragment = new HistoryFragment();
|
historyFragment = new HistoryFragment();
|
||||||
|
moreFragment = new MoreFragment();
|
||||||
|
|
||||||
homeFragment.handleIntent(intent);
|
homeFragment.handleIntent(intent);
|
||||||
initFragments();
|
initFragments();
|
||||||
|
|
@ -128,10 +128,8 @@ public class MainActivity extends AppCompatActivity{
|
||||||
.replace(R.id.frame_layout, homeFragment)
|
.replace(R.id.frame_layout, homeFragment)
|
||||||
.add(R.id.frame_layout, historyFragment)
|
.add(R.id.frame_layout, historyFragment)
|
||||||
.add(R.id.frame_layout, moreFragment)
|
.add(R.id.frame_layout, moreFragment)
|
||||||
.add(R.id.frame_layout, musicEditorFragment)
|
|
||||||
.hide(historyFragment)
|
.hide(historyFragment)
|
||||||
.hide(moreFragment)
|
.hide(moreFragment)
|
||||||
.hide(musicEditorFragment)
|
|
||||||
.commit();
|
.commit();
|
||||||
|
|
||||||
lastFragment = homeFragment;
|
lastFragment = homeFragment;
|
||||||
|
|
@ -156,4 +154,8 @@ public class MainActivity extends AppCompatActivity{
|
||||||
isDownloadServiceRunning = false;
|
isDownloadServiceRunning = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void checkUpdate(){
|
||||||
|
UpdateUtil updateUtil = new UpdateUtil(this);
|
||||||
|
updateUtil.updateApp();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -4,6 +4,7 @@ import android.app.Activity;
|
||||||
import android.graphics.Color;
|
import android.graphics.Color;
|
||||||
import android.os.Handler;
|
import android.os.Handler;
|
||||||
import android.os.Looper;
|
import android.os.Looper;
|
||||||
|
import android.util.Log;
|
||||||
import android.view.LayoutInflater;
|
import android.view.LayoutInflater;
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
import android.view.ViewGroup;
|
import android.view.ViewGroup;
|
||||||
|
|
@ -27,11 +28,13 @@ import java.util.ArrayList;
|
||||||
|
|
||||||
public class HomeRecyclerViewAdapter extends RecyclerView.Adapter<HomeRecyclerViewAdapter.ViewHolder> {
|
public class HomeRecyclerViewAdapter extends RecyclerView.Adapter<HomeRecyclerViewAdapter.ViewHolder> {
|
||||||
private ArrayList<Video> videoList;
|
private ArrayList<Video> videoList;
|
||||||
|
private ArrayList<MaterialCardView> checkedVideos;
|
||||||
private final OnItemClickListener onItemClickListener;
|
private final OnItemClickListener onItemClickListener;
|
||||||
private Activity activity;
|
private Activity activity;
|
||||||
|
|
||||||
public HomeRecyclerViewAdapter(ArrayList<Video> videos, OnItemClickListener onItemClickListener, Activity activity){
|
public HomeRecyclerViewAdapter(ArrayList<Video> videos, OnItemClickListener onItemClickListener, Activity activity){
|
||||||
this.videoList = videos;
|
this.videoList = videos;
|
||||||
|
this.checkedVideos = new ArrayList<>();
|
||||||
this.onItemClickListener = onItemClickListener;
|
this.onItemClickListener = onItemClickListener;
|
||||||
this.activity = activity;
|
this.activity = activity;
|
||||||
}
|
}
|
||||||
|
|
@ -56,6 +59,7 @@ public class HomeRecyclerViewAdapter extends RecyclerView.Adapter<HomeRecyclerVi
|
||||||
View cardView = LayoutInflater.from(parent.getContext())
|
View cardView = LayoutInflater.from(parent.getContext())
|
||||||
.inflate(R.layout.result_card, parent, false);
|
.inflate(R.layout.result_card, parent, false);
|
||||||
|
|
||||||
|
checkedVideos = new ArrayList<>();
|
||||||
return new HomeRecyclerViewAdapter.ViewHolder(cardView, onItemClickListener);
|
return new HomeRecyclerViewAdapter.ViewHolder(cardView, onItemClickListener);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -116,15 +120,27 @@ public class HomeRecyclerViewAdapter extends RecyclerView.Adapter<HomeRecyclerVi
|
||||||
card.setChecked(false);
|
card.setChecked(false);
|
||||||
card.setStrokeWidth(0);
|
card.setStrokeWidth(0);
|
||||||
card.setTag(videoID + "##card");
|
card.setTag(videoID + "##card");
|
||||||
card.setOnClickListener(view -> {
|
card.setOnLongClickListener(view -> {
|
||||||
if(card.isChecked()){
|
checkCard(card, position);
|
||||||
card.setStrokeWidth(0);
|
return true;
|
||||||
}else{
|
|
||||||
card.setStrokeWidth(5);
|
|
||||||
}
|
|
||||||
card.setChecked(!card.isChecked());
|
|
||||||
onItemClickListener.onCardClick(position, card.isChecked());
|
|
||||||
});
|
});
|
||||||
|
card.setOnClickListener(view -> {
|
||||||
|
if(checkedVideos.size() > 0){
|
||||||
|
checkCard(card, position);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
private void checkCard(MaterialCardView card, int position){
|
||||||
|
if(card.isChecked()){
|
||||||
|
card.setStrokeWidth(0);
|
||||||
|
checkedVideos.remove(card);
|
||||||
|
}else{
|
||||||
|
card.setStrokeWidth(5);
|
||||||
|
checkedVideos.add(card);
|
||||||
|
}
|
||||||
|
card.setChecked(!card.isChecked());
|
||||||
|
onItemClickListener.onCardClick(position, card.isChecked());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
@ -137,9 +153,13 @@ public class HomeRecyclerViewAdapter extends RecyclerView.Adapter<HomeRecyclerVi
|
||||||
void onCardClick(int position, boolean add);
|
void onCardClick(int position, boolean add);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setVideoList(ArrayList<Video> videoList){
|
public void setVideoList(ArrayList<Video> list, boolean reset){
|
||||||
this.videoList = videoList;
|
int size = videoList.size();
|
||||||
notifyDataSetChanged();
|
if(reset || size == 0){
|
||||||
|
videoList = new ArrayList<>();
|
||||||
|
}
|
||||||
|
videoList.addAll(list);
|
||||||
|
notifyItemRangeInserted(size, videoList.size());
|
||||||
}
|
}
|
||||||
|
|
||||||
public void clear(){
|
public void clear(){
|
||||||
|
|
|
||||||
|
|
@ -14,6 +14,7 @@ import org.json.JSONException;
|
||||||
import org.json.JSONObject;
|
import org.json.JSONObject;
|
||||||
import java.io.BufferedReader;
|
import java.io.BufferedReader;
|
||||||
import java.io.InputStreamReader;
|
import java.io.InputStreamReader;
|
||||||
|
import java.lang.reflect.Array;
|
||||||
import java.net.HttpURLConnection;
|
import java.net.HttpURLConnection;
|
||||||
import java.net.URL;
|
import java.net.URL;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
|
|
@ -46,6 +47,7 @@ public class YoutubeAPIManager {
|
||||||
}
|
}
|
||||||
|
|
||||||
public ArrayList<Video> search(String query) throws JSONException{
|
public ArrayList<Video> search(String query) throws JSONException{
|
||||||
|
videos = new ArrayList<>();
|
||||||
//short data
|
//short data
|
||||||
JSONObject res = genericRequest("https://youtube.googleapis.com/youtube/v3/search?part=snippet&q="+query+"&maxResults=25®ionCode="+countryCODE+"&key="+key);
|
JSONObject res = genericRequest("https://youtube.googleapis.com/youtube/v3/search?part=snippet&q="+query+"&maxResults=25®ionCode="+countryCODE+"&key="+key);
|
||||||
JSONArray dataArray = res.getJSONArray("items");
|
JSONArray dataArray = res.getJSONArray("items");
|
||||||
|
|
@ -91,7 +93,9 @@ public class YoutubeAPIManager {
|
||||||
return videos;
|
return videos;
|
||||||
}
|
}
|
||||||
|
|
||||||
public ArrayList<Video> getPlaylist(String id, String nextPageToken) throws JSONException{
|
public PlaylistTuple getPlaylist(String id, String nextPageToken) throws JSONException{
|
||||||
|
videos = new ArrayList<>();
|
||||||
|
|
||||||
String url = "https://youtube.googleapis.com/youtube/v3/playlistItems?part=snippet&pageToken="+nextPageToken+"&maxResults=50®ionCode="+countryCODE+"&playlistId="+id+"&key="+key;
|
String url = "https://youtube.googleapis.com/youtube/v3/playlistItems?part=snippet&pageToken="+nextPageToken+"&maxResults=50®ionCode="+countryCODE+"&playlistId="+id+"&key="+key;
|
||||||
//short data
|
//short data
|
||||||
JSONObject res = genericRequest(url);
|
JSONObject res = genericRequest(url);
|
||||||
|
|
@ -131,11 +135,7 @@ public class YoutubeAPIManager {
|
||||||
videos.add(v);
|
videos.add(v);
|
||||||
}
|
}
|
||||||
String next = res.optString("nextPageToken");
|
String next = res.optString("nextPageToken");
|
||||||
if(next != ""){
|
return new PlaylistTuple(next, videos);
|
||||||
ArrayList<Video> nextPage = getPlaylist(id,next);
|
|
||||||
}
|
|
||||||
|
|
||||||
return videos;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -323,5 +323,62 @@ public class YoutubeAPIManager {
|
||||||
return duration;
|
return duration;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// public ArrayList<String> getSearchHints(String query){
|
||||||
|
// String url = "https://google.com/complete/search?client=youtube&q="+query;
|
||||||
|
// ArrayList<String> searchHints = new ArrayList<>();
|
||||||
|
//
|
||||||
|
// BufferedReader reader;
|
||||||
|
// String line;
|
||||||
|
// StringBuilder responseContent = new StringBuilder();
|
||||||
|
// HttpURLConnection conn;
|
||||||
|
// JSONArray json;
|
||||||
|
//
|
||||||
|
// try{
|
||||||
|
// URL req = new URL(url);
|
||||||
|
// conn = (HttpURLConnection) req.openConnection();
|
||||||
|
//
|
||||||
|
// conn.setRequestMethod("GET");
|
||||||
|
// conn.setConnectTimeout(10000);
|
||||||
|
// conn.setReadTimeout(5000);
|
||||||
|
//
|
||||||
|
// if(conn.getResponseCode() < 300){
|
||||||
|
// reader = new BufferedReader(new InputStreamReader(conn.getInputStream()));
|
||||||
|
// while((line = reader.readLine()) != null){
|
||||||
|
// responseContent.append(line);
|
||||||
|
// }
|
||||||
|
// reader.close();
|
||||||
|
// String content = responseContent.substring(19, responseContent.length()-1);
|
||||||
|
//
|
||||||
|
// json = new JSONArray(content);
|
||||||
|
// JSONArray hints = (JSONArray) json.get(1);
|
||||||
|
// for (int i = 0; i < hints.length(); i++){
|
||||||
|
// searchHints.add(hints.getJSONArray(i).get(0).toString());
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// conn.disconnect();
|
||||||
|
// }catch(Exception e){
|
||||||
|
// Log.e(TAG, e.toString());
|
||||||
|
// }
|
||||||
|
// return searchHints;
|
||||||
|
// }
|
||||||
|
|
||||||
|
public class PlaylistTuple {
|
||||||
|
String nextPageToken;
|
||||||
|
ArrayList<Video> videos;
|
||||||
|
|
||||||
|
PlaylistTuple(String token, ArrayList<Video> videos){
|
||||||
|
nextPageToken = token;
|
||||||
|
this.videos = videos;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getNextPageToken() {
|
||||||
|
return nextPageToken;
|
||||||
|
}
|
||||||
|
|
||||||
|
public ArrayList<Video> getVideos() {
|
||||||
|
return videos;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -153,8 +153,6 @@ public class DBManager extends SQLiteOpenHelper {
|
||||||
SQLiteDatabase db = this.getWritableDatabase();
|
SQLiteDatabase db = this.getWritableDatabase();
|
||||||
ContentValues values = new ContentValues();
|
ContentValues values = new ContentValues();
|
||||||
|
|
||||||
db.execSQL("DELETE FROM " + results_table_name);
|
|
||||||
|
|
||||||
for(Video v : videot){
|
for(Video v : videot){
|
||||||
values.put(videoId, v.getVideoId());
|
values.put(videoId, v.getVideoId());
|
||||||
values.put(title, v.getTitle());
|
values.put(title, v.getTitle());
|
||||||
|
|
|
||||||
|
|
@ -23,6 +23,7 @@ import androidx.core.app.ActivityCompat;
|
||||||
import com.deniscerri.ytdl.BuildConfig;
|
import com.deniscerri.ytdl.BuildConfig;
|
||||||
import com.deniscerri.ytdl.DownloaderService;
|
import com.deniscerri.ytdl.DownloaderService;
|
||||||
import com.deniscerri.ytdl.R;
|
import com.deniscerri.ytdl.R;
|
||||||
|
import com.deniscerri.ytdl.page.settings.SettingsFragment;
|
||||||
import com.deniscerri.ytdl.util.NotificationUtil;
|
import com.deniscerri.ytdl.util.NotificationUtil;
|
||||||
import com.google.android.material.appbar.MaterialToolbar;
|
import com.google.android.material.appbar.MaterialToolbar;
|
||||||
import com.google.android.material.floatingactionbutton.ExtendedFloatingActionButton;
|
import com.google.android.material.floatingactionbutton.ExtendedFloatingActionButton;
|
||||||
|
|
@ -113,12 +114,6 @@ public class CustomCommandActivity extends AppCompatActivity {
|
||||||
startDownloadService(getString(R.string.running_ytdlp_command), NotificationUtil.COMMAND_DOWNLOAD_NOTIFICATION_ID);
|
startDownloadService(getString(R.string.running_ytdlp_command), NotificationUtil.COMMAND_DOWNLOAD_NOTIFICATION_ID);
|
||||||
text = text.substring(6).trim();
|
text = text.substring(6).trim();
|
||||||
|
|
||||||
if (!isStoragePermissionGranted()) {
|
|
||||||
Toast.makeText(context, R.string.try_again_after_permission, Toast.LENGTH_LONG).show();
|
|
||||||
stopDownloadService();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
YoutubeDLRequest request = new YoutubeDLRequest(Collections.emptyList());
|
YoutubeDLRequest request = new YoutubeDLRequest(Collections.emptyList());
|
||||||
String commandRegex = "\"([^\"]*)\"|(\\S+)";
|
String commandRegex = "\"([^\"]*)\"|(\\S+)";
|
||||||
Matcher m = Pattern.compile(commandRegex).matcher(text);
|
Matcher m = Pattern.compile(commandRegex).matcher(text);
|
||||||
|
|
@ -131,7 +126,7 @@ public class CustomCommandActivity extends AppCompatActivity {
|
||||||
}
|
}
|
||||||
|
|
||||||
SharedPreferences sharedPreferences = context.getSharedPreferences("root_preferences", Activity.MODE_PRIVATE);
|
SharedPreferences sharedPreferences = context.getSharedPreferences("root_preferences", Activity.MODE_PRIVATE);
|
||||||
String downloadsDir = sharedPreferences.getString("command_path", "");
|
String downloadsDir = sharedPreferences.getString("command_path", getString(R.string.command_path));
|
||||||
File youtubeDLDir = new File(downloadsDir);
|
File youtubeDLDir = new File(downloadsDir);
|
||||||
if (!youtubeDLDir.exists()) {
|
if (!youtubeDLDir.exists()) {
|
||||||
boolean isDirCreated = youtubeDLDir.mkdir();
|
boolean isDirCreated = youtubeDLDir.mkdir();
|
||||||
|
|
@ -165,16 +160,6 @@ public class CustomCommandActivity extends AppCompatActivity {
|
||||||
compositeDisposable.add(disposable);
|
compositeDisposable.add(disposable);
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean isStoragePermissionGranted() {
|
|
||||||
if (ActivityCompat.checkSelfPermission(context, Manifest.permission.WRITE_EXTERNAL_STORAGE)
|
|
||||||
== PackageManager.PERMISSION_GRANTED) {
|
|
||||||
return true;
|
|
||||||
} else {
|
|
||||||
ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE}, 1);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void startDownloadService(String title, int id){
|
public void startDownloadService(String title, int id){
|
||||||
if(isDownloadServiceRunning) return;
|
if(isDownloadServiceRunning) return;
|
||||||
Intent serviceIntent = new Intent(context, DownloaderService.class);
|
Intent serviceIntent = new Intent(context, DownloaderService.class);
|
||||||
|
|
|
||||||
|
|
@ -44,7 +44,6 @@ import java.util.ArrayList;
|
||||||
*/
|
*/
|
||||||
public class HistoryFragment extends Fragment implements HistoryRecyclerViewAdapter.OnItemClickListener, View.OnClickListener{
|
public class HistoryFragment extends Fragment implements HistoryRecyclerViewAdapter.OnItemClickListener, View.OnClickListener{
|
||||||
|
|
||||||
private LinearLayout linearLayout;
|
|
||||||
private View fragmentView;
|
private View fragmentView;
|
||||||
private DBManager dbManager;
|
private DBManager dbManager;
|
||||||
Context context;
|
Context context;
|
||||||
|
|
@ -52,10 +51,10 @@ public class HistoryFragment extends Fragment implements HistoryRecyclerViewAdap
|
||||||
private ShimmerFrameLayout shimmerCards;
|
private ShimmerFrameLayout shimmerCards;
|
||||||
private MaterialToolbar topAppBar;
|
private MaterialToolbar topAppBar;
|
||||||
private RecyclerView recyclerView;
|
private RecyclerView recyclerView;
|
||||||
private NestedScrollView scrollView;
|
|
||||||
private HistoryRecyclerViewAdapter historyRecyclerViewAdapter;
|
private HistoryRecyclerViewAdapter historyRecyclerViewAdapter;
|
||||||
private BottomSheetDialog bottomSheet;
|
private BottomSheetDialog bottomSheet;
|
||||||
private Handler uiHandler;
|
private Handler uiHandler;
|
||||||
|
private RelativeLayout no_results;
|
||||||
|
|
||||||
private ArrayList<Video> historyObjects;
|
private ArrayList<Video> historyObjects;
|
||||||
private static final String TAG = "HistoryFragment";
|
private static final String TAG = "HistoryFragment";
|
||||||
|
|
@ -85,16 +84,15 @@ public class HistoryFragment extends Fragment implements HistoryRecyclerViewAdap
|
||||||
fragmentView = inflater.inflate(R.layout.fragment_history, container, false);
|
fragmentView = inflater.inflate(R.layout.fragment_history, container, false);
|
||||||
context = fragmentView.getContext();
|
context = fragmentView.getContext();
|
||||||
layoutinflater = LayoutInflater.from(context);
|
layoutinflater = LayoutInflater.from(context);
|
||||||
linearLayout = fragmentView.findViewById(R.id.historylinearLayout1);
|
|
||||||
shimmerCards = fragmentView.findViewById(R.id.shimmer_history_framelayout);
|
shimmerCards = fragmentView.findViewById(R.id.shimmer_history_framelayout);
|
||||||
topAppBar = fragmentView.findViewById(R.id.history_toolbar);
|
topAppBar = fragmentView.findViewById(R.id.history_toolbar);
|
||||||
|
no_results = fragmentView.findViewById(R.id.history_no_results);
|
||||||
uiHandler = new Handler(Looper.getMainLooper());
|
uiHandler = new Handler(Looper.getMainLooper());
|
||||||
|
|
||||||
dbManager = new DBManager(context);
|
dbManager = new DBManager(context);
|
||||||
historyObjects = new ArrayList<>();
|
historyObjects = new ArrayList<>();
|
||||||
|
|
||||||
recyclerView = fragmentView.findViewById(R.id.recycler_view_history);
|
recyclerView = fragmentView.findViewById(R.id.recycler_view_history);
|
||||||
scrollView = fragmentView.findViewById(R.id.history_scrollview);
|
|
||||||
|
|
||||||
historyRecyclerViewAdapter = new HistoryRecyclerViewAdapter(historyObjects, this, context);
|
historyRecyclerViewAdapter = new HistoryRecyclerViewAdapter(historyObjects, this, context);
|
||||||
recyclerView.setAdapter(historyRecyclerViewAdapter);
|
recyclerView.setAdapter(historyRecyclerViewAdapter);
|
||||||
|
|
@ -110,7 +108,7 @@ public class HistoryFragment extends Fragment implements HistoryRecyclerViewAdap
|
||||||
shimmerCards.startShimmer();
|
shimmerCards.startShimmer();
|
||||||
shimmerCards.setVisibility(View.VISIBLE);
|
shimmerCards.setVisibility(View.VISIBLE);
|
||||||
historyRecyclerViewAdapter.clear();
|
historyRecyclerViewAdapter.clear();
|
||||||
linearLayout.removeAllViews();
|
no_results.setVisibility(View.GONE);
|
||||||
try{
|
try{
|
||||||
Thread thread = new Thread(() -> {
|
Thread thread = new Thread(() -> {
|
||||||
historyObjects = dbManager.getHistory("");
|
historyObjects = dbManager.getHistory("");
|
||||||
|
|
@ -121,7 +119,7 @@ public class HistoryFragment extends Fragment implements HistoryRecyclerViewAdap
|
||||||
});
|
});
|
||||||
|
|
||||||
if(historyObjects.size() == 0){
|
if(historyObjects.size() == 0){
|
||||||
uiHandler.post(this::addNoResultsView);
|
uiHandler.post(() -> no_results.setVisibility(View.VISIBLE));
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
thread.start();
|
thread.start();
|
||||||
|
|
@ -132,16 +130,10 @@ public class HistoryFragment extends Fragment implements HistoryRecyclerViewAdap
|
||||||
}
|
}
|
||||||
|
|
||||||
public void scrollToTop(){
|
public void scrollToTop(){
|
||||||
scrollView.smoothScrollTo(-100,-100);
|
recyclerView.scrollToPosition(0);
|
||||||
new Handler(Looper.getMainLooper()).post(() -> ((AppBarLayout) topAppBar.getParent()).setExpanded(true, true));
|
new Handler(Looper.getMainLooper()).post(() -> ((AppBarLayout) topAppBar.getParent()).setExpanded(true, true));
|
||||||
}
|
}
|
||||||
|
|
||||||
private void addNoResultsView(){
|
|
||||||
RelativeLayout no_results = new RelativeLayout(context);
|
|
||||||
layoutinflater.inflate(R.layout.history_no_results, no_results);
|
|
||||||
linearLayout.addView(no_results);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void initMenu(){
|
private void initMenu(){
|
||||||
MenuItem.OnActionExpandListener onActionExpandListener = new MenuItem.OnActionExpandListener() {
|
MenuItem.OnActionExpandListener onActionExpandListener = new MenuItem.OnActionExpandListener() {
|
||||||
@Override
|
@Override
|
||||||
|
|
@ -168,7 +160,7 @@ public class HistoryFragment extends Fragment implements HistoryRecyclerViewAdap
|
||||||
historyRecyclerViewAdapter.clear();
|
historyRecyclerViewAdapter.clear();
|
||||||
historyRecyclerViewAdapter.setVideoList(historyObjects);
|
historyRecyclerViewAdapter.setVideoList(historyObjects);
|
||||||
|
|
||||||
if(historyObjects.size() == 0) addNoResultsView();
|
if(historyObjects.size() == 0) no_results.setVisibility(View.VISIBLE);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -180,9 +172,10 @@ public class HistoryFragment extends Fragment implements HistoryRecyclerViewAdap
|
||||||
historyRecyclerViewAdapter.setVideoList(historyObjects);
|
historyRecyclerViewAdapter.setVideoList(historyObjects);
|
||||||
|
|
||||||
if (historyObjects.size() == 0) {
|
if (historyObjects.size() == 0) {
|
||||||
linearLayout.removeAllViews();
|
no_results.setVisibility(View.VISIBLE);
|
||||||
addNoResultsView();
|
}else{
|
||||||
}else linearLayout.removeAllViews();
|
no_results.setVisibility(View.GONE);
|
||||||
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
@ -207,7 +200,7 @@ public class HistoryFragment extends Fragment implements HistoryRecyclerViewAdap
|
||||||
delete_dialog.setPositiveButton(getString(R.string.ok), (dialogInterface, i) -> {
|
delete_dialog.setPositiveButton(getString(R.string.ok), (dialogInterface, i) -> {
|
||||||
dbManager.clearHistory();
|
dbManager.clearHistory();
|
||||||
historyRecyclerViewAdapter.clear();
|
historyRecyclerViewAdapter.clear();
|
||||||
addNoResultsView();
|
no_results.setVisibility(View.VISIBLE);
|
||||||
});
|
});
|
||||||
delete_dialog.show();
|
delete_dialog.show();
|
||||||
return true;
|
return true;
|
||||||
|
|
@ -254,7 +247,7 @@ public class HistoryFragment extends Fragment implements HistoryRecyclerViewAdap
|
||||||
dbManager.clearHistoryItem(v);
|
dbManager.clearHistoryItem(v);
|
||||||
|
|
||||||
if(historyObjects.size() == 0){
|
if(historyObjects.size() == 0){
|
||||||
uiHandler.post(this::addNoResultsView);
|
uiHandler.post(() -> no_results.setVisibility(View.VISIBLE));
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
delete_dialog.show();
|
delete_dialog.show();
|
||||||
|
|
|
||||||
|
|
@ -12,25 +12,19 @@ import android.os.Handler;
|
||||||
import android.os.Looper;
|
import android.os.Looper;
|
||||||
import android.text.InputType;
|
import android.text.InputType;
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
import android.view.KeyEvent;
|
|
||||||
import android.view.LayoutInflater;
|
import android.view.LayoutInflater;
|
||||||
import android.view.MenuItem;
|
import android.view.MenuItem;
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
import android.view.ViewGroup;
|
import android.view.ViewGroup;
|
||||||
import android.view.Window;
|
import android.view.Window;
|
||||||
import android.widget.Button;
|
import android.widget.Button;
|
||||||
import android.widget.LinearLayout;
|
|
||||||
import android.widget.ProgressBar;
|
import android.widget.ProgressBar;
|
||||||
import android.widget.RelativeLayout;
|
|
||||||
import android.widget.TextView;
|
|
||||||
import android.widget.Toast;
|
import android.widget.Toast;
|
||||||
import androidx.annotation.NonNull;
|
import androidx.annotation.NonNull;
|
||||||
import androidx.appcompat.widget.SearchView;
|
import androidx.appcompat.widget.SearchView;
|
||||||
import androidx.cardview.widget.CardView;
|
|
||||||
import androidx.coordinatorlayout.widget.CoordinatorLayout;
|
import androidx.coordinatorlayout.widget.CoordinatorLayout;
|
||||||
import androidx.core.app.ActivityCompat;
|
import androidx.core.app.ActivityCompat;
|
||||||
import androidx.core.content.ContextCompat;
|
import androidx.core.content.ContextCompat;
|
||||||
import androidx.core.widget.NestedScrollView;
|
|
||||||
import androidx.fragment.app.Fragment;
|
import androidx.fragment.app.Fragment;
|
||||||
import androidx.recyclerview.widget.RecyclerView;
|
import androidx.recyclerview.widget.RecyclerView;
|
||||||
|
|
||||||
|
|
@ -49,7 +43,7 @@ import com.google.android.material.appbar.AppBarLayout;
|
||||||
import com.google.android.material.appbar.MaterialToolbar;
|
import com.google.android.material.appbar.MaterialToolbar;
|
||||||
import com.google.android.material.bottomsheet.BottomSheetDialog;
|
import com.google.android.material.bottomsheet.BottomSheetDialog;
|
||||||
import com.google.android.material.button.MaterialButton;
|
import com.google.android.material.button.MaterialButton;
|
||||||
import com.google.android.material.dialog.MaterialAlertDialogBuilder;
|
import com.google.android.material.floatingactionbutton.ExtendedFloatingActionButton;
|
||||||
import com.google.android.material.floatingactionbutton.FloatingActionButton;
|
import com.google.android.material.floatingactionbutton.FloatingActionButton;
|
||||||
import com.google.android.material.textfield.TextInputLayout;
|
import com.google.android.material.textfield.TextInputLayout;
|
||||||
import com.yausername.youtubedl_android.DownloadProgressCallback;
|
import com.yausername.youtubedl_android.DownloadProgressCallback;
|
||||||
|
|
@ -79,14 +73,12 @@ public class HomeFragment extends Fragment implements HomeRecyclerViewAdapter.On
|
||||||
private View fragmentView;
|
private View fragmentView;
|
||||||
private ProgressBar progressBar;
|
private ProgressBar progressBar;
|
||||||
private String inputQuery;
|
private String inputQuery;
|
||||||
private LinearLayout homeLinearLayout;
|
|
||||||
private RecyclerView recyclerView;
|
private RecyclerView recyclerView;
|
||||||
private HomeRecyclerViewAdapter homeRecyclerViewAdapter;
|
private HomeRecyclerViewAdapter homeRecyclerViewAdapter;
|
||||||
private NestedScrollView scrollView;
|
|
||||||
private ShimmerFrameLayout shimmerCards;
|
private ShimmerFrameLayout shimmerCards;
|
||||||
private CoordinatorLayout downloadFabs;
|
private CoordinatorLayout downloadFabs;
|
||||||
|
private CoordinatorLayout downloadAllFab;
|
||||||
private BottomSheetDialog bottomSheet;
|
private BottomSheetDialog bottomSheet;
|
||||||
private LayoutInflater layoutinflater;
|
|
||||||
|
|
||||||
Context context;
|
Context context;
|
||||||
Activity activity;
|
Activity activity;
|
||||||
|
|
@ -103,7 +95,7 @@ public class HomeFragment extends Fragment implements HomeRecyclerViewAdapter.On
|
||||||
private Queue<Video> downloadQueue;
|
private Queue<Video> downloadQueue;
|
||||||
|
|
||||||
MainActivity mainActivity;
|
MainActivity mainActivity;
|
||||||
private static final NotificationUtil notificationUtil = App.notificationUtil;
|
private final NotificationUtil notificationUtil = App.notificationUtil;
|
||||||
|
|
||||||
private final DownloadProgressCallback callback = new DownloadProgressCallback() {
|
private final DownloadProgressCallback callback = new DownloadProgressCallback() {
|
||||||
@Override
|
@Override
|
||||||
|
|
@ -142,16 +134,14 @@ public class HomeFragment extends Fragment implements HomeRecyclerViewAdapter.On
|
||||||
context = fragmentView.getContext();
|
context = fragmentView.getContext();
|
||||||
activity = getActivity();
|
activity = getActivity();
|
||||||
mainActivity = (MainActivity) activity;
|
mainActivity = (MainActivity) activity;
|
||||||
layoutinflater = LayoutInflater.from(context);
|
|
||||||
|
|
||||||
|
|
||||||
//initViews
|
//initViews
|
||||||
homeLinearLayout = fragmentView.findViewById(R.id.linearLayout1);
|
|
||||||
shimmerCards = fragmentView.findViewById(R.id.shimmer_results_framelayout);
|
shimmerCards = fragmentView.findViewById(R.id.shimmer_results_framelayout);
|
||||||
topAppBar = fragmentView.findViewById(R.id.home_toolbar);
|
topAppBar = fragmentView.findViewById(R.id.home_toolbar);
|
||||||
scrollView = fragmentView.findViewById(R.id.home_scrollview);
|
|
||||||
recyclerView = fragmentView.findViewById(R.id.recycler_view_home);
|
recyclerView = fragmentView.findViewById(R.id.recycler_view_home);
|
||||||
downloadFabs = fragmentView.findViewById(R.id.home_download_fabs);
|
downloadFabs = fragmentView.findViewById(R.id.download_selected_coordinator);
|
||||||
|
downloadAllFab = fragmentView.findViewById(R.id.download_all_coordinator);
|
||||||
|
|
||||||
homeRecyclerViewAdapter = new HomeRecyclerViewAdapter(resultObjects, this, activity);
|
homeRecyclerViewAdapter = new HomeRecyclerViewAdapter(resultObjects, this, activity);
|
||||||
recyclerView.setAdapter(homeRecyclerViewAdapter);
|
recyclerView.setAdapter(homeRecyclerViewAdapter);
|
||||||
|
|
@ -174,6 +164,11 @@ public class HomeFragment extends Fragment implements HomeRecyclerViewAdapter.On
|
||||||
music_fab.setOnClickListener(this);
|
music_fab.setOnClickListener(this);
|
||||||
video_fab.setOnClickListener(this);
|
video_fab.setOnClickListener(this);
|
||||||
|
|
||||||
|
|
||||||
|
ExtendedFloatingActionButton download_all_fab = downloadAllFab.findViewById(R.id.download_all_fab);
|
||||||
|
download_all_fab.setTag("downloadAll");
|
||||||
|
download_all_fab.setOnClickListener(this);
|
||||||
|
|
||||||
return fragmentView;
|
return fragmentView;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -182,17 +177,14 @@ public class HomeFragment extends Fragment implements HomeRecyclerViewAdapter.On
|
||||||
shimmerCards.startShimmer();
|
shimmerCards.startShimmer();
|
||||||
shimmerCards.setVisibility(View.VISIBLE);
|
shimmerCards.setVisibility(View.VISIBLE);
|
||||||
homeRecyclerViewAdapter.clear();
|
homeRecyclerViewAdapter.clear();
|
||||||
homeLinearLayout.removeAllViews();
|
|
||||||
try {
|
try {
|
||||||
Thread thread = new Thread(() -> {
|
Thread thread = new Thread(() -> {
|
||||||
Handler uiHandler = new Handler(Looper.getMainLooper());
|
Handler uiHandler = new Handler(Looper.getMainLooper());
|
||||||
dbManager = new DBManager(context);
|
dbManager = new DBManager(context);
|
||||||
youtubeAPIManager = new YoutubeAPIManager(context);
|
youtubeAPIManager = new YoutubeAPIManager(context);
|
||||||
resultObjects = dbManager.getResults();
|
resultObjects = dbManager.getResults();
|
||||||
boolean trending = false;
|
|
||||||
|
|
||||||
if (resultObjects.size() == 0) {
|
if (resultObjects.size() == 0) {
|
||||||
trending = true;
|
|
||||||
try {
|
try {
|
||||||
resultObjects = youtubeAPIManager.getTrending(context);
|
resultObjects = youtubeAPIManager.getTrending(context);
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
|
|
@ -200,20 +192,14 @@ public class HomeFragment extends Fragment implements HomeRecyclerViewAdapter.On
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (resultObjects != null) {
|
if (resultObjects != null) {
|
||||||
scrollToTop();
|
uiHandler.post(this::scrollToTop);
|
||||||
|
if (resultObjects.size() > 1 && resultObjects.get(1).getIsPlaylistItem() == 1) {
|
||||||
if (trending) {
|
uiHandler.post(() -> downloadAllFab.setVisibility(View.VISIBLE));
|
||||||
uiHandler.post(this::addTrendingText);
|
|
||||||
|
|
||||||
} else {
|
|
||||||
if (resultObjects.size() > 1 && resultObjects.get(1).getIsPlaylistItem() == 1) {
|
|
||||||
createDownloadAllCard();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
uiHandler.post(() -> {
|
uiHandler.post(() -> {
|
||||||
homeRecyclerViewAdapter.setVideoList(resultObjects);
|
homeRecyclerViewAdapter.setVideoList(resultObjects, true);
|
||||||
shimmerCards.stopShimmer();
|
shimmerCards.stopShimmer();
|
||||||
shimmerCards.setVisibility(View.GONE);
|
shimmerCards.setVisibility(View.GONE);
|
||||||
});
|
});
|
||||||
|
|
@ -225,16 +211,18 @@ public class HomeFragment extends Fragment implements HomeRecyclerViewAdapter.On
|
||||||
}
|
}
|
||||||
|
|
||||||
private void initMenu() {
|
private void initMenu() {
|
||||||
|
youtubeAPIManager = new YoutubeAPIManager(context);
|
||||||
|
|
||||||
MenuItem.OnActionExpandListener onActionExpandListener = new MenuItem.OnActionExpandListener() {
|
MenuItem.OnActionExpandListener onActionExpandListener = new MenuItem.OnActionExpandListener() {
|
||||||
@Override
|
@Override
|
||||||
public boolean onMenuItemActionExpand(MenuItem menuItem) {
|
public boolean onMenuItemActionExpand(MenuItem menuItem) {
|
||||||
scrollView.setVisibility(View.GONE);
|
recyclerView.setVisibility(View.GONE);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean onMenuItemActionCollapse(MenuItem menuItem) {
|
public boolean onMenuItemActionCollapse(MenuItem menuItem) {
|
||||||
scrollView.setVisibility(View.VISIBLE);
|
recyclerView.setVisibility(View.VISIBLE);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
@ -254,39 +242,39 @@ public class HomeFragment extends Fragment implements HomeRecyclerViewAdapter.On
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean onQueryTextChange(String newText) {
|
public boolean onQueryTextChange(String newText) { return false; }
|
||||||
return false;
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
|
|
||||||
topAppBar.setOnClickListener(view -> scrollToTop());
|
topAppBar.setOnClickListener(view -> scrollToTop());
|
||||||
|
|
||||||
topAppBar.setOnMenuItemClickListener((MenuItem m) -> {
|
topAppBar.setOnMenuItemClickListener((MenuItem m) -> {
|
||||||
switch (m.getItemId()){
|
int itemId = m.getItemId();
|
||||||
case R.id.delete_results:
|
if(itemId == R.id.delete_results){
|
||||||
dbManager.clearResults();
|
dbManager.clearResults();
|
||||||
recyclerView.removeAllViews();
|
recyclerView.removeAllViews();
|
||||||
initCards();
|
downloadAllFab.setVisibility(View.GONE);
|
||||||
return true;
|
initCards();
|
||||||
case R.id.refresh_results:
|
}else if(itemId == R.id.refresh_results){
|
||||||
recyclerView.removeAllViews();
|
recyclerView.removeAllViews();
|
||||||
initCards();
|
selectedObjects = new ArrayList<>();
|
||||||
return true;
|
downloadFabs.setVisibility(View.GONE);
|
||||||
case R.id.open_settings:
|
initCards();
|
||||||
Intent intent = new Intent(context, SettingsActivity.class);
|
}else if(itemId == R.id.open_settings){
|
||||||
startActivity(intent);
|
Intent intent = new Intent(context, SettingsActivity.class);
|
||||||
|
startActivity(intent);
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
});
|
});
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public void handleIntent(Intent intent) {
|
public void handleIntent(Intent intent) {
|
||||||
inputQuery = intent.getStringExtra(Intent.EXTRA_TEXT);
|
inputQuery = intent.getStringExtra(Intent.EXTRA_TEXT);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void scrollToTop() {
|
public void scrollToTop() {
|
||||||
scrollView.smoothScrollTo(-100,-100);
|
recyclerView.scrollToPosition(0);
|
||||||
new Handler(Looper.getMainLooper()).post(() -> ((AppBarLayout) topAppBar.getParent()).setExpanded(true, true));
|
new Handler(Looper.getMainLooper()).post(() -> ((AppBarLayout) topAppBar.getParent()).setExpanded(true, true));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -294,7 +282,7 @@ public class HomeFragment extends Fragment implements HomeRecyclerViewAdapter.On
|
||||||
shimmerCards.startShimmer();
|
shimmerCards.startShimmer();
|
||||||
shimmerCards.setVisibility(View.VISIBLE);
|
shimmerCards.setVisibility(View.VISIBLE);
|
||||||
homeRecyclerViewAdapter.clear();
|
homeRecyclerViewAdapter.clear();
|
||||||
homeLinearLayout.removeAllViews();
|
Log.e(TAG, String.valueOf(homeRecyclerViewAdapter.getItemCount()));
|
||||||
|
|
||||||
dbManager = new DBManager(context);
|
dbManager = new DBManager(context);
|
||||||
youtubeAPIManager = new YoutubeAPIManager(context);
|
youtubeAPIManager = new YoutubeAPIManager(context);
|
||||||
|
|
@ -330,10 +318,10 @@ public class HomeFragment extends Fragment implements HomeRecyclerViewAdapter.On
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
Log.e(TAG, e.toString());
|
Log.e(TAG, e.toString());
|
||||||
}
|
}
|
||||||
|
dbManager.clearResults();
|
||||||
dbManager.addToResults(resultObjects);
|
dbManager.addToResults(resultObjects);
|
||||||
new Handler(Looper.getMainLooper()).post(() -> {
|
new Handler(Looper.getMainLooper()).post(() -> {
|
||||||
homeRecyclerViewAdapter.setVideoList(resultObjects);
|
homeRecyclerViewAdapter.setVideoList(resultObjects, true);
|
||||||
//addEndofResultsText();
|
//addEndofResultsText();
|
||||||
shimmerCards.stopShimmer();
|
shimmerCards.stopShimmer();
|
||||||
shimmerCards.setVisibility(View.GONE);
|
shimmerCards.setVisibility(View.GONE);
|
||||||
|
|
@ -371,11 +359,11 @@ public class HomeFragment extends Fragment implements HomeRecyclerViewAdapter.On
|
||||||
Log.e(TAG, e.toString());
|
Log.e(TAG, e.toString());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
dbManager.clearResults();
|
||||||
dbManager.addToResults(resultObjects);
|
dbManager.addToResults(resultObjects);
|
||||||
|
|
||||||
new Handler(Looper.getMainLooper()).post(() -> {
|
new Handler(Looper.getMainLooper()).post(() -> {
|
||||||
homeRecyclerViewAdapter.setVideoList(resultObjects);
|
homeRecyclerViewAdapter.setVideoList(resultObjects, true);
|
||||||
shimmerCards.stopShimmer();
|
shimmerCards.stopShimmer();
|
||||||
shimmerCards.setVisibility(View.GONE);
|
shimmerCards.setVisibility(View.GONE);
|
||||||
});
|
});
|
||||||
|
|
@ -396,22 +384,35 @@ public class HomeFragment extends Fragment implements HomeRecyclerViewAdapter.On
|
||||||
@Override
|
@Override
|
||||||
public void run() {
|
public void run() {
|
||||||
try {
|
try {
|
||||||
resultObjects = youtubeAPIManager.getPlaylist(query, "");
|
String nextPageToken = "";
|
||||||
|
dbManager.clearResults();
|
||||||
|
homeRecyclerViewAdapter.setVideoList(new ArrayList<>(), true);
|
||||||
|
do {
|
||||||
|
YoutubeAPIManager.PlaylistTuple tmp = youtubeAPIManager.getPlaylist(query, nextPageToken);
|
||||||
|
ArrayList<Video> tmp_vids = tmp.getVideos();
|
||||||
|
String tmp_token = tmp.getNextPageToken();
|
||||||
|
resultObjects.addAll(tmp_vids);
|
||||||
|
new Handler(Looper.getMainLooper()).post(() -> {
|
||||||
|
homeRecyclerViewAdapter.setVideoList(tmp_vids, false);
|
||||||
|
//addEndofResultsText();
|
||||||
|
shimmerCards.stopShimmer();
|
||||||
|
shimmerCards.setVisibility(View.GONE);
|
||||||
|
});
|
||||||
|
Thread.sleep(1000);
|
||||||
|
dbManager.addToResults(tmp_vids);
|
||||||
|
if (tmp_token.isEmpty()) break;
|
||||||
|
if (tmp_token.equals(nextPageToken)) break;
|
||||||
|
nextPageToken = tmp_token;
|
||||||
|
}while (true);
|
||||||
|
|
||||||
|
// DOWNLOAD ALL BUTTON
|
||||||
|
if (resultObjects.size() > 1) {
|
||||||
|
new Handler(Looper.getMainLooper()).post(() -> downloadAllFab.setVisibility(View.VISIBLE));
|
||||||
|
}
|
||||||
|
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
Log.e(TAG, e.toString());
|
Log.e(TAG, e.toString());
|
||||||
}
|
}
|
||||||
dbManager.addToResults(resultObjects);
|
|
||||||
// DOWNLOAD ALL BUTTON
|
|
||||||
if (resultObjects.size() > 1) {
|
|
||||||
createDownloadAllCard();
|
|
||||||
}
|
|
||||||
|
|
||||||
new Handler(Looper.getMainLooper()).post(() -> {
|
|
||||||
homeRecyclerViewAdapter.setVideoList(resultObjects);
|
|
||||||
//addEndofResultsText();
|
|
||||||
shimmerCards.stopShimmer();
|
|
||||||
shimmerCards.setVisibility(View.GONE);
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
thread.start();
|
thread.start();
|
||||||
|
|
@ -424,24 +425,6 @@ public class HomeFragment extends Fragment implements HomeRecyclerViewAdapter.On
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void addTrendingText(){
|
|
||||||
TextView trendingText = new TextView(context);
|
|
||||||
trendingText.setText(R.string.Trending);
|
|
||||||
trendingText.setPadding(70, 0 , 0, 0);
|
|
||||||
homeLinearLayout.addView(trendingText);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void createDownloadAllCard() {
|
|
||||||
RelativeLayout r = new RelativeLayout(context);
|
|
||||||
layoutinflater.inflate(R.layout.download_all_card, r);
|
|
||||||
|
|
||||||
CardView card = r.findViewById(R.id.downloadall_card_view);
|
|
||||||
card.setTag("downloadAll");
|
|
||||||
card.setOnClickListener(this);
|
|
||||||
|
|
||||||
Handler uiHandler = new Handler(Looper.getMainLooper());
|
|
||||||
uiHandler.post(() -> homeLinearLayout.addView(r));
|
|
||||||
}
|
|
||||||
|
|
||||||
public Video findVideo(String id) {
|
public Video findVideo(String id) {
|
||||||
for (int i = 0; i < resultObjects.size(); i++) {
|
for (int i = 0; i < resultObjects.size(); i++) {
|
||||||
|
|
@ -465,11 +448,6 @@ public class HomeFragment extends Fragment implements HomeRecyclerViewAdapter.On
|
||||||
try {
|
try {
|
||||||
video = videos.peek();
|
video = videos.peek();
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!isStoragePermissionGranted()) {
|
|
||||||
Toast.makeText(context, R.string.try_again_after_permission, Toast.LENGTH_LONG).show();
|
|
||||||
mainActivity.stopDownloadService();
|
mainActivity.stopDownloadService();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
@ -548,8 +526,7 @@ public class HomeFragment extends Fragment implements HomeRecyclerViewAdapter.On
|
||||||
progressBar.setVisibility(View.VISIBLE);
|
progressBar.setVisibility(View.VISIBLE);
|
||||||
|
|
||||||
//scroll to Card
|
//scroll to Card
|
||||||
View view = fragmentView.findViewWithTag(id + "##progress");
|
recyclerView.scrollToPosition(resultObjects.indexOf(findVideo(id)));
|
||||||
scrollView.requestChildFocus(view, view);
|
|
||||||
progressBar.setProgress(0);
|
progressBar.setProgress(0);
|
||||||
downloading = true;
|
downloading = true;
|
||||||
|
|
||||||
|
|
@ -562,8 +539,6 @@ public class HomeFragment extends Fragment implements HomeRecyclerViewAdapter.On
|
||||||
progressBar.setProgress(0);
|
progressBar.setProgress(0);
|
||||||
progressBar.setVisibility(View.GONE);
|
progressBar.setVisibility(View.GONE);
|
||||||
|
|
||||||
//TODO show download finished
|
|
||||||
|
|
||||||
if (theClickedButton != null) {
|
if (theClickedButton != null) {
|
||||||
if (type.equals("mp3")) {
|
if (type.equals("mp3")) {
|
||||||
theClickedButton.setIcon(ContextCompat.getDrawable(activity, R.drawable.ic_music_downloaded));
|
theClickedButton.setIcon(ContextCompat.getDrawable(activity, R.drawable.ic_music_downloaded));
|
||||||
|
|
@ -589,8 +564,6 @@ public class HomeFragment extends Fragment implements HomeRecyclerViewAdapter.On
|
||||||
Toast.makeText(context, R.string.failed_download, Toast.LENGTH_LONG).show();
|
Toast.makeText(context, R.string.failed_download, Toast.LENGTH_LONG).show();
|
||||||
progressBar.setProgress(0);
|
progressBar.setProgress(0);
|
||||||
progressBar.setVisibility(View.GONE);
|
progressBar.setVisibility(View.GONE);
|
||||||
|
|
||||||
//TODO notification failed
|
|
||||||
downloading = false;
|
downloading = false;
|
||||||
|
|
||||||
// SCAN NEXT IN QUEUE
|
// SCAN NEXT IN QUEUE
|
||||||
|
|
@ -639,10 +612,11 @@ public class HomeFragment extends Fragment implements HomeRecyclerViewAdapter.On
|
||||||
SharedPreferences sharedPreferences = context.getSharedPreferences("root_preferences", Activity.MODE_PRIVATE);
|
SharedPreferences sharedPreferences = context.getSharedPreferences("root_preferences", Activity.MODE_PRIVATE);
|
||||||
String downloadsDir;
|
String downloadsDir;
|
||||||
if (type.equals("mp3")) {
|
if (type.equals("mp3")) {
|
||||||
downloadsDir = sharedPreferences.getString("music_path", "");
|
downloadsDir = sharedPreferences.getString("music_path", getString(R.string.music_path));
|
||||||
} else {
|
} else {
|
||||||
downloadsDir = sharedPreferences.getString("video_path", "");
|
downloadsDir = sharedPreferences.getString("video_path", getString(R.string.video_path));
|
||||||
}
|
}
|
||||||
|
|
||||||
File youtubeDLDir = new File(downloadsDir);
|
File youtubeDLDir = new File(downloadsDir);
|
||||||
if (!youtubeDLDir.exists()) {
|
if (!youtubeDLDir.exists()) {
|
||||||
boolean isDirCreated = youtubeDLDir.mkdir();
|
boolean isDirCreated = youtubeDLDir.mkdir();
|
||||||
|
|
@ -653,16 +627,6 @@ public class HomeFragment extends Fragment implements HomeRecyclerViewAdapter.On
|
||||||
return youtubeDLDir;
|
return youtubeDLDir;
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean isStoragePermissionGranted() {
|
|
||||||
if (ActivityCompat.checkSelfPermission(context, Manifest.permission.WRITE_EXTERNAL_STORAGE)
|
|
||||||
== PackageManager.PERMISSION_GRANTED) {
|
|
||||||
return true;
|
|
||||||
} else {
|
|
||||||
ActivityCompat.requestPermissions(activity, new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE}, 1);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onButtonClick(int position, String type) {
|
public void onButtonClick(int position, String type) {
|
||||||
Log.e(TAG, type);
|
Log.e(TAG, type);
|
||||||
|
|
@ -675,15 +639,38 @@ public class HomeFragment extends Fragment implements HomeRecyclerViewAdapter.On
|
||||||
Toast.makeText(context, R.string.added_to_queue, Toast.LENGTH_LONG).show();
|
Toast.makeText(context, R.string.added_to_queue, Toast.LENGTH_LONG).show();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
mainActivity.startDownloadService(vid.getTitle(), NotificationUtil.DOWNLOAD_NOTIFICATION_ID);
|
if (isStoragePermissionGranted()){
|
||||||
startDownload(downloadQueue);
|
mainActivity.startDownloadService(vid.getTitle(), NotificationUtil.DOWNLOAD_NOTIFICATION_ID);
|
||||||
|
startDownload(downloadQueue);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public boolean isStoragePermissionGranted() {
|
||||||
|
if (ActivityCompat.checkSelfPermission(requireContext(), Manifest.permission.WRITE_EXTERNAL_STORAGE)
|
||||||
|
== PackageManager.PERMISSION_GRANTED) {
|
||||||
|
return true;
|
||||||
|
}else{
|
||||||
|
downloadQueue = new LinkedList<>();
|
||||||
|
ActivityCompat.requestPermissions(requireActivity(), new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE}, 1);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onCardClick(int position, boolean add) {
|
public void onCardClick(int position, boolean add) {
|
||||||
Video video = resultObjects.get(position);
|
Video video = resultObjects.get(position);
|
||||||
if (add) selectedObjects.add(video); else selectedObjects.remove(video);
|
if (add) selectedObjects.add(video); else selectedObjects.remove(video);
|
||||||
if(selectedObjects.size() > 1) downloadFabs.setVisibility(View.VISIBLE); else downloadFabs.setVisibility(View.GONE);
|
if(selectedObjects.size() > 1){
|
||||||
|
downloadAllFab.setVisibility(View.GONE);
|
||||||
|
downloadFabs.setVisibility(View.VISIBLE);
|
||||||
|
} else {
|
||||||
|
downloadFabs.setVisibility(View.GONE);
|
||||||
|
if (resultObjects.size() > 1 && resultObjects.get(1).getIsPlaylistItem() == 1) {
|
||||||
|
downloadAllFab.setVisibility(View.VISIBLE);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -715,8 +702,10 @@ public class HomeFragment extends Fragment implements HomeRecyclerViewAdapter.On
|
||||||
Toast.makeText(context, R.string.added_to_queue, Toast.LENGTH_LONG).show();
|
Toast.makeText(context, R.string.added_to_queue, Toast.LENGTH_LONG).show();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
mainActivity.startDownloadService(downloadQueue.peek().getTitle(), NotificationUtil.DOWNLOAD_NOTIFICATION_ID);
|
if(isStoragePermissionGranted()){
|
||||||
startDownload(downloadQueue);
|
mainActivity.startDownloadService(downloadQueue.peek().getTitle(), NotificationUtil.DOWNLOAD_NOTIFICATION_ID);
|
||||||
|
startDownload(downloadQueue);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (viewIdName.equals("downloadAll")){
|
if (viewIdName.equals("downloadAll")){
|
||||||
|
|
@ -782,7 +771,9 @@ public class HomeFragment extends Fragment implements HomeRecyclerViewAdapter.On
|
||||||
Toast.makeText(context, R.string.added_to_queue, Toast.LENGTH_LONG).show();
|
Toast.makeText(context, R.string.added_to_queue, Toast.LENGTH_LONG).show();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
mainActivity.startDownloadService(downloadQueue.peek().getTitle(), NotificationUtil.DOWNLOAD_NOTIFICATION_ID);
|
if(isStoragePermissionGranted()){
|
||||||
startDownload(downloadQueue);
|
mainActivity.startDownloadService(downloadQueue.peek().getTitle(), NotificationUtil.DOWNLOAD_NOTIFICATION_ID);
|
||||||
|
startDownload(downloadQueue);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -29,12 +29,8 @@ import io.reactivex.schedulers.Schedulers;
|
||||||
public class MoreFragment extends PreferenceFragmentCompat {
|
public class MoreFragment extends PreferenceFragmentCompat {
|
||||||
Preference updateYTDL;
|
Preference updateYTDL;
|
||||||
Preference updateApp;
|
Preference updateApp;
|
||||||
MaterialCardView materialCardView;
|
|
||||||
|
|
||||||
public static boolean updatingYTDL;
|
|
||||||
public static boolean updatingApp;
|
|
||||||
public static final String TAG = "MoreFragment";
|
public static final String TAG = "MoreFragment";
|
||||||
private final CompositeDisposable compositeDisposable = new CompositeDisposable();
|
private UpdateUtil updateUtil;
|
||||||
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
@ -44,94 +40,16 @@ public class MoreFragment extends PreferenceFragmentCompat {
|
||||||
updateYTDL = findPreference("update_ytdl");
|
updateYTDL = findPreference("update_ytdl");
|
||||||
updateApp = findPreference("update_app");
|
updateApp = findPreference("update_app");
|
||||||
|
|
||||||
|
updateUtil = new UpdateUtil(getContext());
|
||||||
|
|
||||||
updateYTDL.setOnPreferenceClickListener(preference -> {
|
updateYTDL.setOnPreferenceClickListener(preference -> {
|
||||||
updateYoutubeDL();
|
updateUtil.updateYoutubeDL();
|
||||||
return true;
|
return true;
|
||||||
});
|
});
|
||||||
|
|
||||||
updateApp.setOnPreferenceClickListener(preference -> {
|
updateApp.setOnPreferenceClickListener(preference -> {
|
||||||
updateApp();
|
updateUtil.updateApp();
|
||||||
return true;
|
return true;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
private void updateYoutubeDL() {
|
|
||||||
if (updatingYTDL) {
|
|
||||||
Toast.makeText(getContext(), getString(R.string.ytdl_already_updating), Toast.LENGTH_LONG).show();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
Toast.makeText(getContext(), getString(R.string.ytdl_updating_started), Toast.LENGTH_SHORT).show();
|
|
||||||
|
|
||||||
updatingYTDL = true;
|
|
||||||
Disposable disposable = Observable.fromCallable(() -> YoutubeDL.getInstance().updateYoutubeDL(getContext()))
|
|
||||||
.subscribeOn(Schedulers.newThread())
|
|
||||||
.observeOn(AndroidSchedulers.mainThread())
|
|
||||||
.subscribe(status -> {
|
|
||||||
switch (status) {
|
|
||||||
case DONE:
|
|
||||||
Toast.makeText(getContext(), getString(R.string.ytld_update_success), Toast.LENGTH_LONG).show();
|
|
||||||
break;
|
|
||||||
case ALREADY_UP_TO_DATE:
|
|
||||||
Toast.makeText(getContext(), getString(R.string.you_are_in_latest_version), Toast.LENGTH_LONG).show();
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
Toast.makeText(getContext(), status.toString(), Toast.LENGTH_LONG).show();
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
updatingYTDL = false;
|
|
||||||
}, e -> {
|
|
||||||
if(BuildConfig.DEBUG) Log.e(TAG, getString(R.string.ytdl_update_failed), e);
|
|
||||||
Toast.makeText(getContext(), getString(R.string.ytdl_update_failed), Toast.LENGTH_LONG).show();
|
|
||||||
updatingYTDL = false;
|
|
||||||
});
|
|
||||||
compositeDisposable.add(disposable);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
private void updateApp(){
|
|
||||||
if (updatingApp) {
|
|
||||||
Toast.makeText(getContext(), getString(R.string.ytdl_already_updating), Toast.LENGTH_LONG).show();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
UpdateUtil updateUtil = new UpdateUtil(getContext());
|
|
||||||
AtomicReference<JSONObject> res = new AtomicReference<>(new JSONObject());
|
|
||||||
|
|
||||||
try{
|
|
||||||
Thread thread = new Thread(() -> res.set(updateUtil.checkForAppUpdate()));
|
|
||||||
thread.start();
|
|
||||||
thread.join();
|
|
||||||
}catch(Exception e){
|
|
||||||
Log.e(TAG, e.toString());
|
|
||||||
}
|
|
||||||
|
|
||||||
if(res.get() == null){
|
|
||||||
Toast.makeText(getContext(), R.string.error_checking_latest_version, Toast.LENGTH_SHORT).show();
|
|
||||||
}
|
|
||||||
|
|
||||||
String version = "";
|
|
||||||
String body = "";
|
|
||||||
try {
|
|
||||||
version = res.get().getString("tag_name");
|
|
||||||
body = res.get().getString("body");
|
|
||||||
} catch (JSONException ignored) {}
|
|
||||||
|
|
||||||
if(version.equals("v"+BuildConfig.VERSION_NAME)){
|
|
||||||
getActivity().runOnUiThread(() -> Toast.makeText(getContext(), R.string.you_are_running_latest_version, Toast.LENGTH_SHORT).show());
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
MaterialAlertDialogBuilder updateDialog = new MaterialAlertDialogBuilder(getContext())
|
|
||||||
.setTitle(version)
|
|
||||||
.setMessage(body)
|
|
||||||
.setIcon(R.drawable.ic_update_app)
|
|
||||||
.setNegativeButton("Cancel", (dialogInterface, i) -> {})
|
|
||||||
.setPositiveButton("Update", (dialogInterface, i) -> updateUtil.updateApp(res.get()));
|
|
||||||
updateDialog.show();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
@ -1,30 +0,0 @@
|
||||||
package com.deniscerri.ytdl.page;
|
|
||||||
|
|
||||||
import android.os.Bundle;
|
|
||||||
|
|
||||||
import androidx.fragment.app.Fragment;
|
|
||||||
|
|
||||||
import android.view.LayoutInflater;
|
|
||||||
import android.view.View;
|
|
||||||
import android.view.ViewGroup;
|
|
||||||
|
|
||||||
import com.deniscerri.ytdl.R;
|
|
||||||
|
|
||||||
public class MusicEditorFragment extends Fragment {
|
|
||||||
|
|
||||||
public MusicEditorFragment() {
|
|
||||||
// Required empty public constructor
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onCreate(Bundle savedInstanceState) {
|
|
||||||
super.onCreate(savedInstanceState);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public View onCreateView(LayoutInflater inflater, ViewGroup container,
|
|
||||||
Bundle savedInstanceState) {
|
|
||||||
// Inflate the layout for this fragment
|
|
||||||
return inflater.inflate(R.layout.fragment_music_editor, container, false);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,8 +1,11 @@
|
||||||
package com.deniscerri.ytdl.page.settings;
|
package com.deniscerri.ytdl.page.settings;
|
||||||
|
|
||||||
|
import android.Manifest;
|
||||||
import android.app.Activity;
|
import android.app.Activity;
|
||||||
|
import android.content.Context;
|
||||||
import android.content.Intent;
|
import android.content.Intent;
|
||||||
import android.content.SharedPreferences;
|
import android.content.SharedPreferences;
|
||||||
|
import android.content.pm.PackageManager;
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
import android.widget.Toast;
|
import android.widget.Toast;
|
||||||
|
|
@ -12,6 +15,7 @@ import androidx.activity.result.ActivityResultCallback;
|
||||||
import androidx.activity.result.ActivityResultLauncher;
|
import androidx.activity.result.ActivityResultLauncher;
|
||||||
import androidx.activity.result.contract.ActivityResultContracts;
|
import androidx.activity.result.contract.ActivityResultContracts;
|
||||||
import androidx.annotation.NonNull;
|
import androidx.annotation.NonNull;
|
||||||
|
import androidx.core.app.ActivityCompat;
|
||||||
import androidx.preference.EditTextPreference;
|
import androidx.preference.EditTextPreference;
|
||||||
import androidx.preference.ListPreference;
|
import androidx.preference.ListPreference;
|
||||||
import androidx.preference.Preference;
|
import androidx.preference.Preference;
|
||||||
|
|
@ -20,6 +24,7 @@ import androidx.preference.SeekBarPreference;
|
||||||
import androidx.preference.SwitchPreferenceCompat;
|
import androidx.preference.SwitchPreferenceCompat;
|
||||||
import com.deniscerri.ytdl.BuildConfig;
|
import com.deniscerri.ytdl.BuildConfig;
|
||||||
import com.deniscerri.ytdl.R;
|
import com.deniscerri.ytdl.R;
|
||||||
|
import com.deniscerri.ytdl.util.UpdateUtil;
|
||||||
import com.yausername.youtubedl_android.YoutubeDL;
|
import com.yausername.youtubedl_android.YoutubeDL;
|
||||||
import java.nio.charset.StandardCharsets;
|
import java.nio.charset.StandardCharsets;
|
||||||
|
|
||||||
|
|
@ -49,10 +54,11 @@ public class SettingsFragment extends PreferenceFragmentCompat {
|
||||||
|
|
||||||
Preference version;
|
Preference version;
|
||||||
|
|
||||||
|
private UpdateUtil updateUtil;
|
||||||
|
|
||||||
public static final int MUSIC_PATH_CODE = 33333;
|
public static final int MUSIC_PATH_CODE = 33333;
|
||||||
public static final int VIDEO_PATH_CODE = 55555;
|
public static final int VIDEO_PATH_CODE = 55555;
|
||||||
public static final int COMMAND_PATH_CODE = 77777;
|
public static final int COMMAND_PATH_CODE = 77777;
|
||||||
private static boolean firstRun = true;
|
|
||||||
private static final String TAG = "SettingsFragment";
|
private static final String TAG = "SettingsFragment";
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -60,6 +66,16 @@ public class SettingsFragment extends PreferenceFragmentCompat {
|
||||||
public void onCreatePreferences(Bundle savedInstanceState, String rootKey) {
|
public void onCreatePreferences(Bundle savedInstanceState, String rootKey) {
|
||||||
setPreferencesFromResource(R.xml.root_preferences, rootKey);
|
setPreferencesFromResource(R.xml.root_preferences, rootKey);
|
||||||
|
|
||||||
|
updateUtil = new UpdateUtil(requireContext());
|
||||||
|
|
||||||
|
initPreferences();
|
||||||
|
initListeners();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void initPreferences(){
|
||||||
|
SharedPreferences preferences = requireContext().getSharedPreferences("root_preferences", Activity.MODE_PRIVATE);
|
||||||
|
SharedPreferences.Editor editor = preferences.edit();
|
||||||
|
|
||||||
musicPath = findPreference("music_path");
|
musicPath = findPreference("music_path");
|
||||||
videoPath = findPreference("video_path");
|
videoPath = findPreference("video_path");
|
||||||
commandPath = findPreference("command_path");
|
commandPath = findPreference("command_path");
|
||||||
|
|
@ -79,24 +95,14 @@ public class SettingsFragment extends PreferenceFragmentCompat {
|
||||||
version = findPreference("version");
|
version = findPreference("version");
|
||||||
version.setSummary(BuildConfig.VERSION_NAME);
|
version.setSummary(BuildConfig.VERSION_NAME);
|
||||||
|
|
||||||
if(firstRun){
|
if (preferences.getString("music_path", "").isEmpty()){
|
||||||
initPreferences();
|
editor.putString("music_path", getString(R.string.music_path));
|
||||||
}
|
}
|
||||||
initListeners();
|
if (preferences.getString("video_path", "").isEmpty()){
|
||||||
}
|
editor.putString("video_path", getString(R.string.video_path));
|
||||||
|
|
||||||
private void initPreferences(){
|
|
||||||
SharedPreferences preferences = requireContext().getSharedPreferences("root_preferences", Activity.MODE_PRIVATE);
|
|
||||||
SharedPreferences.Editor editor = preferences.edit();
|
|
||||||
|
|
||||||
if(preferences.getString("music_path", "").isEmpty()){
|
|
||||||
editor.putString("music_path", "/storage/emulated/0/Music/");
|
|
||||||
}
|
}
|
||||||
if(preferences.getString("video_path", "").isEmpty()){
|
if (preferences.getString("command_path", "").isEmpty()){
|
||||||
editor.putString("video_path", "/storage/emulated/0/Movies/");
|
editor.putString("command_path", getString(R.string.command_path));
|
||||||
}
|
|
||||||
if(preferences.getString("command_path", "").isEmpty()){
|
|
||||||
editor.putString("command_path", "/storage/emulated/0/Download");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
editor.putInt("concurrent_fragments", concurrentFragments.getValue());
|
editor.putInt("concurrent_fragments", concurrentFragments.getValue());
|
||||||
|
|
@ -111,7 +117,6 @@ public class SettingsFragment extends PreferenceFragmentCompat {
|
||||||
editor.putInt("audio_quality", audioQuality.getValue());
|
editor.putInt("audio_quality", audioQuality.getValue());
|
||||||
|
|
||||||
editor.apply();
|
editor.apply();
|
||||||
firstRun = false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void initListeners(){
|
private void initListeners(){
|
||||||
|
|
@ -209,6 +214,11 @@ public class SettingsFragment extends PreferenceFragmentCompat {
|
||||||
return true;
|
return true;
|
||||||
});
|
});
|
||||||
|
|
||||||
|
version.setOnPreferenceClickListener(preference -> {
|
||||||
|
updateUtil.updateApp();
|
||||||
|
return true;
|
||||||
|
});
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ActivityResultLauncher<Intent> musicPathResultLauncher = registerForActivityResult(
|
ActivityResultLauncher<Intent> musicPathResultLauncher = registerForActivityResult(
|
||||||
|
|
|
||||||
|
|
@ -10,25 +10,81 @@ import android.util.Log;
|
||||||
import android.widget.Toast;
|
import android.widget.Toast;
|
||||||
|
|
||||||
import com.deniscerri.ytdl.App;
|
import com.deniscerri.ytdl.App;
|
||||||
|
import com.deniscerri.ytdl.BuildConfig;
|
||||||
import com.deniscerri.ytdl.R;
|
import com.deniscerri.ytdl.R;
|
||||||
|
import com.google.android.material.card.MaterialCardView;
|
||||||
|
import com.google.android.material.dialog.MaterialAlertDialogBuilder;
|
||||||
|
import com.yausername.youtubedl_android.YoutubeDL;
|
||||||
|
|
||||||
import org.json.JSONArray;
|
import org.json.JSONArray;
|
||||||
|
import org.json.JSONException;
|
||||||
import org.json.JSONObject;
|
import org.json.JSONObject;
|
||||||
import java.io.BufferedReader;
|
import java.io.BufferedReader;
|
||||||
import java.io.InputStreamReader;
|
import java.io.InputStreamReader;
|
||||||
import java.net.HttpURLConnection;
|
import java.net.HttpURLConnection;
|
||||||
import java.net.URL;
|
import java.net.URL;
|
||||||
|
import java.util.concurrent.atomic.AtomicReference;
|
||||||
|
|
||||||
|
import io.reactivex.Observable;
|
||||||
|
import io.reactivex.android.schedulers.AndroidSchedulers;
|
||||||
|
import io.reactivex.disposables.CompositeDisposable;
|
||||||
|
import io.reactivex.disposables.Disposable;
|
||||||
|
import io.reactivex.schedulers.Schedulers;
|
||||||
|
|
||||||
public class UpdateUtil {
|
public class UpdateUtil {
|
||||||
Context context;
|
Context context;
|
||||||
private final String TAG = "UpdateUtil";
|
private final String TAG = "UpdateUtil";
|
||||||
private DownloadManager downloadManager;
|
private DownloadManager downloadManager;
|
||||||
|
public static boolean updatingYTDL;
|
||||||
|
public static boolean updatingApp;
|
||||||
|
MaterialCardView materialCardView;
|
||||||
|
private final CompositeDisposable compositeDisposable = new CompositeDisposable();
|
||||||
|
|
||||||
public UpdateUtil(Context context){
|
public UpdateUtil(Context context){
|
||||||
this.context = context;
|
this.context = context;
|
||||||
downloadManager = (DownloadManager) context.getSystemService(Context.DOWNLOAD_SERVICE);
|
downloadManager = (DownloadManager) context.getSystemService(Context.DOWNLOAD_SERVICE);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void updateApp(){
|
||||||
|
if (updatingApp) {
|
||||||
|
Toast.makeText(context, context.getString(R.string.ytdl_already_updating), Toast.LENGTH_LONG).show();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
AtomicReference<JSONObject> res = new AtomicReference<>(new JSONObject());
|
||||||
|
try{
|
||||||
|
Thread thread = new Thread(() -> res.set(checkForAppUpdate()));
|
||||||
|
thread.start();
|
||||||
|
thread.join();
|
||||||
|
}catch(Exception e){
|
||||||
|
Log.e(TAG, e.toString());
|
||||||
|
}
|
||||||
|
|
||||||
|
if(res.get() == null){
|
||||||
|
Toast.makeText(context, R.string.error_checking_latest_version, Toast.LENGTH_SHORT).show();
|
||||||
|
}
|
||||||
|
|
||||||
|
String version = "";
|
||||||
|
String body = "";
|
||||||
|
try {
|
||||||
|
version = res.get().getString("tag_name");
|
||||||
|
body = res.get().getString("body");
|
||||||
|
} catch (JSONException ignored) {}
|
||||||
|
|
||||||
|
if(version.equals("v"+BuildConfig.VERSION_NAME)){
|
||||||
|
Toast.makeText(context, R.string.you_are_in_latest_version, Toast.LENGTH_SHORT).show();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
MaterialAlertDialogBuilder updateDialog = new MaterialAlertDialogBuilder(context)
|
||||||
|
.setTitle(version)
|
||||||
|
.setMessage(body)
|
||||||
|
.setIcon(R.drawable.ic_update_app)
|
||||||
|
.setNegativeButton("Cancel", (dialogInterface, i) -> {})
|
||||||
|
.setPositiveButton("Update", (dialogInterface, i) -> startAppUpdate(res.get()));
|
||||||
|
updateDialog.show();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
public JSONObject checkForAppUpdate(){
|
public JSONObject checkForAppUpdate(){
|
||||||
String url = "https://api.github.com/repos/deniscerri/ytdlnis/releases/latest";
|
String url = "https://api.github.com/repos/deniscerri/ytdlnis/releases/latest";
|
||||||
|
|
||||||
|
|
@ -69,7 +125,7 @@ public class UpdateUtil {
|
||||||
return json;
|
return json;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void updateApp(JSONObject updateInfo){
|
private void startAppUpdate(JSONObject updateInfo){
|
||||||
try{
|
try{
|
||||||
JSONArray versions = updateInfo.getJSONArray("assets");
|
JSONArray versions = updateInfo.getJSONArray("assets");
|
||||||
String url = "";
|
String url = "";
|
||||||
|
|
@ -95,7 +151,7 @@ public class UpdateUtil {
|
||||||
|
|
||||||
downloadManager.enqueue(new DownloadManager.Request(uri)
|
downloadManager.enqueue(new DownloadManager.Request(uri)
|
||||||
.setAllowedNetworkTypes(DownloadManager.Request.NETWORK_WIFI |
|
.setAllowedNetworkTypes(DownloadManager.Request.NETWORK_WIFI |
|
||||||
DownloadManager.Request.NETWORK_MOBILE)
|
DownloadManager.Request.NETWORK_MOBILE)
|
||||||
.setAllowedOverRoaming(true)
|
.setAllowedOverRoaming(true)
|
||||||
.setNotificationVisibility(DownloadManager.Request.VISIBILITY_VISIBLE_NOTIFY_COMPLETED)
|
.setNotificationVisibility(DownloadManager.Request.VISIBILITY_VISIBLE_NOTIFY_COMPLETED)
|
||||||
.setTitle(context.getString(R.string.downloading_update))
|
.setTitle(context.getString(R.string.downloading_update))
|
||||||
|
|
@ -104,5 +160,38 @@ public class UpdateUtil {
|
||||||
}catch(Exception ignored){}
|
}catch(Exception ignored){}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void updateYoutubeDL() {
|
||||||
|
if (updatingYTDL) {
|
||||||
|
Toast.makeText(context, context.getString(R.string.ytdl_already_updating), Toast.LENGTH_LONG).show();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
Toast.makeText(context, context.getString(R.string.ytdl_updating_started), Toast.LENGTH_SHORT).show();
|
||||||
|
|
||||||
|
updatingYTDL = true;
|
||||||
|
Disposable disposable = Observable.fromCallable(() -> YoutubeDL.getInstance().updateYoutubeDL(context))
|
||||||
|
.subscribeOn(Schedulers.newThread())
|
||||||
|
.observeOn(AndroidSchedulers.mainThread())
|
||||||
|
.subscribe(status -> {
|
||||||
|
switch (status) {
|
||||||
|
case DONE:
|
||||||
|
Toast.makeText(context, context.getString(R.string.ytld_update_success), Toast.LENGTH_LONG).show();
|
||||||
|
break;
|
||||||
|
case ALREADY_UP_TO_DATE:
|
||||||
|
Toast.makeText(context, context.getString(R.string.you_are_in_latest_version), Toast.LENGTH_LONG).show();
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
Toast.makeText(context, status.toString(), Toast.LENGTH_LONG).show();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
updatingYTDL = false;
|
||||||
|
}, e -> {
|
||||||
|
if(BuildConfig.DEBUG) Log.e(TAG, context.getString(R.string.ytdl_update_failed), e);
|
||||||
|
Toast.makeText(context, context.getString(R.string.ytdl_update_failed), Toast.LENGTH_LONG).show();
|
||||||
|
updatingYTDL = false;
|
||||||
|
});
|
||||||
|
compositeDisposable.add(disposable);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -6,86 +6,6 @@
|
||||||
android:id="@+id/historycoordinator"
|
android:id="@+id/historycoordinator"
|
||||||
xmlns:android="http://schemas.android.com/apk/res/android">
|
xmlns:android="http://schemas.android.com/apk/res/android">
|
||||||
|
|
||||||
<androidx.core.widget.NestedScrollView
|
|
||||||
android:id="@+id/history_scrollview"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="match_parent"
|
|
||||||
android:scrollbars="vertical"
|
|
||||||
app:layout_behavior="com.google.android.material.appbar.AppBarLayout$ScrollingViewBehavior">
|
|
||||||
|
|
||||||
<LinearLayout
|
|
||||||
android:id="@+id/home_main_linearlayout"
|
|
||||||
android:orientation="vertical"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="match_parent">
|
|
||||||
|
|
||||||
<LinearLayout
|
|
||||||
android:id="@+id/historylinearLayout1"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_gravity="center"
|
|
||||||
|
|
||||||
android:layout_height="match_parent"
|
|
||||||
android:orientation="vertical" />
|
|
||||||
|
|
||||||
<androidx.recyclerview.widget.RecyclerView
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:id="@+id/recycler_view_history"
|
|
||||||
android:orientation="vertical"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:scrollbars="vertical"
|
|
||||||
android:nestedScrollingEnabled="false"
|
|
||||||
android:layout_margin="10dp"
|
|
||||||
app:layoutManager="androidx.recyclerview.widget.LinearLayoutManager"
|
|
||||||
>
|
|
||||||
|
|
||||||
</androidx.recyclerview.widget.RecyclerView>
|
|
||||||
|
|
||||||
<com.facebook.shimmer.ShimmerFrameLayout
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="match_parent"
|
|
||||||
android:id="@+id/shimmer_history_framelayout"
|
|
||||||
android:orientation="vertical">
|
|
||||||
|
|
||||||
|
|
||||||
<LinearLayout
|
|
||||||
android:id="@+id/shimmer_history_linear_layout"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_margin="10dp"
|
|
||||||
android:orientation="vertical">
|
|
||||||
|
|
||||||
<include layout="@layout/history_card_shimmer" />
|
|
||||||
|
|
||||||
<include layout="@layout/history_card_shimmer" />
|
|
||||||
|
|
||||||
<include layout="@layout/history_card_shimmer" />
|
|
||||||
|
|
||||||
<include layout="@layout/history_card_shimmer" />
|
|
||||||
|
|
||||||
<include layout="@layout/history_card_shimmer" />
|
|
||||||
|
|
||||||
<include layout="@layout/history_card_shimmer" />
|
|
||||||
|
|
||||||
<include layout="@layout/history_card_shimmer" />
|
|
||||||
|
|
||||||
<include layout="@layout/history_card_shimmer" />
|
|
||||||
|
|
||||||
<include layout="@layout/history_card_shimmer" />
|
|
||||||
|
|
||||||
<include layout="@layout/history_card_shimmer" />
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
</LinearLayout>
|
|
||||||
|
|
||||||
</com.facebook.shimmer.ShimmerFrameLayout>
|
|
||||||
|
|
||||||
</LinearLayout>
|
|
||||||
|
|
||||||
</androidx.core.widget.NestedScrollView>
|
|
||||||
|
|
||||||
|
|
||||||
<com.google.android.material.appbar.AppBarLayout
|
<com.google.android.material.appbar.AppBarLayout
|
||||||
android:id="@+id/history_appbarlayout"
|
android:id="@+id/history_appbarlayout"
|
||||||
app:liftOnScroll="false"
|
app:liftOnScroll="false"
|
||||||
|
|
@ -105,6 +25,64 @@
|
||||||
|
|
||||||
</com.google.android.material.appbar.AppBarLayout>
|
</com.google.android.material.appbar.AppBarLayout>
|
||||||
|
|
||||||
|
<androidx.recyclerview.widget.RecyclerView
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:id="@+id/recycler_view_history"
|
||||||
|
android:orientation="vertical"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:scrollbars="vertical"
|
||||||
|
android:nestedScrollingEnabled="false"
|
||||||
|
android:layout_margin="10dp"
|
||||||
|
app:layout_behavior="com.google.android.material.appbar.AppBarLayout$ScrollingViewBehavior"
|
||||||
|
app:layoutManager="androidx.recyclerview.widget.LinearLayoutManager"
|
||||||
|
>
|
||||||
|
|
||||||
|
</androidx.recyclerview.widget.RecyclerView>
|
||||||
|
|
||||||
|
<include layout="@layout/history_no_results"
|
||||||
|
android:visibility="gone" />
|
||||||
|
|
||||||
|
<com.facebook.shimmer.ShimmerFrameLayout
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent"
|
||||||
|
android:layout_marginTop="?attr/actionBarSize"
|
||||||
|
android:id="@+id/shimmer_history_framelayout"
|
||||||
|
android:orientation="vertical">
|
||||||
|
|
||||||
|
|
||||||
|
<LinearLayout
|
||||||
|
android:id="@+id/shimmer_history_linear_layout"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_margin="10dp"
|
||||||
|
android:orientation="vertical">
|
||||||
|
|
||||||
|
<include layout="@layout/history_card_shimmer" />
|
||||||
|
|
||||||
|
<include layout="@layout/history_card_shimmer" />
|
||||||
|
|
||||||
|
<include layout="@layout/history_card_shimmer" />
|
||||||
|
|
||||||
|
<include layout="@layout/history_card_shimmer" />
|
||||||
|
|
||||||
|
<include layout="@layout/history_card_shimmer" />
|
||||||
|
|
||||||
|
<include layout="@layout/history_card_shimmer" />
|
||||||
|
|
||||||
|
<include layout="@layout/history_card_shimmer" />
|
||||||
|
|
||||||
|
<include layout="@layout/history_card_shimmer" />
|
||||||
|
|
||||||
|
<include layout="@layout/history_card_shimmer" />
|
||||||
|
|
||||||
|
<include layout="@layout/history_card_shimmer" />
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
</LinearLayout>
|
||||||
|
|
||||||
|
</com.facebook.shimmer.ShimmerFrameLayout>
|
||||||
|
|
||||||
<include layout="@layout/history_bottom_sheet"
|
<include layout="@layout/history_bottom_sheet"
|
||||||
android:visibility="gone" />
|
android:visibility="gone" />
|
||||||
|
|
|
||||||
|
|
@ -6,74 +6,9 @@
|
||||||
android:id="@+id/homecoordinator"
|
android:id="@+id/homecoordinator"
|
||||||
xmlns:android="http://schemas.android.com/apk/res/android">
|
xmlns:android="http://schemas.android.com/apk/res/android">
|
||||||
|
|
||||||
<androidx.core.widget.NestedScrollView
|
|
||||||
android:id="@+id/home_scrollview"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="match_parent"
|
|
||||||
android:scrollbars="vertical"
|
|
||||||
app:layout_behavior="com.google.android.material.appbar.AppBarLayout$ScrollingViewBehavior">
|
|
||||||
|
|
||||||
<LinearLayout
|
|
||||||
android:id="@+id/home_main_linearlayout"
|
|
||||||
android:orientation="vertical"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="match_parent">
|
|
||||||
|
|
||||||
<LinearLayout
|
|
||||||
android:id="@+id/linearLayout1"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:orientation="vertical" />
|
|
||||||
|
|
||||||
<androidx.recyclerview.widget.RecyclerView
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:id="@+id/recycler_view_home"
|
|
||||||
android:orientation="vertical"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:scrollbars="vertical"
|
|
||||||
android:nestedScrollingEnabled="false"
|
|
||||||
android:layout_margin="10dp"
|
|
||||||
app:layoutManager="androidx.recyclerview.widget.LinearLayoutManager"
|
|
||||||
>
|
|
||||||
|
|
||||||
</androidx.recyclerview.widget.RecyclerView>
|
|
||||||
|
|
||||||
<com.facebook.shimmer.ShimmerFrameLayout
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="match_parent"
|
|
||||||
android:id="@+id/shimmer_results_framelayout"
|
|
||||||
android:orientation="vertical">
|
|
||||||
|
|
||||||
|
|
||||||
<LinearLayout
|
|
||||||
android:id="@+id/shimmer_linear_layout"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_margin="10dp"
|
|
||||||
android:orientation="vertical">
|
|
||||||
|
|
||||||
<include layout="@layout/result_card_shimmer" />
|
|
||||||
|
|
||||||
<include layout="@layout/result_card_shimmer" />
|
|
||||||
|
|
||||||
<include layout="@layout/result_card_shimmer" />
|
|
||||||
|
|
||||||
<include layout="@layout/result_card_shimmer" />
|
|
||||||
|
|
||||||
<include layout="@layout/result_card_shimmer" />
|
|
||||||
|
|
||||||
|
|
||||||
</LinearLayout>
|
|
||||||
|
|
||||||
</com.facebook.shimmer.ShimmerFrameLayout>
|
|
||||||
|
|
||||||
</LinearLayout>
|
|
||||||
|
|
||||||
</androidx.core.widget.NestedScrollView>
|
|
||||||
|
|
||||||
<com.google.android.material.appbar.AppBarLayout
|
<com.google.android.material.appbar.AppBarLayout
|
||||||
android:id="@+id/home_appbarlayout"
|
android:id="@+id/home_appbarlayout"
|
||||||
app:liftOnScroll="false"
|
app:liftOnScroll="true"
|
||||||
android:background="@android:color/transparent"
|
android:background="@android:color/transparent"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content">
|
android:layout_height="wrap_content">
|
||||||
|
|
@ -90,8 +25,72 @@
|
||||||
|
|
||||||
</com.google.android.material.appbar.AppBarLayout>
|
</com.google.android.material.appbar.AppBarLayout>
|
||||||
|
|
||||||
|
|
||||||
|
<androidx.recyclerview.widget.RecyclerView
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:id="@+id/recycler_view_home"
|
||||||
|
android:nestedScrollingEnabled="false"
|
||||||
|
android:orientation="vertical"
|
||||||
|
android:layout_height="match_parent"
|
||||||
|
android:scrollbars="vertical"
|
||||||
|
android:layout_marginLeft="10dp"
|
||||||
|
android:layout_marginRight="10dp"
|
||||||
|
android:clipToPadding="false"
|
||||||
|
android:paddingBottom="150dp"
|
||||||
|
app:layout_behavior="com.google.android.material.appbar.AppBarLayout$ScrollingViewBehavior"
|
||||||
|
app:layoutManager="androidx.recyclerview.widget.LinearLayoutManager"
|
||||||
|
/>
|
||||||
|
|
||||||
|
|
||||||
|
<com.facebook.shimmer.ShimmerFrameLayout
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent"
|
||||||
|
android:id="@+id/shimmer_results_framelayout"
|
||||||
|
android:layout_marginTop="?attr/actionBarSize"
|
||||||
|
android:orientation="vertical">
|
||||||
|
|
||||||
|
|
||||||
|
<LinearLayout
|
||||||
|
android:id="@+id/shimmer_linear_layout"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_margin="10dp"
|
||||||
|
android:orientation="vertical">
|
||||||
|
|
||||||
|
<include layout="@layout/result_card_shimmer" />
|
||||||
|
|
||||||
|
<include layout="@layout/result_card_shimmer" />
|
||||||
|
|
||||||
|
<include layout="@layout/result_card_shimmer" />
|
||||||
|
|
||||||
|
<include layout="@layout/result_card_shimmer" />
|
||||||
|
|
||||||
|
<include layout="@layout/result_card_shimmer" />
|
||||||
|
|
||||||
|
|
||||||
|
</LinearLayout>
|
||||||
|
|
||||||
|
</com.facebook.shimmer.ShimmerFrameLayout>
|
||||||
|
|
||||||
<androidx.coordinatorlayout.widget.CoordinatorLayout
|
<androidx.coordinatorlayout.widget.CoordinatorLayout
|
||||||
android:id="@+id/home_download_fabs"
|
android:id="@+id/download_all_coordinator"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:visibility="gone"
|
||||||
|
android:layout_height="match_parent">
|
||||||
|
|
||||||
|
<com.google.android.material.floatingactionbutton.ExtendedFloatingActionButton
|
||||||
|
android:id="@+id/download_all_fab"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_margin="16dp"
|
||||||
|
android:layout_gravity="bottom|end"
|
||||||
|
android:text="@string/download_all"
|
||||||
|
app:icon="@drawable/ic_down"/>
|
||||||
|
|
||||||
|
</androidx.coordinatorlayout.widget.CoordinatorLayout>
|
||||||
|
|
||||||
|
<androidx.coordinatorlayout.widget.CoordinatorLayout
|
||||||
|
android:id="@+id/download_selected_coordinator"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:visibility="gone"
|
android:visibility="gone"
|
||||||
android:layout_height="match_parent">
|
android:layout_height="match_parent">
|
||||||
|
|
@ -108,7 +107,6 @@
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:background="?attr/colorPrimaryContainer"
|
android:background="?attr/colorPrimaryContainer"
|
||||||
android:padding="5dp"
|
|
||||||
android:orientation="horizontal">
|
android:orientation="horizontal">
|
||||||
|
|
||||||
<com.google.android.material.floatingactionbutton.FloatingActionButton
|
<com.google.android.material.floatingactionbutton.FloatingActionButton
|
||||||
|
|
@ -126,6 +124,7 @@
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_gravity="bottom|end"
|
android:layout_gravity="bottom|end"
|
||||||
|
android:layout_marginLeft="5dp"
|
||||||
app:srcCompat="@drawable/ic_video"/>
|
app:srcCompat="@drawable/ic_video"/>
|
||||||
|
|
||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
|
|
|
||||||
|
|
@ -1,14 +0,0 @@
|
||||||
<?xml version="1.0" encoding="utf-8"?>
|
|
||||||
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
|
||||||
xmlns:tools="http://schemas.android.com/tools"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="match_parent"
|
|
||||||
tools:context=".page.MusicEditorFragment">
|
|
||||||
|
|
||||||
<!-- TODO: Update blank fragment layout -->
|
|
||||||
<TextView
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="match_parent"
|
|
||||||
android:text="ello" />
|
|
||||||
|
|
||||||
</FrameLayout>
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<RelativeLayout android:id="@+id/history_shimmer_relative_layout"
|
<RelativeLayout android:id="@+id/history_shimmer_relative_layout"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="100dp"
|
android:layout_height="150dp"
|
||||||
app:layout_constraintDimensionRatio="H,2.66:1"
|
app:layout_constraintDimensionRatio="H,2.66:1"
|
||||||
app:layout_constraintStart_toStartOf="parent"
|
app:layout_constraintStart_toStartOf="parent"
|
||||||
app:layout_constraintEnd_toEndOf="parent"
|
app:layout_constraintEnd_toEndOf="parent"
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,7 @@
|
||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
<RelativeLayout
|
||||||
|
android:id="@+id/history_no_results"
|
||||||
|
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
xmlns:tools="http://schemas.android.com/tools"
|
xmlns:tools="http://schemas.android.com/tools"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="match_parent">
|
android:layout_height="match_parent">
|
||||||
|
|
|
||||||
|
|
@ -7,9 +7,6 @@
|
||||||
<item android:title="@string/history"
|
<item android:title="@string/history"
|
||||||
android:icon="@drawable/ic_history"
|
android:icon="@drawable/ic_history"
|
||||||
android:id="@+id/history"/>
|
android:id="@+id/history"/>
|
||||||
<item android:title="@string/music_editor"
|
|
||||||
android:icon="@drawable/ic_music_downloaded"
|
|
||||||
android:id="@+id/music_editor"/>
|
|
||||||
<item android:title="@string/more"
|
<item android:title="@string/more"
|
||||||
android:icon="@drawable/ic_more"
|
android:icon="@drawable/ic_more"
|
||||||
android:id="@+id/more"/>
|
android:id="@+id/more"/>
|
||||||
|
|
|
||||||
|
|
@ -53,8 +53,15 @@
|
||||||
<string name="run">Ekzekuto</string>
|
<string name="run">Ekzekuto</string>
|
||||||
<string name="running_ytdlp_command">Duke Ekzekutuar Komandën yt-dlp</string>
|
<string name="running_ytdlp_command">Duke Ekzekutuar Komandën yt-dlp</string>
|
||||||
<string name="command_directory">Direktoria e Komandës</string>
|
<string name="command_directory">Direktoria e Komandës</string>
|
||||||
<string name="you_are_running_latest_version">Ti je në versionin e fundit</string>
|
|
||||||
<string name="error_checking_latest_version">Gabim në kontrollin e versionit!</string>
|
<string name="error_checking_latest_version">Gabim në kontrollin e versionit!</string>
|
||||||
<string name="couldnt_find_apk">Nuk u gjet një apk e vlefshme!</string>
|
<string name="couldnt_find_apk">Nuk u gjet një apk e vlefshme!</string>
|
||||||
<string name="downloading_update">Duke Përditësuar</string>
|
<string name="downloading_update">Duke Përditësuar</string>
|
||||||
|
<string name="chooose_range">Zgjidh Shtrirjen</string>
|
||||||
|
<string name="audio">Audio</string>
|
||||||
|
<string name="video">Video</string>
|
||||||
|
<string name="first">E para</string>
|
||||||
|
<string name="last">E fundit</string>
|
||||||
|
<string name="choose_range_desc">Cilëso cilën pjesë të listës do të shkarkosh. Lëre siç është që t\'i shkarkosh të gjitha</string>
|
||||||
|
<string name="last_cant_be_smaller_than_first">Indeksi i fundit nuk mund të jetë më i vogël se indeksi i parë</string>
|
||||||
|
<string name="first_cant_be_larger_than_last">Indeksi i parë nuk mund të jetë më i madh se indeksi i fundit</string>
|
||||||
</resources>
|
</resources>
|
||||||
|
|
@ -53,7 +53,6 @@
|
||||||
<string name="run">Run</string>
|
<string name="run">Run</string>
|
||||||
<string name="running_ytdlp_command">Running yt-dlp Custom Command</string>
|
<string name="running_ytdlp_command">Running yt-dlp Custom Command</string>
|
||||||
<string name="command_directory">Custom Command Directory</string>
|
<string name="command_directory">Custom Command Directory</string>
|
||||||
<string name="you_are_running_latest_version">You are running the latest version!</string>
|
|
||||||
<string name="error_checking_latest_version">Error checking for latest version!</string>
|
<string name="error_checking_latest_version">Error checking for latest version!</string>
|
||||||
<string name="couldnt_find_apk">Couldn\'t find a suitable apk!</string>
|
<string name="couldnt_find_apk">Couldn\'t find a suitable apk!</string>
|
||||||
<string name="downloading_update">Downloading Update</string>
|
<string name="downloading_update">Downloading Update</string>
|
||||||
|
|
@ -65,4 +64,7 @@
|
||||||
<string name="choose_range_desc">Write the range to download from the playlist. Leave as it is to download everything!</string>
|
<string name="choose_range_desc">Write the range to download from the playlist. Leave as it is to download everything!</string>
|
||||||
<string name="last_cant_be_smaller_than_first">Last index cannot be smaller than the first!</string>
|
<string name="last_cant_be_smaller_than_first">Last index cannot be smaller than the first!</string>
|
||||||
<string name="first_cant_be_larger_than_last">First index cannot be larger than the last!</string>
|
<string name="first_cant_be_larger_than_last">First index cannot be larger than the last!</string>
|
||||||
|
<string name="music_path" translatable="false">/storage/emulated/0/Download</string>
|
||||||
|
<string name="video_path" translatable="false">/storage/emulated/0/Download</string>
|
||||||
|
<string name="command_path" translatable="false">/storage/emulated/0/Download</string>
|
||||||
</resources>
|
</resources>
|
||||||
|
|
|
||||||
|
|
@ -5,16 +5,19 @@
|
||||||
<Preference
|
<Preference
|
||||||
app:icon="@drawable/ic_music_downloaded"
|
app:icon="@drawable/ic_music_downloaded"
|
||||||
app:key="music_path"
|
app:key="music_path"
|
||||||
|
app:defaultValue="@string/music_path"
|
||||||
app:title="@string/music_directory" />
|
app:title="@string/music_directory" />
|
||||||
|
|
||||||
<Preference
|
<Preference
|
||||||
app:icon="@drawable/ic_video_downloaded"
|
app:icon="@drawable/ic_video_downloaded"
|
||||||
app:key="video_path"
|
app:key="video_path"
|
||||||
|
app:defaultValue="@string/video_path"
|
||||||
app:title="@string/video_directory" />
|
app:title="@string/video_directory" />
|
||||||
|
|
||||||
<Preference
|
<Preference
|
||||||
app:icon="@drawable/ic_baseline_keyboard_arrow_right_24"
|
app:icon="@drawable/ic_baseline_keyboard_arrow_right_24"
|
||||||
app:key="command_path"
|
app:key="command_path"
|
||||||
|
app:defaultValue="@string/command_path"
|
||||||
app:title="@string/command_directory" />
|
app:title="@string/command_directory" />
|
||||||
|
|
||||||
</PreferenceCategory>
|
</PreferenceCategory>
|
||||||
|
|
@ -108,6 +111,6 @@
|
||||||
app:allowDividerAbove="true"
|
app:allowDividerAbove="true"
|
||||||
app:icon="@drawable/ic_info"
|
app:icon="@drawable/ic_info"
|
||||||
app:key="version"
|
app:key="version"
|
||||||
app:title="@string/version"></Preference>
|
app:title="@string/version"/>
|
||||||
|
|
||||||
</PreferenceScreen>
|
</PreferenceScreen>
|
||||||
Loading…
Reference in a new issue