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>
|
||||
</option>
|
||||
</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" />
|
||||
</component>
|
||||
<component name="ProjectType">
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@
|
|||
"formatVersion": 1,
|
||||
"database": {
|
||||
"version": 1,
|
||||
"identityHash": "5939be553c41327f4f64e1d62d008968",
|
||||
"identityHash": "c8effa77edcd8cf5e46a79fd1a791535",
|
||||
"entities": [
|
||||
{
|
||||
"tableName": "results",
|
||||
|
|
@ -198,7 +198,7 @@
|
|||
},
|
||||
{
|
||||
"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": [
|
||||
{
|
||||
"fieldPath": "url",
|
||||
|
|
@ -236,24 +236,6 @@
|
|||
"affinity": "TEXT",
|
||||
"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",
|
||||
"columnName": "audioFormat",
|
||||
|
|
@ -266,6 +248,24 @@
|
|||
"affinity": "TEXT",
|
||||
"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",
|
||||
"columnName": "formatDesc",
|
||||
|
|
@ -321,6 +321,18 @@
|
|||
"affinity": "INTEGER",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "ext",
|
||||
"columnName": "ext",
|
||||
"affinity": "TEXT",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "filesize",
|
||||
"columnName": "filesize",
|
||||
"affinity": "TEXT",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "status",
|
||||
"columnName": "status",
|
||||
|
|
@ -386,7 +398,7 @@
|
|||
"views": [],
|
||||
"setupQueries": [
|
||||
"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"?>
|
||||
<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.WRITE_EXTERNAL_STORAGE" />
|
||||
|
|
@ -77,6 +78,17 @@
|
|||
android:name="android.support.FILE_PROVIDER_PATHS"
|
||||
android:resource="@xml/provider_paths" />
|
||||
</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>
|
||||
|
||||
</manifest>
|
||||
|
|
@ -17,6 +17,7 @@ import androidx.core.app.ActivityCompat
|
|||
import androidx.core.view.WindowInsetsCompat
|
||||
import androidx.fragment.app.Fragment
|
||||
import androidx.fragment.app.FragmentManager
|
||||
import androidx.work.WorkManager
|
||||
import com.deniscerri.ytdlnis.DownloaderService.LocalBinder
|
||||
import com.deniscerri.ytdlnis.database.models.ResultItem
|
||||
import com.deniscerri.ytdlnis.databinding.ActivityMainBinding
|
||||
|
|
@ -38,17 +39,14 @@ import java.util.*
|
|||
import kotlin.system.exitProcess
|
||||
|
||||
class MainActivity : AppCompatActivity() {
|
||||
|
||||
private lateinit var binding: ActivityMainBinding
|
||||
lateinit var context: Context
|
||||
private lateinit var homeFragment: HomeFragment
|
||||
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
|
||||
private lateinit var listeners: ArrayList<IDownloaderListener>
|
||||
private var iDownloaderService: IDownloaderService? = null
|
||||
private lateinit var workManager: WorkManager
|
||||
|
||||
|
||||
private val serviceConnection: ServiceConnection = object : ServiceConnection {
|
||||
override fun onServiceConnected(className: ComponentName, service: IBinder) {
|
||||
|
|
@ -83,6 +81,8 @@ class MainActivity : AppCompatActivity() {
|
|||
reconnectDownloadService()
|
||||
checkUpdate()
|
||||
fm = supportFragmentManager
|
||||
workManager = WorkManager.getInstance(context)
|
||||
|
||||
homeFragment = HomeFragment()
|
||||
downloadsFragment = DownloadsFragment()
|
||||
moreFragment = MoreFragment()
|
||||
|
|
@ -256,6 +256,10 @@ class MainActivity : AppCompatActivity() {
|
|||
stopDownloadService()
|
||||
}
|
||||
|
||||
fun cancelAllDownloads() {
|
||||
workManager.cancelAllWork();
|
||||
}
|
||||
|
||||
fun removeItemFromDownloadQueue(video: ResultItem?, type: String?) {
|
||||
iDownloaderService!!.removeItemFromDownloadQueue(video, type)
|
||||
}
|
||||
|
|
@ -368,5 +372,11 @@ class MainActivity : AppCompatActivity() {
|
|||
|
||||
companion object {
|
||||
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,
|
||||
DBManager::class.java,
|
||||
"YTDLnisDatabase"
|
||||
).build()
|
||||
)
|
||||
.allowMainThreadQueries()
|
||||
.build()
|
||||
instance = dbInstance
|
||||
dbInstance
|
||||
}
|
||||
|
|
|
|||
|
|
@ -7,8 +7,8 @@ import com.deniscerri.ytdlnis.database.models.ResultItem
|
|||
|
||||
@Dao
|
||||
interface FormatDao {
|
||||
@Query("SELECT * FROM formats")
|
||||
fun getFormatsByItemId() : LiveData<List<Format>>
|
||||
@Query("SELECT * FROM formats WHERE itemId=:itemId")
|
||||
fun getFormatsByItemId(itemId: Int) : List<Format>
|
||||
|
||||
@Insert(onConflict = OnConflictStrategy.REPLACE)
|
||||
suspend fun insert(item: Format)
|
||||
|
|
|
|||
|
|
@ -6,32 +6,32 @@ import androidx.room.PrimaryKey
|
|||
|
||||
@Entity(tableName = "downloads")
|
||||
data class DownloadItem(
|
||||
val url: String,
|
||||
val title: String,
|
||||
val author: String,
|
||||
val thumb: String,
|
||||
val duration: String,
|
||||
val type: String,
|
||||
val audioQualityId: String,
|
||||
val videoQualityId: String,
|
||||
val customTemplateId: Int,
|
||||
val audioFormat: String,
|
||||
val videoFormat: String,
|
||||
val formatDesc: String,
|
||||
@ColumnInfo(defaultValue = "0")
|
||||
val url: String,
|
||||
var title: String,
|
||||
var author: String,
|
||||
val thumb: String,
|
||||
val duration: String,
|
||||
val type: String,
|
||||
var audioFormat: String,
|
||||
var videoFormat: String,
|
||||
var audioFormatId: String,
|
||||
var videoFormatId: String,
|
||||
var customTemplateId: Int,
|
||||
val formatDesc: String,
|
||||
@ColumnInfo(defaultValue = "0")
|
||||
val removeAudio: Boolean,
|
||||
val downloadPath: String,
|
||||
val website: String,
|
||||
val downloadSize: String,
|
||||
val playlistTitle: String,
|
||||
val embedSubs: Boolean,
|
||||
val addChapters: Boolean,
|
||||
val SaveThumb: Boolean,
|
||||
var ext: String,
|
||||
var filesize: String,
|
||||
@ColumnInfo(defaultValue = "Queued")
|
||||
val downloadPath: String,
|
||||
val website: String,
|
||||
val downloadSize: String,
|
||||
val playlistTitle: String,
|
||||
val embedSubs: Boolean,
|
||||
val addChapters: Boolean,
|
||||
val SaveThumb: Boolean,
|
||||
var ext: String,
|
||||
var filesize: String,
|
||||
@ColumnInfo(defaultValue = "Queued")
|
||||
var status: String,
|
||||
val workID: Int
|
||||
val workID: Int
|
||||
){
|
||||
@PrimaryKey(autoGenerate = true)
|
||||
var id: Int? = null
|
||||
|
|
|
|||
|
|
@ -5,13 +5,13 @@ import androidx.room.PrimaryKey
|
|||
|
||||
@Entity(tableName = "results")
|
||||
data class ResultItem(
|
||||
val url: String,
|
||||
val title: String,
|
||||
val author: String,
|
||||
val duration: String,
|
||||
val thumb: String,
|
||||
val website: String,
|
||||
var playlistTitle: String
|
||||
val url: String,
|
||||
var title: String,
|
||||
var author: String,
|
||||
val duration: String,
|
||||
val thumb: String,
|
||||
val website: String,
|
||||
var playlistTitle: String
|
||||
){
|
||||
@PrimaryKey(autoGenerate = true)
|
||||
var id: Int? = null
|
||||
|
|
|
|||
|
|
@ -3,13 +3,15 @@ package com.deniscerri.ytdlnis.database.repository
|
|||
import android.content.Context
|
||||
import android.util.Log
|
||||
import androidx.lifecycle.LiveData
|
||||
import com.deniscerri.ytdlnis.database.dao.CommandTemplateDao
|
||||
import com.deniscerri.ytdlnis.database.dao.FormatDao
|
||||
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.ResultItem
|
||||
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"
|
||||
val allResults : LiveData<List<ResultItem>> = resultDao.getResults()
|
||||
|
||||
|
|
@ -119,5 +121,12 @@ class ResultRepository(private val resultDao: ResultDao, private val formatDao:
|
|||
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
|
||||
|
||||
import android.app.Application
|
||||
import android.content.Context
|
||||
import android.util.Log
|
||||
import androidx.lifecycle.*
|
||||
import com.deniscerri.ytdlnis.App
|
||||
import com.deniscerri.ytdlnis.R
|
||||
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.repository.ResultRepository
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.launch
|
||||
import java.util.regex.Pattern
|
||||
import kotlin.coroutines.coroutineContext
|
||||
|
||||
class ResultViewModel(application: Application) : AndroidViewModel(application) {
|
||||
private val tag: String = "ResultViewModel"
|
||||
|
|
@ -19,7 +25,8 @@ class ResultViewModel(application: Application) : AndroidViewModel(application)
|
|||
init {
|
||||
val dao = DBManager.getInstance(application).resultDao
|
||||
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
|
||||
loadingItems.postValue(false)
|
||||
}
|
||||
|
|
@ -86,4 +93,31 @@ class ResultViewModel(application: Application) : AndroidViewModel(application)
|
|||
fun update(item: ResultItem) = viewModelScope.launch(Dispatchers.IO){
|
||||
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(
|
||||
this,
|
||||
activity
|
||||
requireActivity()
|
||||
)
|
||||
recyclerView = view.findViewById(R.id.recyclerviewdownloadss)
|
||||
recyclerView?.layoutManager = LinearLayoutManager(context)
|
||||
|
|
|
|||
|
|
@ -7,13 +7,17 @@ import android.content.Intent
|
|||
import android.os.Bundle
|
||||
import android.os.Handler
|
||||
import android.os.Looper
|
||||
import android.text.Editable
|
||||
import android.text.InputType
|
||||
import android.text.TextWatcher
|
||||
import android.util.Log
|
||||
import android.view.*
|
||||
import android.view.View.GONE
|
||||
import android.view.View.VISIBLE
|
||||
import android.widget.*
|
||||
import androidx.appcompat.widget.SearchView
|
||||
import androidx.coordinatorlayout.widget.CoordinatorLayout
|
||||
import androidx.core.text.trimmedLength
|
||||
import androidx.fragment.app.Fragment
|
||||
import androidx.lifecycle.ViewModelProvider
|
||||
import androidx.recyclerview.widget.LinearLayoutManager
|
||||
|
|
@ -22,6 +26,7 @@ import com.deniscerri.ytdlnis.MainActivity
|
|||
import com.deniscerri.ytdlnis.R
|
||||
import com.deniscerri.ytdlnis.adapter.HomeAdapter
|
||||
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.viewmodel.ResultViewModel
|
||||
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.progressindicator.LinearProgressIndicator
|
||||
import com.google.android.material.textfield.TextInputLayout
|
||||
import kotlinx.coroutines.runBlocking
|
||||
import java.text.DecimalFormat
|
||||
import java.util.*
|
||||
import kotlin.math.log10
|
||||
import kotlin.math.pow
|
||||
|
||||
class HomeFragment : Fragment(), HomeAdapter.OnItemClickListener, View.OnClickListener {
|
||||
private var progressBar: LinearProgressIndicator? = null
|
||||
|
|
@ -121,7 +130,7 @@ class HomeFragment : Fragment(), HomeAdapter.OnItemClickListener, View.OnClickLi
|
|||
homeAdapter =
|
||||
HomeAdapter(
|
||||
this,
|
||||
activity
|
||||
requireActivity()
|
||||
)
|
||||
recyclerView = view.findViewById(R.id.recyclerViewHome)
|
||||
recyclerView?.layoutManager = LinearLayoutManager(context)
|
||||
|
|
@ -336,11 +345,10 @@ class HomeFragment : Fragment(), HomeAdapter.OnItemClickListener, View.OnClickLi
|
|||
selectedObjects = ArrayList()
|
||||
downloadAllFabCoordinator!!.visibility = GONE
|
||||
downloadFabs!!.visibility = GONE
|
||||
}
|
||||
// } else if (itemId == R.id.cancel_download) {
|
||||
// try {
|
||||
// mainActivity!!.cancelDownloadService()
|
||||
// topAppBar!!.menu.findItem(itemId).isVisible = false
|
||||
} else if (itemId == R.id.cancel_download) {
|
||||
try {
|
||||
mainActivity!!.cancelAllDownloads()
|
||||
topAppBar!!.menu.findItem(itemId).isVisible = false
|
||||
// for (i in downloadInfo!!.downloadQueue.indices) {
|
||||
// val vid = downloadInfo!!.downloadQueue[i]
|
||||
// val type = vid.downloadedType
|
||||
|
|
@ -348,9 +356,9 @@ class HomeFragment : Fragment(), HomeAdapter.OnItemClickListener, View.OnClickLi
|
|||
// }
|
||||
// downloadQueue = ArrayList()
|
||||
// downloading = false
|
||||
// } catch (ignored: Exception) {
|
||||
// }
|
||||
// }
|
||||
} catch (ignored: Exception) {
|
||||
}
|
||||
}
|
||||
true
|
||||
}
|
||||
}
|
||||
|
|
@ -380,11 +388,11 @@ class HomeFragment : Fragment(), HomeAdapter.OnItemClickListener, View.OnClickLi
|
|||
}
|
||||
|
||||
@SuppressLint("ResourceType")
|
||||
override fun onButtonClick(position: Int, type: String) {
|
||||
// Log.e(TAG, type)
|
||||
// val vid = resultsList!![position]
|
||||
// vid!!.downloadedType = type
|
||||
// val btn = recyclerView!!.findViewWithTag<MaterialButton>(vid.videoId + "##" + type)
|
||||
override fun onButtonClick(videoURL: String, type: String?) {
|
||||
Log.e(TAG, type!! + " " + videoURL)
|
||||
val item = resultsList!!.find { it?.url == videoURL }
|
||||
Log.e(TAG, resultsList!![0].toString() + " " + videoURL)
|
||||
val btn = recyclerView!!.findViewWithTag<MaterialButton>("""${item?.url}##$type""")
|
||||
// if (downloading) {
|
||||
// try {
|
||||
// if (btn.getTag(R.id.cancelDownload) == "true") {
|
||||
|
|
@ -394,20 +402,20 @@ class HomeFragment : Fragment(), HomeAdapter.OnItemClickListener, View.OnClickLi
|
|||
// } catch (ignored: Exception) {
|
||||
// }
|
||||
// }
|
||||
// val sharedPreferences =
|
||||
// context!!.getSharedPreferences("root_preferences", Activity.MODE_PRIVATE)
|
||||
// if (sharedPreferences.getBoolean("download_card", true)) {
|
||||
val sharedPreferences =
|
||||
requireContext().getSharedPreferences("root_preferences", Activity.MODE_PRIVATE)
|
||||
if (sharedPreferences.getBoolean("download_card", true)) {
|
||||
// selectedObjects!!.clear()
|
||||
// selectedObjects!!.add(resultsList!![position])
|
||||
// showConfigureDownloadCard(type)
|
||||
// } else {
|
||||
// selectedObjects!!.add(item!!)
|
||||
showConfigureSingleDownloadCard(item!!, type)
|
||||
} else {
|
||||
// downloadQueue!!.add(vid)
|
||||
// updateDownloadingStatusOnResult(vid, type, true)
|
||||
// if (isStoragePermissionGranted) {
|
||||
// mainActivity!!.startDownloadService(downloadQueue, listener)
|
||||
// downloadQueue!!.clear()
|
||||
// }
|
||||
// }
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -436,8 +444,8 @@ class HomeFragment : Fragment(), HomeAdapter.OnItemClickListener, View.OnClickLi
|
|||
// }
|
||||
}
|
||||
|
||||
override fun onCardClick(position: Int, add: Boolean) {
|
||||
val item = resultsList!![position]
|
||||
override fun onCardClick(videoURL: String, add: Boolean) {
|
||||
val item = resultsList?.find { it -> it?.url == videoURL }
|
||||
if (add) selectedObjects!!.add(item!!) else selectedObjects!!.remove(item)
|
||||
if (selectedObjects!!.size > 1) {
|
||||
downloadAllFabCoordinator!!.visibility = GONE
|
||||
|
|
@ -456,7 +464,7 @@ class HomeFragment : Fragment(), HomeAdapter.OnItemClickListener, View.OnClickLi
|
|||
} catch (e: Exception) {
|
||||
""
|
||||
}
|
||||
if (!viewIdName.isEmpty()) {
|
||||
if (viewIdName.isNotEmpty()) {
|
||||
if (viewIdName.contains("audio") || viewIdName.contains("video")) {
|
||||
val buttonData =
|
||||
viewIdName.split("##".toRegex()).dropLastWhile { it.isEmpty() }.toTypedArray()
|
||||
|
|
@ -465,39 +473,39 @@ class HomeFragment : Fragment(), HomeAdapter.OnItemClickListener, View.OnClickLi
|
|||
}
|
||||
}
|
||||
if (viewIdName == "downloadAll") {
|
||||
//remove previously selected
|
||||
for (i in selectedObjects!!.indices) {
|
||||
val vid = findVideo(
|
||||
selectedObjects!![i].url
|
||||
)
|
||||
homeAdapter!!.notifyItemChanged(resultsList!!.indexOf(vid))
|
||||
}
|
||||
selectedObjects = ArrayList()
|
||||
downloadFabs!!.visibility = GONE
|
||||
bottomSheet = BottomSheetDialog(fragmentContext!!)
|
||||
bottomSheet!!.requestWindowFeature(Window.FEATURE_NO_TITLE)
|
||||
bottomSheet!!.setContentView(R.layout.home_download_all_bottom_sheet)
|
||||
val first = bottomSheet!!.findViewById<TextInputLayout>(R.id.first_textinput)
|
||||
first!!.editText!!.setText(1.toString())
|
||||
val last = bottomSheet!!.findViewById<TextInputLayout>(R.id.last_textinput)
|
||||
last!!.editText!!.setText(resultsList!!.size.toString())
|
||||
val audio = bottomSheet!!.findViewById<Button>(R.id.bottomsheet_audio_button)
|
||||
audio!!.setOnClickListener {
|
||||
val start = first.editText!!.text.toString().toInt()
|
||||
val end = last.editText!!.text.toString().toInt()
|
||||
initDownloadAll(bottomSheet!!, start, end, "audio")
|
||||
}
|
||||
val video = bottomSheet!!.findViewById<Button>(R.id.bottomsheet_video_button)
|
||||
video!!.setOnClickListener {
|
||||
val start = first.editText!!.text.toString().toInt()
|
||||
val end = last.editText!!.text.toString().toInt()
|
||||
initDownloadAll(bottomSheet!!, start, end, "video")
|
||||
}
|
||||
bottomSheet!!.show()
|
||||
bottomSheet!!.window!!.setLayout(
|
||||
ViewGroup.LayoutParams.MATCH_PARENT,
|
||||
ViewGroup.LayoutParams.MATCH_PARENT
|
||||
)
|
||||
// //remove previously selected
|
||||
// for (i in selectedObjects!!.indices) {
|
||||
// val vid = findVideo(
|
||||
// selectedObjects!![i].url
|
||||
// )
|
||||
// homeAdapter!!.notifyItemChanged(resultsList!!.indexOf(vid))
|
||||
// }
|
||||
// selectedObjects = ArrayList()
|
||||
// downloadFabs!!.visibility = GONE
|
||||
// bottomSheet = BottomSheetDialog(fragmentContext!!)
|
||||
// bottomSheet!!.requestWindowFeature(Window.FEATURE_NO_TITLE)
|
||||
// bottomSheet!!.setContentView(R.layout.home_download_all_bottom_sheet)
|
||||
// val first = bottomSheet!!.findViewById<TextInputLayout>(R.id.first_textinput)
|
||||
// first!!.editText!!.setText(1.toString())
|
||||
// val last = bottomSheet!!.findViewById<TextInputLayout>(R.id.last_textinput)
|
||||
// last!!.editText!!.setText(resultsList!!.size.toString())
|
||||
// val audio = bottomSheet!!.findViewById<Button>(R.id.bottomsheet_audio_button)
|
||||
// audio!!.setOnClickListener {
|
||||
// val start = first.editText!!.text.toString().toInt()
|
||||
// val end = last.editText!!.text.toString().toInt()
|
||||
// initDownloadAll(bottomSheet!!, start, end, "audio")
|
||||
// }
|
||||
// val video = bottomSheet!!.findViewById<Button>(R.id.bottomsheet_video_button)
|
||||
// video!!.setOnClickListener {
|
||||
// val start = first.editText!!.text.toString().toInt()
|
||||
// val end = last.editText!!.text.toString().toInt()
|
||||
// initDownloadAll(bottomSheet!!, start, end, "video")
|
||||
// }
|
||||
// bottomSheet!!.show()
|
||||
// bottomSheet!!.window!!.setLayout(
|
||||
// ViewGroup.LayoutParams.MATCH_PARENT,
|
||||
// ViewGroup.LayoutParams.MATCH_PARENT
|
||||
// )
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -569,75 +577,122 @@ class HomeFragment : Fragment(), HomeAdapter.OnItemClickListener, View.OnClickLi
|
|||
// }
|
||||
}
|
||||
|
||||
private fun showConfigureDownloadCard(type: String) {
|
||||
// val sharedPreferences =
|
||||
// context!!.getSharedPreferences("root_preferences", Activity.MODE_PRIVATE)
|
||||
// val editor = sharedPreferences.edit()
|
||||
// try {
|
||||
// bottomSheet = BottomSheetDialog(fragmentContext!!)
|
||||
// bottomSheet!!.requestWindowFeature(Window.FEATURE_NO_TITLE)
|
||||
private fun showConfigureSingleDownloadCard(item: ResultItem, type: String) {
|
||||
val sharedPreferences =
|
||||
requireContext().getSharedPreferences("root_preferences", Activity.MODE_PRIVATE)
|
||||
val embedSubs = sharedPreferences.getBoolean("embed_subtitles", false)
|
||||
val addChapters = sharedPreferences.getBoolean("add_chapters", false)
|
||||
val saveThumb = sharedPreferences.getBoolean("write_thumbnail", false)
|
||||
|
||||
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") {
|
||||
// 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 audioFormat = bottomSheet!!.findViewById<TextInputLayout>(R.id.audio_format)
|
||||
// val autoCompleteTextView =
|
||||
|
|
@ -687,8 +742,8 @@ class HomeFragment : Fragment(), HomeAdapter.OnItemClickListener, View.OnClickLi
|
|||
// }
|
||||
// })
|
||||
// }
|
||||
// val videoFormats = context!!.resources.getStringArray(R.array.video_formats)
|
||||
// val videoQualities = context!!.resources.getStringArray(R.array.video_quality)
|
||||
// val videoFormats = context!!.resources.getStringArray(R.array.video_containers)
|
||||
// val videoQualities = context!!.resources.getStringArray(R.array.video_formats)
|
||||
// val videoFormat = bottomSheet!!.findViewById<TextInputLayout>(R.id.video_format)
|
||||
// var autoCompleteTextView =
|
||||
// bottomSheet!!.findViewById<AutoCompleteTextView>(R.id.video_format_textview)
|
||||
|
|
@ -773,14 +828,21 @@ class HomeFragment : Fragment(), HomeAdapter.OnItemClickListener, View.OnClickLi
|
|||
// }
|
||||
// bottomSheet!!.cancel()
|
||||
// }
|
||||
// bottomSheet!!.show()
|
||||
// bottomSheet!!.window!!.setLayout(
|
||||
// ViewGroup.LayoutParams.MATCH_PARENT,
|
||||
// ViewGroup.LayoutParams.MATCH_PARENT
|
||||
// )
|
||||
// } catch (e: Exception) {
|
||||
// Toast.makeText(fragmentContext, e.message, Toast.LENGTH_LONG).show()
|
||||
// }
|
||||
bottomSheet!!.show()
|
||||
bottomSheet!!.window!!.setLayout(
|
||||
ViewGroup.LayoutParams.MATCH_PARENT,
|
||||
ViewGroup.LayoutParams.MATCH_PARENT
|
||||
)
|
||||
} catch (e: Exception) {
|
||||
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 {
|
||||
|
|
|
|||
|
|
@ -59,8 +59,8 @@ class DownloadWorker(
|
|||
|
||||
val tempFolder = StringBuilder(context.cacheDir.absolutePath + """/${downloadItem.title}##${downloadItem.type}""")
|
||||
when(type){
|
||||
"audio" -> tempFolder.append("##${downloadItem.audioQualityId}")
|
||||
"video" -> tempFolder.append("##${downloadItem.videoQualityId}")
|
||||
"audio" -> tempFolder.append("##${downloadItem.audioFormatId}")
|
||||
"video" -> tempFolder.append("##${downloadItem.videoFormatId}")
|
||||
"command" -> tempFolder.append("##${downloadItem.customTemplateId}")
|
||||
}
|
||||
var tempFileDir = File(tempFolder.toString())
|
||||
|
|
@ -95,7 +95,7 @@ class DownloadWorker(
|
|||
when(type){
|
||||
"audio" -> {
|
||||
request.addOption("-x")
|
||||
var audioQualityId : String = downloadItem.audioQualityId
|
||||
var audioQualityId : String = downloadItem.audioFormatId
|
||||
if (audioQualityId == "0") audioQualityId = "ba"
|
||||
var format = downloadItem.audioFormat
|
||||
if (format.isEmpty()){
|
||||
|
|
@ -110,7 +110,7 @@ class DownloadWorker(
|
|||
request.addOption("--embed-thumbnail")
|
||||
request.addOption("--convert-thumbnails", "png")
|
||||
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 =
|
||||
"--ppa \"ffmpeg: -c:v png -vf crop=\\\"'if(gt(ih,iw),iw,ih)':'if(gt(iw,ih),ih,iw)'\\\"\""
|
||||
config.writeText(configData)
|
||||
|
|
@ -142,8 +142,8 @@ class DownloadWorker(
|
|||
if (embedSubs) {
|
||||
request.addOption("--embed-subs", "")
|
||||
}
|
||||
var videoQualityId = downloadItem.videoQualityId
|
||||
val audioQualityId = downloadItem.audioQualityId
|
||||
var videoQualityId = downloadItem.videoFormatId
|
||||
val audioQualityId = downloadItem.audioFormatId
|
||||
if (videoQualityId.isEmpty()) videoQualityId = "bestvideo"
|
||||
val formatArgument = StringBuilder(videoQualityId)
|
||||
if (videoQualityId != "worst"){
|
||||
|
|
|
|||
|
|
@ -9,76 +9,86 @@
|
|||
android:layout_height="match_parent"
|
||||
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
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="vertical"
|
||||
>
|
||||
android:paddingBottom="15dp"
|
||||
android:orientation="horizontal">
|
||||
|
||||
<com.google.android.material.textfield.TextInputLayout
|
||||
android:id="@+id/title_textinput"
|
||||
android:layout_width="match_parent"
|
||||
android:id="@+id/downloadContainer"
|
||||
style="@style/Widget.Material3.TextInputLayout.FilledBox.ExposedDropdownMenu"
|
||||
android:layout_width="0dp"
|
||||
android:layout_weight="30"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="15dp"
|
||||
app:errorEnabled="true"
|
||||
android:hint="@string/title"
|
||||
style="@style/Widget.Material3.TextInputLayout.FilledBox">
|
||||
android:hint="@string/container">
|
||||
|
||||
<com.google.android.material.textfield.TextInputEditText
|
||||
<AutoCompleteTextView
|
||||
android:id="@+id/container_textview"
|
||||
android:layout_width="match_parent"
|
||||
android:inputType="text"
|
||||
android:layout_height="wrap_content"
|
||||
android:inputType="none"
|
||||
app:simpleItems="@array/audio_containers"
|
||||
/>
|
||||
|
||||
</com.google.android.material.textfield.TextInputLayout>
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
<com.google.android.material.textfield.TextInputLayout
|
||||
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:orientation="horizontal">
|
||||
android:hint="@string/format">
|
||||
|
||||
<com.google.android.material.textfield.TextInputLayout
|
||||
android:id="@+id/author_textinput"
|
||||
android:layout_width="0dp"
|
||||
android:layout_weight="45"
|
||||
<AutoCompleteTextView
|
||||
android:id="@+id/format_textview"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
app:errorEnabled="true"
|
||||
android:hint="@string/author"
|
||||
style="@style/Widget.Material3.TextInputLayout.FilledBox">
|
||||
android:inputType="none"
|
||||
app:simpleItems="@array/audio_formats"
|
||||
/>
|
||||
|
||||
<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/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>
|
||||
</com.google.android.material.textfield.TextInputLayout>
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
|
||||
<com.google.android.material.textfield.TextInputLayout
|
||||
android:id="@+id/outputPath_textinput"
|
||||
android:layout_width="match_parent"
|
||||
|
|
|
|||
|
|
@ -31,34 +31,51 @@
|
|||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="bottom"
|
||||
android:gravity="end"
|
||||
android:paddingTop="10dp"
|
||||
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
|
||||
style="@style/Widget.Material3.Button.ElevatedButton.Icon"
|
||||
android:textSize="11sp"
|
||||
android:id="@+id/bottomsheet_schedule_button"
|
||||
android:padding="10dp"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginEnd="10dp"
|
||||
app:icon="@drawable/ic_clock"
|
||||
android:text="@string/schedule" />
|
||||
|
||||
<Button
|
||||
style="@style/Widget.Material3.Button.ElevatedButton.Icon"
|
||||
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
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_gravity="bottom"
|
||||
android:gravity="end"
|
||||
android:orientation="horizontal">
|
||||
|
||||
<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>
|
||||
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
<resources>
|
||||
<string-array name="music_formats">
|
||||
<string-array name="audio_containers">
|
||||
<item>mp3</item>
|
||||
<item>m4a</item>
|
||||
<item>aac</item>
|
||||
|
|
@ -9,22 +9,27 @@
|
|||
<item>wav</item>
|
||||
</string-array>
|
||||
|
||||
<string-array name="video_formats">
|
||||
<item>DEFAULT</item>
|
||||
<string-array name="audio_formats">
|
||||
<item>@string/worst</item>
|
||||
<item>@string/best</item>
|
||||
</string-array>
|
||||
|
||||
<string-array name="video_containers">
|
||||
<item>@string/defaultValue</item>
|
||||
<item>mp4</item>
|
||||
<item>mkv</item>
|
||||
<item>webm</item>
|
||||
</string-array>
|
||||
|
||||
<string-array name="video_quality">
|
||||
<item>Best Quality</item>
|
||||
<item>2160p</item>
|
||||
<item>1440p</item>
|
||||
<item>1080p</item>
|
||||
<item>720p</item>
|
||||
<item>480p</item>
|
||||
<item>360p</item>
|
||||
<string-array name="video_formats">
|
||||
<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 name="sponsorblock_settings_entries">
|
||||
|
|
|
|||
|
|
@ -160,4 +160,9 @@
|
|||
<string name="schedule">Schedule</string>
|
||||
<string name="concurrent_downloads">Concurrent Downloads</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>
|
||||
|
|
@ -125,8 +125,8 @@
|
|||
|
||||
<ListPreference
|
||||
android:defaultValue="mp3"
|
||||
android:entries="@array/music_formats"
|
||||
android:entryValues="@array/music_formats"
|
||||
android:entries="@array/audio_containers"
|
||||
android:entryValues="@array/audio_containers"
|
||||
android:icon="@drawable/ic_code"
|
||||
app:key="audio_format"
|
||||
app:summary="mp3"
|
||||
|
|
@ -134,8 +134,8 @@
|
|||
|
||||
<ListPreference
|
||||
android:defaultValue="mkv"
|
||||
android:entries="@array/video_formats"
|
||||
android:entryValues="@array/video_formats"
|
||||
android:entries="@array/video_containers"
|
||||
android:entryValues="@array/video_containers"
|
||||
android:icon="@drawable/ic_code"
|
||||
app:key="video_format"
|
||||
app:summary="DEFAULT"
|
||||
|
|
@ -154,8 +154,8 @@
|
|||
|
||||
<ListPreference
|
||||
android:defaultValue="Best Quality"
|
||||
android:entries="@array/video_quality"
|
||||
android:entryValues="@array/video_quality"
|
||||
android:entries="@array/video_formats"
|
||||
android:entryValues="@array/video_formats"
|
||||
android:icon="@drawable/ic_video"
|
||||
app:key="video_quality"
|
||||
app:summary="Best Quality"
|
||||
|
|
|
|||
Loading…
Reference in a new issue