fixed some things in download card
This commit is contained in:
parent
2371ab734d
commit
19eab5e054
22 changed files with 842 additions and 715 deletions
|
|
@ -167,7 +167,7 @@
|
||||||
</value>
|
</value>
|
||||||
</option>
|
</option>
|
||||||
</component>
|
</component>
|
||||||
<component name="ProjectRootManager" version="2" languageLevel="JDK_11" project-jdk-name="1.8" project-jdk-type="JavaSDK">
|
<component name="ProjectRootManager" version="2" languageLevel="JDK_11" project-jdk-name="11" project-jdk-type="JavaSDK">
|
||||||
<output url="file://$PROJECT_DIR$/build/classes" />
|
<output url="file://$PROJECT_DIR$/build/classes" />
|
||||||
</component>
|
</component>
|
||||||
<component name="ProjectType">
|
<component name="ProjectType">
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,7 @@
|
||||||
"formatVersion": 1,
|
"formatVersion": 1,
|
||||||
"database": {
|
"database": {
|
||||||
"version": 1,
|
"version": 1,
|
||||||
"identityHash": "5939be553c41327f4f64e1d62d008968",
|
"identityHash": "c8effa77edcd8cf5e46a79fd1a791535",
|
||||||
"entities": [
|
"entities": [
|
||||||
{
|
{
|
||||||
"tableName": "results",
|
"tableName": "results",
|
||||||
|
|
@ -198,7 +198,7 @@
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"tableName": "downloads",
|
"tableName": "downloads",
|
||||||
"createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`url` TEXT NOT NULL, `title` TEXT NOT NULL, `author` TEXT NOT NULL, `thumb` TEXT NOT NULL, `duration` TEXT NOT NULL, `type` TEXT NOT NULL, `audioQualityId` TEXT NOT NULL, `videoQualityId` TEXT NOT NULL, `customTemplateId` INTEGER NOT NULL, `audioFormat` TEXT NOT NULL, `videoFormat` TEXT NOT NULL, `formatDesc` TEXT NOT NULL, `removeAudio` INTEGER NOT NULL DEFAULT 0, `downloadPath` TEXT NOT NULL, `website` TEXT NOT NULL, `downloadSize` TEXT NOT NULL, `playlistTitle` TEXT NOT NULL, `embedSubs` INTEGER NOT NULL, `addChapters` INTEGER NOT NULL, `SaveThumb` INTEGER NOT NULL, `status` TEXT NOT NULL DEFAULT 'Queued', `workID` INTEGER NOT NULL, `id` INTEGER PRIMARY KEY AUTOINCREMENT)",
|
"createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`url` TEXT NOT NULL, `title` TEXT NOT NULL, `author` TEXT NOT NULL, `thumb` TEXT NOT NULL, `duration` TEXT NOT NULL, `type` TEXT NOT NULL, `audioFormat` TEXT NOT NULL, `videoFormat` TEXT NOT NULL, `audioFormatId` TEXT NOT NULL, `videoFormatId` TEXT NOT NULL, `customTemplateId` INTEGER NOT NULL, `formatDesc` TEXT NOT NULL, `removeAudio` INTEGER NOT NULL DEFAULT 0, `downloadPath` TEXT NOT NULL, `website` TEXT NOT NULL, `downloadSize` TEXT NOT NULL, `playlistTitle` TEXT NOT NULL, `embedSubs` INTEGER NOT NULL, `addChapters` INTEGER NOT NULL, `SaveThumb` INTEGER NOT NULL, `ext` TEXT NOT NULL, `filesize` TEXT NOT NULL, `status` TEXT NOT NULL DEFAULT 'Queued', `workID` INTEGER NOT NULL, `id` INTEGER PRIMARY KEY AUTOINCREMENT)",
|
||||||
"fields": [
|
"fields": [
|
||||||
{
|
{
|
||||||
"fieldPath": "url",
|
"fieldPath": "url",
|
||||||
|
|
@ -236,24 +236,6 @@
|
||||||
"affinity": "TEXT",
|
"affinity": "TEXT",
|
||||||
"notNull": true
|
"notNull": true
|
||||||
},
|
},
|
||||||
{
|
|
||||||
"fieldPath": "audioQualityId",
|
|
||||||
"columnName": "audioQualityId",
|
|
||||||
"affinity": "TEXT",
|
|
||||||
"notNull": true
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"fieldPath": "videoQualityId",
|
|
||||||
"columnName": "videoQualityId",
|
|
||||||
"affinity": "TEXT",
|
|
||||||
"notNull": true
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"fieldPath": "customTemplateId",
|
|
||||||
"columnName": "customTemplateId",
|
|
||||||
"affinity": "INTEGER",
|
|
||||||
"notNull": true
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"fieldPath": "audioFormat",
|
"fieldPath": "audioFormat",
|
||||||
"columnName": "audioFormat",
|
"columnName": "audioFormat",
|
||||||
|
|
@ -266,6 +248,24 @@
|
||||||
"affinity": "TEXT",
|
"affinity": "TEXT",
|
||||||
"notNull": true
|
"notNull": true
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"fieldPath": "audioFormatId",
|
||||||
|
"columnName": "audioFormatId",
|
||||||
|
"affinity": "TEXT",
|
||||||
|
"notNull": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldPath": "videoFormatId",
|
||||||
|
"columnName": "videoFormatId",
|
||||||
|
"affinity": "TEXT",
|
||||||
|
"notNull": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldPath": "customTemplateId",
|
||||||
|
"columnName": "customTemplateId",
|
||||||
|
"affinity": "INTEGER",
|
||||||
|
"notNull": true
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"fieldPath": "formatDesc",
|
"fieldPath": "formatDesc",
|
||||||
"columnName": "formatDesc",
|
"columnName": "formatDesc",
|
||||||
|
|
@ -321,6 +321,18 @@
|
||||||
"affinity": "INTEGER",
|
"affinity": "INTEGER",
|
||||||
"notNull": true
|
"notNull": true
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"fieldPath": "ext",
|
||||||
|
"columnName": "ext",
|
||||||
|
"affinity": "TEXT",
|
||||||
|
"notNull": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldPath": "filesize",
|
||||||
|
"columnName": "filesize",
|
||||||
|
"affinity": "TEXT",
|
||||||
|
"notNull": true
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"fieldPath": "status",
|
"fieldPath": "status",
|
||||||
"columnName": "status",
|
"columnName": "status",
|
||||||
|
|
@ -386,7 +398,7 @@
|
||||||
"views": [],
|
"views": [],
|
||||||
"setupQueries": [
|
"setupQueries": [
|
||||||
"CREATE TABLE IF NOT EXISTS room_master_table (id INTEGER PRIMARY KEY,identity_hash TEXT)",
|
"CREATE TABLE IF NOT EXISTS room_master_table (id INTEGER PRIMARY KEY,identity_hash TEXT)",
|
||||||
"INSERT OR REPLACE INTO room_master_table (id,identity_hash) VALUES(42, '5939be553c41327f4f64e1d62d008968')"
|
"INSERT OR REPLACE INTO room_master_table (id,identity_hash) VALUES(42, 'c8effa77edcd8cf5e46a79fd1a791535')"
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -1,5 +1,6 @@
|
||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
|
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
xmlns:tools="http://schemas.android.com/tools">
|
||||||
|
|
||||||
<uses-permission android:name="android.permission.INTERNET" />
|
<uses-permission android:name="android.permission.INTERNET" />
|
||||||
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
|
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
|
||||||
|
|
@ -77,6 +78,17 @@
|
||||||
android:name="android.support.FILE_PROVIDER_PATHS"
|
android:name="android.support.FILE_PROVIDER_PATHS"
|
||||||
android:resource="@xml/provider_paths" />
|
android:resource="@xml/provider_paths" />
|
||||||
</provider>
|
</provider>
|
||||||
|
<provider
|
||||||
|
android:name="androidx.startup.InitializationProvider"
|
||||||
|
android:authorities="${applicationId}.androidx-startup"
|
||||||
|
android:exported="false"
|
||||||
|
tools:node="merge">
|
||||||
|
<!-- If you are using androidx.startup to initialize other components -->
|
||||||
|
<meta-data
|
||||||
|
android:name="androidx.work.WorkManagerInitializer"
|
||||||
|
android:value="androidx.startup"
|
||||||
|
tools:node="remove" />
|
||||||
|
</provider>
|
||||||
</application>
|
</application>
|
||||||
|
|
||||||
</manifest>
|
</manifest>
|
||||||
|
|
@ -17,6 +17,7 @@ import androidx.core.app.ActivityCompat
|
||||||
import androidx.core.view.WindowInsetsCompat
|
import androidx.core.view.WindowInsetsCompat
|
||||||
import androidx.fragment.app.Fragment
|
import androidx.fragment.app.Fragment
|
||||||
import androidx.fragment.app.FragmentManager
|
import androidx.fragment.app.FragmentManager
|
||||||
|
import androidx.work.WorkManager
|
||||||
import com.deniscerri.ytdlnis.DownloaderService.LocalBinder
|
import com.deniscerri.ytdlnis.DownloaderService.LocalBinder
|
||||||
import com.deniscerri.ytdlnis.database.models.ResultItem
|
import com.deniscerri.ytdlnis.database.models.ResultItem
|
||||||
import com.deniscerri.ytdlnis.databinding.ActivityMainBinding
|
import com.deniscerri.ytdlnis.databinding.ActivityMainBinding
|
||||||
|
|
@ -38,17 +39,14 @@ import java.util.*
|
||||||
import kotlin.system.exitProcess
|
import kotlin.system.exitProcess
|
||||||
|
|
||||||
class MainActivity : AppCompatActivity() {
|
class MainActivity : AppCompatActivity() {
|
||||||
|
|
||||||
private lateinit var binding: ActivityMainBinding
|
private lateinit var binding: ActivityMainBinding
|
||||||
lateinit var context: Context
|
lateinit var context: Context
|
||||||
private lateinit var homeFragment: HomeFragment
|
private lateinit var homeFragment: HomeFragment
|
||||||
private lateinit var downloadsFragment: DownloadsFragment
|
private lateinit var downloadsFragment: DownloadsFragment
|
||||||
private lateinit var moreFragment: MoreFragment
|
|
||||||
private lateinit var lastFragment: Fragment
|
|
||||||
private lateinit var fm: FragmentManager
|
|
||||||
private var isDownloadServiceRunning = false
|
|
||||||
var downloaderService: DownloaderService? = null
|
var downloaderService: DownloaderService? = null
|
||||||
private lateinit var listeners: ArrayList<IDownloaderListener>
|
private lateinit var workManager: WorkManager
|
||||||
private var iDownloaderService: IDownloaderService? = null
|
|
||||||
|
|
||||||
private val serviceConnection: ServiceConnection = object : ServiceConnection {
|
private val serviceConnection: ServiceConnection = object : ServiceConnection {
|
||||||
override fun onServiceConnected(className: ComponentName, service: IBinder) {
|
override fun onServiceConnected(className: ComponentName, service: IBinder) {
|
||||||
|
|
@ -83,6 +81,8 @@ class MainActivity : AppCompatActivity() {
|
||||||
reconnectDownloadService()
|
reconnectDownloadService()
|
||||||
checkUpdate()
|
checkUpdate()
|
||||||
fm = supportFragmentManager
|
fm = supportFragmentManager
|
||||||
|
workManager = WorkManager.getInstance(context)
|
||||||
|
|
||||||
homeFragment = HomeFragment()
|
homeFragment = HomeFragment()
|
||||||
downloadsFragment = DownloadsFragment()
|
downloadsFragment = DownloadsFragment()
|
||||||
moreFragment = MoreFragment()
|
moreFragment = MoreFragment()
|
||||||
|
|
@ -256,6 +256,10 @@ class MainActivity : AppCompatActivity() {
|
||||||
stopDownloadService()
|
stopDownloadService()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun cancelAllDownloads() {
|
||||||
|
workManager.cancelAllWork();
|
||||||
|
}
|
||||||
|
|
||||||
fun removeItemFromDownloadQueue(video: ResultItem?, type: String?) {
|
fun removeItemFromDownloadQueue(video: ResultItem?, type: String?) {
|
||||||
iDownloaderService!!.removeItemFromDownloadQueue(video, type)
|
iDownloaderService!!.removeItemFromDownloadQueue(video, type)
|
||||||
}
|
}
|
||||||
|
|
@ -368,5 +372,11 @@ class MainActivity : AppCompatActivity() {
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
private const val TAG = "MainActivity"
|
private const val TAG = "MainActivity"
|
||||||
|
private lateinit var moreFragment: MoreFragment
|
||||||
|
private lateinit var lastFragment: Fragment
|
||||||
|
private lateinit var fm: FragmentManager
|
||||||
|
private var isDownloadServiceRunning = false
|
||||||
|
private lateinit var listeners: ArrayList<IDownloaderListener>
|
||||||
|
private var iDownloaderService: IDownloaderService? = null
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -1,214 +0,0 @@
|
||||||
package com.deniscerri.ytdlnis.adapter;
|
|
||||||
|
|
||||||
import android.app.Activity;
|
|
||||||
import android.graphics.Color;
|
|
||||||
import android.graphics.ColorMatrix;
|
|
||||||
import android.graphics.ColorMatrixColorFilter;
|
|
||||||
import android.os.Handler;
|
|
||||||
import android.os.Looper;
|
|
||||||
import android.util.Log;
|
|
||||||
import android.view.LayoutInflater;
|
|
||||||
import android.view.View;
|
|
||||||
import android.view.ViewGroup;
|
|
||||||
import android.widget.ImageView;
|
|
||||||
import android.widget.LinearLayout;
|
|
||||||
import android.widget.TextView;
|
|
||||||
|
|
||||||
import androidx.annotation.NonNull;
|
|
||||||
import androidx.core.content.ContextCompat;
|
|
||||||
import androidx.recyclerview.widget.DiffUtil;
|
|
||||||
import androidx.recyclerview.widget.ListAdapter;
|
|
||||||
import androidx.recyclerview.widget.RecyclerView;
|
|
||||||
|
|
||||||
import com.deniscerri.ytdlnis.R;
|
|
||||||
import com.deniscerri.ytdlnis.database.models.HistoryItem;
|
|
||||||
import com.google.android.material.button.MaterialButton;
|
|
||||||
import com.google.android.material.card.MaterialCardView;
|
|
||||||
import com.squareup.picasso.Picasso;
|
|
||||||
|
|
||||||
import java.io.File;
|
|
||||||
import java.text.DateFormat;
|
|
||||||
import java.text.SimpleDateFormat;
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.Calendar;
|
|
||||||
import java.util.Date;
|
|
||||||
import java.util.Locale;
|
|
||||||
|
|
||||||
public class HistoryAdapter extends ListAdapter<HistoryItem, HistoryAdapter.ViewHolder> {
|
|
||||||
private ArrayList<Integer> checkedItems;
|
|
||||||
private final OnItemClickListener onItemClickListener;
|
|
||||||
private Activity activity;
|
|
||||||
|
|
||||||
public HistoryAdapter(OnItemClickListener onItemClickListener, Activity activity) {
|
|
||||||
super(DIFF_CALLBACK);
|
|
||||||
this.checkedItems = new ArrayList<>();
|
|
||||||
this.onItemClickListener = onItemClickListener;
|
|
||||||
this.activity = activity;
|
|
||||||
}
|
|
||||||
|
|
||||||
private static final DiffUtil.ItemCallback<HistoryItem> DIFF_CALLBACK = new DiffUtil.ItemCallback<HistoryItem>() {
|
|
||||||
@Override
|
|
||||||
public boolean areItemsTheSame(@NonNull HistoryItem oldItem, @NonNull HistoryItem newItem) {
|
|
||||||
return oldItem.getId() == newItem.getId();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean areContentsTheSame(@NonNull HistoryItem oldItem, @NonNull HistoryItem newItem) {
|
|
||||||
return oldItem.getTime() == newItem.getTime();
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public int getItemViewType(int position) {
|
|
||||||
return super.getItemViewType(position);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static class ViewHolder extends RecyclerView.ViewHolder {
|
|
||||||
private MaterialCardView cardView;
|
|
||||||
|
|
||||||
public ViewHolder(@NonNull View itemView, OnItemClickListener onItemClickListener) {
|
|
||||||
super(itemView);
|
|
||||||
cardView = itemView.findViewById(R.id.downloads_card_view);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@NonNull
|
|
||||||
@Override
|
|
||||||
public ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
|
|
||||||
View cardView = LayoutInflater.from(parent.getContext())
|
|
||||||
.inflate(R.layout.downloads_card, parent, false);
|
|
||||||
|
|
||||||
return new HistoryAdapter.ViewHolder(cardView, onItemClickListener);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onBindViewHolder(@NonNull ViewHolder holder, int position) {
|
|
||||||
HistoryItem video = getItem(position);
|
|
||||||
MaterialCardView card = holder.cardView;
|
|
||||||
// THUMBNAIL ----------------------------------
|
|
||||||
ImageView thumbnail = card.findViewById(R.id.downloads_image_view);
|
|
||||||
String imageURL= video.getThumb();
|
|
||||||
|
|
||||||
Handler uiHandler = new Handler(Looper.getMainLooper());
|
|
||||||
if (!imageURL.isEmpty()){
|
|
||||||
uiHandler.post(() -> Picasso.get().load(imageURL).into(thumbnail));
|
|
||||||
}else {
|
|
||||||
uiHandler.post(() -> Picasso.get().load(R.color.black).into(thumbnail));
|
|
||||||
}
|
|
||||||
thumbnail.setColorFilter(Color.argb(95, 0, 0, 0));
|
|
||||||
|
|
||||||
// TITLE ----------------------------------
|
|
||||||
TextView videoTitle = card.findViewById(R.id.downloads_title);
|
|
||||||
String title = video.getTitle();
|
|
||||||
|
|
||||||
if(title.length() > 100){
|
|
||||||
title = title.substring(0, 40) + "...";
|
|
||||||
}
|
|
||||||
videoTitle.setText(title);
|
|
||||||
|
|
||||||
// Bottom Info ----------------------------------
|
|
||||||
TextView bottomInfo = card.findViewById(R.id.downloads_info_bottom);
|
|
||||||
String info = video.getAuthor();
|
|
||||||
if (!video.getDuration().isEmpty()){
|
|
||||||
if (!video.getAuthor().isEmpty()) info += " • ";
|
|
||||||
info += video.getDuration();
|
|
||||||
}
|
|
||||||
bottomInfo.setText(info);
|
|
||||||
|
|
||||||
// TIME DOWNLOADED ----------------------------------
|
|
||||||
TextView datetime = card.findViewById(R.id.downloads_info_time);
|
|
||||||
long time = video.getTime();
|
|
||||||
String downloadedTime;
|
|
||||||
if (time == 0){
|
|
||||||
downloadedTime = activity.getString(R.string.currently_downloading) + " " + video.getType();
|
|
||||||
}else{
|
|
||||||
Calendar cal = Calendar.getInstance();
|
|
||||||
Date date = new Date(time*1000L);
|
|
||||||
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 timeString = formatter.format(date);
|
|
||||||
downloadedTime = day + " " + month + " " + year + " - " + timeString;
|
|
||||||
}
|
|
||||||
datetime.setText(downloadedTime);
|
|
||||||
|
|
||||||
// BUTTON ----------------------------------
|
|
||||||
LinearLayout buttonLayout = card.findViewById(R.id.downloads_download_button_layout);
|
|
||||||
MaterialButton btn = buttonLayout.findViewById(R.id.downloads_download_button_type);
|
|
||||||
|
|
||||||
boolean filePresent = true;
|
|
||||||
|
|
||||||
//IS IN THE FILE SYSTEM?
|
|
||||||
String path = video.getDownloadPath();
|
|
||||||
File file = new File(path);
|
|
||||||
if(!file.exists() && !path.isEmpty()){
|
|
||||||
filePresent = false;
|
|
||||||
thumbnail.setColorFilter(new ColorMatrixColorFilter(new ColorMatrix(){{setSaturation(0f);}}));
|
|
||||||
thumbnail.setAlpha(0.7f);
|
|
||||||
}
|
|
||||||
|
|
||||||
if(!video.getType().isEmpty()){
|
|
||||||
if(video.getType().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);
|
|
||||||
|
|
||||||
if(checkedItems.contains(position)){
|
|
||||||
card.setChecked(true);
|
|
||||||
card.setStrokeWidth(5);
|
|
||||||
}else{
|
|
||||||
card.setChecked(false);
|
|
||||||
card.setStrokeWidth(0);
|
|
||||||
}
|
|
||||||
|
|
||||||
boolean finalFilePresent = filePresent;
|
|
||||||
card.setOnLongClickListener(view -> {
|
|
||||||
checkCard(card, position);
|
|
||||||
return true;
|
|
||||||
});
|
|
||||||
card.setOnClickListener(view -> {
|
|
||||||
if(checkedItems.size() > 0){
|
|
||||||
checkCard(card, video.getId());
|
|
||||||
}else{
|
|
||||||
onItemClickListener.onCardClick(video.getId(), finalFilePresent);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
private void checkCard(MaterialCardView card, int videoID){
|
|
||||||
if(card.isChecked()){
|
|
||||||
card.setStrokeWidth(0);
|
|
||||||
checkedItems.remove(videoID);
|
|
||||||
}else{
|
|
||||||
card.setStrokeWidth(5);
|
|
||||||
checkedItems.add(videoID);
|
|
||||||
}
|
|
||||||
card.setChecked(!card.isChecked());
|
|
||||||
onItemClickListener.onCardSelect(videoID, card.isChecked());
|
|
||||||
}
|
|
||||||
|
|
||||||
public interface OnItemClickListener {
|
|
||||||
void onCardClick(int position, boolean isPresent);
|
|
||||||
void onCardSelect(int position, boolean isChecked);
|
|
||||||
void onButtonClick(int position);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void clearCheckedVideos(){
|
|
||||||
int size = checkedItems.size();
|
|
||||||
for (int i = 0; i < size; i++){
|
|
||||||
int position = checkedItems.get(i);
|
|
||||||
notifyItemChanged(position);
|
|
||||||
}
|
|
||||||
checkedItems.clear();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -0,0 +1,189 @@
|
||||||
|
package com.deniscerri.ytdlnis.adapter
|
||||||
|
|
||||||
|
import android.app.Activity
|
||||||
|
import android.graphics.Color
|
||||||
|
import android.graphics.ColorMatrix
|
||||||
|
import android.graphics.ColorMatrixColorFilter
|
||||||
|
import android.os.Handler
|
||||||
|
import android.os.Looper
|
||||||
|
import android.view.LayoutInflater
|
||||||
|
import android.view.View
|
||||||
|
import android.view.ViewGroup
|
||||||
|
import android.widget.ImageView
|
||||||
|
import android.widget.LinearLayout
|
||||||
|
import android.widget.TextView
|
||||||
|
import androidx.core.content.ContextCompat
|
||||||
|
import androidx.recyclerview.widget.AsyncDifferConfig
|
||||||
|
import androidx.recyclerview.widget.DiffUtil
|
||||||
|
import androidx.recyclerview.widget.ListAdapter
|
||||||
|
import androidx.recyclerview.widget.RecyclerView
|
||||||
|
import com.deniscerri.ytdlnis.R
|
||||||
|
import com.deniscerri.ytdlnis.database.models.HistoryItem
|
||||||
|
import com.google.android.material.button.MaterialButton
|
||||||
|
import com.google.android.material.card.MaterialCardView
|
||||||
|
import com.squareup.picasso.Picasso
|
||||||
|
import java.io.File
|
||||||
|
import java.text.DateFormat
|
||||||
|
import java.text.SimpleDateFormat
|
||||||
|
import java.util.*
|
||||||
|
|
||||||
|
class HistoryAdapter(onItemClickListener: OnItemClickListener, activity: Activity) : ListAdapter<HistoryItem?, HistoryAdapter.ViewHolder>(AsyncDifferConfig.Builder(DIFF_CALLBACK).build()) {
|
||||||
|
private val checkedItems: ArrayList<Int>
|
||||||
|
private val onItemClickListener: OnItemClickListener
|
||||||
|
private val activity: Activity
|
||||||
|
|
||||||
|
init {
|
||||||
|
checkedItems = ArrayList()
|
||||||
|
this.onItemClickListener = onItemClickListener
|
||||||
|
this.activity = activity
|
||||||
|
}
|
||||||
|
|
||||||
|
class ViewHolder(itemView: View, onItemClickListener: OnItemClickListener?) : RecyclerView.ViewHolder(itemView) {
|
||||||
|
val cardView: MaterialCardView
|
||||||
|
|
||||||
|
init {
|
||||||
|
cardView = itemView.findViewById(R.id.downloads_card_view)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
|
||||||
|
val cardView = LayoutInflater.from(parent.context)
|
||||||
|
.inflate(R.layout.downloads_card, parent, false)
|
||||||
|
return ViewHolder(cardView, onItemClickListener)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onBindViewHolder(holder: ViewHolder, position: Int) {
|
||||||
|
val video = getItem(position)
|
||||||
|
val card = holder.cardView
|
||||||
|
// THUMBNAIL ----------------------------------
|
||||||
|
val thumbnail = card.findViewById<ImageView>(R.id.downloads_image_view)
|
||||||
|
val imageURL = video!!.thumb
|
||||||
|
val uiHandler = Handler(Looper.getMainLooper())
|
||||||
|
if (imageURL.isNotEmpty()) {
|
||||||
|
uiHandler.post { Picasso.get().load(imageURL).into(thumbnail) }
|
||||||
|
} else {
|
||||||
|
uiHandler.post { Picasso.get().load(R.color.black).into(thumbnail) }
|
||||||
|
}
|
||||||
|
thumbnail.setColorFilter(Color.argb(95, 0, 0, 0))
|
||||||
|
|
||||||
|
// TITLE ----------------------------------
|
||||||
|
val videoTitle = card.findViewById<TextView>(R.id.downloads_title)
|
||||||
|
var title = video.title
|
||||||
|
if (title.length > 100) {
|
||||||
|
title = title.substring(0, 40) + "..."
|
||||||
|
}
|
||||||
|
videoTitle.text = title
|
||||||
|
|
||||||
|
// Bottom Info ----------------------------------
|
||||||
|
val bottomInfo = card.findViewById<TextView>(R.id.downloads_info_bottom)
|
||||||
|
var info = video.author
|
||||||
|
if (video.duration.isNotEmpty()) {
|
||||||
|
if (video.author.isNotEmpty()) info += " • "
|
||||||
|
info += video.duration
|
||||||
|
}
|
||||||
|
bottomInfo.text = info
|
||||||
|
|
||||||
|
// TIME DOWNLOADED ----------------------------------
|
||||||
|
val datetime = card.findViewById<TextView>(R.id.downloads_info_time)
|
||||||
|
val time = video.time
|
||||||
|
val downloadedTime: String
|
||||||
|
if (time == 0L) {
|
||||||
|
downloadedTime = activity.getString(R.string.currently_downloading) + " " + video.type
|
||||||
|
} else {
|
||||||
|
val cal = Calendar.getInstance()
|
||||||
|
val date = Date(time * 1000L)
|
||||||
|
cal.time = date
|
||||||
|
val day = cal[Calendar.DAY_OF_MONTH]
|
||||||
|
val month = cal.getDisplayName(Calendar.MONTH, Calendar.LONG, Locale.getDefault())
|
||||||
|
val year = cal[Calendar.YEAR]
|
||||||
|
val formatter: DateFormat = SimpleDateFormat("HH:mm", Locale.getDefault())
|
||||||
|
val timeString = formatter.format(date)
|
||||||
|
downloadedTime = "$day $month $year - $timeString"
|
||||||
|
}
|
||||||
|
datetime.text = downloadedTime
|
||||||
|
|
||||||
|
// BUTTON ----------------------------------
|
||||||
|
val buttonLayout = card.findViewById<LinearLayout>(R.id.downloads_download_button_layout)
|
||||||
|
val btn = buttonLayout.findViewById<MaterialButton>(R.id.downloads_download_button_type)
|
||||||
|
var filePresent = true
|
||||||
|
|
||||||
|
//IS IN THE FILE SYSTEM?
|
||||||
|
val path = video.downloadPath
|
||||||
|
val file = File(path)
|
||||||
|
if (!file.exists() && path.isNotEmpty()) {
|
||||||
|
filePresent = false
|
||||||
|
thumbnail.colorFilter = ColorMatrixColorFilter(object : ColorMatrix() {
|
||||||
|
init {
|
||||||
|
setSaturation(0f)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
thumbnail.alpha = 0.7f
|
||||||
|
}
|
||||||
|
if (video.type.isNotEmpty()) {
|
||||||
|
if (video.type == "audio") {
|
||||||
|
if (filePresent) btn.icon = ContextCompat.getDrawable(activity, R.drawable.ic_music_downloaded) else btn.icon = ContextCompat.getDrawable(activity, R.drawable.ic_music)
|
||||||
|
} else {
|
||||||
|
if (filePresent) btn.icon = ContextCompat.getDrawable(activity, R.drawable.ic_video_downloaded) else btn.icon = ContextCompat.getDrawable(activity, R.drawable.ic_video)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (btn.hasOnClickListeners()) btn.setOnClickListener(null)
|
||||||
|
if (checkedItems.contains(position)) {
|
||||||
|
card.isChecked = true
|
||||||
|
card.strokeWidth = 5
|
||||||
|
} else {
|
||||||
|
card.isChecked = false
|
||||||
|
card.strokeWidth = 0
|
||||||
|
}
|
||||||
|
val finalFilePresent = filePresent
|
||||||
|
card.setOnLongClickListener {
|
||||||
|
checkCard(card, position)
|
||||||
|
true
|
||||||
|
}
|
||||||
|
card.setOnClickListener {
|
||||||
|
if (checkedItems.size > 0) {
|
||||||
|
checkCard(card, video.id!!)
|
||||||
|
} else {
|
||||||
|
onItemClickListener.onCardClick(video.id!!, finalFilePresent)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun checkCard(card: MaterialCardView, videoID: Int) {
|
||||||
|
if (card.isChecked) {
|
||||||
|
card.strokeWidth = 0
|
||||||
|
checkedItems.removeAt(videoID)
|
||||||
|
} else {
|
||||||
|
card.strokeWidth = 5
|
||||||
|
checkedItems.add(videoID)
|
||||||
|
}
|
||||||
|
card.isChecked = !card.isChecked
|
||||||
|
onItemClickListener.onCardSelect(videoID, card.isChecked)
|
||||||
|
}
|
||||||
|
|
||||||
|
interface OnItemClickListener {
|
||||||
|
fun onCardClick(position: Int, isPresent: Boolean)
|
||||||
|
fun onCardSelect(position: Int, isChecked: Boolean)
|
||||||
|
fun onButtonClick(position: Int)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun clearCheckedVideos() {
|
||||||
|
val size = checkedItems.size
|
||||||
|
for (i in 0 until size) {
|
||||||
|
val position = checkedItems[i]
|
||||||
|
notifyItemChanged(position)
|
||||||
|
}
|
||||||
|
checkedItems.clear()
|
||||||
|
}
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
private val DIFF_CALLBACK: DiffUtil.ItemCallback<HistoryItem> = object : DiffUtil.ItemCallback<HistoryItem>() {
|
||||||
|
override fun areItemsTheSame(oldItem: HistoryItem, newItem: HistoryItem): Boolean {
|
||||||
|
return oldItem.id === newItem.id
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun areContentsTheSame(oldItem: HistoryItem, newItem: HistoryItem): Boolean {
|
||||||
|
return oldItem.time == newItem.time
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -1,212 +0,0 @@
|
||||||
package com.deniscerri.ytdlnis.adapter;
|
|
||||||
|
|
||||||
import android.app.Activity;
|
|
||||||
import android.graphics.Color;
|
|
||||||
import android.os.Handler;
|
|
||||||
import android.os.Looper;
|
|
||||||
import android.view.LayoutInflater;
|
|
||||||
import android.view.View;
|
|
||||||
import android.view.ViewGroup;
|
|
||||||
import android.widget.ImageView;
|
|
||||||
import android.widget.LinearLayout;
|
|
||||||
import android.widget.TextView;
|
|
||||||
|
|
||||||
import androidx.annotation.NonNull;
|
|
||||||
import androidx.recyclerview.widget.DiffUtil;
|
|
||||||
import androidx.recyclerview.widget.ListAdapter;
|
|
||||||
import androidx.recyclerview.widget.RecyclerView;
|
|
||||||
|
|
||||||
import com.deniscerri.ytdlnis.R;
|
|
||||||
import com.deniscerri.ytdlnis.database.models.ResultItem;
|
|
||||||
import com.google.android.material.button.MaterialButton;
|
|
||||||
import com.google.android.material.card.MaterialCardView;
|
|
||||||
import com.google.android.material.progressindicator.LinearProgressIndicator;
|
|
||||||
import com.squareup.picasso.Picasso;
|
|
||||||
|
|
||||||
import java.util.ArrayList;
|
|
||||||
|
|
||||||
public class HomeAdapter extends ListAdapter<ResultItem, HomeAdapter.ViewHolder> {
|
|
||||||
private final ArrayList<Integer> checkedVideos;
|
|
||||||
private final OnItemClickListener onItemClickListener;
|
|
||||||
private Activity activity;
|
|
||||||
|
|
||||||
public HomeAdapter(HomeAdapter.OnItemClickListener onItemClickListener, Activity activity){
|
|
||||||
super(DIFF_CALLBACK);
|
|
||||||
this.checkedVideos = new ArrayList<>();
|
|
||||||
this.onItemClickListener = onItemClickListener;
|
|
||||||
this.activity = activity;
|
|
||||||
}
|
|
||||||
|
|
||||||
private static final DiffUtil.ItemCallback<ResultItem> DIFF_CALLBACK = new DiffUtil.ItemCallback<ResultItem>() {
|
|
||||||
@Override
|
|
||||||
public boolean areItemsTheSame(@NonNull ResultItem oldItem, @NonNull ResultItem newItem) {
|
|
||||||
return oldItem.getId() == newItem.getId();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean areContentsTheSame(@NonNull ResultItem oldItem, @NonNull ResultItem newItem) {
|
|
||||||
return oldItem.getUrl().equals(newItem.getUrl());
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public int getItemViewType(int position) {
|
|
||||||
return super.getItemViewType(position);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static class ViewHolder extends RecyclerView.ViewHolder {
|
|
||||||
private MaterialCardView cardView;
|
|
||||||
|
|
||||||
public ViewHolder(@NonNull View itemView, OnItemClickListener onItemClickListener) {
|
|
||||||
super(itemView);
|
|
||||||
cardView = itemView.findViewById(R.id.result_card_view);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
@NonNull
|
|
||||||
@Override
|
|
||||||
public ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
|
|
||||||
View cardView = LayoutInflater.from(parent.getContext())
|
|
||||||
.inflate(R.layout.result_card, parent, false);
|
|
||||||
return new HomeAdapter.ViewHolder(cardView, onItemClickListener);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onBindViewHolder(@NonNull ViewHolder holder, int position) {
|
|
||||||
ResultItem video = getItem(position);
|
|
||||||
MaterialCardView card = holder.cardView;
|
|
||||||
// THUMBNAIL ----------------------------------
|
|
||||||
ImageView thumbnail = card.findViewById(R.id.result_image_view);
|
|
||||||
String imageURL= video.getThumb();
|
|
||||||
if (!imageURL.isEmpty()){
|
|
||||||
Handler uiHandler = new Handler(Looper.getMainLooper());
|
|
||||||
uiHandler.post(() -> Picasso.get().load(imageURL).into(thumbnail));
|
|
||||||
thumbnail.setColorFilter(Color.argb(70, 0, 0, 0));
|
|
||||||
}else {
|
|
||||||
Handler uiHandler = new Handler(Looper.getMainLooper());
|
|
||||||
uiHandler.post(() -> Picasso.get().load(R.color.black).into(thumbnail));
|
|
||||||
thumbnail.setColorFilter(Color.argb(70, 0, 0, 0));
|
|
||||||
}
|
|
||||||
|
|
||||||
// TITLE ----------------------------------
|
|
||||||
TextView videoTitle = card.findViewById(R.id.result_title);
|
|
||||||
String title = video.getTitle();
|
|
||||||
|
|
||||||
if(title.length() > 100){
|
|
||||||
title = title.substring(0, 40) + "...";
|
|
||||||
}
|
|
||||||
videoTitle.setText(title);
|
|
||||||
|
|
||||||
// Bottom Info ----------------------------------
|
|
||||||
|
|
||||||
TextView author = card.findViewById(R.id.author);
|
|
||||||
author.setText(video.getAuthor());
|
|
||||||
|
|
||||||
TextView duration = card.findViewById(R.id.duration);
|
|
||||||
if (!video.getDuration().isEmpty()){
|
|
||||||
duration.setText(video.getDuration());
|
|
||||||
}
|
|
||||||
|
|
||||||
// BUTTONS ----------------------------------
|
|
||||||
int videoID = video.getId();
|
|
||||||
|
|
||||||
LinearLayout buttonLayout = card.findViewById(R.id.download_button_layout);
|
|
||||||
|
|
||||||
MaterialButton musicBtn = buttonLayout.findViewById(R.id.download_music);
|
|
||||||
musicBtn.setTag(videoID + "##audio");
|
|
||||||
musicBtn.setTag(R.id.cancelDownload, "false");
|
|
||||||
musicBtn.setOnClickListener(view -> onItemClickListener.onButtonClick(position, "audio"));
|
|
||||||
|
|
||||||
MaterialButton videoBtn = buttonLayout.findViewById(R.id.download_video);
|
|
||||||
videoBtn.setTag(videoID + "##video");
|
|
||||||
videoBtn.setTag(R.id.cancelDownload, "false");
|
|
||||||
videoBtn.setOnClickListener(view -> onItemClickListener.onButtonClick(position, "video"));
|
|
||||||
|
|
||||||
|
|
||||||
// PROGRESS BAR ----------------------------------------------------
|
|
||||||
|
|
||||||
LinearProgressIndicator progressBar = card.findViewById(R.id.download_progress);
|
|
||||||
progressBar.setTag(videoID + "##progress");
|
|
||||||
progressBar.setProgress(0);
|
|
||||||
progressBar.setIndeterminate(true);
|
|
||||||
progressBar.setVisibility(View.GONE);
|
|
||||||
|
|
||||||
// if (video.isDownloading()){
|
|
||||||
// progressBar.setVisibility(View.VISIBLE);
|
|
||||||
// }else {
|
|
||||||
// progressBar.setProgress(0);
|
|
||||||
// progressBar.setIndeterminate(true);
|
|
||||||
// progressBar.setVisibility(View.GONE);
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// if (video.isDownloadingAudio()) {
|
|
||||||
// musicBtn.setIcon(ContextCompat.getDrawable(activity, R.drawable.ic_cancel));
|
|
||||||
// musicBtn.setTag(R.id.cancelDownload, "true");
|
|
||||||
// }else{
|
|
||||||
// if(video.isAudioDownloaded() == 1){
|
|
||||||
// musicBtn.setIcon(ContextCompat.getDrawable(activity, R.drawable.ic_music_downloaded));
|
|
||||||
// }else{
|
|
||||||
// musicBtn.setIcon(ContextCompat.getDrawable(activity, R.drawable.ic_music));
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// if (video.isDownloadingVideo()){
|
|
||||||
// videoBtn.setIcon(ContextCompat.getDrawable(activity, R.drawable.ic_cancel));
|
|
||||||
// videoBtn.setTag(R.id.cancelDownload, "true");
|
|
||||||
// }else{
|
|
||||||
// if(video.isVideoDownloaded() == 1){
|
|
||||||
// videoBtn.setIcon(ContextCompat.getDrawable(activity, R.drawable.ic_video_downloaded));
|
|
||||||
// }else{
|
|
||||||
// videoBtn.setIcon(ContextCompat.getDrawable(activity, R.drawable.ic_video));
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
|
|
||||||
|
|
||||||
if(checkedVideos.contains(videoID)){
|
|
||||||
card.setChecked(true);
|
|
||||||
card.setStrokeWidth(5);
|
|
||||||
}else{
|
|
||||||
card.setChecked(false);
|
|
||||||
card.setStrokeWidth(0);
|
|
||||||
}
|
|
||||||
|
|
||||||
card.setTag(videoID + "##card");
|
|
||||||
card.setOnLongClickListener(view -> {
|
|
||||||
checkCard(card, videoID);
|
|
||||||
return true;
|
|
||||||
});
|
|
||||||
card.setOnClickListener(view -> {
|
|
||||||
if(checkedVideos.size() > 0){
|
|
||||||
checkCard(card, videoID);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
private void checkCard(MaterialCardView card, int videoID){
|
|
||||||
if(card.isChecked()){
|
|
||||||
card.setStrokeWidth(0);
|
|
||||||
checkedVideos.remove(Integer.valueOf(videoID));
|
|
||||||
}else{
|
|
||||||
card.setStrokeWidth(5);
|
|
||||||
checkedVideos.add(videoID);
|
|
||||||
}
|
|
||||||
card.setChecked(!card.isChecked());
|
|
||||||
onItemClickListener.onCardClick(videoID, card.isChecked());
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
public interface OnItemClickListener {
|
|
||||||
void onButtonClick(int videoID, String type);
|
|
||||||
void onCardClick(int videoID, boolean add);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void clearCheckedVideos(){
|
|
||||||
int size = checkedVideos.size();
|
|
||||||
for (int i = 0; i < size; i++){
|
|
||||||
int position = checkedVideos.get(i);
|
|
||||||
notifyItemChanged(position);
|
|
||||||
}
|
|
||||||
checkedVideos.clear();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
186
app/src/main/java/com/deniscerri/ytdlnis/adapter/HomeAdapter.kt
Normal file
186
app/src/main/java/com/deniscerri/ytdlnis/adapter/HomeAdapter.kt
Normal file
|
|
@ -0,0 +1,186 @@
|
||||||
|
package com.deniscerri.ytdlnis.adapter
|
||||||
|
|
||||||
|
import android.app.Activity
|
||||||
|
import android.graphics.Color
|
||||||
|
import android.os.Handler
|
||||||
|
import android.os.Looper
|
||||||
|
import android.view.LayoutInflater
|
||||||
|
import android.view.View
|
||||||
|
import android.view.ViewGroup
|
||||||
|
import android.widget.ImageView
|
||||||
|
import android.widget.LinearLayout
|
||||||
|
import android.widget.TextView
|
||||||
|
import androidx.recyclerview.widget.AsyncDifferConfig
|
||||||
|
import androidx.recyclerview.widget.DiffUtil
|
||||||
|
import androidx.recyclerview.widget.ListAdapter
|
||||||
|
import androidx.recyclerview.widget.RecyclerView
|
||||||
|
import com.deniscerri.ytdlnis.R
|
||||||
|
import com.deniscerri.ytdlnis.database.models.ResultItem
|
||||||
|
import com.google.android.material.button.MaterialButton
|
||||||
|
import com.google.android.material.card.MaterialCardView
|
||||||
|
import com.google.android.material.progressindicator.LinearProgressIndicator
|
||||||
|
import com.squareup.picasso.Picasso
|
||||||
|
|
||||||
|
class HomeAdapter(onItemClickListener: OnItemClickListener, activity: Activity) : ListAdapter<ResultItem?, HomeAdapter.ViewHolder>(AsyncDifferConfig.Builder(DIFF_CALLBACK).build()) {
|
||||||
|
private val checkedVideos: ArrayList<String>
|
||||||
|
private val onItemClickListener: OnItemClickListener
|
||||||
|
private val activity: Activity
|
||||||
|
|
||||||
|
init {
|
||||||
|
checkedVideos = ArrayList()
|
||||||
|
this.onItemClickListener = onItemClickListener
|
||||||
|
this.activity = activity
|
||||||
|
}
|
||||||
|
|
||||||
|
class ViewHolder(itemView: View, onItemClickListener: OnItemClickListener?) : RecyclerView.ViewHolder(itemView) {
|
||||||
|
val cardView: MaterialCardView
|
||||||
|
|
||||||
|
init {
|
||||||
|
cardView = itemView.findViewById(R.id.result_card_view)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
|
||||||
|
val cardView = LayoutInflater.from(parent.context)
|
||||||
|
.inflate(R.layout.result_card, parent, false)
|
||||||
|
return ViewHolder(cardView, onItemClickListener)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onBindViewHolder(holder: ViewHolder, position: Int) {
|
||||||
|
val video = getItem(position)
|
||||||
|
val card = holder.cardView
|
||||||
|
// THUMBNAIL ----------------------------------
|
||||||
|
val thumbnail = card.findViewById<ImageView>(R.id.result_image_view)
|
||||||
|
val imageURL = video!!.thumb
|
||||||
|
if (imageURL.isNotEmpty()) {
|
||||||
|
val uiHandler = Handler(Looper.getMainLooper())
|
||||||
|
uiHandler.post { Picasso.get().load(imageURL).into(thumbnail) }
|
||||||
|
thumbnail.setColorFilter(Color.argb(70, 0, 0, 0))
|
||||||
|
} else {
|
||||||
|
val uiHandler = Handler(Looper.getMainLooper())
|
||||||
|
uiHandler.post { Picasso.get().load(R.color.black).into(thumbnail) }
|
||||||
|
thumbnail.setColorFilter(Color.argb(70, 0, 0, 0))
|
||||||
|
}
|
||||||
|
|
||||||
|
// TITLE ----------------------------------
|
||||||
|
val videoTitle = card.findViewById<TextView>(R.id.result_title)
|
||||||
|
var title = video.title
|
||||||
|
if (title.length > 100) {
|
||||||
|
title = title.substring(0, 40) + "..."
|
||||||
|
}
|
||||||
|
videoTitle.text = title
|
||||||
|
|
||||||
|
// Bottom Info ----------------------------------
|
||||||
|
val author = card.findViewById<TextView>(R.id.author)
|
||||||
|
author.text = video.author
|
||||||
|
val duration = card.findViewById<TextView>(R.id.duration)
|
||||||
|
if (video.duration.isNotEmpty()) {
|
||||||
|
duration.text = video.duration
|
||||||
|
}
|
||||||
|
|
||||||
|
// BUTTONS ----------------------------------
|
||||||
|
val videoURL = video.url
|
||||||
|
val buttonLayout = card.findViewById<LinearLayout>(R.id.download_button_layout)
|
||||||
|
val musicBtn = buttonLayout.findViewById<MaterialButton>(R.id.download_music)
|
||||||
|
musicBtn.tag = "$videoURL##audio"
|
||||||
|
musicBtn.setTag(R.id.cancelDownload, "false")
|
||||||
|
musicBtn.setOnClickListener { onItemClickListener.onButtonClick(videoURL, "audio") }
|
||||||
|
val videoBtn = buttonLayout.findViewById<MaterialButton>(R.id.download_video)
|
||||||
|
videoBtn.tag = "$videoURL##video"
|
||||||
|
videoBtn.setTag(R.id.cancelDownload, "false")
|
||||||
|
videoBtn.setOnClickListener { onItemClickListener.onButtonClick(videoURL, "video") }
|
||||||
|
|
||||||
|
|
||||||
|
// PROGRESS BAR ----------------------------------------------------
|
||||||
|
val progressBar = card.findViewById<LinearProgressIndicator>(R.id.download_progress)
|
||||||
|
progressBar.tag = "$videoURL##progress"
|
||||||
|
progressBar.progress = 0
|
||||||
|
progressBar.isIndeterminate = true
|
||||||
|
progressBar.visibility = View.GONE
|
||||||
|
|
||||||
|
// if (video.isDownloading()){
|
||||||
|
// progressBar.setVisibility(View.VISIBLE);
|
||||||
|
// }else {
|
||||||
|
// progressBar.setProgress(0);
|
||||||
|
// progressBar.setIndeterminate(true);
|
||||||
|
// progressBar.setVisibility(View.GONE);
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// if (video.isDownloadingAudio()) {
|
||||||
|
// musicBtn.setIcon(ContextCompat.getDrawable(activity, R.drawable.ic_cancel));
|
||||||
|
// musicBtn.setTag(R.id.cancelDownload, "true");
|
||||||
|
// }else{
|
||||||
|
// if(video.isAudioDownloaded() == 1){
|
||||||
|
// musicBtn.setIcon(ContextCompat.getDrawable(activity, R.drawable.ic_music_downloaded));
|
||||||
|
// }else{
|
||||||
|
// musicBtn.setIcon(ContextCompat.getDrawable(activity, R.drawable.ic_music));
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// if (video.isDownloadingVideo()){
|
||||||
|
// videoBtn.setIcon(ContextCompat.getDrawable(activity, R.drawable.ic_cancel));
|
||||||
|
// videoBtn.setTag(R.id.cancelDownload, "true");
|
||||||
|
// }else{
|
||||||
|
// if(video.isVideoDownloaded() == 1){
|
||||||
|
// videoBtn.setIcon(ContextCompat.getDrawable(activity, R.drawable.ic_video_downloaded));
|
||||||
|
// }else{
|
||||||
|
// videoBtn.setIcon(ContextCompat.getDrawable(activity, R.drawable.ic_video));
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
if (checkedVideos.contains(videoURL)) {
|
||||||
|
card.isChecked = true
|
||||||
|
card.strokeWidth = 5
|
||||||
|
} else {
|
||||||
|
card.isChecked = false
|
||||||
|
card.strokeWidth = 0
|
||||||
|
}
|
||||||
|
card.tag = "$videoURL##card"
|
||||||
|
card.setOnLongClickListener {
|
||||||
|
checkCard(card, videoURL)
|
||||||
|
true
|
||||||
|
}
|
||||||
|
card.setOnClickListener {
|
||||||
|
if (checkedVideos.size > 0) {
|
||||||
|
checkCard(card, videoURL)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun checkCard(card: MaterialCardView, videoURL: String) {
|
||||||
|
if (card.isChecked) {
|
||||||
|
card.strokeWidth = 0
|
||||||
|
checkedVideos.remove(videoURL)
|
||||||
|
} else {
|
||||||
|
card.strokeWidth = 5
|
||||||
|
checkedVideos.add(videoURL)
|
||||||
|
}
|
||||||
|
card.isChecked = !card.isChecked
|
||||||
|
onItemClickListener.onCardClick(videoURL, card.isChecked)
|
||||||
|
}
|
||||||
|
|
||||||
|
interface OnItemClickListener {
|
||||||
|
fun onButtonClick(videoURL: String, type: String?)
|
||||||
|
fun onCardClick(videoURL: String, add: Boolean)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun clearCheckedVideos() {
|
||||||
|
// val size = checkedVideos.size
|
||||||
|
// for (i in 0 until size) {
|
||||||
|
// val position = checkedVideos[i]
|
||||||
|
// notifyItemChanged(position)
|
||||||
|
// }
|
||||||
|
// checkedVideos.clear()
|
||||||
|
}
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
private val DIFF_CALLBACK: DiffUtil.ItemCallback<ResultItem> = object : DiffUtil.ItemCallback<ResultItem>() {
|
||||||
|
override fun areItemsTheSame(oldItem: ResultItem, newItem: ResultItem): Boolean {
|
||||||
|
return oldItem.id === newItem.id
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun areContentsTheSame(oldItem: ResultItem, newItem: ResultItem): Boolean {
|
||||||
|
return oldItem.url == newItem.url
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -30,7 +30,9 @@ abstract class DBManager : RoomDatabase(){
|
||||||
context.applicationContext,
|
context.applicationContext,
|
||||||
DBManager::class.java,
|
DBManager::class.java,
|
||||||
"YTDLnisDatabase"
|
"YTDLnisDatabase"
|
||||||
).build()
|
)
|
||||||
|
.allowMainThreadQueries()
|
||||||
|
.build()
|
||||||
instance = dbInstance
|
instance = dbInstance
|
||||||
dbInstance
|
dbInstance
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -7,8 +7,8 @@ import com.deniscerri.ytdlnis.database.models.ResultItem
|
||||||
|
|
||||||
@Dao
|
@Dao
|
||||||
interface FormatDao {
|
interface FormatDao {
|
||||||
@Query("SELECT * FROM formats")
|
@Query("SELECT * FROM formats WHERE itemId=:itemId")
|
||||||
fun getFormatsByItemId() : LiveData<List<Format>>
|
fun getFormatsByItemId(itemId: Int) : List<Format>
|
||||||
|
|
||||||
@Insert(onConflict = OnConflictStrategy.REPLACE)
|
@Insert(onConflict = OnConflictStrategy.REPLACE)
|
||||||
suspend fun insert(item: Format)
|
suspend fun insert(item: Format)
|
||||||
|
|
|
||||||
|
|
@ -6,32 +6,32 @@ import androidx.room.PrimaryKey
|
||||||
|
|
||||||
@Entity(tableName = "downloads")
|
@Entity(tableName = "downloads")
|
||||||
data class DownloadItem(
|
data class DownloadItem(
|
||||||
val url: String,
|
val url: String,
|
||||||
val title: String,
|
var title: String,
|
||||||
val author: String,
|
var author: String,
|
||||||
val thumb: String,
|
val thumb: String,
|
||||||
val duration: String,
|
val duration: String,
|
||||||
val type: String,
|
val type: String,
|
||||||
val audioQualityId: String,
|
var audioFormat: String,
|
||||||
val videoQualityId: String,
|
var videoFormat: String,
|
||||||
val customTemplateId: Int,
|
var audioFormatId: String,
|
||||||
val audioFormat: String,
|
var videoFormatId: String,
|
||||||
val videoFormat: String,
|
var customTemplateId: Int,
|
||||||
val formatDesc: String,
|
val formatDesc: String,
|
||||||
@ColumnInfo(defaultValue = "0")
|
@ColumnInfo(defaultValue = "0")
|
||||||
val removeAudio: Boolean,
|
val removeAudio: Boolean,
|
||||||
val downloadPath: String,
|
val downloadPath: String,
|
||||||
val website: String,
|
val website: String,
|
||||||
val downloadSize: String,
|
val downloadSize: String,
|
||||||
val playlistTitle: String,
|
val playlistTitle: String,
|
||||||
val embedSubs: Boolean,
|
val embedSubs: Boolean,
|
||||||
val addChapters: Boolean,
|
val addChapters: Boolean,
|
||||||
val SaveThumb: Boolean,
|
val SaveThumb: Boolean,
|
||||||
var ext: String,
|
var ext: String,
|
||||||
var filesize: String,
|
var filesize: String,
|
||||||
@ColumnInfo(defaultValue = "Queued")
|
@ColumnInfo(defaultValue = "Queued")
|
||||||
var status: String,
|
var status: String,
|
||||||
val workID: Int
|
val workID: Int
|
||||||
){
|
){
|
||||||
@PrimaryKey(autoGenerate = true)
|
@PrimaryKey(autoGenerate = true)
|
||||||
var id: Int? = null
|
var id: Int? = null
|
||||||
|
|
|
||||||
|
|
@ -5,13 +5,13 @@ import androidx.room.PrimaryKey
|
||||||
|
|
||||||
@Entity(tableName = "results")
|
@Entity(tableName = "results")
|
||||||
data class ResultItem(
|
data class ResultItem(
|
||||||
val url: String,
|
val url: String,
|
||||||
val title: String,
|
var title: String,
|
||||||
val author: String,
|
var author: String,
|
||||||
val duration: String,
|
val duration: String,
|
||||||
val thumb: String,
|
val thumb: String,
|
||||||
val website: String,
|
val website: String,
|
||||||
var playlistTitle: String
|
var playlistTitle: String
|
||||||
){
|
){
|
||||||
@PrimaryKey(autoGenerate = true)
|
@PrimaryKey(autoGenerate = true)
|
||||||
var id: Int? = null
|
var id: Int? = null
|
||||||
|
|
|
||||||
|
|
@ -3,13 +3,15 @@ package com.deniscerri.ytdlnis.database.repository
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
import android.util.Log
|
import android.util.Log
|
||||||
import androidx.lifecycle.LiveData
|
import androidx.lifecycle.LiveData
|
||||||
|
import com.deniscerri.ytdlnis.database.dao.CommandTemplateDao
|
||||||
import com.deniscerri.ytdlnis.database.dao.FormatDao
|
import com.deniscerri.ytdlnis.database.dao.FormatDao
|
||||||
import com.deniscerri.ytdlnis.database.dao.ResultDao
|
import com.deniscerri.ytdlnis.database.dao.ResultDao
|
||||||
|
import com.deniscerri.ytdlnis.database.models.CommandTemplate
|
||||||
import com.deniscerri.ytdlnis.database.models.Format
|
import com.deniscerri.ytdlnis.database.models.Format
|
||||||
import com.deniscerri.ytdlnis.database.models.ResultItem
|
import com.deniscerri.ytdlnis.database.models.ResultItem
|
||||||
import com.deniscerri.ytdlnis.util.InfoUtil
|
import com.deniscerri.ytdlnis.util.InfoUtil
|
||||||
|
|
||||||
class ResultRepository(private val resultDao: ResultDao, private val formatDao: FormatDao, private val context: Context) {
|
class ResultRepository(private val resultDao: ResultDao, private val formatDao: FormatDao, private val commandTemplateDao: CommandTemplateDao, private val context: Context) {
|
||||||
private val tag: String = "ResultRepository"
|
private val tag: String = "ResultRepository"
|
||||||
val allResults : LiveData<List<ResultItem>> = resultDao.getResults()
|
val allResults : LiveData<List<ResultItem>> = resultDao.getResults()
|
||||||
|
|
||||||
|
|
@ -119,5 +121,12 @@ class ResultRepository(private val resultDao: ResultDao, private val formatDao:
|
||||||
resultDao.update(item)
|
resultDao.update(item)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun getFormats(item: ResultItem): List<Format> {
|
||||||
|
return formatDao.getFormatsByItemId(item.id!!)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun getTemplates() : List<CommandTemplate> {
|
||||||
|
return commandTemplateDao.getAllTemplates()
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
@ -1,14 +1,20 @@
|
||||||
package com.deniscerri.ytdlnis.database.viewmodel
|
package com.deniscerri.ytdlnis.database.viewmodel
|
||||||
|
|
||||||
import android.app.Application
|
import android.app.Application
|
||||||
|
import android.content.Context
|
||||||
import android.util.Log
|
import android.util.Log
|
||||||
import androidx.lifecycle.*
|
import androidx.lifecycle.*
|
||||||
|
import com.deniscerri.ytdlnis.App
|
||||||
|
import com.deniscerri.ytdlnis.R
|
||||||
import com.deniscerri.ytdlnis.database.DBManager
|
import com.deniscerri.ytdlnis.database.DBManager
|
||||||
|
import com.deniscerri.ytdlnis.database.dao.FormatDao
|
||||||
|
import com.deniscerri.ytdlnis.database.models.Format
|
||||||
import com.deniscerri.ytdlnis.database.models.ResultItem
|
import com.deniscerri.ytdlnis.database.models.ResultItem
|
||||||
import com.deniscerri.ytdlnis.database.repository.ResultRepository
|
import com.deniscerri.ytdlnis.database.repository.ResultRepository
|
||||||
import kotlinx.coroutines.Dispatchers
|
import kotlinx.coroutines.Dispatchers
|
||||||
import kotlinx.coroutines.launch
|
import kotlinx.coroutines.launch
|
||||||
import java.util.regex.Pattern
|
import java.util.regex.Pattern
|
||||||
|
import kotlin.coroutines.coroutineContext
|
||||||
|
|
||||||
class ResultViewModel(application: Application) : AndroidViewModel(application) {
|
class ResultViewModel(application: Application) : AndroidViewModel(application) {
|
||||||
private val tag: String = "ResultViewModel"
|
private val tag: String = "ResultViewModel"
|
||||||
|
|
@ -19,7 +25,8 @@ class ResultViewModel(application: Application) : AndroidViewModel(application)
|
||||||
init {
|
init {
|
||||||
val dao = DBManager.getInstance(application).resultDao
|
val dao = DBManager.getInstance(application).resultDao
|
||||||
val formatDao = DBManager.getInstance(application).formatDao
|
val formatDao = DBManager.getInstance(application).formatDao
|
||||||
repository = ResultRepository(dao, formatDao, getApplication<Application>().applicationContext)
|
val commandDao = DBManager.getInstance(application).commandTemplateDao
|
||||||
|
repository = ResultRepository(dao, formatDao, commandDao, getApplication<Application>().applicationContext)
|
||||||
items = repository.allResults
|
items = repository.allResults
|
||||||
loadingItems.postValue(false)
|
loadingItems.postValue(false)
|
||||||
}
|
}
|
||||||
|
|
@ -86,4 +93,31 @@ class ResultViewModel(application: Application) : AndroidViewModel(application)
|
||||||
fun update(item: ResultItem) = viewModelScope.launch(Dispatchers.IO){
|
fun update(item: ResultItem) = viewModelScope.launch(Dispatchers.IO){
|
||||||
repository.update(item);
|
repository.update(item);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun getFormats(item: ResultItem, type: String) : List<Format> {
|
||||||
|
val list = repository.getFormats(item)
|
||||||
|
val formats = mutableListOf<Format>()
|
||||||
|
if (list.isEmpty()){
|
||||||
|
when(type){
|
||||||
|
"audio" -> {
|
||||||
|
val audioFormats = getApplication<App>().resources.getStringArray(R.array.audio_formats)
|
||||||
|
audioFormats.forEach { formats.add(Format(item.id!!, it, "", "", 0, it)) }
|
||||||
|
}
|
||||||
|
"video" -> {
|
||||||
|
val videoFormats = getApplication<App>().resources.getStringArray(R.array.video_formats)
|
||||||
|
videoFormats.forEach { formats.add(Format(item.id!!, it, "", "", 0, it)) }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return formats
|
||||||
|
}
|
||||||
|
when(type){
|
||||||
|
"audio" -> return list.filter { it.format.contains("audio", ignoreCase = true) }
|
||||||
|
"video" -> return list.filter { !it.format.contains("audio", ignoreCase = true) }
|
||||||
|
}
|
||||||
|
val templates = repository.getTemplates()
|
||||||
|
templates.forEach {
|
||||||
|
formats.add(Format(item.id!!, it.title, it.id.toString(), "", 0, it.content))
|
||||||
|
}
|
||||||
|
return formats
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -105,7 +105,7 @@ class DownloadsFragment : Fragment(), HistoryAdapter.OnItemClickListener,
|
||||||
historyAdapter =
|
historyAdapter =
|
||||||
HistoryAdapter(
|
HistoryAdapter(
|
||||||
this,
|
this,
|
||||||
activity
|
requireActivity()
|
||||||
)
|
)
|
||||||
recyclerView = view.findViewById(R.id.recyclerviewdownloadss)
|
recyclerView = view.findViewById(R.id.recyclerviewdownloadss)
|
||||||
recyclerView?.layoutManager = LinearLayoutManager(context)
|
recyclerView?.layoutManager = LinearLayoutManager(context)
|
||||||
|
|
|
||||||
|
|
@ -7,13 +7,17 @@ import android.content.Intent
|
||||||
import android.os.Bundle
|
import android.os.Bundle
|
||||||
import android.os.Handler
|
import android.os.Handler
|
||||||
import android.os.Looper
|
import android.os.Looper
|
||||||
|
import android.text.Editable
|
||||||
import android.text.InputType
|
import android.text.InputType
|
||||||
|
import android.text.TextWatcher
|
||||||
|
import android.util.Log
|
||||||
import android.view.*
|
import android.view.*
|
||||||
import android.view.View.GONE
|
import android.view.View.GONE
|
||||||
import android.view.View.VISIBLE
|
import android.view.View.VISIBLE
|
||||||
import android.widget.*
|
import android.widget.*
|
||||||
import androidx.appcompat.widget.SearchView
|
import androidx.appcompat.widget.SearchView
|
||||||
import androidx.coordinatorlayout.widget.CoordinatorLayout
|
import androidx.coordinatorlayout.widget.CoordinatorLayout
|
||||||
|
import androidx.core.text.trimmedLength
|
||||||
import androidx.fragment.app.Fragment
|
import androidx.fragment.app.Fragment
|
||||||
import androidx.lifecycle.ViewModelProvider
|
import androidx.lifecycle.ViewModelProvider
|
||||||
import androidx.recyclerview.widget.LinearLayoutManager
|
import androidx.recyclerview.widget.LinearLayoutManager
|
||||||
|
|
@ -22,6 +26,7 @@ import com.deniscerri.ytdlnis.MainActivity
|
||||||
import com.deniscerri.ytdlnis.R
|
import com.deniscerri.ytdlnis.R
|
||||||
import com.deniscerri.ytdlnis.adapter.HomeAdapter
|
import com.deniscerri.ytdlnis.adapter.HomeAdapter
|
||||||
import com.deniscerri.ytdlnis.database.DatabaseManager
|
import com.deniscerri.ytdlnis.database.DatabaseManager
|
||||||
|
import com.deniscerri.ytdlnis.database.models.DownloadItem
|
||||||
import com.deniscerri.ytdlnis.database.models.ResultItem
|
import com.deniscerri.ytdlnis.database.models.ResultItem
|
||||||
import com.deniscerri.ytdlnis.database.viewmodel.ResultViewModel
|
import com.deniscerri.ytdlnis.database.viewmodel.ResultViewModel
|
||||||
import com.deniscerri.ytdlnis.databinding.FragmentDownloadsBinding
|
import com.deniscerri.ytdlnis.databinding.FragmentDownloadsBinding
|
||||||
|
|
@ -38,7 +43,11 @@ import com.google.android.material.floatingactionbutton.ExtendedFloatingActionBu
|
||||||
import com.google.android.material.floatingactionbutton.FloatingActionButton
|
import com.google.android.material.floatingactionbutton.FloatingActionButton
|
||||||
import com.google.android.material.progressindicator.LinearProgressIndicator
|
import com.google.android.material.progressindicator.LinearProgressIndicator
|
||||||
import com.google.android.material.textfield.TextInputLayout
|
import com.google.android.material.textfield.TextInputLayout
|
||||||
|
import kotlinx.coroutines.runBlocking
|
||||||
|
import java.text.DecimalFormat
|
||||||
import java.util.*
|
import java.util.*
|
||||||
|
import kotlin.math.log10
|
||||||
|
import kotlin.math.pow
|
||||||
|
|
||||||
class HomeFragment : Fragment(), HomeAdapter.OnItemClickListener, View.OnClickListener {
|
class HomeFragment : Fragment(), HomeAdapter.OnItemClickListener, View.OnClickListener {
|
||||||
private var progressBar: LinearProgressIndicator? = null
|
private var progressBar: LinearProgressIndicator? = null
|
||||||
|
|
@ -121,7 +130,7 @@ class HomeFragment : Fragment(), HomeAdapter.OnItemClickListener, View.OnClickLi
|
||||||
homeAdapter =
|
homeAdapter =
|
||||||
HomeAdapter(
|
HomeAdapter(
|
||||||
this,
|
this,
|
||||||
activity
|
requireActivity()
|
||||||
)
|
)
|
||||||
recyclerView = view.findViewById(R.id.recyclerViewHome)
|
recyclerView = view.findViewById(R.id.recyclerViewHome)
|
||||||
recyclerView?.layoutManager = LinearLayoutManager(context)
|
recyclerView?.layoutManager = LinearLayoutManager(context)
|
||||||
|
|
@ -336,11 +345,10 @@ class HomeFragment : Fragment(), HomeAdapter.OnItemClickListener, View.OnClickLi
|
||||||
selectedObjects = ArrayList()
|
selectedObjects = ArrayList()
|
||||||
downloadAllFabCoordinator!!.visibility = GONE
|
downloadAllFabCoordinator!!.visibility = GONE
|
||||||
downloadFabs!!.visibility = GONE
|
downloadFabs!!.visibility = GONE
|
||||||
}
|
} else if (itemId == R.id.cancel_download) {
|
||||||
// } else if (itemId == R.id.cancel_download) {
|
try {
|
||||||
// try {
|
mainActivity!!.cancelAllDownloads()
|
||||||
// mainActivity!!.cancelDownloadService()
|
topAppBar!!.menu.findItem(itemId).isVisible = false
|
||||||
// topAppBar!!.menu.findItem(itemId).isVisible = false
|
|
||||||
// for (i in downloadInfo!!.downloadQueue.indices) {
|
// for (i in downloadInfo!!.downloadQueue.indices) {
|
||||||
// val vid = downloadInfo!!.downloadQueue[i]
|
// val vid = downloadInfo!!.downloadQueue[i]
|
||||||
// val type = vid.downloadedType
|
// val type = vid.downloadedType
|
||||||
|
|
@ -348,9 +356,9 @@ class HomeFragment : Fragment(), HomeAdapter.OnItemClickListener, View.OnClickLi
|
||||||
// }
|
// }
|
||||||
// downloadQueue = ArrayList()
|
// downloadQueue = ArrayList()
|
||||||
// downloading = false
|
// downloading = false
|
||||||
// } catch (ignored: Exception) {
|
} catch (ignored: Exception) {
|
||||||
// }
|
}
|
||||||
// }
|
}
|
||||||
true
|
true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -380,11 +388,11 @@ class HomeFragment : Fragment(), HomeAdapter.OnItemClickListener, View.OnClickLi
|
||||||
}
|
}
|
||||||
|
|
||||||
@SuppressLint("ResourceType")
|
@SuppressLint("ResourceType")
|
||||||
override fun onButtonClick(position: Int, type: String) {
|
override fun onButtonClick(videoURL: String, type: String?) {
|
||||||
// Log.e(TAG, type)
|
Log.e(TAG, type!! + " " + videoURL)
|
||||||
// val vid = resultsList!![position]
|
val item = resultsList!!.find { it?.url == videoURL }
|
||||||
// vid!!.downloadedType = type
|
Log.e(TAG, resultsList!![0].toString() + " " + videoURL)
|
||||||
// val btn = recyclerView!!.findViewWithTag<MaterialButton>(vid.videoId + "##" + type)
|
val btn = recyclerView!!.findViewWithTag<MaterialButton>("""${item?.url}##$type""")
|
||||||
// if (downloading) {
|
// if (downloading) {
|
||||||
// try {
|
// try {
|
||||||
// if (btn.getTag(R.id.cancelDownload) == "true") {
|
// if (btn.getTag(R.id.cancelDownload) == "true") {
|
||||||
|
|
@ -394,20 +402,20 @@ class HomeFragment : Fragment(), HomeAdapter.OnItemClickListener, View.OnClickLi
|
||||||
// } catch (ignored: Exception) {
|
// } catch (ignored: Exception) {
|
||||||
// }
|
// }
|
||||||
// }
|
// }
|
||||||
// val sharedPreferences =
|
val sharedPreferences =
|
||||||
// context!!.getSharedPreferences("root_preferences", Activity.MODE_PRIVATE)
|
requireContext().getSharedPreferences("root_preferences", Activity.MODE_PRIVATE)
|
||||||
// if (sharedPreferences.getBoolean("download_card", true)) {
|
if (sharedPreferences.getBoolean("download_card", true)) {
|
||||||
// selectedObjects!!.clear()
|
// selectedObjects!!.clear()
|
||||||
// selectedObjects!!.add(resultsList!![position])
|
// selectedObjects!!.add(item!!)
|
||||||
// showConfigureDownloadCard(type)
|
showConfigureSingleDownloadCard(item!!, type)
|
||||||
// } else {
|
} else {
|
||||||
// downloadQueue!!.add(vid)
|
// downloadQueue!!.add(vid)
|
||||||
// updateDownloadingStatusOnResult(vid, type, true)
|
// updateDownloadingStatusOnResult(vid, type, true)
|
||||||
// if (isStoragePermissionGranted) {
|
// if (isStoragePermissionGranted) {
|
||||||
// mainActivity!!.startDownloadService(downloadQueue, listener)
|
// mainActivity!!.startDownloadService(downloadQueue, listener)
|
||||||
// downloadQueue!!.clear()
|
// downloadQueue!!.clear()
|
||||||
// }
|
// }
|
||||||
// }
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -436,8 +444,8 @@ class HomeFragment : Fragment(), HomeAdapter.OnItemClickListener, View.OnClickLi
|
||||||
// }
|
// }
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onCardClick(position: Int, add: Boolean) {
|
override fun onCardClick(videoURL: String, add: Boolean) {
|
||||||
val item = resultsList!![position]
|
val item = resultsList?.find { it -> it?.url == videoURL }
|
||||||
if (add) selectedObjects!!.add(item!!) else selectedObjects!!.remove(item)
|
if (add) selectedObjects!!.add(item!!) else selectedObjects!!.remove(item)
|
||||||
if (selectedObjects!!.size > 1) {
|
if (selectedObjects!!.size > 1) {
|
||||||
downloadAllFabCoordinator!!.visibility = GONE
|
downloadAllFabCoordinator!!.visibility = GONE
|
||||||
|
|
@ -456,7 +464,7 @@ class HomeFragment : Fragment(), HomeAdapter.OnItemClickListener, View.OnClickLi
|
||||||
} catch (e: Exception) {
|
} catch (e: Exception) {
|
||||||
""
|
""
|
||||||
}
|
}
|
||||||
if (!viewIdName.isEmpty()) {
|
if (viewIdName.isNotEmpty()) {
|
||||||
if (viewIdName.contains("audio") || viewIdName.contains("video")) {
|
if (viewIdName.contains("audio") || viewIdName.contains("video")) {
|
||||||
val buttonData =
|
val buttonData =
|
||||||
viewIdName.split("##".toRegex()).dropLastWhile { it.isEmpty() }.toTypedArray()
|
viewIdName.split("##".toRegex()).dropLastWhile { it.isEmpty() }.toTypedArray()
|
||||||
|
|
@ -465,39 +473,39 @@ class HomeFragment : Fragment(), HomeAdapter.OnItemClickListener, View.OnClickLi
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (viewIdName == "downloadAll") {
|
if (viewIdName == "downloadAll") {
|
||||||
//remove previously selected
|
// //remove previously selected
|
||||||
for (i in selectedObjects!!.indices) {
|
// for (i in selectedObjects!!.indices) {
|
||||||
val vid = findVideo(
|
// val vid = findVideo(
|
||||||
selectedObjects!![i].url
|
// selectedObjects!![i].url
|
||||||
)
|
// )
|
||||||
homeAdapter!!.notifyItemChanged(resultsList!!.indexOf(vid))
|
// homeAdapter!!.notifyItemChanged(resultsList!!.indexOf(vid))
|
||||||
}
|
// }
|
||||||
selectedObjects = ArrayList()
|
// selectedObjects = ArrayList()
|
||||||
downloadFabs!!.visibility = GONE
|
// downloadFabs!!.visibility = GONE
|
||||||
bottomSheet = BottomSheetDialog(fragmentContext!!)
|
// bottomSheet = BottomSheetDialog(fragmentContext!!)
|
||||||
bottomSheet!!.requestWindowFeature(Window.FEATURE_NO_TITLE)
|
// bottomSheet!!.requestWindowFeature(Window.FEATURE_NO_TITLE)
|
||||||
bottomSheet!!.setContentView(R.layout.home_download_all_bottom_sheet)
|
// bottomSheet!!.setContentView(R.layout.home_download_all_bottom_sheet)
|
||||||
val first = bottomSheet!!.findViewById<TextInputLayout>(R.id.first_textinput)
|
// val first = bottomSheet!!.findViewById<TextInputLayout>(R.id.first_textinput)
|
||||||
first!!.editText!!.setText(1.toString())
|
// first!!.editText!!.setText(1.toString())
|
||||||
val last = bottomSheet!!.findViewById<TextInputLayout>(R.id.last_textinput)
|
// val last = bottomSheet!!.findViewById<TextInputLayout>(R.id.last_textinput)
|
||||||
last!!.editText!!.setText(resultsList!!.size.toString())
|
// last!!.editText!!.setText(resultsList!!.size.toString())
|
||||||
val audio = bottomSheet!!.findViewById<Button>(R.id.bottomsheet_audio_button)
|
// val audio = bottomSheet!!.findViewById<Button>(R.id.bottomsheet_audio_button)
|
||||||
audio!!.setOnClickListener {
|
// audio!!.setOnClickListener {
|
||||||
val start = first.editText!!.text.toString().toInt()
|
// val start = first.editText!!.text.toString().toInt()
|
||||||
val end = last.editText!!.text.toString().toInt()
|
// val end = last.editText!!.text.toString().toInt()
|
||||||
initDownloadAll(bottomSheet!!, start, end, "audio")
|
// initDownloadAll(bottomSheet!!, start, end, "audio")
|
||||||
}
|
// }
|
||||||
val video = bottomSheet!!.findViewById<Button>(R.id.bottomsheet_video_button)
|
// val video = bottomSheet!!.findViewById<Button>(R.id.bottomsheet_video_button)
|
||||||
video!!.setOnClickListener {
|
// video!!.setOnClickListener {
|
||||||
val start = first.editText!!.text.toString().toInt()
|
// val start = first.editText!!.text.toString().toInt()
|
||||||
val end = last.editText!!.text.toString().toInt()
|
// val end = last.editText!!.text.toString().toInt()
|
||||||
initDownloadAll(bottomSheet!!, start, end, "video")
|
// initDownloadAll(bottomSheet!!, start, end, "video")
|
||||||
}
|
// }
|
||||||
bottomSheet!!.show()
|
// bottomSheet!!.show()
|
||||||
bottomSheet!!.window!!.setLayout(
|
// bottomSheet!!.window!!.setLayout(
|
||||||
ViewGroup.LayoutParams.MATCH_PARENT,
|
// ViewGroup.LayoutParams.MATCH_PARENT,
|
||||||
ViewGroup.LayoutParams.MATCH_PARENT
|
// ViewGroup.LayoutParams.MATCH_PARENT
|
||||||
)
|
// )
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -569,75 +577,122 @@ class HomeFragment : Fragment(), HomeAdapter.OnItemClickListener, View.OnClickLi
|
||||||
// }
|
// }
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun showConfigureDownloadCard(type: String) {
|
private fun showConfigureSingleDownloadCard(item: ResultItem, type: String) {
|
||||||
// val sharedPreferences =
|
val sharedPreferences =
|
||||||
// context!!.getSharedPreferences("root_preferences", Activity.MODE_PRIVATE)
|
requireContext().getSharedPreferences("root_preferences", Activity.MODE_PRIVATE)
|
||||||
// val editor = sharedPreferences.edit()
|
val embedSubs = sharedPreferences.getBoolean("embed_subtitles", false)
|
||||||
// try {
|
val addChapters = sharedPreferences.getBoolean("add_chapters", false)
|
||||||
// bottomSheet = BottomSheetDialog(fragmentContext!!)
|
val saveThumb = sharedPreferences.getBoolean("write_thumbnail", false)
|
||||||
// bottomSheet!!.requestWindowFeature(Window.FEATURE_NO_TITLE)
|
|
||||||
|
var downloadItem = DownloadItem(
|
||||||
|
item.url,
|
||||||
|
item.title,
|
||||||
|
item.author,
|
||||||
|
item.thumb,
|
||||||
|
item.duration,
|
||||||
|
type,
|
||||||
|
"", "", "", "", 0, "", false,
|
||||||
|
"", item.website, "", item.playlistTitle, embedSubs, addChapters, saveThumb, "",
|
||||||
|
"", "", 0
|
||||||
|
)
|
||||||
|
|
||||||
|
val editor = sharedPreferences.edit()
|
||||||
|
try {
|
||||||
|
bottomSheet = BottomSheetDialog(fragmentContext!!)
|
||||||
|
bottomSheet!!.requestWindowFeature(Window.FEATURE_NO_TITLE)
|
||||||
|
bottomSheet!!.setContentView(R.layout.home_download_single_bottom_sheet)
|
||||||
|
val title = bottomSheet!!.findViewById<TextInputLayout>(R.id.title_textinput)
|
||||||
|
title!!.editText!!.setText(item.title)
|
||||||
|
title.editText!!.addTextChangedListener(object: TextWatcher {
|
||||||
|
override fun beforeTextChanged(p0: CharSequence?, p1: Int, p2: Int, p3: Int) {}
|
||||||
|
override fun onTextChanged(p0: CharSequence?, p1: Int, p2: Int, p3: Int) {}
|
||||||
|
override fun afterTextChanged(p0: Editable?) {
|
||||||
|
downloadItem.title = p0.toString()
|
||||||
|
item.title = p0.toString()
|
||||||
|
resultViewModel.update(item)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
val author = bottomSheet!!.findViewById<TextInputLayout>(R.id.author_textinput)
|
||||||
|
author!!.editText!!.setText(item.author)
|
||||||
|
author.editText!!.addTextChangedListener(object: TextWatcher {
|
||||||
|
override fun beforeTextChanged(p0: CharSequence?, p1: Int, p2: Int, p3: Int) {}
|
||||||
|
override fun onTextChanged(p0: CharSequence?, p1: Int, p2: Int, p3: Int) {}
|
||||||
|
override fun afterTextChanged(p0: Editable?) {
|
||||||
|
downloadItem.author = p0.toString()
|
||||||
|
item.author = p0.toString()
|
||||||
|
resultViewModel.update(item)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
var formats = resultViewModel.getFormats(item, type)
|
||||||
|
Log.e(TAG, formats.toString())
|
||||||
|
val formatTitles = formats.map {
|
||||||
|
if (it.format_note.contains("AUDIO_QUALITY_"))
|
||||||
|
it.format_note.replace("AUDIO_QUALITY_", "") +
|
||||||
|
if (it.filesize == 0L) "" else " / " + convertFileSize(it.filesize)
|
||||||
|
else it.format_note +
|
||||||
|
if (it.filesize == 0L) "" else " / " + convertFileSize(it.filesize)}
|
||||||
|
|
||||||
|
val format = bottomSheet!!.findViewById<TextInputLayout>(R.id.format)
|
||||||
|
val autoCompleteTextView = bottomSheet!!.findViewById<AutoCompleteTextView>(R.id.format_textview)
|
||||||
|
autoCompleteTextView?.setAdapter(ArrayAdapter(requireContext(), android.R.layout.simple_dropdown_item_1line, formatTitles))
|
||||||
|
autoCompleteTextView!!.setText(formatTitles[formats.lastIndex], false)
|
||||||
|
(format!!.editText as AutoCompleteTextView?)!!.onItemClickListener =
|
||||||
|
AdapterView.OnItemClickListener { _: AdapterView<*>?, _: View?, index: Int, _: Long ->
|
||||||
|
when(type){
|
||||||
|
"audio" -> {
|
||||||
|
downloadItem.audioFormat = formats[index].format
|
||||||
|
downloadItem.audioFormatId = formats[index].format_id
|
||||||
|
}
|
||||||
|
|
||||||
|
"video" -> {
|
||||||
|
downloadItem.videoFormat = formats[index].format
|
||||||
|
downloadItem.videoFormatId = formats[index].format_id
|
||||||
|
}
|
||||||
|
|
||||||
|
"command" -> {
|
||||||
|
downloadItem.customTemplateId = formats[index].format_id.toInt()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
lateinit var selectedContainer : String
|
||||||
|
val containers = when (type){
|
||||||
|
"audio" -> requireContext().resources.getStringArray(R.array.audio_containers)
|
||||||
|
"video" -> requireContext().resources.getStringArray(R.array.video_containers)
|
||||||
|
else -> null
|
||||||
|
}
|
||||||
|
val container = bottomSheet!!.findViewById<TextInputLayout>(R.id.downloadContainer)
|
||||||
|
val containerAutoCompleteTextView = bottomSheet!!.findViewById<AutoCompleteTextView>(R.id.container_textview)
|
||||||
|
if (containers == null){
|
||||||
|
containerAutoCompleteTextView!!.setText(getString(R.string.custom_command), false)
|
||||||
|
containerAutoCompleteTextView.isClickable = false
|
||||||
|
containerAutoCompleteTextView.isLongClickable = false
|
||||||
|
}else{
|
||||||
|
// val containerTitles = containers.map {
|
||||||
|
// if (it.format_note.contains("AUDIO_QUALITY_"))
|
||||||
|
// it.format_note.replace("AUDIO_QUALITY_", "") + " / " + convertFileSize(it.filesize)
|
||||||
|
// else it.format_note + " / " + convertFileSize(it.filesize) }
|
||||||
|
|
||||||
|
selectedContainer = when(type){
|
||||||
|
"audio" -> formats.find { downloadItem.audioFormat == it.format }?.ext ?: sharedPreferences.getString("audio_format", "mp3")!!
|
||||||
|
else -> formats.find { downloadItem.videoFormat == it.format }?.ext ?: sharedPreferences.getString("video_format", "DEFAULT")!!
|
||||||
|
}
|
||||||
|
containerAutoCompleteTextView!!.setText(selectedContainer, false)
|
||||||
|
(container!!.editText as AutoCompleteTextView?)!!.onItemClickListener =
|
||||||
|
AdapterView.OnItemClickListener { _: AdapterView<*>?, _: View?, index: Int, _: Long ->
|
||||||
|
downloadItem.ext = containers[index]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// when(type) {
|
||||||
|
// "audio" -> {
|
||||||
|
//
|
||||||
|
// }
|
||||||
|
// }
|
||||||
// if (type == "audio") {
|
// if (type == "audio") {
|
||||||
// bottomSheet!!.setContentView(R.layout.home_download_audio_bottom_sheet)
|
|
||||||
// val title = bottomSheet!!.findViewById<TextInputLayout>(R.id.title_textinput)
|
|
||||||
// if (selectedObjects!!.size > 1) {
|
|
||||||
// title!!.editText!!.setText(getString(R.string.mutliple_titles))
|
|
||||||
// title.editText!!.isClickable = false
|
|
||||||
// title.editText!!.isLongClickable = false
|
|
||||||
// } else {
|
|
||||||
// title!!.editText!!.setText(selectedObjects!![0]!!.title)
|
|
||||||
// title.editText!!.addTextChangedListener(object : TextWatcher {
|
|
||||||
// override fun beforeTextChanged(
|
|
||||||
// charSequence: CharSequence,
|
|
||||||
// i: Int,
|
|
||||||
// i1: Int,
|
|
||||||
// i2: Int
|
|
||||||
// ) {
|
|
||||||
// }
|
|
||||||
//
|
//
|
||||||
// override fun onTextChanged(
|
|
||||||
// charSequence: CharSequence,
|
|
||||||
// i: Int,
|
|
||||||
// i1: Int,
|
|
||||||
// i2: Int
|
|
||||||
// ) {
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// override fun afterTextChanged(editable: Editable) {
|
|
||||||
// val index = resultsList!!.indexOf(selectedObjects!![0])
|
|
||||||
// resultsList!![index]!!.title = editable.toString()
|
|
||||||
// }
|
|
||||||
// })
|
|
||||||
// }
|
|
||||||
// val author = bottomSheet!!.findViewById<TextInputLayout>(R.id.author_textinput)
|
|
||||||
// if (selectedObjects!!.size > 1) {
|
|
||||||
// author!!.editText!!.setText(getString(R.string.mutliple_authors))
|
|
||||||
// author.editText!!.isClickable = false
|
|
||||||
// author.editText!!.isLongClickable = false
|
|
||||||
// } else {
|
|
||||||
// author!!.editText!!.setText(selectedObjects!![0]!!.author)
|
|
||||||
// author.editText!!.addTextChangedListener(object : TextWatcher {
|
|
||||||
// override fun beforeTextChanged(
|
|
||||||
// charSequence: CharSequence,
|
|
||||||
// i: Int,
|
|
||||||
// i1: Int,
|
|
||||||
// i2: Int
|
|
||||||
// ) {
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// override fun onTextChanged(
|
|
||||||
// charSequence: CharSequence,
|
|
||||||
// i: Int,
|
|
||||||
// i1: Int,
|
|
||||||
// i2: Int
|
|
||||||
// ) {
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// override fun afterTextChanged(editable: Editable) {
|
|
||||||
// val index = resultsList!!.indexOf(selectedObjects!![0])
|
|
||||||
// resultsList!![index]!!.author = editable.toString()
|
|
||||||
// }
|
|
||||||
// })
|
|
||||||
// }
|
|
||||||
// val audioFormats = context!!.resources.getStringArray(R.array.music_formats)
|
// val audioFormats = context!!.resources.getStringArray(R.array.music_formats)
|
||||||
// val audioFormat = bottomSheet!!.findViewById<TextInputLayout>(R.id.audio_format)
|
// val audioFormat = bottomSheet!!.findViewById<TextInputLayout>(R.id.audio_format)
|
||||||
// val autoCompleteTextView =
|
// val autoCompleteTextView =
|
||||||
|
|
@ -687,8 +742,8 @@ class HomeFragment : Fragment(), HomeAdapter.OnItemClickListener, View.OnClickLi
|
||||||
// }
|
// }
|
||||||
// })
|
// })
|
||||||
// }
|
// }
|
||||||
// val videoFormats = context!!.resources.getStringArray(R.array.video_formats)
|
// val videoFormats = context!!.resources.getStringArray(R.array.video_containers)
|
||||||
// val videoQualities = context!!.resources.getStringArray(R.array.video_quality)
|
// val videoQualities = context!!.resources.getStringArray(R.array.video_formats)
|
||||||
// val videoFormat = bottomSheet!!.findViewById<TextInputLayout>(R.id.video_format)
|
// val videoFormat = bottomSheet!!.findViewById<TextInputLayout>(R.id.video_format)
|
||||||
// var autoCompleteTextView =
|
// var autoCompleteTextView =
|
||||||
// bottomSheet!!.findViewById<AutoCompleteTextView>(R.id.video_format_textview)
|
// bottomSheet!!.findViewById<AutoCompleteTextView>(R.id.video_format_textview)
|
||||||
|
|
@ -773,14 +828,21 @@ class HomeFragment : Fragment(), HomeAdapter.OnItemClickListener, View.OnClickLi
|
||||||
// }
|
// }
|
||||||
// bottomSheet!!.cancel()
|
// bottomSheet!!.cancel()
|
||||||
// }
|
// }
|
||||||
// bottomSheet!!.show()
|
bottomSheet!!.show()
|
||||||
// bottomSheet!!.window!!.setLayout(
|
bottomSheet!!.window!!.setLayout(
|
||||||
// ViewGroup.LayoutParams.MATCH_PARENT,
|
ViewGroup.LayoutParams.MATCH_PARENT,
|
||||||
// ViewGroup.LayoutParams.MATCH_PARENT
|
ViewGroup.LayoutParams.MATCH_PARENT
|
||||||
// )
|
)
|
||||||
// } catch (e: Exception) {
|
} catch (e: Exception) {
|
||||||
// Toast.makeText(fragmentContext, e.message, Toast.LENGTH_LONG).show()
|
Log.e(TAG, e.printStackTrace().toString());
|
||||||
// }
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun convertFileSize(s: Long): String{
|
||||||
|
if (s <= 0) return "0"
|
||||||
|
val units = arrayOf("B", "kB", "MB", "GB", "TB")
|
||||||
|
val digitGroups = (log10(s.toDouble()) / log10(1024.0)).toInt()
|
||||||
|
return DecimalFormat("#,##0.#").format(s / 1024.0.pow(digitGroups.toDouble())) + " " + units[digitGroups]
|
||||||
}
|
}
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
|
|
|
||||||
|
|
@ -59,8 +59,8 @@ class DownloadWorker(
|
||||||
|
|
||||||
val tempFolder = StringBuilder(context.cacheDir.absolutePath + """/${downloadItem.title}##${downloadItem.type}""")
|
val tempFolder = StringBuilder(context.cacheDir.absolutePath + """/${downloadItem.title}##${downloadItem.type}""")
|
||||||
when(type){
|
when(type){
|
||||||
"audio" -> tempFolder.append("##${downloadItem.audioQualityId}")
|
"audio" -> tempFolder.append("##${downloadItem.audioFormatId}")
|
||||||
"video" -> tempFolder.append("##${downloadItem.videoQualityId}")
|
"video" -> tempFolder.append("##${downloadItem.videoFormatId}")
|
||||||
"command" -> tempFolder.append("##${downloadItem.customTemplateId}")
|
"command" -> tempFolder.append("##${downloadItem.customTemplateId}")
|
||||||
}
|
}
|
||||||
var tempFileDir = File(tempFolder.toString())
|
var tempFileDir = File(tempFolder.toString())
|
||||||
|
|
@ -95,7 +95,7 @@ class DownloadWorker(
|
||||||
when(type){
|
when(type){
|
||||||
"audio" -> {
|
"audio" -> {
|
||||||
request.addOption("-x")
|
request.addOption("-x")
|
||||||
var audioQualityId : String = downloadItem.audioQualityId
|
var audioQualityId : String = downloadItem.audioFormatId
|
||||||
if (audioQualityId == "0") audioQualityId = "ba"
|
if (audioQualityId == "0") audioQualityId = "ba"
|
||||||
var format = downloadItem.audioFormat
|
var format = downloadItem.audioFormat
|
||||||
if (format.isEmpty()){
|
if (format.isEmpty()){
|
||||||
|
|
@ -110,7 +110,7 @@ class DownloadWorker(
|
||||||
request.addOption("--embed-thumbnail")
|
request.addOption("--embed-thumbnail")
|
||||||
request.addOption("--convert-thumbnails", "png")
|
request.addOption("--convert-thumbnails", "png")
|
||||||
try {
|
try {
|
||||||
val config = File(context.cacheDir, "config" + downloadItem.title + "##" + downloadItem.audioQualityId + ".txt")
|
val config = File(context.cacheDir, "config" + downloadItem.title + "##" + downloadItem.audioFormatId + ".txt")
|
||||||
val configData =
|
val configData =
|
||||||
"--ppa \"ffmpeg: -c:v png -vf crop=\\\"'if(gt(ih,iw),iw,ih)':'if(gt(iw,ih),ih,iw)'\\\"\""
|
"--ppa \"ffmpeg: -c:v png -vf crop=\\\"'if(gt(ih,iw),iw,ih)':'if(gt(iw,ih),ih,iw)'\\\"\""
|
||||||
config.writeText(configData)
|
config.writeText(configData)
|
||||||
|
|
@ -142,8 +142,8 @@ class DownloadWorker(
|
||||||
if (embedSubs) {
|
if (embedSubs) {
|
||||||
request.addOption("--embed-subs", "")
|
request.addOption("--embed-subs", "")
|
||||||
}
|
}
|
||||||
var videoQualityId = downloadItem.videoQualityId
|
var videoQualityId = downloadItem.videoFormatId
|
||||||
val audioQualityId = downloadItem.audioQualityId
|
val audioQualityId = downloadItem.audioFormatId
|
||||||
if (videoQualityId.isEmpty()) videoQualityId = "bestvideo"
|
if (videoQualityId.isEmpty()) videoQualityId = "bestvideo"
|
||||||
val formatArgument = StringBuilder(videoQualityId)
|
val formatArgument = StringBuilder(videoQualityId)
|
||||||
if (videoQualityId != "worst"){
|
if (videoQualityId != "worst"){
|
||||||
|
|
|
||||||
|
|
@ -9,76 +9,86 @@
|
||||||
android:layout_height="match_parent"
|
android:layout_height="match_parent"
|
||||||
android:orientation="vertical">
|
android:orientation="vertical">
|
||||||
|
|
||||||
|
|
||||||
|
<com.google.android.material.textfield.TextInputLayout
|
||||||
|
android:id="@+id/title_textinput"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginTop="15dp"
|
||||||
|
app:errorEnabled="true"
|
||||||
|
android:hint="@string/title"
|
||||||
|
style="@style/Widget.Material3.TextInputLayout.FilledBox">
|
||||||
|
|
||||||
|
<com.google.android.material.textfield.TextInputEditText
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:inputType="text"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
/>
|
||||||
|
|
||||||
|
</com.google.android.material.textfield.TextInputLayout>
|
||||||
|
|
||||||
|
<com.google.android.material.textfield.TextInputLayout
|
||||||
|
android:id="@+id/author_textinput"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
app:errorEnabled="true"
|
||||||
|
android:hint="@string/author"
|
||||||
|
style="@style/Widget.Material3.TextInputLayout.FilledBox">
|
||||||
|
|
||||||
|
<com.google.android.material.textfield.TextInputEditText
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:inputType="text"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
/>
|
||||||
|
|
||||||
|
</com.google.android.material.textfield.TextInputLayout>
|
||||||
|
|
||||||
<LinearLayout
|
<LinearLayout
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:orientation="vertical"
|
android:paddingBottom="15dp"
|
||||||
>
|
android:orientation="horizontal">
|
||||||
|
|
||||||
<com.google.android.material.textfield.TextInputLayout
|
<com.google.android.material.textfield.TextInputLayout
|
||||||
android:id="@+id/title_textinput"
|
android:id="@+id/downloadContainer"
|
||||||
android:layout_width="match_parent"
|
style="@style/Widget.Material3.TextInputLayout.FilledBox.ExposedDropdownMenu"
|
||||||
|
android:layout_width="0dp"
|
||||||
|
android:layout_weight="30"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_marginTop="15dp"
|
android:hint="@string/container">
|
||||||
app:errorEnabled="true"
|
|
||||||
android:hint="@string/title"
|
|
||||||
style="@style/Widget.Material3.TextInputLayout.FilledBox">
|
|
||||||
|
|
||||||
<com.google.android.material.textfield.TextInputEditText
|
<AutoCompleteTextView
|
||||||
|
android:id="@+id/container_textview"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:inputType="text"
|
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
|
android:inputType="none"
|
||||||
|
app:simpleItems="@array/audio_containers"
|
||||||
/>
|
/>
|
||||||
|
|
||||||
</com.google.android.material.textfield.TextInputLayout>
|
</com.google.android.material.textfield.TextInputLayout>
|
||||||
|
|
||||||
<LinearLayout
|
<com.google.android.material.textfield.TextInputLayout
|
||||||
android:layout_width="match_parent"
|
android:id="@+id/format"
|
||||||
|
style="@style/Widget.Material3.TextInputLayout.FilledBox.ExposedDropdownMenu"
|
||||||
|
android:layout_width="0dp"
|
||||||
|
android:paddingStart="10dp"
|
||||||
|
android:layout_weight="65"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:orientation="horizontal">
|
android:hint="@string/format">
|
||||||
|
|
||||||
<com.google.android.material.textfield.TextInputLayout
|
<AutoCompleteTextView
|
||||||
android:id="@+id/author_textinput"
|
android:id="@+id/format_textview"
|
||||||
android:layout_width="0dp"
|
android:layout_width="match_parent"
|
||||||
android:layout_weight="45"
|
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
app:errorEnabled="true"
|
android:inputType="none"
|
||||||
android:hint="@string/author"
|
app:simpleItems="@array/audio_formats"
|
||||||
style="@style/Widget.Material3.TextInputLayout.FilledBox">
|
/>
|
||||||
|
|
||||||
<com.google.android.material.textfield.TextInputEditText
|
</com.google.android.material.textfield.TextInputLayout>
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:inputType="text"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
/>
|
|
||||||
|
|
||||||
</com.google.android.material.textfield.TextInputLayout>
|
|
||||||
|
|
||||||
<com.google.android.material.textfield.TextInputLayout
|
|
||||||
android:id="@+id/audio_format"
|
|
||||||
style="@style/Widget.Material3.TextInputLayout.FilledBox.ExposedDropdownMenu"
|
|
||||||
android:layout_width="0dp"
|
|
||||||
android:paddingStart="10dp"
|
|
||||||
android:layout_weight="45"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:hint="@string/audio_format">
|
|
||||||
|
|
||||||
<AutoCompleteTextView
|
|
||||||
android:id="@+id/audio_format_textview"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:inputType="none"
|
|
||||||
app:simpleItems="@array/music_formats"
|
|
||||||
/>
|
|
||||||
|
|
||||||
</com.google.android.material.textfield.TextInputLayout>
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
</LinearLayout>
|
|
||||||
|
|
||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
|
|
||||||
|
|
||||||
<com.google.android.material.textfield.TextInputLayout
|
<com.google.android.material.textfield.TextInputLayout
|
||||||
android:id="@+id/outputPath_textinput"
|
android:id="@+id/outputPath_textinput"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
|
|
|
||||||
|
|
@ -31,34 +31,51 @@
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_gravity="bottom"
|
android:layout_gravity="bottom"
|
||||||
android:gravity="end"
|
android:paddingTop="10dp"
|
||||||
android:orientation="horizontal">
|
android:orientation="horizontal">
|
||||||
|
|
||||||
<Button
|
|
||||||
style="?attr/materialIconButtonOutlinedStyle"
|
|
||||||
android:id="@+id/bottomsheet_cancel_button"
|
|
||||||
android:layout_width="wrap_content"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_marginEnd="10dp"
|
|
||||||
app:icon="@drawable/ic_cancel" />
|
|
||||||
|
|
||||||
<Button
|
<Button
|
||||||
style="@style/Widget.Material3.Button.ElevatedButton.Icon"
|
style="@style/Widget.Material3.Button.ElevatedButton.Icon"
|
||||||
|
android:textSize="11sp"
|
||||||
android:id="@+id/bottomsheet_schedule_button"
|
android:id="@+id/bottomsheet_schedule_button"
|
||||||
|
android:padding="10dp"
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_marginEnd="10dp"
|
android:layout_marginEnd="10dp"
|
||||||
app:icon="@drawable/ic_clock"
|
app:icon="@drawable/ic_clock"
|
||||||
android:text="@string/schedule" />
|
android:text="@string/schedule" />
|
||||||
|
|
||||||
<Button
|
<LinearLayout
|
||||||
style="@style/Widget.Material3.Button.ElevatedButton.Icon"
|
android:layout_width="match_parent"
|
||||||
android:id="@+id/bottomsheet_download_button"
|
android:layout_height="match_parent"
|
||||||
android:layout_width="wrap_content"
|
android:layout_gravity="bottom"
|
||||||
android:layout_height="wrap_content"
|
android:gravity="end"
|
||||||
android:text="@string/download"
|
android:orientation="horizontal">
|
||||||
app:icon="@drawable/ic_down"
|
|
||||||
android:autoLink="all"/>
|
<Button
|
||||||
|
style="@style/Widget.Material3.Button.OutlinedButton.Icon"
|
||||||
|
android:textSize="11sp"
|
||||||
|
android:padding="10dp"
|
||||||
|
android:id="@+id/bottomsheet_cancel_button"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:text="@string/cancel"
|
||||||
|
android:layout_marginEnd="10dp"
|
||||||
|
app:icon="@drawable/ic_cancel" />
|
||||||
|
|
||||||
|
<Button
|
||||||
|
style="@style/Widget.Material3.Button.ElevatedButton.Icon"
|
||||||
|
android:textSize="11sp"
|
||||||
|
android:padding="10dp"
|
||||||
|
android:id="@+id/bottomsheet_download_button"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:text="@string/download"
|
||||||
|
app:icon="@drawable/ic_down"
|
||||||
|
android:autoLink="all"/>
|
||||||
|
|
||||||
|
</LinearLayout>
|
||||||
|
|
||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
<resources>
|
<resources>
|
||||||
<string-array name="music_formats">
|
<string-array name="audio_containers">
|
||||||
<item>mp3</item>
|
<item>mp3</item>
|
||||||
<item>m4a</item>
|
<item>m4a</item>
|
||||||
<item>aac</item>
|
<item>aac</item>
|
||||||
|
|
@ -9,22 +9,27 @@
|
||||||
<item>wav</item>
|
<item>wav</item>
|
||||||
</string-array>
|
</string-array>
|
||||||
|
|
||||||
<string-array name="video_formats">
|
<string-array name="audio_formats">
|
||||||
<item>DEFAULT</item>
|
<item>@string/worst</item>
|
||||||
|
<item>@string/best</item>
|
||||||
|
</string-array>
|
||||||
|
|
||||||
|
<string-array name="video_containers">
|
||||||
|
<item>@string/defaultValue</item>
|
||||||
<item>mp4</item>
|
<item>mp4</item>
|
||||||
<item>mkv</item>
|
<item>mkv</item>
|
||||||
<item>webm</item>
|
<item>webm</item>
|
||||||
</string-array>
|
</string-array>
|
||||||
|
|
||||||
<string-array name="video_quality">
|
<string-array name="video_formats">
|
||||||
<item>Best Quality</item>
|
|
||||||
<item>2160p</item>
|
|
||||||
<item>1440p</item>
|
|
||||||
<item>1080p</item>
|
|
||||||
<item>720p</item>
|
|
||||||
<item>480p</item>
|
|
||||||
<item>360p</item>
|
|
||||||
<item>Worst Quality</item>
|
<item>Worst Quality</item>
|
||||||
|
<item>360p</item>
|
||||||
|
<item>480p</item>
|
||||||
|
<item>720p</item>
|
||||||
|
<item>1080p</item>
|
||||||
|
<item>1440p</item>
|
||||||
|
<item>2160p</item>
|
||||||
|
<item>Best Quality</item>
|
||||||
</string-array>
|
</string-array>
|
||||||
|
|
||||||
<string-array name="sponsorblock_settings_entries">
|
<string-array name="sponsorblock_settings_entries">
|
||||||
|
|
|
||||||
|
|
@ -160,4 +160,9 @@
|
||||||
<string name="schedule">Schedule</string>
|
<string name="schedule">Schedule</string>
|
||||||
<string name="concurrent_downloads">Concurrent Downloads</string>
|
<string name="concurrent_downloads">Concurrent Downloads</string>
|
||||||
<string name="concurrent_downloads_summary">Number of downloads executing at the same time</string>
|
<string name="concurrent_downloads_summary">Number of downloads executing at the same time</string>
|
||||||
|
<string name="best">Best</string>
|
||||||
|
<string name="worst">Worst</string>
|
||||||
|
<string name="defaultValue">Default</string>
|
||||||
|
<string name="format">Format</string>
|
||||||
|
<string name="container">Container</string>
|
||||||
</resources>
|
</resources>
|
||||||
|
|
@ -125,8 +125,8 @@
|
||||||
|
|
||||||
<ListPreference
|
<ListPreference
|
||||||
android:defaultValue="mp3"
|
android:defaultValue="mp3"
|
||||||
android:entries="@array/music_formats"
|
android:entries="@array/audio_containers"
|
||||||
android:entryValues="@array/music_formats"
|
android:entryValues="@array/audio_containers"
|
||||||
android:icon="@drawable/ic_code"
|
android:icon="@drawable/ic_code"
|
||||||
app:key="audio_format"
|
app:key="audio_format"
|
||||||
app:summary="mp3"
|
app:summary="mp3"
|
||||||
|
|
@ -134,8 +134,8 @@
|
||||||
|
|
||||||
<ListPreference
|
<ListPreference
|
||||||
android:defaultValue="mkv"
|
android:defaultValue="mkv"
|
||||||
android:entries="@array/video_formats"
|
android:entries="@array/video_containers"
|
||||||
android:entryValues="@array/video_formats"
|
android:entryValues="@array/video_containers"
|
||||||
android:icon="@drawable/ic_code"
|
android:icon="@drawable/ic_code"
|
||||||
app:key="video_format"
|
app:key="video_format"
|
||||||
app:summary="DEFAULT"
|
app:summary="DEFAULT"
|
||||||
|
|
@ -154,8 +154,8 @@
|
||||||
|
|
||||||
<ListPreference
|
<ListPreference
|
||||||
android:defaultValue="Best Quality"
|
android:defaultValue="Best Quality"
|
||||||
android:entries="@array/video_quality"
|
android:entries="@array/video_formats"
|
||||||
android:entryValues="@array/video_quality"
|
android:entryValues="@array/video_formats"
|
||||||
android:icon="@drawable/ic_video"
|
android:icon="@drawable/ic_video"
|
||||||
app:key="video_quality"
|
app:key="video_quality"
|
||||||
app:summary="Best Quality"
|
app:summary="Best Quality"
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue