added downloading items on the downloads tab, they can be cancelled

TODO, update home fragment when downloads tab cancels
This commit is contained in:
Denis Çerri 2022-10-11 01:07:32 +02:00
parent a3f0667c7d
commit b6f6edb690
No known key found for this signature in database
GPG key ID: 3F50F14A8E7F7A13
20 changed files with 367 additions and 155 deletions

View file

@ -320,7 +320,7 @@
<PersistentState> <PersistentState>
<option name="values"> <option name="values">
<map> <map>
<entry key="url" value="file:/$USER_HOME$/AppData/Local/Android/Sdk/icons/material/materialicons/arrow_upward/baseline_arrow_upward_24.xml" /> <entry key="url" value="file:/$USER_HOME$/AppData/Local/Android/Sdk/icons/material/materialicons/history/baseline_history_24.xml" />
</map> </map>
</option> </option>
</PersistentState> </PersistentState>
@ -331,7 +331,7 @@
<option name="values"> <option name="values">
<map> <map>
<entry key="color" value="00a6ff" /> <entry key="color" value="00a6ff" />
<entry key="outputName" value="ic_up" /> <entry key="outputName" value="ic_history" />
<entry key="sourceFile" value="C:\Users\denis\Desktop\adaptiveproduct_youtube_foreground_color_108 (1).svg" /> <entry key="sourceFile" value="C:\Users\denis\Desktop\adaptiveproduct_youtube_foreground_color_108 (1).svg" />
</map> </map>
</option> </option>

View file

@ -51,6 +51,7 @@
<entry key="..\:/Users/denis/Documents/GitHub/ytdlnis/app/src/main/res/drawable/ic_downloads.xml" value="0.2395" /> <entry key="..\:/Users/denis/Documents/GitHub/ytdlnis/app/src/main/res/drawable/ic_downloads.xml" value="0.2395" />
<entry key="..\:/Users/denis/Documents/GitHub/ytdlnis/app/src/main/res/drawable/ic_filter.xml" value="0.1965" /> <entry key="..\:/Users/denis/Documents/GitHub/ytdlnis/app/src/main/res/drawable/ic_filter.xml" value="0.1965" />
<entry key="..\:/Users/denis/Documents/GitHub/ytdlnis/app/src/main/res/drawable/ic_go_up.xml" value="0.1275" /> <entry key="..\:/Users/denis/Documents/GitHub/ytdlnis/app/src/main/res/drawable/ic_go_up.xml" value="0.1275" />
<entry key="..\:/Users/denis/Documents/GitHub/ytdlnis/app/src/main/res/drawable/ic_history.xml" value="0.1965" />
<entry key="..\:/Users/denis/Documents/GitHub/ytdlnis/app/src/main/res/drawable/ic_home.xml" value="0.1275" /> <entry key="..\:/Users/denis/Documents/GitHub/ytdlnis/app/src/main/res/drawable/ic_home.xml" value="0.1275" />
<entry key="..\:/Users/denis/Documents/GitHub/ytdlnis/app/src/main/res/drawable/ic_image.xml" value="0.109" /> <entry key="..\:/Users/denis/Documents/GitHub/ytdlnis/app/src/main/res/drawable/ic_image.xml" value="0.109" />
<entry key="..\:/Users/denis/Documents/GitHub/ytdlnis/app/src/main/res/drawable/ic_info.xml" value="0.109" /> <entry key="..\:/Users/denis/Documents/GitHub/ytdlnis/app/src/main/res/drawable/ic_info.xml" value="0.109" />
@ -81,7 +82,7 @@
<entry key="..\:/Users/denis/Documents/GitHub/ytdlnis/app/src/main/res/layout/activity_settings.xml" value="0.16875" /> <entry key="..\:/Users/denis/Documents/GitHub/ytdlnis/app/src/main/res/layout/activity_settings.xml" value="0.16875" />
<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/downloads_bottom_sheet.xml" value="0.18854166666666666" /> <entry key="..\:/Users/denis/Documents/GitHub/ytdlnis/app/src/main/res/layout/downloads_bottom_sheet.xml" value="0.18854166666666666" />
<entry key="..\:/Users/denis/Documents/GitHub/ytdlnis/app/src/main/res/layout/downloads_card.xml" value="0.18854166666666666" /> <entry key="..\:/Users/denis/Documents/GitHub/ytdlnis/app/src/main/res/layout/downloads_card.xml" value="0.33" />
<entry key="..\:/Users/denis/Documents/GitHub/ytdlnis/app/src/main/res/layout/downloads_card_shimmer.xml" value="0.18854166666666666" /> <entry key="..\:/Users/denis/Documents/GitHub/ytdlnis/app/src/main/res/layout/downloads_card_shimmer.xml" value="0.18854166666666666" />
<entry key="..\:/Users/denis/Documents/GitHub/ytdlnis/app/src/main/res/layout/downloads_filter_sheet.xml" value="0.18854166666666666" /> <entry key="..\:/Users/denis/Documents/GitHub/ytdlnis/app/src/main/res/layout/downloads_filter_sheet.xml" value="0.18854166666666666" />
<entry key="..\:/Users/denis/Documents/GitHub/ytdlnis/app/src/main/res/layout/downloads_no_results.xml" value="0.18854166666666666" /> <entry key="..\:/Users/denis/Documents/GitHub/ytdlnis/app/src/main/res/layout/downloads_no_results.xml" value="0.18854166666666666" />

View file

@ -49,10 +49,6 @@
android:name=".DownloaderService" android:name=".DownloaderService"
android:enabled="true" android:enabled="true"
android:exported="false" /> android:exported="false" />
<meta-data
android:name = "ytAPIkey"
android:value = "${ytAPI}"
/>
</application> </application>
</manifest> </manifest>

View file

@ -40,7 +40,7 @@ import io.reactivex.schedulers.Schedulers;
public class DownloaderService extends Service { public class DownloaderService extends Service {
private LocalBinder binder = new LocalBinder(); private LocalBinder binder = new LocalBinder();
private Map<Activity, IDownloaderListener> activities = new ConcurrentHashMap<>(); private Map<Activity, ArrayList<IDownloaderListener>> activities = new ConcurrentHashMap<>();
private DownloadInfo downloadInfo = new DownloadInfo(); private DownloadInfo downloadInfo = new DownloadInfo();
private LinkedList<Video> downloadQueue = new LinkedList<>(); private LinkedList<Video> downloadQueue = new LinkedList<>();
private CompositeDisposable compositeDisposable = new CompositeDisposable(); private CompositeDisposable compositeDisposable = new CompositeDisposable();
@ -60,12 +60,15 @@ public class DownloaderService extends Service {
} }
notificationUtil.updateDownloadNotification(downloadNotificationID, notificationUtil.updateDownloadNotification(downloadNotificationID,
line, (int) progress, downloadQueue.size(), title); line, (int) progress, downloadQueue.size(), title);
try{ try{
for (Activity activity: activities.keySet()){ for (Activity activity: activities.keySet()){
activity.runOnUiThread(() -> { activity.runOnUiThread(() -> {
IDownloaderListener callback = activities.get(activity); if (activities.get(activity) != null){
callback.onDownloadProgress(downloadInfo); for (int i = 0; i < activities.get(activity).size(); i++){
IDownloaderListener callback = activities.get(activity).get(i);
callback.onDownloadProgress(downloadInfo);
}
}
}); });
} }
}catch (Exception ignored){} }catch (Exception ignored){}
@ -135,9 +138,9 @@ public class DownloaderService extends Service {
return downloadInfo; return downloadInfo;
} }
public void addActivity(Activity activity, IDownloaderListener callback) { public void addActivity(Activity activity, ArrayList<IDownloaderListener> callbacks) {
if(!activities.containsKey(activity)){ if(!activities.containsKey(activity)){
activities.put(activity, callback); activities.put(activity, callbacks);
} }
} }
@ -186,8 +189,10 @@ public class DownloaderService extends Service {
try{ try{
for (Activity activity: activities.keySet()){ for (Activity activity: activities.keySet()){
activity.runOnUiThread(() -> { activity.runOnUiThread(() -> {
IDownloaderListener callback = activities.get(activity); for (int i = 0; i < activities.get(activity).size(); i++){
callback.onDownloadServiceEnd(); IDownloaderListener callback = activities.get(activity).get(i);
callback.onDownloadServiceEnd();
}
}); });
} }
}catch (Exception e){ }catch (Exception e){
@ -199,8 +204,10 @@ public class DownloaderService extends Service {
try{ try{
for (Activity activity: activities.keySet()){ for (Activity activity: activities.keySet()){
activity.runOnUiThread(() -> { activity.runOnUiThread(() -> {
IDownloaderListener callback = activities.get(activity); for (int i = 0; i < activities.get(activity).size(); i++){
callback.onDownloadCancel(downloadInfo); IDownloaderListener callback = activities.get(activity).get(i);
callback.onDownloadCancel(downloadInfo);
}
}); });
} }
}catch (Exception e){ }catch (Exception e){
@ -212,8 +219,10 @@ public class DownloaderService extends Service {
try{ try{
for (Activity activity: activities.keySet()){ for (Activity activity: activities.keySet()){
activity.runOnUiThread(() -> { activity.runOnUiThread(() -> {
IDownloaderListener callback = activities.get(activity); for (int i = 0; i < activities.get(activity).size(); i++){
callback.onDownloadEnd(downloadInfo); IDownloaderListener callback = activities.get(activity).get(i);
callback.onDownloadEnd(downloadInfo);
}
}); });
} }
}catch (Exception e){ }catch (Exception e){
@ -238,15 +247,16 @@ public class DownloaderService extends Service {
try{ try{
for (Activity activity: activities.keySet()){ for (Activity activity: activities.keySet()){
activity.runOnUiThread(() -> { activity.runOnUiThread(() -> {
IDownloaderListener callback = activities.get(activity); for (int i = 0; i < activities.get(activity).size(); i++){
callback.onDownloadStart(downloadInfo); IDownloaderListener callback = activities.get(activity).get(i);
callback.onDownloadStart(downloadInfo);
}
}); });
} }
}catch (Exception err){ }catch (Exception err){
err.printStackTrace(); err.printStackTrace();
} }
String url = video.getURL(); String url = video.getURL();
YoutubeDLRequest request = new YoutubeDLRequest(url); YoutubeDLRequest request = new YoutubeDLRequest(url);
String type = video.getDownloadedType(); String type = video.getDownloadedType();
@ -332,8 +342,10 @@ public class DownloaderService extends Service {
try{ try{
for (Activity activity: activities.keySet()){ for (Activity activity: activities.keySet()){
activity.runOnUiThread(() -> { activity.runOnUiThread(() -> {
IDownloaderListener callback = activities.get(activity); for (int i = 0; i < activities.get(activity).size(); i++){
callback.onDownloadEnd(downloadInfo); IDownloaderListener callback = activities.get(activity).get(i);
callback.onDownloadEnd(downloadInfo);
}
}); });
} }
}catch (Exception e){ }catch (Exception e){
@ -351,8 +363,10 @@ public class DownloaderService extends Service {
try{ try{
for (Activity activity: activities.keySet()){ for (Activity activity: activities.keySet()){
activity.runOnUiThread(() -> { activity.runOnUiThread(() -> {
IDownloaderListener callback = activities.get(activity); for (int i = 0; i < activities.get(activity).size(); i++){
callback.onDownloadError(downloadInfo); IDownloaderListener callback = activities.get(activity).get(i);
callback.onDownloadError(downloadInfo);
}
}); });
} }
}catch (Exception err){ }catch (Exception err){
@ -405,9 +419,11 @@ public class DownloaderService extends Service {
try{ try{
for (Activity activity: activities.keySet()){ for (Activity activity: activities.keySet()){
activity.runOnUiThread(() -> { activity.runOnUiThread(() -> {
IDownloaderListener callback = activities.get(activity); for (int i = 0; i < activities.get(activity).size(); i++){
callback.onDownloadEnd(downloadInfo); IDownloaderListener callback = activities.get(activity).get(i);
callback.onDownloadServiceEnd(); callback.onDownloadEnd(downloadInfo);
callback.onDownloadServiceEnd();
}
}); });
} }
}catch (Exception e){ }catch (Exception e){
@ -418,9 +434,11 @@ public class DownloaderService extends Service {
try{ try{
for (Activity activity: activities.keySet()){ for (Activity activity: activities.keySet()){
activity.runOnUiThread(() -> { activity.runOnUiThread(() -> {
IDownloaderListener callback = activities.get(activity); for (int i = 0; i < activities.get(activity).size(); i++){
callback.onDownloadError(downloadInfo); IDownloaderListener callback = activities.get(activity).get(i);
callback.onDownloadServiceEnd(); callback.onDownloadError(downloadInfo);
callback.onDownloadServiceEnd();
}
}); });
} }
}catch (Exception err){ }catch (Exception err){

View file

@ -14,6 +14,8 @@ 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 com.deniscerri.ytdlnis.database.DBManager;
import com.deniscerri.ytdlnis.database.Video; import com.deniscerri.ytdlnis.database.Video;
import com.deniscerri.ytdlnis.databinding.ActivityMainBinding; import com.deniscerri.ytdlnis.databinding.ActivityMainBinding;
import com.deniscerri.ytdlnis.page.DownloadsFragment; import com.deniscerri.ytdlnis.page.DownloadsFragment;
@ -24,7 +26,12 @@ import com.deniscerri.ytdlnis.service.IDownloaderListener;
import com.deniscerri.ytdlnis.service.IDownloaderService; import com.deniscerri.ytdlnis.service.IDownloaderService;
import com.deniscerri.ytdlnis.util.UpdateUtil; import com.deniscerri.ytdlnis.util.UpdateUtil;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.Locale;
public class MainActivity extends AppCompatActivity{ public class MainActivity extends AppCompatActivity{
@ -53,9 +60,9 @@ public class MainActivity extends AppCompatActivity{
iDownloaderService = (IDownloaderService) service; iDownloaderService = (IDownloaderService) service;
isDownloadServiceRunning = true; isDownloadServiceRunning = true;
try{ try{
iDownloaderService.addActivity(MainActivity.this, listeners);
for (int i = 0; i < listeners.size(); i++){ for (int i = 0; i < listeners.size(); i++){
IDownloaderListener listener = listeners.get(i); IDownloaderListener listener = listeners.get(i);
iDownloaderService.addActivity(MainActivity.this, listener);
listener.onDownloadStart(iDownloaderService.getDownloadInfo()); listener.onDownloadStart(iDownloaderService.getDownloadInfo());
} }
}catch(Exception e){ }catch(Exception e){
@ -164,6 +171,7 @@ public class MainActivity extends AppCompatActivity{
} }
public void startDownloadService(ArrayList<Video> downloadQueue, IDownloaderListener awaitingListener){ public void startDownloadService(ArrayList<Video> downloadQueue, IDownloaderListener awaitingListener){
addQueueToDownloads(downloadQueue);
if(isDownloadServiceRunning){ if(isDownloadServiceRunning){
iDownloaderService.updateQueue(downloadQueue); iDownloaderService.updateQueue(downloadQueue);
return; return;
@ -174,6 +182,21 @@ public class MainActivity extends AppCompatActivity{
context.getApplicationContext().bindService(serviceIntent, serviceConnection, Context.BIND_AUTO_CREATE); context.getApplicationContext().bindService(serviceIntent, serviceConnection, Context.BIND_AUTO_CREATE);
} }
public void addQueueToDownloads(ArrayList<Video> downloadQueue) {
try {
DBManager dbManager = new DBManager(context);
for (int i = downloadQueue.size() - 1; i >= 0; i--){
Video v = downloadQueue.get(i);
v.setQueuedDownload(true);
dbManager.addToHistory(v);
}
dbManager.close();
downloadsFragment.initCards();
} catch (Exception e) {
e.printStackTrace();
}
}
public void stopDownloadService(){ public void stopDownloadService(){
if(!isDownloadServiceRunning) return; if(!isDownloadServiceRunning) return;
iDownloaderService.removeActivity(this); iDownloaderService.removeActivity(this);
@ -230,8 +253,4 @@ public class MainActivity extends AppCompatActivity{
} }
} }
public void updateHistoryFragment(){
downloadsFragment.initCards();
}
} }

View file

@ -1,17 +1,20 @@
package com.deniscerri.ytdlnis.adapter; package com.deniscerri.ytdlnis.adapter;
import android.app.Activity;
import android.content.Context; import android.content.Context;
import android.graphics.Color; import android.graphics.Color;
import android.graphics.ColorMatrix; import android.graphics.ColorMatrix;
import android.graphics.ColorMatrixColorFilter; import android.graphics.ColorMatrixColorFilter;
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;
import android.widget.ImageView; import android.widget.ImageView;
import android.widget.LinearLayout; import android.widget.LinearLayout;
import android.widget.TextView; import android.widget.TextView;
import android.widget.Toast;
import androidx.annotation.NonNull; import androidx.annotation.NonNull;
import androidx.cardview.widget.CardView; import androidx.cardview.widget.CardView;
@ -21,6 +24,7 @@ import androidx.recyclerview.widget.RecyclerView;
import com.deniscerri.ytdlnis.R; import com.deniscerri.ytdlnis.R;
import com.deniscerri.ytdlnis.database.Video; import com.deniscerri.ytdlnis.database.Video;
import com.google.android.material.button.MaterialButton; import com.google.android.material.button.MaterialButton;
import com.google.android.material.progressindicator.LinearProgressIndicator;
import com.squareup.picasso.Picasso; import com.squareup.picasso.Picasso;
import java.io.File; import java.io.File;
@ -30,13 +34,13 @@ public class DownloadsRecyclerViewAdapter extends RecyclerView.Adapter<Downloads
private ArrayList<Video> videoList; private ArrayList<Video> videoList;
private ArrayList<String> websites; private ArrayList<String> websites;
private final OnItemClickListener onItemClickListener; private final OnItemClickListener onItemClickListener;
private Context context; private Activity activity;
public DownloadsRecyclerViewAdapter(ArrayList<Video> videos, OnItemClickListener onItemClickListener, Context context){ public DownloadsRecyclerViewAdapter(ArrayList<Video> videos, OnItemClickListener onItemClickListener, Activity activity){
this.videoList = videos; this.videoList = videos;
this.websites = new ArrayList<>(); this.websites = new ArrayList<>();
this.onItemClickListener = onItemClickListener; this.onItemClickListener = onItemClickListener;
this.context = context; this.activity = activity;
} }
@Override @Override
@ -91,30 +95,47 @@ public class DownloadsRecyclerViewAdapter extends RecyclerView.Adapter<Downloads
// TIME DOWNLOADED ---------------------------------- // TIME DOWNLOADED ----------------------------------
TextView datetime = card.findViewById(R.id.downloads_info_time); TextView datetime = card.findViewById(R.id.downloads_info_time);
String downloadedTime = video.getDownloadedTime(); String downloadedTime = video.getDownloadedTime();
if (downloadedTime == null) downloadedTime = activity.getString(R.string.currently_downloading) + " " + video.getDownloadedType();
datetime.setText(downloadedTime); datetime.setText(downloadedTime);
//IS IN THE FILE SYSTEM?
String path = video.getDownloadPath();
File file = new File(path);
boolean filePresent = true;
if(!file.exists() && !path.isEmpty()){
filePresent = false;
thumbnail.setColorFilter(new ColorMatrixColorFilter(new ColorMatrix(){{setSaturation(0f);}}));
thumbnail.setAlpha(0.7f);
}
// BUTTON ---------------------------------- // BUTTON ----------------------------------
LinearLayout buttonLayout = card.findViewById(R.id.downloads_download_button_layout); LinearLayout buttonLayout = card.findViewById(R.id.downloads_download_button_layout);
MaterialButton btn = buttonLayout.findViewById(R.id.downloads_download_button_type); MaterialButton btn = buttonLayout.findViewById(R.id.downloads_download_button_type);
if(video.getDownloadedType() != null){ // PROGRESS BAR ----------------------------------------------------
if(video.getDownloadedType().equals("audio")){ LinearProgressIndicator progressBar = card.findViewById(R.id.download_progress);
if (filePresent) btn.setIcon(ContextCompat.getDrawable(context, R.drawable.ic_music_downloaded)); progressBar.setTag(video.getURL()+video.getDownloadedType()+"##progress");
else btn.setIcon(ContextCompat.getDrawable(context, R.drawable.ic_music));
}else{ if (video.isQueuedDownload()){
if (filePresent) btn.setIcon(ContextCompat.getDrawable(context, R.drawable.ic_video_downloaded)); progressBar.setVisibility(View.VISIBLE);
else btn.setIcon(ContextCompat.getDrawable(context, R.drawable.ic_video)); btn.setOnClickListener(view -> onItemClickListener.onButtonClick(position));
btn.setIcon(ContextCompat.getDrawable(activity, R.drawable.ic_cancel));
}else {
progressBar.setVisibility(View.GONE);
progressBar.setIndeterminate(true);
//IS IN THE FILE SYSTEM?
String path = video.getDownloadPath();
File file = new File(path);
boolean filePresent = true;
if(!file.exists() && !path.isEmpty()){
filePresent = false;
thumbnail.setColorFilter(new ColorMatrixColorFilter(new ColorMatrix(){{setSaturation(0f);}}));
thumbnail.setAlpha(0.7f);
} }
if(video.getDownloadedType() != null){
if(video.getDownloadedType().equals("audio")){
if (filePresent) btn.setIcon(ContextCompat.getDrawable(activity, R.drawable.ic_music_downloaded));
else btn.setIcon(ContextCompat.getDrawable(activity, R.drawable.ic_music));
}else{
if (filePresent) btn.setIcon(ContextCompat.getDrawable(activity, R.drawable.ic_video_downloaded));
else btn.setIcon(ContextCompat.getDrawable(activity, R.drawable.ic_video));
}
}
if (btn.hasOnClickListeners()) btn.setOnClickListener(null);
} }
card.setOnClickListener(view -> onItemClickListener.onCardClick(position)); card.setOnClickListener(view -> onItemClickListener.onCardClick(position));
@ -127,6 +148,7 @@ public class DownloadsRecyclerViewAdapter extends RecyclerView.Adapter<Downloads
public interface OnItemClickListener { public interface OnItemClickListener {
void onCardClick(int position); void onCardClick(int position);
void onButtonClick(int position);
} }
public void setVideoList(ArrayList<Video> videoList){ public void setVideoList(ArrayList<Video> videoList){

View file

@ -18,7 +18,7 @@ import java.util.ArrayList;
public class DBManager extends SQLiteOpenHelper { public class DBManager extends SQLiteOpenHelper {
public static final String db_name = "ytdlnis_db"; public static final String db_name = "ytdlnis_db";
public static final int db_version = 10; public static final int db_version = 7;
public static final String results_table_name = "results"; public static final String results_table_name = "results";
public static final String history_table_name = "history"; public static final String history_table_name = "history";
public static final String id = "id"; public static final String id = "id";
@ -38,7 +38,7 @@ public class DBManager extends SQLiteOpenHelper {
public static final String downloadingAudio = "downloadingAudio"; public static final String downloadingAudio = "downloadingAudio";
public static final String downloadingVideo = "downloadingVideo"; public static final String downloadingVideo = "downloadingVideo";
public static final String playlistTitle = "playlistTitle"; public static final String playlistTitle = "playlistTitle";
public static final String isQueuedDownload = "isQueuedDownload";
public DBManager(Context context){ public DBManager(Context context){
super(context, db_name, null, db_version); super(context, db_name, null, db_version);
@ -74,7 +74,8 @@ public class DBManager extends SQLiteOpenHelper {
+ type + " TEXT," + type + " TEXT,"
+ time + " TEXT," + time + " TEXT,"
+ downloadPath + " TEXT," + downloadPath + " TEXT,"
+ website + " TEXT)"; + website + " TEXT,"
+ isQueuedDownload + " INTEGER)";
sqLiteDatabase.execSQL(query); sqLiteDatabase.execSQL(query);
} }
@ -198,7 +199,8 @@ public class DBManager extends SQLiteOpenHelper {
cursor.getString(cursor.getColumnIndex(type)), cursor.getString(cursor.getColumnIndex(type)),
cursor.getString(cursor.getColumnIndex(time)), cursor.getString(cursor.getColumnIndex(time)),
cursor.getString(cursor.getColumnIndex(downloadPath)), cursor.getString(cursor.getColumnIndex(downloadPath)),
cursor.getString(cursor.getColumnIndex(website)))); cursor.getString(cursor.getColumnIndex(website)),
cursor.getInt(cursor.getColumnIndex(isQueuedDownload))));
} while (cursor.moveToNext()); } while (cursor.moveToNext());
} }
@ -244,11 +246,32 @@ public class DBManager extends SQLiteOpenHelper {
values.put(time, v.getDownloadedTime()); values.put(time, v.getDownloadedTime());
values.put(downloadPath, v.getDownloadPath()); values.put(downloadPath, v.getDownloadPath());
values.put(website, v.getWebsite()); values.put(website, v.getWebsite());
values.put(isQueuedDownload, (v.isQueuedDownload()) ? 1 : 0);
db.insert(history_table_name, null, values); db.insert(history_table_name, null, values);
db.close(); db.close();
} }
public void updateHistoryItem(Video v){
SQLiteDatabase db = this.getWritableDatabase();
ContentValues values = new ContentValues();
values.put(url, v.getURL());
values.put(title, v.getTitle());
values.put(author, v.getAuthor());
values.put(duration, v.getDuration());
values.put(thumb, v.getThumb());
values.put(type, v.getDownloadedType());
values.put(time, v.getDownloadedTime());
values.put(downloadPath, v.getDownloadPath());
values.put(website, v.getWebsite());
values.put(isQueuedDownload, (v.isQueuedDownload()) ? 1 : 0);
String where = url + "='"+v.getURL()+"' AND "+isQueuedDownload+"=1 AND "+type+"='"+v.getDownloadedType()+"'";
db.update(history_table_name, values, where, null);
db.close();
}
public void updateDownloadStatusOnResult(String id, String type, boolean downloaded){ public void updateDownloadStatusOnResult(String id, String type, boolean downloaded){
SQLiteDatabase db = this.getReadableDatabase(); SQLiteDatabase db = this.getReadableDatabase();
ContentValues values = new ContentValues(); ContentValues values = new ContentValues();

View file

@ -20,6 +20,7 @@ public class Video implements Parcelable {
private String website; private String website;
private boolean downloadingAudio; private boolean downloadingAudio;
private boolean downloadingVideo; private boolean downloadingVideo;
private boolean queuedDownload;
private String playlistTitle; private String playlistTitle;
// RESULTS OBJECT // RESULTS OBJECT
@ -42,7 +43,7 @@ public class Video implements Parcelable {
//HISTORY OBJECT //HISTORY OBJECT
public Video(int id, String url, String title, String author, String duration, String thumb, public Video(int id, String url, String title, String author, String duration, String thumb,
String downloadedType, String downloadedTime, String downloadPath, String website) { String downloadedType, String downloadedTime, String downloadPath, String website, int queued) {
this.id = id; this.id = id;
this.url = url; this.url = url;
this.title = title; this.title = title;
@ -53,6 +54,7 @@ public class Video implements Parcelable {
this.downloadedTime = downloadedTime; this.downloadedTime = downloadedTime;
this.downloadPath = downloadPath; this.downloadPath = downloadPath;
this.website = website; this.website = website;
this.queuedDownload = (queued == 1);
} }
private boolean intToBoolean(int i){ private boolean intToBoolean(int i){
@ -237,6 +239,14 @@ public class Video implements Parcelable {
this.playlistTitle = playlistTitle; this.playlistTitle = playlistTitle;
} }
public boolean isQueuedDownload() {
return queuedDownload;
}
public void setQueuedDownload(boolean queuedDownload) {
this.queuedDownload = queuedDownload;
}
@Override @Override
public int describeContents() { public int describeContents() {
return 0; return 0;

View file

@ -25,6 +25,9 @@ import com.deniscerri.ytdlnis.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;
import java.lang.reflect.Array;
import java.util.ArrayList;
public class CustomCommandActivity extends AppCompatActivity { public class CustomCommandActivity extends AppCompatActivity {
private static final String TAG = "CustomCommandActivity"; private static final String TAG = "CustomCommandActivity";
private MaterialToolbar topAppBar; private MaterialToolbar topAppBar;
@ -45,7 +48,9 @@ public class CustomCommandActivity extends AppCompatActivity {
iDownloaderService = (IDownloaderService) service; iDownloaderService = (IDownloaderService) service;
isDownloadServiceRunning = true; isDownloadServiceRunning = true;
try{ try{
iDownloaderService.addActivity(CustomCommandActivity.this, listener); ArrayList<IDownloaderListener> listeners = new ArrayList<>();
listeners.add(listener);
iDownloaderService.addActivity(CustomCommandActivity.this, listeners);
listener.onDownloadStart(iDownloaderService.getDownloadInfo()); listener.onDownloadStart(iDownloaderService.getDownloadInfo());
}catch(Exception e){ }catch(Exception e){
e.printStackTrace(); e.printStackTrace();

View file

@ -5,15 +5,13 @@ import android.content.ClipData;
import android.content.ClipboardManager; import android.content.ClipboardManager;
import android.content.Context; import android.content.Context;
import android.content.Intent; import android.content.Intent;
import android.graphics.drawable.Drawable; import android.media.MediaScannerConnection;
import android.net.Uri; import android.net.Uri;
import android.os.Bundle; import android.os.Bundle;
import androidx.appcompat.widget.SearchView; import androidx.appcompat.widget.SearchView;
import androidx.core.content.ContextCompat; import androidx.core.content.ContextCompat;
import androidx.core.content.res.ResourcesCompat;
import androidx.fragment.app.Fragment; import androidx.fragment.app.Fragment;
import androidx.recyclerview.widget.RecyclerView; import androidx.recyclerview.widget.RecyclerView;
import android.os.Handler; import android.os.Handler;
import android.os.Looper; import android.os.Looper;
import android.text.InputType; import android.text.InputType;
@ -28,7 +26,7 @@ import android.widget.LinearLayout;
import android.widget.RelativeLayout; import android.widget.RelativeLayout;
import android.widget.TextView; import android.widget.TextView;
import android.widget.Toast; import android.widget.Toast;
import com.deniscerri.ytdlnis.MainActivity;
import com.deniscerri.ytdlnis.R; import com.deniscerri.ytdlnis.R;
import com.deniscerri.ytdlnis.adapter.DownloadsRecyclerViewAdapter; import com.deniscerri.ytdlnis.adapter.DownloadsRecyclerViewAdapter;
import com.deniscerri.ytdlnis.database.DBManager; import com.deniscerri.ytdlnis.database.DBManager;
@ -42,8 +40,16 @@ import com.google.android.material.bottomsheet.BottomSheetDialog;
import com.google.android.material.chip.Chip; import com.google.android.material.chip.Chip;
import com.google.android.material.chip.ChipGroup; import com.google.android.material.chip.ChipGroup;
import com.google.android.material.dialog.MaterialAlertDialogBuilder; import com.google.android.material.dialog.MaterialAlertDialogBuilder;
import com.google.android.material.progressindicator.LinearProgressIndicator;
import java.io.File;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.LinkedList;
import java.util.Locale;
/** /**
* A fragment representing a list of Items. * A fragment representing a list of Items.
@ -54,6 +60,7 @@ public class DownloadsFragment extends Fragment implements DownloadsRecyclerView
private DBManager dbManager; private DBManager dbManager;
Context context; Context context;
Activity activity; Activity activity;
MainActivity mainActivity;
Context fragmentContext; Context fragmentContext;
private LayoutInflater layoutinflater; private LayoutInflater layoutinflater;
private ShimmerFrameLayout shimmerCards; private ShimmerFrameLayout shimmerCards;
@ -67,6 +74,7 @@ public class DownloadsFragment extends Fragment implements DownloadsRecyclerView
private LinearLayout selectionChips; private LinearLayout selectionChips;
private ChipGroup websiteGroup; private ChipGroup websiteGroup;
private ArrayList<Video> downloadsObjects; private ArrayList<Video> downloadsObjects;
private LinearProgressIndicator progressBar;
private String format = ""; private String format = "";
private String website = ""; private String website = "";
private String sort = "DESC"; private String sort = "DESC";
@ -79,27 +87,90 @@ public class DownloadsFragment extends Fragment implements DownloadsRecyclerView
public void onDownloadStart(DownloadInfo downloadInfo) { public void onDownloadStart(DownloadInfo downloadInfo) {
try{ try{
if(downloadInfo != null){
Video v = downloadInfo.getVideo();
progressBar = fragmentView.findViewWithTag(v.getURL()+v.getDownloadedType()+"##progress");
}
}catch(Exception ignored){} }catch(Exception ignored){}
} }
public void onDownloadProgress(DownloadInfo info) { public void onDownloadProgress(DownloadInfo info) {
activity.runOnUiThread(() -> { activity.runOnUiThread(() -> {
try{ try{
int progress = info.getProgress();
}catch(Exception ignored){} Video v = info.getVideo();
if (progress > 0) {
progressBar = fragmentView.findViewWithTag(v.getURL()+v.getDownloadedType()+"##progress");
progressBar.setProgressCompat(progress, true);
}
}catch(Exception ignored){
}
}); });
} }
public void onDownloadError(DownloadInfo info){ public void onDownloadError(DownloadInfo info){
try{ try{
int position = downloadsObjects.indexOf(info.getVideo());
Video v = downloadsObjects.get(position);
dbManager = new DBManager(context);
dbManager.clearHistoryItem(v);
downloadsRecyclerViewAdapter.notifyItemRemoved(position);
}catch(Exception ignored){} }catch(Exception ignored){}
} }
public void onDownloadEnd(DownloadInfo downloadInfo) { public void onDownloadEnd(DownloadInfo downloadInfo) {
Video item = downloadInfo.getVideo();
String url = item.getURL();
String type = downloadInfo.getDownloadType();
item = findVideo(url, type);
try{ try{
// MEDIA SCAN
ArrayList<File> files = new ArrayList<>();
String title = downloadInfo.getVideo().getTitle().replaceAll("[^a-zA-Z0-9]","");
String pathTmp = "";
File path = new File(downloadInfo.getDownloadPath());
for( File file : path.listFiles() ){
if(file.isFile()){
pathTmp = file.getAbsolutePath().replaceAll("[^a-zA-Z0-9]","");
if (pathTmp.contains(title)){
files.add(file);
}
}
}
String[] paths = new String[files.size()];
for (int i = 0; i < files.size(); i++) paths[i] = files.get(i).getAbsolutePath();
MediaScannerConnection.scanFile(context, paths, null, null);
item.setDownloadedType(type);
Calendar cal = Calendar.getInstance();
Date date = new Date();
cal.setTime(date);
int day = cal.get(Calendar.DAY_OF_MONTH);
String month = cal.getDisplayName(Calendar.MONTH, Calendar.LONG, Locale.getDefault());
int year = cal.get(Calendar.YEAR);
DateFormat formatter = new SimpleDateFormat("HH:mm", Locale.getDefault());
String time = formatter.format(date);
String downloadedTime = day + " " + month + " " + year + " " + time;
String downloadPath = "";
try{
downloadPath = paths[0];
}catch(Exception e){
e.printStackTrace();
}
dbManager = new DBManager(context);
try {
item.setDownloadedTime(downloadedTime);
item.setDownloadPath(downloadPath);
item.setQueuedDownload(false);
dbManager.updateHistoryItem(item);
dbManager.close();
downloadsRecyclerViewAdapter.notifyItemChanged(downloadsObjects.indexOf(item));
} catch (Exception ignored) {
}
}catch(Exception ignored){} }catch(Exception ignored){}
} }
@ -136,6 +207,7 @@ public class DownloadsFragment extends Fragment implements DownloadsRecyclerView
fragmentView = inflater.inflate(R.layout.fragment_downloads, container, false); fragmentView = inflater.inflate(R.layout.fragment_downloads, container, false);
context = fragmentView.getContext().getApplicationContext(); context = fragmentView.getContext().getApplicationContext();
activity = getActivity(); activity = getActivity();
mainActivity = (MainActivity) activity;
fragmentContext = fragmentView.getContext(); fragmentContext = fragmentView.getContext();
layoutinflater = LayoutInflater.from(context); layoutinflater = LayoutInflater.from(context);
shimmerCards = fragmentView.findViewById(R.id.shimmer_downloads_framelayout); shimmerCards = fragmentView.findViewById(R.id.shimmer_downloads_framelayout);
@ -149,8 +221,7 @@ public class DownloadsFragment extends Fragment implements DownloadsRecyclerView
downloadsObjects = new ArrayList<>(); downloadsObjects = new ArrayList<>();
recyclerView = fragmentView.findViewById(R.id.recycler_view_downloads); recyclerView = fragmentView.findViewById(R.id.recycler_view_downloads);
downloadsRecyclerViewAdapter = new DownloadsRecyclerViewAdapter(downloadsObjects, this, activity);
downloadsRecyclerViewAdapter = new DownloadsRecyclerViewAdapter(downloadsObjects, this, context);
recyclerView.setAdapter(downloadsRecyclerViewAdapter); recyclerView.setAdapter(downloadsRecyclerViewAdapter);
recyclerView.setNestedScrollingEnabled(false); recyclerView.setNestedScrollingEnabled(false);
@ -160,7 +231,6 @@ public class DownloadsFragment extends Fragment implements DownloadsRecyclerView
return fragmentView; return fragmentView;
} }
public void initCards(){ public void initCards(){
shimmerCards.startShimmer(); shimmerCards.startShimmer();
shimmerCards.setVisibility(View.VISIBLE); shimmerCards.setVisibility(View.VISIBLE);
@ -210,6 +280,8 @@ public class DownloadsFragment extends Fragment implements DownloadsRecyclerView
} }
}; };
MaterialToolbar toolbar = fragmentView.findViewById(R.id.downloads_toolbar);
topAppBar.getMenu().findItem(R.id.search_downloads).setOnActionExpandListener(onActionExpandListener); topAppBar.getMenu().findItem(R.id.search_downloads).setOnActionExpandListener(onActionExpandListener);
SearchView searchView = (SearchView) topAppBar.getMenu().findItem(R.id.search_downloads).getActionView(); SearchView searchView = (SearchView) topAppBar.getMenu().findItem(R.id.search_downloads).getActionView();
searchView.setInputType(InputType.TYPE_CLASS_TEXT); searchView.setInputType(InputType.TYPE_CLASS_TEXT);
@ -318,7 +390,7 @@ public class DownloadsFragment extends Fragment implements DownloadsRecyclerView
} }
private void initChips(){ private void initChips(){
//sort //sort and history/downloading switch
Chip sortChip = fragmentView.findViewById(R.id.sort_chip); Chip sortChip = fragmentView.findViewById(R.id.sort_chip);
sortChip.setOnClickListener(view -> { sortChip.setOnClickListener(view -> {
sortSheet = new BottomSheetDialog(fragmentContext); sortSheet = new BottomSheetDialog(fragmentContext);
@ -358,6 +430,9 @@ public class DownloadsFragment extends Fragment implements DownloadsRecyclerView
audio.setOnClickListener(view -> { audio.setOnClickListener(view -> {
if (audio.isChecked()) { if (audio.isChecked()) {
format = "audio"; format = "audio";
if (recyclerView.getVisibility() == View.GONE){
}
downloadsObjects = dbManager.getHistory(searchQuery,format,website,sort); downloadsObjects = dbManager.getHistory(searchQuery,format,website,sort);
audio.setChecked(true); audio.setChecked(true);
}else { }else {
@ -388,6 +463,8 @@ public class DownloadsFragment extends Fragment implements DownloadsRecyclerView
} }
private void updateWebsiteChips(){ private void updateWebsiteChips(){
websiteGroup.removeAllViews(); websiteGroup.removeAllViews();
@ -503,5 +580,27 @@ public class DownloadsFragment extends Fragment implements DownloadsRecyclerView
bottomSheet.getWindow().setLayout(ViewGroup.LayoutParams.MATCH_PARENT,ViewGroup.LayoutParams.MATCH_PARENT); bottomSheet.getWindow().setLayout(ViewGroup.LayoutParams.MATCH_PARENT,ViewGroup.LayoutParams.MATCH_PARENT);
} }
@Override
public void onButtonClick(int position) {
try {
Video vid = downloadsObjects.get(position);
downloadsObjects.remove(position);
dbManager = new DBManager(context);
dbManager.clearHistoryItem(vid);
downloadsRecyclerViewAdapter.setVideoList(downloadsObjects);
mainActivity.removeItemFromDownloadQueue(vid);
}catch (Exception ignored){}
}
public Video findVideo(String url, String type) {
for (int i = 0; i < downloadsObjects.size(); i++) {
Video v = downloadsObjects.get(i);
if ((v.getURL()).equals(url) && v.getDownloadedType().equals(type) && v.isQueuedDownload()) {
return v;
}
}
return null;
}
} }

View file

@ -143,32 +143,7 @@ public class HomeFragment extends Fragment implements HomeRecyclerViewAdapter.On
if (type.equals("audio")) item.setDownloadedAudio(1); if (type.equals("audio")) item.setDownloadedAudio(1);
else item.setDownloadedVideo(1); else item.setDownloadedVideo(1);
homeRecyclerViewAdapter.notifyItemChanged(resultObjects.indexOf(findVideo(id))); homeRecyclerViewAdapter.notifyItemChanged(resultObjects.indexOf(findVideo(id)));
// MEDIA SCAN
ArrayList<File> files = new ArrayList<>();
String title = downloadInfo.getVideo().getTitle().replaceAll("[^a-zA-Z0-9]","");
String pathTmp = "";
File path = new File(downloadInfo.getDownloadPath());
for( File file : path.listFiles() ){
if(file.isFile()){
pathTmp = file.getAbsolutePath().replaceAll("[^a-zA-Z0-9]","");
if (pathTmp.contains(title)){
files.add(file);
}
}
}
String[] paths = new String[files.size()];
for (int i = 0; i < files.size(); i++) paths[i] = files.get(i).getAbsolutePath();
MediaScannerConnection.scanFile(context, paths, null, null);
String typeTmp = item.getDownloadedType();
item.setDownloadedType(type);
addToHistory(item, new Date(), paths);
item.setDownloadedType(typeTmp);
updateDownloadStatusOnResult(item, type, true); updateDownloadStatusOnResult(item, type, true);
mainActivity.updateHistoryFragment();
downloading = false; downloading = false;
topAppBar.getMenu().findItem(R.id.cancel_download).setVisible(false); topAppBar.getMenu().findItem(R.id.cancel_download).setVisible(false);
}catch(Exception ignored){} }catch(Exception ignored){}

View file

@ -6,7 +6,7 @@ import java.util.ArrayList;
public interface IDownloaderService { public interface IDownloaderService {
DownloadInfo getDownloadInfo(); DownloadInfo getDownloadInfo();
void addActivity(Activity activity, IDownloaderListener callback); void addActivity(Activity activity, ArrayList<IDownloaderListener> callback);
void removeActivity(Activity activity); void removeActivity(Activity activity);
void updateQueue(ArrayList<Video> queue); void updateQueue(ArrayList<Video> queue);
void cancelDownload(boolean cancelAll); void cancelDownload(boolean cancelAll);

View file

@ -34,15 +34,10 @@ public class InfoUtil {
private DBManager dbManager; private DBManager dbManager;
public InfoUtil(Context context) { public InfoUtil(Context context) {
@Nullable ApplicationInfo applicationInfo;
try{ try{
SharedPreferences sharedPreferences = context.getSharedPreferences("root_preferences", Activity.MODE_PRIVATE); SharedPreferences sharedPreferences = context.getSharedPreferences("root_preferences", Activity.MODE_PRIVATE);
key = sharedPreferences.getString("api_key", ""); key = sharedPreferences.getString("api_key", "");
applicationInfo = context.getPackageManager().getApplicationInfo(context.getPackageName(), PackageManager.GET_META_DATA);
if (key.isEmpty()) key = applicationInfo.metaData.getString("ytAPIkey");
Log.e(TAG, key);
dbManager = new DBManager(context); dbManager = new DBManager(context);
Thread thread = new Thread(() -> { Thread thread = new Thread(() -> {
//get Locale //get Locale
JSONObject country = genericRequest("https://ipwho.is/"); JSONObject country = genericRequest("https://ipwho.is/");

View file

@ -0,0 +1,5 @@
<vector android:height="24dp" android:tint="#FFFFFF"
android:viewportHeight="24" android:viewportWidth="24"
android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
<path android:fillColor="@android:color/white" android:pathData="M13,3c-4.97,0 -9,4.03 -9,9L1,12l3.89,3.89 0.07,0.14L9,12L6,12c0,-3.87 3.13,-7 7,-7s7,3.13 7,7 -3.13,7 -7,7c-1.93,0 -3.68,-0.79 -4.94,-2.06l-1.42,1.42C8.27,19.99 10.51,21 13,21c4.97,0 9,-4.03 9,-9s-4.03,-9 -9,-9zM12,8v5l4.28,2.54 0.72,-1.21 -3.5,-2.08L13.5,8L12,8z"/>
</vector>

View file

@ -32,6 +32,16 @@
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="match_parent" /> android:layout_height="match_parent" />
<com.google.android.material.progressindicator.LinearProgressIndicator
android:id="@+id/download_progress"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_gravity="bottom"
android:indeterminate="true"
android:visibility="gone"
android:alpha="0.7"
android:scaleY="100" />
<TextView <TextView
android:id="@+id/downloads_title" android:id="@+id/downloads_title"
android:layout_width="300dp" android:layout_width="300dp"
@ -93,12 +103,12 @@
android:paddingRight="20dp"> android:paddingRight="20dp">
<com.google.android.material.button.MaterialButton <com.google.android.material.button.MaterialButton
style="@style/Widget.MaterialComponents.ExtendedFloatingActionButton.Icon" style="@style/Widget.Material3.ExtendedFloatingActionButton.Icon.Secondary"
android:id="@+id/downloads_download_button_type" android:id="@+id/downloads_download_button_type"
android:layout_width="48dp" android:layout_width="55dp"
android:layout_height="48dp" android:layout_height="55dp"
app:cornerRadius="10dp" app:cornerRadius="10dp"
android:layout_marginLeft="10dp" android:layout_marginStart="10dp"
/> />

View file

@ -25,7 +25,7 @@
</com.google.android.material.appbar.AppBarLayout> </com.google.android.material.appbar.AppBarLayout>
<LinearLayout <RelativeLayout
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="match_parent" android:layout_height="match_parent"
android:orientation="vertical" android:orientation="vertical"
@ -33,6 +33,7 @@
app:layout_behavior="com.google.android.material.appbar.AppBarLayout$ScrollingViewBehavior"> app:layout_behavior="com.google.android.material.appbar.AppBarLayout$ScrollingViewBehavior">
<HorizontalScrollView <HorizontalScrollView
android:id="@+id/chips_recycler_horizontalscrollview"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:scrollbars="none" android:scrollbars="none"
android:layout_height="wrap_content"> android:layout_height="wrap_content">
@ -44,7 +45,9 @@
<com.google.android.material.chip.ChipGroup <com.google.android.material.chip.ChipGroup
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content"> android:layout_height="wrap_content"
app:selectionRequired="false"
app:singleSelection="false">
<com.google.android.material.chip.Chip <com.google.android.material.chip.Chip
android:id="@+id/sort_chip" android:id="@+id/sort_chip"
@ -101,6 +104,7 @@
android:id="@+id/recycler_view_downloads" android:id="@+id/recycler_view_downloads"
android:orientation="vertical" android:orientation="vertical"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_below="@+id/chips_recycler_horizontalscrollview"
android:scrollbars="vertical" android:scrollbars="vertical"
android:nestedScrollingEnabled="false" android:nestedScrollingEnabled="false"
android:clipToPadding="false" android:clipToPadding="false"
@ -110,54 +114,72 @@
</androidx.recyclerview.widget.RecyclerView> </androidx.recyclerview.widget.RecyclerView>
</LinearLayout> <androidx.recyclerview.widget.RecyclerView
android:layout_width="match_parent"
android:id="@+id/recycler_view_progress_downloads"
android:orientation="vertical"
android:layout_height="wrap_content"
android:layout_below="@+id/chips_recycler_horizontalscrollview"
android:scrollbars="vertical"
android:nestedScrollingEnabled="false"
android:clipToPadding="false"
android:paddingBottom="150dp"
android:visibility="gone"
app:layoutManager="androidx.recyclerview.widget.LinearLayoutManager"
>
</androidx.recyclerview.widget.RecyclerView>
<com.facebook.shimmer.ShimmerFrameLayout
android:layout_width="match_parent"
android:visibility="gone"
android:layout_height="match_parent"
android:layout_below="@+id/chips_recycler_horizontalscrollview"
android:id="@+id/shimmer_downloads_framelayout"
android:orientation="vertical">
<LinearLayout
android:id="@+id/shimmer_downloads_linear_layout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_margin="10dp"
android:orientation="vertical">
<include layout="@layout/downloads_card_shimmer" />
<include layout="@layout/downloads_card_shimmer" />
<include layout="@layout/downloads_card_shimmer" />
<include layout="@layout/downloads_card_shimmer" />
<include layout="@layout/downloads_card_shimmer" />
<include layout="@layout/downloads_card_shimmer" />
<include layout="@layout/downloads_card_shimmer" />
<include layout="@layout/downloads_card_shimmer" />
<include layout="@layout/downloads_card_shimmer" />
<include layout="@layout/downloads_card_shimmer" />
</LinearLayout>
</com.facebook.shimmer.ShimmerFrameLayout>
</RelativeLayout>
<include layout="@layout/downloads_no_results" <include layout="@layout/downloads_no_results"
android:visibility="gone" /> android:visibility="gone" />
<com.facebook.shimmer.ShimmerFrameLayout
android:layout_width="match_parent"
android:visibility="gone"
android:layout_height="match_parent"
android:layout_marginTop="?attr/actionBarSize"
android:id="@+id/shimmer_downloads_framelayout"
android:orientation="vertical">
<LinearLayout
android:id="@+id/shimmer_downloads_linear_layout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_margin="10dp"
android:orientation="vertical">
<include layout="@layout/downloads_card_shimmer" />
<include layout="@layout/downloads_card_shimmer" />
<include layout="@layout/downloads_card_shimmer" />
<include layout="@layout/downloads_card_shimmer" />
<include layout="@layout/downloads_card_shimmer" />
<include layout="@layout/downloads_card_shimmer" />
<include layout="@layout/downloads_card_shimmer" />
<include layout="@layout/downloads_card_shimmer" />
<include layout="@layout/downloads_card_shimmer" />
<include layout="@layout/downloads_card_shimmer" />
</LinearLayout>
</com.facebook.shimmer.ShimmerFrameLayout>
<include layout="@layout/downloads_bottom_sheet" <include layout="@layout/downloads_bottom_sheet"
android:visibility="gone" /> android:visibility="gone" />

View file

@ -42,6 +42,7 @@
android:layout_height="match_parent" android:layout_height="match_parent"
android:layout_gravity="bottom" android:layout_gravity="bottom"
android:indeterminate="true" android:indeterminate="true"
android:visibility="gone"
android:alpha="0.7" android:alpha="0.7"
android:scaleY="100" /> android:scaleY="100" />

View file

@ -105,4 +105,5 @@
<string name="sort_by">Rendit</string> <string name="sort_by">Rendit</string>
<string name="newest_first">Të rejat në fillim</string> <string name="newest_first">Të rejat në fillim</string>
<string name="oldest_first">Të vjetrat në fillim</string> <string name="oldest_first">Të vjetrat në fillim</string>
<string name="currently_downloading">Duke Shkarkuar</string>
</resources> </resources>

View file

@ -110,4 +110,5 @@
<string name="oldest_first">Oldest First</string> <string name="oldest_first">Oldest First</string>
<item type="id" name="cancelDownload" /> <item type="id" name="cancelDownload" />
<string name="trendingPlaylist" translatable="false">ytdlnis-TRENDING</string> <string name="trendingPlaylist" translatable="false">ytdlnis-TRENDING</string>
<string name="currently_downloading">Downloading</string>
</resources> </resources>

View file

@ -35,4 +35,13 @@
<item name="android:layout_marginStart">5dp</item> <item name="android:layout_marginStart">5dp</item>
</style> </style>
<style name="Divider.Vertical.NoLine" parent="Divider">
<item name="android:layout_width">0dp</item>
<item name="android:layout_height">match_parent</item>
<item name="android:layout_marginTop">10dp</item>
<item name="android:layout_marginBottom">10dp</item>
<item name="android:layout_marginEnd">5dp</item>
<item name="android:layout_marginStart">5dp</item>
</style>
</resources> </resources>