implemented diffutil on history recyclerview

This commit is contained in:
Denis Çerri 2023-01-15 16:48:51 +01:00
parent d91b6dc217
commit 542121d446
No known key found for this signature in database
GPG key ID: 96B3554AF5B193EE
13 changed files with 440 additions and 684 deletions

View file

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

View file

@ -2,7 +2,7 @@
"formatVersion": 1,
"database": {
"version": 1,
"identityHash": "12ee531d801d7e6e3fd888f4907adc81",
"identityHash": "1709c1d446102722d4dc7f2cb96cd40e",
"entities": [
{
"tableName": "results",
@ -68,7 +68,7 @@
},
{
"tableName": "history",
"createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `url` TEXT NOT NULL, `title` TEXT NOT NULL, `author` TEXT NOT NULL, `duration` TEXT NOT NULL, `thumb` TEXT NOT NULL, `type` TEXT NOT NULL, `time` TEXT NOT NULL, `downloadPath` TEXT NOT NULL, `website` TEXT NOT NULL)",
"createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `url` TEXT NOT NULL, `title` TEXT NOT NULL, `author` TEXT NOT NULL, `duration` TEXT NOT NULL, `thumb` TEXT NOT NULL, `type` TEXT NOT NULL, `time` INTEGER NOT NULL, `downloadPath` TEXT NOT NULL, `website` TEXT NOT NULL)",
"fields": [
{
"fieldPath": "id",
@ -115,7 +115,7 @@
{
"fieldPath": "time",
"columnName": "time",
"affinity": "TEXT",
"affinity": "INTEGER",
"notNull": true
},
{
@ -142,7 +142,7 @@
},
{
"tableName": "downloads",
"createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `url` TEXT NOT NULL, `title` TEXT NOT NULL, `author` TEXT NOT NULL, `duration` TEXT NOT NULL, `thumb` TEXT NOT NULL, `type` TEXT NOT NULL, `downloadPath` TEXT NOT NULL, `website` TEXT NOT NULL)",
"createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `url` TEXT NOT NULL, `title` TEXT NOT NULL, `author` TEXT NOT NULL, `duration` TEXT NOT NULL, `thumb` TEXT NOT NULL, `formatId` INTEGER NOT NULL, `formatDesc` TEXT NOT NULL, `downloadPath` TEXT NOT NULL, `website` TEXT NOT NULL, `downloadSize` TEXT NOT NULL)",
"fields": [
{
"fieldPath": "id",
@ -181,8 +181,14 @@
"notNull": true
},
{
"fieldPath": "type",
"columnName": "type",
"fieldPath": "formatId",
"columnName": "formatId",
"affinity": "INTEGER",
"notNull": true
},
{
"fieldPath": "formatDesc",
"columnName": "formatDesc",
"affinity": "TEXT",
"notNull": true
},
@ -197,6 +203,12 @@
"columnName": "website",
"affinity": "TEXT",
"notNull": true
},
{
"fieldPath": "downloadSize",
"columnName": "downloadSize",
"affinity": "TEXT",
"notNull": true
}
],
"primaryKey": {
@ -212,7 +224,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, '12ee531d801d7e6e3fd888f4907adc81')"
"INSERT OR REPLACE INTO room_master_table (id,identity_hash) VALUES(42, '1709c1d446102722d4dc7f2cb96cd40e')"
]
}
}

View file

@ -1,192 +0,0 @@
{
"formatVersion": 1,
"database": {
"version": 7,
"identityHash": "9951239671c916d8805c4156bb69cb6b",
"entities": [
{
"tableName": "results",
"createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `videoId` TEXT NOT NULL, `url` TEXT NOT NULL, `title` TEXT NOT NULL, `author` TEXT NOT NULL, `duration` TEXT NOT NULL, `thumb` TEXT NOT NULL, `downloadedAudio` INTEGER NOT NULL, `downloadedVideo` INTEGER NOT NULL, `isPlaylistItem` INTEGER NOT NULL, `website` TEXT NOT NULL, `downloadingAudio` INTEGER NOT NULL, `downloadingVideo` INTEGER NOT NULL, `playlistTitle` TEXT NOT NULL)",
"fields": [
{
"fieldPath": "id",
"columnName": "id",
"affinity": "INTEGER",
"notNull": true
},
{
"fieldPath": "videoId",
"columnName": "videoId",
"affinity": "TEXT",
"notNull": true
},
{
"fieldPath": "url",
"columnName": "url",
"affinity": "TEXT",
"notNull": true
},
{
"fieldPath": "title",
"columnName": "title",
"affinity": "TEXT",
"notNull": true
},
{
"fieldPath": "author",
"columnName": "author",
"affinity": "TEXT",
"notNull": true
},
{
"fieldPath": "duration",
"columnName": "duration",
"affinity": "TEXT",
"notNull": true
},
{
"fieldPath": "thumb",
"columnName": "thumb",
"affinity": "TEXT",
"notNull": true
},
{
"fieldPath": "downloadedAudio",
"columnName": "downloadedAudio",
"affinity": "INTEGER",
"notNull": true
},
{
"fieldPath": "downloadedVideo",
"columnName": "downloadedVideo",
"affinity": "INTEGER",
"notNull": true
},
{
"fieldPath": "isPlaylistItem",
"columnName": "isPlaylistItem",
"affinity": "INTEGER",
"notNull": true
},
{
"fieldPath": "website",
"columnName": "website",
"affinity": "TEXT",
"notNull": true
},
{
"fieldPath": "downloadingAudio",
"columnName": "downloadingAudio",
"affinity": "INTEGER",
"notNull": true
},
{
"fieldPath": "downloadingVideo",
"columnName": "downloadingVideo",
"affinity": "INTEGER",
"notNull": true
},
{
"fieldPath": "playlistTitle",
"columnName": "playlistTitle",
"affinity": "TEXT",
"notNull": true
}
],
"primaryKey": {
"columnNames": [
"id"
],
"autoGenerate": true
},
"indices": [],
"foreignKeys": []
},
{
"tableName": "history",
"createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `url` TEXT NOT NULL, `title` TEXT NOT NULL, `author` TEXT NOT NULL, `duration` TEXT NOT NULL, `thumb` TEXT NOT NULL, `type` TEXT NOT NULL, `time` TEXT NOT NULL, `downloadPath` TEXT NOT NULL, `website` TEXT NOT NULL, `isQueuedDownload` INTEGER NOT NULL)",
"fields": [
{
"fieldPath": "id",
"columnName": "id",
"affinity": "INTEGER",
"notNull": true
},
{
"fieldPath": "url",
"columnName": "url",
"affinity": "TEXT",
"notNull": true
},
{
"fieldPath": "title",
"columnName": "title",
"affinity": "TEXT",
"notNull": true
},
{
"fieldPath": "author",
"columnName": "author",
"affinity": "TEXT",
"notNull": true
},
{
"fieldPath": "duration",
"columnName": "duration",
"affinity": "TEXT",
"notNull": true
},
{
"fieldPath": "thumb",
"columnName": "thumb",
"affinity": "TEXT",
"notNull": true
},
{
"fieldPath": "type",
"columnName": "type",
"affinity": "TEXT",
"notNull": true
},
{
"fieldPath": "time",
"columnName": "time",
"affinity": "TEXT",
"notNull": true
},
{
"fieldPath": "downloadPath",
"columnName": "downloadPath",
"affinity": "TEXT",
"notNull": true
},
{
"fieldPath": "website",
"columnName": "website",
"affinity": "TEXT",
"notNull": true
},
{
"fieldPath": "isQueuedDownload",
"columnName": "isQueuedDownload",
"affinity": "INTEGER",
"notNull": true
}
],
"primaryKey": {
"columnNames": [
"id"
],
"autoGenerate": true
},
"indices": [],
"foreignKeys": []
}
],
"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, '9951239671c916d8805c4156bb69cb6b')"
]
}
}

View file

@ -1,7 +1,6 @@
package com.deniscerri.ytdlnis.adapter;
import android.app.Activity;
import android.content.Context;
import android.graphics.Color;
import android.graphics.ColorMatrix;
import android.graphics.ColorMatrixColorFilter;
@ -14,40 +13,51 @@ import android.view.ViewGroup;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.TextView;
import android.widget.Toast;
import androidx.annotation.NonNull;
import androidx.cardview.widget.CardView;
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.Video;
import com.deniscerri.ytdlnis.database.models.HistoryItem;
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.io.File;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.List;
import java.util.Calendar;
import java.util.Date;
import java.util.Locale;
public class DownloadsRecyclerViewAdapter extends RecyclerView.Adapter<DownloadsRecyclerViewAdapter.ViewHolder> {
private List<HistoryItem> videoList;
private ArrayList<Integer> checkedVideos;
private ArrayList<String> websites;
public class HistoryRecyclerViewAdapter extends ListAdapter<HistoryItem, HistoryRecyclerViewAdapter.ViewHolder> {
private ArrayList<Integer> checkedItems;
private final OnItemClickListener onItemClickListener;
private Activity activity;
public DownloadsRecyclerViewAdapter(OnItemClickListener onItemClickListener, Activity activity){
this.videoList = new ArrayList<>();
this.websites = new ArrayList<>();
this.checkedVideos = new ArrayList<>();
public HistoryRecyclerViewAdapter(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);
@ -68,27 +78,25 @@ public class DownloadsRecyclerViewAdapter extends RecyclerView.Adapter<Downloads
View cardView = LayoutInflater.from(parent.getContext())
.inflate(R.layout.downloads_card, parent, false);
return new DownloadsRecyclerViewAdapter.ViewHolder(cardView, onItemClickListener);
return new HistoryRecyclerViewAdapter.ViewHolder(cardView, onItemClickListener);
}
@Override
public void onBindViewHolder(@NonNull ViewHolder holder, int position) {
HistoryItem video = videoList.get(position);
Log.e("AAA", video.toString());
HistoryItem video = getItem(position);
Log.e("AAA", String.valueOf(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()){
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));
}
thumbnail.setColorFilter(Color.argb(95, 0, 0, 0));
// TITLE ----------------------------------
TextView videoTitle = card.findViewById(R.id.downloads_title);
@ -110,8 +118,22 @@ public class DownloadsRecyclerViewAdapter extends RecyclerView.Adapter<Downloads
// TIME DOWNLOADED ----------------------------------
TextView datetime = card.findViewById(R.id.downloads_info_time);
String downloadedTime = video.getTime();
if (downloadedTime.isEmpty()) downloadedTime = activity.getString(R.string.currently_downloading) + " " + video.getType();
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 ----------------------------------
@ -141,7 +163,7 @@ public class DownloadsRecyclerViewAdapter extends RecyclerView.Adapter<Downloads
if (btn.hasOnClickListeners()) btn.setOnClickListener(null);
if(checkedVideos.contains(position)){
if(checkedItems.contains(position)){
card.setChecked(true);
card.setStrokeWidth(5);
}else{
@ -155,35 +177,25 @@ public class DownloadsRecyclerViewAdapter extends RecyclerView.Adapter<Downloads
return true;
});
card.setOnClickListener(view -> {
if(checkedVideos.size() > 0){
checkCard(card, position);
if(checkedItems.size() > 0){
checkCard(card, video.getId());
}else{
onItemClickListener.onCardClick(position, finalFilePresent);
onItemClickListener.onCardClick(video.getId(), finalFilePresent);
}
});
}
public void setVideoList(List<HistoryItem> list){
videoList.clear();
videoList.addAll(list);
notifyDataSetChanged();
}
private void checkCard(MaterialCardView card, int position){
private void checkCard(MaterialCardView card, int videoID){
if(card.isChecked()){
card.setStrokeWidth(0);
checkedVideos.remove(Integer.valueOf(position));
checkedItems.remove(videoID);
}else{
card.setStrokeWidth(5);
checkedVideos.add(position);
checkedItems.add(videoID);
}
card.setChecked(!card.isChecked());
onItemClickListener.onCardSelect(position, card.isChecked());
}
@Override
public int getItemCount() {
return videoList.size();
onItemClickListener.onCardSelect(videoID, card.isChecked());
}
public interface OnItemClickListener {
@ -192,44 +204,12 @@ public class DownloadsRecyclerViewAdapter extends RecyclerView.Adapter<Downloads
void onButtonClick(int position);
}
public ArrayList<String> getWebsites(){
return websites;
}
public void updateWebsiteList(){
websites = new ArrayList<>();
for (HistoryItem video : videoList){
if (!websites.contains(video.getWebsite())) websites.add(video.getWebsite());
}
}
public void clear(){
int size = videoList.size();
videoList.clear();
websites.clear();
notifyItemRangeRemoved(0, size);
}
public void clearCheckedVideos(){
int size = checkedVideos.size();
int size = checkedItems.size();
for (int i = 0; i < size; i++){
int position = checkedVideos.get(i);
int position = checkedItems.get(i);
notifyItemChanged(position);
}
checkedVideos.clear();
checkedItems.clear();
}
public void add(ArrayList<HistoryItem> vids){
int position = videoList.size() + 1;
videoList.addAll(vids);
notifyItemRangeInserted(position, vids.size());
updateWebsiteList();
}
public void remove(int index){
videoList.remove(index);
notifyItemRemoved(index);
updateWebsiteList();
}
}

View file

@ -3,7 +3,6 @@ package com.deniscerri.ytdlnis.database.dao
import androidx.lifecycle.LiveData
import androidx.room.*
import com.deniscerri.ytdlnis.database.models.HistoryItem
import com.deniscerri.ytdlnis.util.FileUtil
@Dao
interface HistoryDao {
@ -12,7 +11,7 @@ interface HistoryDao {
"CASE WHEN :sort = 'ASC' THEN id END ASC," +
"CASE WHEN :sort = 'DESC' THEN id END DESC," +
"CASE WHEN :sort = '' THEN id END DESC ")
fun getHistory(query : String, format : String, site : String, sort : String) : LiveData<List<HistoryItem>>
fun getHistory(query : String, format : String, site : String, sort : String) : List<HistoryItem>
@Query("SELECT * FROM history")
fun getAllHistory() : LiveData<List<HistoryItem>>
@ -23,8 +22,8 @@ interface HistoryDao {
@Insert(onConflict = OnConflictStrategy.REPLACE)
suspend fun insert(item: HistoryItem)
@Delete
suspend fun delete(item: HistoryItem)
@Query("DELETE FROM history WHERE id=:id")
suspend fun delete(id: Int)
@Query("DELETE FROM history")
suspend fun deleteAll()

View file

@ -12,7 +12,9 @@ data class DownloadItem(
val author: String,
val duration: String,
val thumb: String,
val type: String,
val formatId: Int,
val formatDesc: String,
val downloadPath: String,
val website: String
val website: String,
val downloadSize: String
)

View file

@ -6,14 +6,14 @@ import androidx.room.PrimaryKey
@Entity(tableName = "history")
data class HistoryItem(
@PrimaryKey(autoGenerate = true)
val id: Int,
var id: Int,
val url: String,
val title: String,
val author: String,
val duration: String,
val thumb: String,
val type: String,
val time: String,
val time: Long,
val downloadPath: String,
val website: String
//val isQueuedDownload: Int

View file

@ -3,6 +3,8 @@ package com.deniscerri.ytdlnis.database.models
import androidx.room.Entity
import androidx.room.PrimaryKey
import com.google.gson.annotations.SerializedName
import com.yausername.youtubedl_android.mapper.VideoFormat
import com.yausername.youtubedl_android.mapper.VideoInfo
@Entity(tableName = "results")
data class ResultItem(

View file

@ -1,26 +1,41 @@
package com.deniscerri.ytdlnis.database.repository
import android.util.Log
import androidx.lifecycle.LiveData
import androidx.lifecycle.MutableLiveData
import androidx.room.Transaction
import com.deniscerri.ytdlnis.database.dao.DownloadDao
import com.deniscerri.ytdlnis.database.dao.HistoryDao
import com.deniscerri.ytdlnis.database.models.DownloadItem
import com.deniscerri.ytdlnis.database.models.HistoryItem
import com.deniscerri.ytdlnis.util.FileUtil
import java.io.File
class HistoryRepository(private val historyDao: HistoryDao) {
val allHistory : LiveData<List<HistoryItem>> = historyDao.getAllHistory()
val items : LiveData<List<HistoryItem>> = historyDao.getAllHistory()
enum class HistorySort{
DESC, ASC
}
suspend fun getItem(id: Int) : HistoryItem?{
suspend fun getItem(id: Int) : HistoryItem {
return historyDao.getHistoryItem(id)
}
fun getFiltered(query : String, format : String, site : String, sort: HistorySort) : List<HistoryItem> {
return historyDao.getHistory(query, format, site, sort.toString())
}
suspend fun insert(item: HistoryItem){
historyDao.insert(item)
}
suspend fun delete(item: HistoryItem){
historyDao.delete(item)
suspend fun delete(item: HistoryItem, deleteFile: Boolean){
Log.e("ASd", item.id.toString())
historyDao.delete(item.id)
if (deleteFile){
val fileUtil = FileUtil()
fileUtil.deleteFile(item.downloadPath)
}
}
suspend fun deleteAll(){
@ -37,9 +52,9 @@ class HistoryRepository(private val historyDao: HistoryDao) {
suspend fun clearDeletedHistory(){
val fileUtil = FileUtil()
allHistory.value?.forEach { item ->
items.value?.forEach { item ->
if (!fileUtil.exists(item.downloadPath)){
delete(item)
delete(item, false)
}
}
}

View file

@ -1,33 +1,88 @@
package com.deniscerri.ytdlnis.database.viewmodel
import android.app.Application
import android.util.Log
import android.widget.Toast
import androidx.lifecycle.AndroidViewModel
import androidx.lifecycle.LiveData
import androidx.lifecycle.MediatorLiveData
import androidx.lifecycle.MutableLiveData
import androidx.lifecycle.Observer
import androidx.lifecycle.viewModelScope
import com.deniscerri.ytdlnis.database.DBManager
import com.deniscerri.ytdlnis.database.models.DownloadItem
import com.deniscerri.ytdlnis.database.models.HistoryItem
import com.deniscerri.ytdlnis.database.repository.DownloadRepository
import com.deniscerri.ytdlnis.database.repository.HistoryRepository
import com.deniscerri.ytdlnis.database.repository.HistoryRepository.HistorySort
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
class HistoryViewModel(application: Application) : AndroidViewModel(application) {
private val repository : HistoryRepository
val allHistory : LiveData<List<HistoryItem>>
private val sortType = MutableLiveData(HistorySort.DESC)
private val websiteFilter = MutableLiveData("")
private val queryFilter = MutableLiveData("")
private val formatFilter = MutableLiveData("")
val allItems : LiveData<List<HistoryItem>>
private var _items = MediatorLiveData<List<HistoryItem>>()
init {
val dao = DBManager.getInstance(application).historyDao
repository = HistoryRepository(dao)
allHistory = repository.allHistory
allItems = repository.items
_items.addSource(allItems, Observer {
filter(queryFilter.value!!, formatFilter.value!!, websiteFilter.value!!, sortType.value!!)
})
_items.addSource(formatFilter, Observer {
Log.e("aa", "audio");
filter(queryFilter.value!!, formatFilter.value!!, websiteFilter.value!!, sortType.value!!)
})
_items.addSource(sortType, Observer {
Log.e("aa", "asssssssssssss");
filter(queryFilter.value!!, formatFilter.value!!, websiteFilter.value!!, sortType.value!!)
})
_items.addSource(websiteFilter, Observer {
Log.e("Aa", "website")
filter(queryFilter.value!!, formatFilter.value!!, websiteFilter.value!!, sortType.value!!)
})
_items.addSource(queryFilter, Observer {
filter(queryFilter.value!!, formatFilter.value!!, websiteFilter.value!!, sortType.value!!)
})
}
fun getFilteredList() : LiveData<List<HistoryItem>>{
return _items;
}
fun setSorting(sort: HistorySort){
Log.e("aa", "asssssssssssss");
sortType.value = sort
}
fun setWebsiteFilter(filter : String){
websiteFilter.value = filter
}
fun setQueryFilter(filter: String){
queryFilter.value = filter
}
fun setFormatFilter(filter: String){
Log.e("aa", "audio");
formatFilter.value = filter
}
fun filter(query : String, format : String, site : String, sort: HistorySort) = viewModelScope.launch(Dispatchers.IO){
_items.postValue(repository.getFiltered(query, format, site, sort))
}
fun insert(item: HistoryItem) = viewModelScope.launch(Dispatchers.IO){
repository.insert(item)
}
fun delete(item: HistoryItem) = viewModelScope.launch(Dispatchers.IO){
repository.delete(item)
fun delete(item: HistoryItem, deleteFile: Boolean) = viewModelScope.launch(Dispatchers.IO){
repository.delete(item, deleteFile)
}
fun deleteAll() = viewModelScope.launch(Dispatchers.IO) {

View file

@ -3,7 +3,6 @@ package com.deniscerri.ytdlnis.ui
import android.app.Activity
import android.content.*
import android.net.Uri
import android.os.Binder
import android.os.Bundle
import android.os.Handler
import android.os.Looper
@ -15,22 +14,17 @@ import android.widget.*
import androidx.appcompat.widget.SearchView
import androidx.core.content.FileProvider
import androidx.fragment.app.Fragment
import androidx.lifecycle.Observer
import androidx.lifecycle.ViewModel
import androidx.lifecycle.ViewModelProvider
import androidx.recyclerview.widget.LinearLayoutManager
import androidx.recyclerview.widget.RecyclerView
import com.deniscerri.ytdlnis.MainActivity
import com.deniscerri.ytdlnis.R
import com.deniscerri.ytdlnis.adapter.DownloadsRecyclerViewAdapter
import com.deniscerri.ytdlnis.adapter.HistoryRecyclerViewAdapter
import com.deniscerri.ytdlnis.database.DatabaseManager
import com.deniscerri.ytdlnis.database.Video
import com.deniscerri.ytdlnis.database.models.HistoryItem
import com.deniscerri.ytdlnis.database.viewmodel.DownloadViewModel
import com.deniscerri.ytdlnis.database.repository.HistoryRepository.HistorySort
import com.deniscerri.ytdlnis.database.viewmodel.HistoryViewModel
import com.deniscerri.ytdlnis.databinding.FragmentDownloadsBinding
import com.deniscerri.ytdlnis.databinding.FragmentHomeBinding
import com.deniscerri.ytdlnis.service.DownloadInfo
import com.deniscerri.ytdlnis.util.FileUtil
import com.facebook.shimmer.ShimmerFrameLayout
import com.google.android.material.appbar.AppBarLayout
@ -40,50 +34,40 @@ import com.google.android.material.chip.Chip
import com.google.android.material.chip.ChipGroup
import com.google.android.material.dialog.MaterialAlertDialogBuilder
import com.google.android.material.floatingactionbutton.ExtendedFloatingActionButton
import com.google.android.material.progressindicator.LinearProgressIndicator
import java.io.File
/**
* A fragment representing a list of Items.
*/
class DownloadsFragment : Fragment(), DownloadsRecyclerViewAdapter.OnItemClickListener,
View.OnClickListener, OnLongClickListener {
class DownloadsFragment : Fragment(), HistoryRecyclerViewAdapter.OnItemClickListener,
OnClickListener, OnLongClickListener {
private lateinit var historyViewModel : HistoryViewModel
private var downloading = false
private var fragmentView: View? = null
private var databaseManager: DatabaseManager? = null
var activity: Activity? = null
var mainActivity: MainActivity? = null
var fragmentContext: Context? = null
private var activity: Activity? = null
private var mainActivity: MainActivity? = null
private var fragmentContext: Context? = null
private var layoutinflater: LayoutInflater? = null
private var shimmerCards: ShimmerFrameLayout? = null
private var topAppBar: MaterialToolbar? = null
private var recyclerView: RecyclerView? = null
private var downloadsRecyclerViewAdapter: DownloadsRecyclerViewAdapter? = null
private var historyRecyclerViewAdapter: HistoryRecyclerViewAdapter? = null
private var bottomSheet: BottomSheetDialog? = null
private var sortSheet: BottomSheetDialog? = null
private var uiHandler: Handler? = null
private var no_results: RelativeLayout? = null
private var noResults: RelativeLayout? = null
private var selectionChips: LinearLayout? = null
private var websiteGroup: ChipGroup? = null
private var downloadsObjects: List<HistoryItem?>? = null
var selectedObjects: ArrayList<Video?>? = null
private var progressBar: LinearProgressIndicator? = null
private var downloadsList: List<HistoryItem?>? = null
private var allDownloadsList: List<HistoryItem?>? = null
private var selectedObjects: ArrayList<HistoryItem>? = null
private var deleteFab: ExtendedFloatingActionButton? = null
private var fileUtil: FileUtil? = null
private var format = ""
private var website = ""
private var sort = "DESC"
private var searchQuery = ""
private var _binding : FragmentDownloadsBinding? = null
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setHasOptionsMenu(true)
}
override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?
@ -100,9 +84,10 @@ class DownloadsFragment : Fragment(), DownloadsRecyclerViewAdapter.OnItemClickLi
super.onViewCreated(view, savedInstanceState)
fragmentContext = context
layoutinflater = LayoutInflater.from(context)
shimmerCards = view.findViewById(R.id.shimmer_downloads_framelayout)
topAppBar = view.findViewById(R.id.downloads_toolbar)
no_results = view.findViewById(R.id.downloads_no_results)
noResults = view.findViewById(R.id.downloads_no_results)
selectionChips = view.findViewById(R.id.downloads_selection_chips)
websiteGroup = view.findViewById(R.id.website_chip_group)
deleteFab = view.findViewById(R.id.delete_selected_fab)
@ -110,77 +95,58 @@ class DownloadsFragment : Fragment(), DownloadsRecyclerViewAdapter.OnItemClickLi
deleteFab?.tag = "deleteSelected"
deleteFab?.setOnClickListener(this)
uiHandler = Handler(Looper.getMainLooper())
downloadsObjects = ArrayList()
selectedObjects = ArrayList()
downloading = mainActivity!!.isDownloadServiceRunning()
downloadsObjects = mutableListOf()
downloadsList = mutableListOf()
allDownloadsList = mutableListOf()
downloadsRecyclerViewAdapter =
DownloadsRecyclerViewAdapter(this, activity)
historyRecyclerViewAdapter =
HistoryRecyclerViewAdapter(
this,
activity
)
recyclerView = view.findViewById(R.id.recyclerviewdownloadss)
recyclerView?.layoutManager = LinearLayoutManager(context)
recyclerView?.adapter = downloadsRecyclerViewAdapter
recyclerView?.adapter = historyRecyclerViewAdapter
downloadsRecyclerViewAdapter!!.clear()
no_results?.visibility = GONE
noResults?.visibility = GONE
selectionChips?.visibility = VISIBLE
shimmerCards?.visibility = GONE
historyViewModel = ViewModelProvider(this)[HistoryViewModel::class.java]
historyViewModel.allHistory.observe(viewLifecycleOwner) {
downloadsRecyclerViewAdapter!!.setVideoList(it);
Toast.makeText(context, "CHANGED", Toast.LENGTH_SHORT).show()
historyViewModel.allItems.observe(viewLifecycleOwner) {
allDownloadsList = it
if(it.isEmpty()){
noResults!!.visibility = VISIBLE
selectionChips!!.visibility = GONE
websiteGroup!!.removeAllViews()
}else{
noResults!!.visibility = GONE
selectionChips!!.visibility = VISIBLE
updateWebsiteChips(it)
}
}
historyViewModel.getFilteredList().observe(viewLifecycleOwner) {
historyRecyclerViewAdapter!!.submitList(it)
downloadsList = it
}
initMenu()
//initChips()
// initCards()
initChips()
}
// fun initCards() {
// shimmerCards!!.startShimmer()
// shimmerCards!!.visibility = View.VISIBLE
// downloadsRecyclerViewAdapter!!.clear()
// no_results!!.visibility = View.GONE
// selectionChips!!.visibility = View.VISIBLE
// databaseManager = DatabaseManager(context)
// try {
// val thread = Thread {
// if (!downloading) databaseManager!!.clearDownloadingHistory()
// downloadsObjects = databaseManager!!.getHistory("", format, website, sort)
// uiHandler!!.post {
// downloadsRecyclerViewAdapter!!.add(downloadsObjects)
// shimmerCards!!.stopShimmer()
// shimmerCards!!.visibility = View.GONE
// updateWebsiteChips()
// }
// if ((downloadsObjects as ArrayList<Video>?)?.size == 0) {
// uiHandler!!.post {
// no_results!!.visibility = View.VISIBLE
// selectionChips!!.visibility = View.GONE
// websiteGroup!!.removeAllViews()
// }
// }
// databaseManager!!.close()
// }
// thread.start()
// } catch (e: Exception) {
// Log.e(TAG, e.toString())
// }
// }
//
fun scrollToTop() {
// recyclerView!!.scrollToPosition(0)
// Handler(Looper.getMainLooper()).post {
// (topAppBar!!.parent as AppBarLayout).setExpanded(
// true,
// true
// )
// }
recyclerView!!.scrollToPosition(0)
Handler(Looper.getMainLooper()).post {
(topAppBar!!.parent as AppBarLayout).setExpanded(
true,
true
)
}
}
private fun initMenu() {
@ -194,7 +160,6 @@ class DownloadsFragment : Fragment(), DownloadsRecyclerViewAdapter.OnItemClickLi
return true
}
}
val toolbar = fragmentView!!.findViewById<MaterialToolbar>(R.id.downloads_toolbar)
topAppBar!!.menu.findItem(R.id.search_downloads)
.setOnActionExpandListener(onActionExpandListener)
val searchView = topAppBar!!.menu.findItem(R.id.search_downloads).actionView as SearchView?
@ -203,301 +168,228 @@ class DownloadsFragment : Fragment(), DownloadsRecyclerViewAdapter.OnItemClickLi
databaseManager = DatabaseManager(context)
searchView.setOnQueryTextListener(object : SearchView.OnQueryTextListener {
override fun onQueryTextSubmit(query: String): Boolean {
// searchQuery = query
// topAppBar!!.menu.findItem(R.id.search_downloads).collapseActionView()
// downloadsObjects = databaseManager!!.getHistory(query, format, website, sort)
// downloadsRecyclerViewAdapter!!.clear()
// downloadsRecyclerViewAdapter!!.add(downloadsObjects)
// if ((downloadsObjects as ArrayList<Video>?)?.size == 0) {
// no_results!!.visibility = View.VISIBLE
// selectionChips!!.visibility = View.GONE
// websiteGroup!!.removeAllViews()
// }
topAppBar!!.menu.findItem(R.id.search_downloads).collapseActionView()
historyViewModel.setQueryFilter(query)
return true
}
override fun onQueryTextChange(newText: String): Boolean {
// searchQuery = newText
// downloadsObjects = databaseManager!!.getHistory(newText, format, website, sort)
// downloadsRecyclerViewAdapter!!.clear()
// downloadsRecyclerViewAdapter!!.add(downloadsObjects)
// if ((downloadsObjects as ArrayList<Video>?)?.size == 0) {
// no_results!!.visibility = View.VISIBLE
// selectionChips!!.visibility = View.GONE
// } else {
// no_results!!.visibility = View.GONE
// selectionChips!!.visibility = View.VISIBLE
// }
historyViewModel.setQueryFilter(newText)
return true
}
})
topAppBar!!.setOnClickListener { view: View? -> scrollToTop() }
topAppBar!!.setOnClickListener { scrollToTop() }
topAppBar!!.setOnMenuItemClickListener { m: MenuItem ->
val itemID = m.itemId
if (itemID == R.id.remove_downloads) {
// if (downloadsObjects!!.size == 0) {
// Toast.makeText(context, R.string.history_is_empty, Toast.LENGTH_SHORT).show()
// return@setOnMenuItemClickListener true
// }
// val delete_dialog = MaterialAlertDialogBuilder(fragmentContext!!)
// delete_dialog.setTitle(getString(R.string.confirm_delete_history))
// delete_dialog.setMessage(getString(R.string.confirm_delete_history_desc))
// delete_dialog.setNegativeButton(getString(R.string.cancel)) { dialogInterface: DialogInterface, i: Int -> dialogInterface.cancel() }
// delete_dialog.setPositiveButton(getString(R.string.ok)) { dialogInterface: DialogInterface?, i: Int ->
// databaseManager!!.clearHistory()
// downloadsRecyclerViewAdapter!!.clear()
// downloadsObjects!!.clear()
// no_results!!.visibility = View.VISIBLE
// selectionChips!!.visibility = View.GONE
// websiteGroup!!.removeAllViews()
// }
// delete_dialog.show()
} else if (itemID == R.id.remove_deleted_downloads) {
// if (downloadsObjects!!.size == 0) {
// Toast.makeText(context, R.string.history_is_empty, Toast.LENGTH_SHORT).show()
// return@setOnMenuItemClickListener true
// }
// val delete_dialog = MaterialAlertDialogBuilder(fragmentContext!!)
// delete_dialog.setTitle(getString(R.string.confirm_delete_history))
// delete_dialog.setMessage(getString(R.string.confirm_delete_history_deleted_desc))
// delete_dialog.setNegativeButton(getString(R.string.cancel)) { dialogInterface: DialogInterface, i: Int -> dialogInterface.cancel() }
// delete_dialog.setPositiveButton(getString(R.string.ok)) { dialogInterface: DialogInterface?, i: Int ->
// databaseManager!!.clearDeletedHistory()
// initCards()
// }
// delete_dialog.show()
} else if (itemID == R.id.remove_duplicates) {
// if (downloadsObjects!!.size == 0) {
// Toast.makeText(context, R.string.history_is_empty, Toast.LENGTH_SHORT).show()
// return@setOnMenuItemClickListener true
// }
// val delete_dialog = MaterialAlertDialogBuilder(fragmentContext!!)
// delete_dialog.setTitle(getString(R.string.confirm_delete_history))
// delete_dialog.setMessage(getString(R.string.confirm_delete_history_duplicates_desc))
// delete_dialog.setNegativeButton(getString(R.string.cancel)) { dialogInterface: DialogInterface, i: Int -> dialogInterface.cancel() }
// delete_dialog.setPositiveButton(getString(R.string.ok)) { dialogInterface: DialogInterface?, i: Int ->
// databaseManager!!.clearDuplicateHistory()
// initCards()
// }
// delete_dialog.show()
} else if (itemID == R.id.remove_downloading) {
// if (downloadsObjects!!.size == 0) {
// Toast.makeText(context, R.string.history_is_empty, Toast.LENGTH_SHORT).show()
// return@setOnMenuItemClickListener true
// }
// val delete_dialog = MaterialAlertDialogBuilder(fragmentContext!!)
// delete_dialog.setTitle(getString(R.string.confirm_delete_history))
// delete_dialog.setMessage(getString(R.string.confirm_delete_downloading_desc))
// delete_dialog.setNegativeButton(getString(R.string.cancel)) { dialogInterface: DialogInterface, i: Int -> dialogInterface.cancel() }
// delete_dialog.setPositiveButton(getString(R.string.ok)) { dialogInterface: DialogInterface?, i: Int ->
// databaseManager!!.clearDownloadingHistory()
// mainActivity!!.cancelDownloadService()
// initCards()
// }
// delete_dialog.show()
when (m.itemId) {
R.id.remove_downloads -> {
if(allDownloadsList!!.isEmpty()){
Toast.makeText(context, R.string.history_is_empty, Toast.LENGTH_SHORT).show()
}else{
val deleteDialog = MaterialAlertDialogBuilder(fragmentContext!!)
deleteDialog.setTitle(getString(R.string.confirm_delete_history))
deleteDialog.setMessage(getString(R.string.confirm_delete_history_desc))
deleteDialog.setNegativeButton(getString(R.string.cancel)) { dialogInterface: DialogInterface, _: Int -> dialogInterface.cancel() }
deleteDialog.setPositiveButton(getString(R.string.ok)) { _: DialogInterface?, _: Int ->
historyViewModel.deleteAll()
}
deleteDialog.show()
}
}
R.id.remove_deleted_downloads -> {
if(allDownloadsList!!.isEmpty()){
Toast.makeText(context, R.string.history_is_empty, Toast.LENGTH_SHORT).show()
}else{
val deleteDialog = MaterialAlertDialogBuilder(fragmentContext!!)
deleteDialog.setTitle(getString(R.string.confirm_delete_history))
deleteDialog.setMessage(getString(R.string.confirm_delete_history_desc))
deleteDialog.setNegativeButton(getString(R.string.cancel)) { dialogInterface: DialogInterface, _: Int -> dialogInterface.cancel() }
deleteDialog.setPositiveButton(getString(R.string.ok)) { _: DialogInterface?, _: Int ->
historyViewModel.clearDeleted()
}
deleteDialog.show()
}
}
R.id.remove_duplicates -> {
if(allDownloadsList!!.isEmpty()){
Toast.makeText(context, R.string.history_is_empty, Toast.LENGTH_SHORT).show()
}else{
val deleteDialog = MaterialAlertDialogBuilder(fragmentContext!!)
deleteDialog.setTitle(getString(R.string.confirm_delete_history))
deleteDialog.setMessage(getString(R.string.confirm_delete_history_desc))
deleteDialog.setNegativeButton(getString(R.string.cancel)) { dialogInterface: DialogInterface, _: Int -> dialogInterface.cancel() }
deleteDialog.setPositiveButton(getString(R.string.ok)) { _: DialogInterface?, _: Int ->
historyViewModel.deleteDuplicates()
}
deleteDialog.show()
}
}
R.id.remove_downloading -> {
}
}
true
}
}
// private fun initChips() {
// //sort and history/downloading switch
// val sortChip = fragmentView!!.findViewById<Chip>(R.id.sort_chip)
// sortChip.setOnClickListener { view: View? ->
// sortSheet = BottomSheetDialog(fragmentContext!!)
// sortSheet!!.requestWindowFeature(Window.FEATURE_NO_TITLE)
// sortSheet!!.setContentView(R.layout.downloads_sort_sheet)
// val newest = sortSheet!!.findViewById<TextView>(R.id.newest)
// val oldest = sortSheet!!.findViewById<TextView>(R.id.oldest)
// newest!!.setOnClickListener { view1: View? ->
// sort = "DESC"
// downloadsObjects = databaseManager!!.getHistory(searchQuery, format, website, sort)
// downloadsRecyclerViewAdapter!!.clear()
// downloadsRecyclerViewAdapter!!.add(downloadsObjects)
// sortSheet!!.cancel()
// }
// oldest!!.setOnClickListener { view1: View? ->
// sort = "ASC"
// downloadsObjects = databaseManager!!.getHistory(searchQuery, format, website, sort)
// downloadsRecyclerViewAdapter!!.clear()
// downloadsRecyclerViewAdapter!!.add(downloadsObjects)
// sortSheet!!.cancel()
// }
// val cancel = sortSheet!!.findViewById<TextView>(R.id.cancel)
// cancel!!.setOnClickListener { view1: View? -> sortSheet!!.cancel() }
// sortSheet!!.show()
// sortSheet!!.window!!.setLayout(
// ViewGroup.LayoutParams.MATCH_PARENT,
// ViewGroup.LayoutParams.MATCH_PARENT
// )
// }
//
// //format
// val audio = fragmentView!!.findViewById<Chip>(R.id.audio_chip)
// audio.setOnClickListener { view: View? ->
// if (audio.isChecked) {
// format = "audio"
// if (recyclerView!!.visibility == View.GONE) {
// }
// downloadsObjects = databaseManager!!.getHistory(searchQuery, format, website, sort)
// audio.isChecked = true
// } else {
// format = ""
// downloadsObjects = databaseManager!!.getHistory(searchQuery, format, website, sort)
// audio.isChecked = false
// }
// downloadsRecyclerViewAdapter!!.clear()
// downloadsRecyclerViewAdapter!!.add(downloadsObjects)
// }
// val video = fragmentView!!.findViewById<Chip>(R.id.video_chip)
// video.setOnClickListener { view: View? ->
// if (video.isChecked) {
// format = "video"
// downloadsObjects = databaseManager!!.getHistory(searchQuery, format, website, sort)
// video.isChecked = true
// } else {
// format = ""
// downloadsObjects = databaseManager!!.getHistory(searchQuery, format, website, sort)
// video.isChecked = false
// }
// downloadsRecyclerViewAdapter!!.clear()
// downloadsRecyclerViewAdapter!!.add(downloadsObjects)
// }
// }
//
// private fun updateWebsiteChips() {
// websiteGroup!!.removeAllViews()
// val websites = downloadsRecyclerViewAdapter!!.websites
// for (i in websites.indices) {
// val w = websites[i]
// val tmp = layoutinflater!!.inflate(R.layout.filter_chip, websiteGroup, false) as Chip
// tmp.text = w
// tmp.id = i
// tmp.setOnClickListener { view: View ->
// if (tmp.isChecked) {
// website = tmp.text as String
// downloadsObjects =
// databaseManager!!.getHistory(searchQuery, format, website, sort)
// websiteGroup!!.check(view.id)
// } else {
// website = ""
// downloadsObjects =
// databaseManager!!.getHistory(searchQuery, format, website, sort)
// websiteGroup!!.clearCheck()
// }
// downloadsRecyclerViewAdapter!!.clear()
// downloadsRecyclerViewAdapter!!.add(downloadsObjects)
// }
// websiteGroup!!.addView(tmp)
// }
// }
private fun initChips() {
val sortChip = fragmentView!!.findViewById<Chip>(R.id.sortChip)
sortChip.setOnClickListener {
sortSheet = BottomSheetDialog(requireContext())
sortSheet!!.requestWindowFeature(Window.FEATURE_NO_TITLE)
sortSheet!!.setContentView(R.layout.downloads_sort_sheet)
val newest = sortSheet!!.findViewById<TextView>(R.id.newest)
val oldest = sortSheet!!.findViewById<TextView>(R.id.oldest)
newest!!.setOnClickListener {
historyViewModel.setSorting(HistorySort.DESC)
sortSheet!!.cancel()
}
oldest!!.setOnClickListener {
historyViewModel.setSorting(HistorySort.ASC)
sortSheet!!.cancel()
}
val cancel = sortSheet!!.findViewById<TextView>(R.id.cancel)
cancel!!.setOnClickListener { sortSheet!!.cancel() }
sortSheet!!.show()
sortSheet!!.window!!.setLayout(
ViewGroup.LayoutParams.MATCH_PARENT,
ViewGroup.LayoutParams.MATCH_PARENT
)
}
//format
val audio = fragmentView!!.findViewById<Chip>(R.id.audio_chip)
audio.setOnClickListener {
if (audio.isChecked) {
historyViewModel.setFormatFilter("audio")
audio.isChecked = true
} else {
historyViewModel.setFormatFilter("")
audio.isChecked = false
}
}
val video = fragmentView!!.findViewById<Chip>(R.id.video_chip)
video.setOnClickListener {
if (video.isChecked) {
historyViewModel.setFormatFilter("video")
video.isChecked = true
} else {
historyViewModel.setFormatFilter("")
video.isChecked = false
}
}
}
private fun updateWebsiteChips(list : List<HistoryItem>) {
val websites = mutableListOf<String>()
for (item in list){
if (!websites.contains(item.website)) websites.add(item.website)
}
websiteGroup!!.removeAllViews()
//val websites = downloadsRecyclerViewAdapter!!.websites
for (i in websites.indices) {
val w = websites[i]
val tmp = layoutinflater!!.inflate(R.layout.filter_chip, websiteGroup, false) as Chip
tmp.text = w
tmp.id = i
tmp.setOnClickListener {
Log.e(TAG, tmp.isChecked.toString())
if (tmp.isChecked) {
historyViewModel.setWebsiteFilter(tmp.text as String)
tmp.isChecked = true
} else {
historyViewModel.setWebsiteFilter("")
tmp.isChecked = false
}
}
websiteGroup!!.addView(tmp)
}
}
override fun onClick(v: View) {
// val id = v.id
// if (id == R.id.bottomsheet_remove_button) {
// removedownloadsItem(v.tag as Int)
// } else if (id == R.id.bottom_sheet_link) {
// openLinkIntent(v.tag as Int)
// } else if (id == R.id.bottomsheet_open_file_button) {
// openFileIntent(v.tag as Int)
// } else if (id == R.id.delete_selected_fab) {
// removeSelectedItems()
// }
when (v.id) {
R.id.bottomsheet_remove_button -> {
removeItem(v.tag as Int)
}
R.id.bottom_sheet_link -> {
openLinkIntent(v.tag as Int)
}
R.id.bottomsheet_open_file_button -> {
openFileIntent(v.tag as Int)
}
R.id.delete_selected_fab -> {
removeSelectedItems()
}
}
}
override fun onLongClick(v: View): Boolean {
// val id = v.id
// if (id == R.id.bottom_sheet_link) {
// copyLinkToClipBoard(v.tag as Int)
// return true
// }
val id = v.id
if (id == R.id.bottom_sheet_link) {
copyLinkToClipBoard(v.tag as Int)
return true
}
return false
}
// private fun removeSelectedItems() {
// if (bottomSheet != null) bottomSheet!!.hide()
// val delete_file = booleanArrayOf(false)
// databaseManager = DatabaseManager(context)
// val delete_dialog = MaterialAlertDialogBuilder(fragmentContext!!)
// delete_dialog.setTitle(getString(R.string.you_are_going_to_delete_multiple_items))
// delete_dialog.setMultiChoiceItems(
// arrayOf(getString(R.string.delete_files_too)),
// booleanArrayOf(false)
// ) { dialogInterface: DialogInterface?, i: Int, b: Boolean -> delete_file[0] = b }
// delete_dialog.setNegativeButton(getString(R.string.cancel)) { dialogInterface: DialogInterface, i: Int -> dialogInterface.cancel() }
// delete_dialog.setPositiveButton(getString(R.string.ok)) { dialogInterface: DialogInterface?, i: Int ->
// for (j in selectedObjects!!.indices) {
// val v = selectedObjects!![j]
// val position = downloadsObjects!!.indexOf(v)
// downloadsObjects!!.remove(v)
// downloadsRecyclerViewAdapter!!.remove(position)
// databaseManager!!.clearHistoryItem(v, delete_file[0])
// }
// updateWebsiteChips()
// databaseManager!!.close()
// selectedObjects = ArrayList()
// downloadsRecyclerViewAdapter!!.clearCheckedVideos()
// deleteFab!!.visibility = View.GONE
// if (downloadsObjects!!.size == 0) {
// uiHandler!!.post {
// no_results!!.visibility = View.VISIBLE
// selectionChips!!.visibility = View.GONE
// websiteGroup!!.removeAllViews()
// }
// }
// }
// delete_dialog.show()
// }
//
// private fun removedownloadsItem(position: Int) {
// if (bottomSheet != null) bottomSheet!!.hide()
// val delete_file = booleanArrayOf(false)
// databaseManager = DatabaseManager(context)
// val v = downloadsObjects!![position]
// val delete_dialog = MaterialAlertDialogBuilder(fragmentContext!!)
// delete_dialog.setTitle(getString(R.string.you_are_going_to_delete) + " \"" + v!!.title + "\"!")
// delete_dialog.setMultiChoiceItems(
// arrayOf(getString(R.string.delete_file_too)),
// booleanArrayOf(false)
// ) { dialogInterface: DialogInterface?, i: Int, b: Boolean -> delete_file[0] = b }
// delete_dialog.setNegativeButton(getString(R.string.cancel)) { dialogInterface: DialogInterface, i: Int -> dialogInterface.cancel() }
// delete_dialog.setPositiveButton(getString(R.string.ok)) { dialogInterface: DialogInterface?, i: Int ->
// downloadsObjects!!.removeAt(position)
// downloadsRecyclerViewAdapter!!.remove(position)
// updateWebsiteChips()
// databaseManager!!.clearHistoryItem(v, delete_file[0])
// databaseManager!!.close()
// if (downloadsObjects!!.size == 0) {
// uiHandler!!.post {
// no_results!!.visibility = View.VISIBLE
// selectionChips!!.visibility = View.GONE
// websiteGroup!!.removeAllViews()
// }
// }
// }
// delete_dialog.show()
// }
//
// private fun copyLinkToClipBoard(position: Int) {
// val url = downloadsObjects!![position]!!.getURL()
// val clipboard = context?.getSystemService(Context.CLIPBOARD_SERVICE) as ClipboardManager
// val clip = ClipData.newPlainText(getString(R.string.url), url)
// clipboard.setPrimaryClip(clip)
// if (bottomSheet != null) bottomSheet!!.hide()
// Toast.makeText(context, getString(R.string.link_copied_to_clipboard), Toast.LENGTH_SHORT)
// .show()
// }
//
// private fun openLinkIntent(position: Int) {
// val url = downloadsObjects!![position]!!.getURL()
// val i = Intent(Intent.ACTION_VIEW)
// i.data = Uri.parse(url)
// if (bottomSheet != null) bottomSheet!!.hide()
// startActivity(i)
// }
private fun removeSelectedItems() {
if (bottomSheet != null) bottomSheet!!.hide()
val deleteFile = booleanArrayOf(false)
val deleteDialog = MaterialAlertDialogBuilder(fragmentContext!!)
deleteDialog.setTitle(getString(R.string.you_are_going_to_delete_multiple_items))
deleteDialog.setMultiChoiceItems(
arrayOf(getString(R.string.delete_files_too)),
booleanArrayOf(false)
) { _: DialogInterface?, _: Int, b: Boolean -> deleteFile[0] = b }
deleteDialog.setNegativeButton(getString(R.string.cancel)) { dialogInterface: DialogInterface, _: Int -> dialogInterface.cancel() }
deleteDialog.setPositiveButton(getString(R.string.ok)) { _: DialogInterface?, _: Int ->
for (item in selectedObjects!!){
historyViewModel.delete(item, deleteFile[0])
}
selectedObjects = ArrayList()
historyRecyclerViewAdapter!!.clearCheckedVideos()
deleteFab!!.visibility = GONE
}
deleteDialog.show()
}
private fun openFileIntent(position: Int) {
val downloadPath = downloadsObjects!![position]!!.downloadPath
private fun removeItem(id: Int) {
if (bottomSheet != null) bottomSheet!!.hide()
val deleteFile = booleanArrayOf(false)
val v = findItem(id)
val deleteDialog = MaterialAlertDialogBuilder(fragmentContext!!)
deleteDialog.setTitle(getString(R.string.you_are_going_to_delete) + " \"" + v!!.title + "\"!")
deleteDialog.setMultiChoiceItems(
arrayOf(getString(R.string.delete_file_too)),
booleanArrayOf(false)
) { _: DialogInterface?, _: Int, b: Boolean -> deleteFile[0] = b }
deleteDialog.setNegativeButton(getString(R.string.cancel)) { dialogInterface: DialogInterface, _: Int -> dialogInterface.cancel() }
deleteDialog.setPositiveButton(getString(R.string.ok)) { _: DialogInterface?, _: Int ->
historyViewModel.delete(v, deleteFile[0])
}
deleteDialog.show()
}
private fun copyLinkToClipBoard(id: Int) {
val url = findItem(id)?.url
val clipboard = context?.getSystemService(Context.CLIPBOARD_SERVICE) as ClipboardManager
val clip = ClipData.newPlainText(getString(R.string.url), url)
clipboard.setPrimaryClip(clip)
if (bottomSheet != null) bottomSheet!!.hide()
Toast.makeText(context, getString(R.string.link_copied_to_clipboard), Toast.LENGTH_SHORT)
.show()
}
private fun openLinkIntent(id: Int) {
val url = findItem(id)?.url
val i = Intent(Intent.ACTION_VIEW)
i.data = Uri.parse(url)
if (bottomSheet != null) bottomSheet!!.hide()
startActivity(i)
}
private fun openFileIntent(id: Int) {
val downloadPath = findItem(id)!!.downloadPath
val file = File(downloadPath)
val uri = FileProvider.getUriForFile(
fragmentContext!!,
@ -511,11 +403,11 @@ class DownloadsFragment : Fragment(), DownloadsRecyclerViewAdapter.OnItemClickLi
startActivity(i)
}
override fun onCardClick(position: Int, isFilePresent: Boolean) {
override fun onCardClick(id: Int, isFilePresent: Boolean) {
bottomSheet = BottomSheetDialog(fragmentContext!!)
bottomSheet!!.requestWindowFeature(Window.FEATURE_NO_TITLE)
bottomSheet!!.setContentView(R.layout.downloads_bottom_sheet)
val video = downloadsObjects!![position]
val video = findItem(id)
val title = bottomSheet!!.findViewById<TextView>(R.id.bottom_sheet_title)
title!!.text = video!!.title
val author = bottomSheet!!.findViewById<TextView>(R.id.bottom_sheet_author)
@ -523,14 +415,14 @@ class DownloadsFragment : Fragment(), DownloadsRecyclerViewAdapter.OnItemClickLi
val link = bottomSheet!!.findViewById<Button>(R.id.bottom_sheet_link)
val url = video.url
link!!.text = url
link.tag = position
link.tag = id
link.setOnClickListener(this)
link.setOnLongClickListener(this)
val remove = bottomSheet!!.findViewById<Button>(R.id.bottomsheet_remove_button)
remove!!.tag = position
remove!!.tag = id
remove.setOnClickListener(this)
val openFile = bottomSheet!!.findViewById<Button>(R.id.bottomsheet_open_file_button)
openFile!!.tag = position
openFile!!.tag = id
openFile.setOnClickListener(this)
if (!isFilePresent) openFile.visibility = GONE
bottomSheet!!.show()
@ -540,43 +432,33 @@ class DownloadsFragment : Fragment(), DownloadsRecyclerViewAdapter.OnItemClickLi
)
}
override fun onCardSelect(position: Int, add: Boolean) {
// val video = downloadsObjects!![position]
// if (add) selectedObjects!!.add(video) else selectedObjects!!.remove(video)
// if (selectedObjects!!.size > 1) {
// deleteFab!!.visibility = View.VISIBLE
// } else {
// deleteFab!!.visibility = View.GONE
// }
override fun onCardSelect(id: Int, add: Boolean) {
val item = findItem(id)
if (add) selectedObjects!!.add(item!!)
else selectedObjects!!.remove(item)
if (selectedObjects!!.size > 1) {
deleteFab!!.visibility = VISIBLE
} else {
deleteFab!!.visibility = GONE
}
}
//
override fun onButtonClick(position: Int) {
// val vid = downloadsObjects!![position]
// try {
// mainActivity!!.removeItemFromDownloadQueue(vid, vid!!.downloadedType)
// //mainActivity!!.removeItemFromDownloadQueue(vid, vid!!.downloadedType)
// } catch (e: Exception) {
// val info = DownloadInfo()
// info.video = vid
// info.downloadType = vid!!.downloadedType
// }
}
//
fun findVideo(url: String, type: String): HistoryItem? {
for (i in downloadsObjects!!.indices) {
val v = downloadsObjects!![i]
if (v!!.url == url && v.type == type) {
return v
}
}
return null
private fun findItem(id : Int): HistoryItem? {
return downloadsList?.find { it?.id == id }
}
companion object {
private const val TAG = "downloadsFragment"
fun newInstance(): DownloadsFragment {
val fragment = DownloadsFragment()
val args = Bundle()
return fragment
}
}
}

View file

@ -1,5 +1,5 @@
<vector android:height="24dp" android:tint="#FFFFFF"
android:viewportHeight="24" android:viewportWidth="24"
android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
<path android:fillColor="@android:color/white" android:pathData="M19.35,10.04C18.67,6.59 15.64,4 12,4 9.11,4 6.6,5.64 5.35,8.04 2.34,8.36 0,10.91 0,14c0,3.31 2.69,6 6,6h13c2.76,0 5,-2.24 5,-5 0,-2.64 -2.05,-4.78 -4.65,-4.96zM19,18L6,18c-2.21,0 -4,-1.79 -4,-4 0,-2.05 1.53,-3.76 3.56,-3.97l1.07,-0.11 0.5,-0.95C8.08,7.14 9.94,6 12,6c2.62,0 4.88,1.86 5.39,4.43l0.3,1.5 1.53,0.11c1.56,0.1 2.78,1.41 2.78,2.96 0,1.65 -1.35,3 -3,3zM13.45,10h-2.9v3L8,13l4,4 4,-4h-2.55z"/>
<path android:fillColor="@android:color/white" android:pathData="M5,20h14v-2H5V20zM19,9h-4V3H9v6H5l7,7L19,9z"/>
</vector>

View file

@ -50,12 +50,13 @@
app:singleSelection="false">
<com.google.android.material.chip.Chip
android:id="@+id/sort_chip"
android:id="@+id/sortChip"
style="@style/Widget.Material3.Chip.Assist"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:chipIcon="@drawable/ic_down"
android:text="@string/sort_by"/>
android:onClick="sortBy"
android:text="@string/sort_by"
app:chipIcon="@drawable/ic_down" />
</com.google.android.material.chip.ChipGroup>