From 19eab5e054c44dcda47c21b5f859a98f459a200c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Denis=20=C3=87erri?= <64997243+deniscerri@users.noreply.github.com> Date: Sun, 22 Jan 2023 18:16:22 +0100 Subject: [PATCH] fixed some things in download card --- .idea/misc.xml | 2 +- .../1.json | 54 +-- app/src/main/AndroidManifest.xml | 14 +- .../com/deniscerri/ytdlnis/MainActivity.kt | 22 +- .../ytdlnis/adapter/HistoryAdapter.java | 214 ------------ .../ytdlnis/adapter/HistoryAdapter.kt | 189 ++++++++++ .../ytdlnis/adapter/HomeAdapter.java | 212 ----------- .../deniscerri/ytdlnis/adapter/HomeAdapter.kt | 186 ++++++++++ .../deniscerri/ytdlnis/database/DBManager.kt | 4 +- .../ytdlnis/database/dao/FormatDao.kt | 4 +- .../ytdlnis/database/models/DownloadItem.kt | 48 +-- .../ytdlnis/database/models/ResultItem.kt | 14 +- .../database/repository/ResultRepository.kt | 11 +- .../database/viewmodel/ResultViewModel.kt | 36 +- .../ytdlnis/ui/DownloadsFragment.kt | 2 +- .../com/deniscerri/ytdlnis/ui/HomeFragment.kt | 330 +++++++++++------- .../deniscerri/ytdlnis/work/DownloadWorker.kt | 12 +- .../home_download_settings_components.xml | 110 +++--- .../home_download_single_bottom_sheet.xml | 49 ++- app/src/main/res/values/arrays.xml | 27 +- app/src/main/res/values/strings.xml | 5 + app/src/main/res/xml/root_preferences.xml | 12 +- 22 files changed, 842 insertions(+), 715 deletions(-) delete mode 100644 app/src/main/java/com/deniscerri/ytdlnis/adapter/HistoryAdapter.java create mode 100644 app/src/main/java/com/deniscerri/ytdlnis/adapter/HistoryAdapter.kt delete mode 100644 app/src/main/java/com/deniscerri/ytdlnis/adapter/HomeAdapter.java create mode 100644 app/src/main/java/com/deniscerri/ytdlnis/adapter/HomeAdapter.kt diff --git a/.idea/misc.xml b/.idea/misc.xml index 9b4350ec..ea595dfd 100644 --- a/.idea/misc.xml +++ b/.idea/misc.xml @@ -167,7 +167,7 @@ - + diff --git a/app/schemas/com.deniscerri.ytdlnis.database.DBManager/1.json b/app/schemas/com.deniscerri.ytdlnis.database.DBManager/1.json index cc350343..b899fe52 100644 --- a/app/schemas/com.deniscerri.ytdlnis.database.DBManager/1.json +++ b/app/schemas/com.deniscerri.ytdlnis.database.DBManager/1.json @@ -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')" ] } } \ No newline at end of file diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index 997d8281..d938c82c 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -1,5 +1,6 @@ - + @@ -77,6 +78,17 @@ android:name="android.support.FILE_PROVIDER_PATHS" android:resource="@xml/provider_paths" /> + + + + \ No newline at end of file diff --git a/app/src/main/java/com/deniscerri/ytdlnis/MainActivity.kt b/app/src/main/java/com/deniscerri/ytdlnis/MainActivity.kt index 25b13c0f..e9107f3a 100644 --- a/app/src/main/java/com/deniscerri/ytdlnis/MainActivity.kt +++ b/app/src/main/java/com/deniscerri/ytdlnis/MainActivity.kt @@ -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 - 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 + private var iDownloaderService: IDownloaderService? = null } } \ No newline at end of file diff --git a/app/src/main/java/com/deniscerri/ytdlnis/adapter/HistoryAdapter.java b/app/src/main/java/com/deniscerri/ytdlnis/adapter/HistoryAdapter.java deleted file mode 100644 index 63ff9f4f..00000000 --- a/app/src/main/java/com/deniscerri/ytdlnis/adapter/HistoryAdapter.java +++ /dev/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 { - private ArrayList 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 DIFF_CALLBACK = new DiffUtil.ItemCallback() { - @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(); - } -} diff --git a/app/src/main/java/com/deniscerri/ytdlnis/adapter/HistoryAdapter.kt b/app/src/main/java/com/deniscerri/ytdlnis/adapter/HistoryAdapter.kt new file mode 100644 index 00000000..2b5c0242 --- /dev/null +++ b/app/src/main/java/com/deniscerri/ytdlnis/adapter/HistoryAdapter.kt @@ -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(AsyncDifferConfig.Builder(DIFF_CALLBACK).build()) { + private val checkedItems: ArrayList + 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(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(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(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(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(R.id.downloads_download_button_layout) + val btn = buttonLayout.findViewById(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 = object : DiffUtil.ItemCallback() { + 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 + } + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/deniscerri/ytdlnis/adapter/HomeAdapter.java b/app/src/main/java/com/deniscerri/ytdlnis/adapter/HomeAdapter.java deleted file mode 100644 index 7b4bdf4d..00000000 --- a/app/src/main/java/com/deniscerri/ytdlnis/adapter/HomeAdapter.java +++ /dev/null @@ -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 { - private final ArrayList 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 DIFF_CALLBACK = new DiffUtil.ItemCallback() { - @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(); - } -} diff --git a/app/src/main/java/com/deniscerri/ytdlnis/adapter/HomeAdapter.kt b/app/src/main/java/com/deniscerri/ytdlnis/adapter/HomeAdapter.kt new file mode 100644 index 00000000..6f992a36 --- /dev/null +++ b/app/src/main/java/com/deniscerri/ytdlnis/adapter/HomeAdapter.kt @@ -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(AsyncDifferConfig.Builder(DIFF_CALLBACK).build()) { + private val checkedVideos: ArrayList + 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(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(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(R.id.author) + author.text = video.author + val duration = card.findViewById(R.id.duration) + if (video.duration.isNotEmpty()) { + duration.text = video.duration + } + + // BUTTONS ---------------------------------- + val videoURL = video.url + val buttonLayout = card.findViewById(R.id.download_button_layout) + val musicBtn = buttonLayout.findViewById(R.id.download_music) + musicBtn.tag = "$videoURL##audio" + musicBtn.setTag(R.id.cancelDownload, "false") + musicBtn.setOnClickListener { onItemClickListener.onButtonClick(videoURL, "audio") } + val videoBtn = buttonLayout.findViewById(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(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 = object : DiffUtil.ItemCallback() { + 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 + } + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/deniscerri/ytdlnis/database/DBManager.kt b/app/src/main/java/com/deniscerri/ytdlnis/database/DBManager.kt index f0ab6c3c..a3fa8979 100644 --- a/app/src/main/java/com/deniscerri/ytdlnis/database/DBManager.kt +++ b/app/src/main/java/com/deniscerri/ytdlnis/database/DBManager.kt @@ -30,7 +30,9 @@ abstract class DBManager : RoomDatabase(){ context.applicationContext, DBManager::class.java, "YTDLnisDatabase" - ).build() + ) + .allowMainThreadQueries() + .build() instance = dbInstance dbInstance } diff --git a/app/src/main/java/com/deniscerri/ytdlnis/database/dao/FormatDao.kt b/app/src/main/java/com/deniscerri/ytdlnis/database/dao/FormatDao.kt index e349b147..7f5119ec 100644 --- a/app/src/main/java/com/deniscerri/ytdlnis/database/dao/FormatDao.kt +++ b/app/src/main/java/com/deniscerri/ytdlnis/database/dao/FormatDao.kt @@ -7,8 +7,8 @@ import com.deniscerri.ytdlnis.database.models.ResultItem @Dao interface FormatDao { - @Query("SELECT * FROM formats") - fun getFormatsByItemId() : LiveData> + @Query("SELECT * FROM formats WHERE itemId=:itemId") + fun getFormatsByItemId(itemId: Int) : List @Insert(onConflict = OnConflictStrategy.REPLACE) suspend fun insert(item: Format) diff --git a/app/src/main/java/com/deniscerri/ytdlnis/database/models/DownloadItem.kt b/app/src/main/java/com/deniscerri/ytdlnis/database/models/DownloadItem.kt index 75848851..ff8c5579 100644 --- a/app/src/main/java/com/deniscerri/ytdlnis/database/models/DownloadItem.kt +++ b/app/src/main/java/com/deniscerri/ytdlnis/database/models/DownloadItem.kt @@ -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 diff --git a/app/src/main/java/com/deniscerri/ytdlnis/database/models/ResultItem.kt b/app/src/main/java/com/deniscerri/ytdlnis/database/models/ResultItem.kt index 285dc47b..2fa3711e 100644 --- a/app/src/main/java/com/deniscerri/ytdlnis/database/models/ResultItem.kt +++ b/app/src/main/java/com/deniscerri/ytdlnis/database/models/ResultItem.kt @@ -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 diff --git a/app/src/main/java/com/deniscerri/ytdlnis/database/repository/ResultRepository.kt b/app/src/main/java/com/deniscerri/ytdlnis/database/repository/ResultRepository.kt index 90229802..299b11e1 100644 --- a/app/src/main/java/com/deniscerri/ytdlnis/database/repository/ResultRepository.kt +++ b/app/src/main/java/com/deniscerri/ytdlnis/database/repository/ResultRepository.kt @@ -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> = resultDao.getResults() @@ -119,5 +121,12 @@ class ResultRepository(private val resultDao: ResultDao, private val formatDao: resultDao.update(item) } + fun getFormats(item: ResultItem): List { + return formatDao.getFormatsByItemId(item.id!!) + } + + fun getTemplates() : List { + return commandTemplateDao.getAllTemplates() + } } \ No newline at end of file diff --git a/app/src/main/java/com/deniscerri/ytdlnis/database/viewmodel/ResultViewModel.kt b/app/src/main/java/com/deniscerri/ytdlnis/database/viewmodel/ResultViewModel.kt index d19fc9bb..db307810 100644 --- a/app/src/main/java/com/deniscerri/ytdlnis/database/viewmodel/ResultViewModel.kt +++ b/app/src/main/java/com/deniscerri/ytdlnis/database/viewmodel/ResultViewModel.kt @@ -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().applicationContext) + val commandDao = DBManager.getInstance(application).commandTemplateDao + repository = ResultRepository(dao, formatDao, commandDao, getApplication().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 { + val list = repository.getFormats(item) + val formats = mutableListOf() + if (list.isEmpty()){ + when(type){ + "audio" -> { + val audioFormats = getApplication().resources.getStringArray(R.array.audio_formats) + audioFormats.forEach { formats.add(Format(item.id!!, it, "", "", 0, it)) } + } + "video" -> { + val videoFormats = getApplication().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 + } } \ No newline at end of file diff --git a/app/src/main/java/com/deniscerri/ytdlnis/ui/DownloadsFragment.kt b/app/src/main/java/com/deniscerri/ytdlnis/ui/DownloadsFragment.kt index 9eefd042..feebd549 100644 --- a/app/src/main/java/com/deniscerri/ytdlnis/ui/DownloadsFragment.kt +++ b/app/src/main/java/com/deniscerri/ytdlnis/ui/DownloadsFragment.kt @@ -105,7 +105,7 @@ class DownloadsFragment : Fragment(), HistoryAdapter.OnItemClickListener, historyAdapter = HistoryAdapter( this, - activity + requireActivity() ) recyclerView = view.findViewById(R.id.recyclerviewdownloadss) recyclerView?.layoutManager = LinearLayoutManager(context) diff --git a/app/src/main/java/com/deniscerri/ytdlnis/ui/HomeFragment.kt b/app/src/main/java/com/deniscerri/ytdlnis/ui/HomeFragment.kt index 1bffb7d4..aed56f93 100644 --- a/app/src/main/java/com/deniscerri/ytdlnis/ui/HomeFragment.kt +++ b/app/src/main/java/com/deniscerri/ytdlnis/ui/HomeFragment.kt @@ -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(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("""${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(R.id.first_textinput) - first!!.editText!!.setText(1.toString()) - val last = bottomSheet!!.findViewById(R.id.last_textinput) - last!!.editText!!.setText(resultsList!!.size.toString()) - val audio = bottomSheet!!.findViewById