From 1adba854e899ffa158fab9d6454f6f5c55e74bdf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Denis=20=C3=87erri?= <64997243+deniscerri@users.noreply.github.com> Date: Sat, 25 Feb 2023 20:32:26 +0100 Subject: [PATCH] added search history --- .../1.json | 30 ++++- .../deniscerri/ytdlnis/database/DBManager.kt | 3 +- .../ytdlnis/database/dao/SearchHistoryDao.kt | 21 ++++ .../database/models/SearchHistoryItem.kt | 12 ++ .../repository/SearchHistoryRepository.kt | 22 ++++ .../database/viewmodel/ResultViewModel.kt | 16 +++ .../com/deniscerri/ytdlnis/ui/HomeFragment.kt | 108 ++---------------- .../com/deniscerri/ytdlnis/util/InfoUtil.kt | 6 +- app/src/main/res/menu/main_menu.xml | 5 + app/src/main/res/values/strings.xml | 1 + 10 files changed, 124 insertions(+), 100 deletions(-) create mode 100644 app/src/main/java/com/deniscerri/ytdlnis/database/dao/SearchHistoryDao.kt create mode 100644 app/src/main/java/com/deniscerri/ytdlnis/database/models/SearchHistoryItem.kt create mode 100644 app/src/main/java/com/deniscerri/ytdlnis/database/repository/SearchHistoryRepository.kt diff --git a/app/schemas/com.deniscerri.ytdlnis.database.DBManager/1.json b/app/schemas/com.deniscerri.ytdlnis.database.DBManager/1.json index 3c32d030..bfef4c81 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": "ae6989cdbd101bb25c22cc38d8ec456d", + "identityHash": "2a124f7c327413ab152e18a9e4a66ef7", "entities": [ { "tableName": "results", @@ -313,12 +313,38 @@ }, "indices": [], "foreignKeys": [] + }, + { + "tableName": "searchHistory", + "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `query` TEXT NOT NULL)", + "fields": [ + { + "fieldPath": "id", + "columnName": "id", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "query", + "columnName": "query", + "affinity": "TEXT", + "notNull": true + } + ], + "primaryKey": { + "autoGenerate": true, + "columnNames": [ + "id" + ] + }, + "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, 'ae6989cdbd101bb25c22cc38d8ec456d')" + "INSERT OR REPLACE INTO room_master_table (id,identity_hash) VALUES(42, '2a124f7c327413ab152e18a9e4a66ef7')" ] } } \ 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 efb48be0..aea2c35a 100644 --- a/app/src/main/java/com/deniscerri/ytdlnis/database/DBManager.kt +++ b/app/src/main/java/com/deniscerri/ytdlnis/database/DBManager.kt @@ -10,7 +10,7 @@ import com.deniscerri.ytdlnis.database.models.* @TypeConverters(Converters::class) @Database( - entities = [ResultItem::class, HistoryItem::class, DownloadItem::class, CommandTemplate::class], + entities = [ResultItem::class, HistoryItem::class, DownloadItem::class, CommandTemplate::class, SearchHistoryItem::class], version = 1, autoMigrations = [] ) @@ -19,6 +19,7 @@ abstract class DBManager : RoomDatabase(){ abstract val historyDao : HistoryDao abstract val downloadDao : DownloadDao abstract val commandTemplateDao : CommandTemplateDao + abstract val searchHistoryDao: SearchHistoryDao companion object { //prevents multiple instances of db getting created at the same time diff --git a/app/src/main/java/com/deniscerri/ytdlnis/database/dao/SearchHistoryDao.kt b/app/src/main/java/com/deniscerri/ytdlnis/database/dao/SearchHistoryDao.kt new file mode 100644 index 00000000..f2457c9b --- /dev/null +++ b/app/src/main/java/com/deniscerri/ytdlnis/database/dao/SearchHistoryDao.kt @@ -0,0 +1,21 @@ +package com.deniscerri.ytdlnis.database.dao + +import androidx.room.Dao +import androidx.room.Insert +import androidx.room.Query +import com.deniscerri.ytdlnis.database.models.SearchHistoryItem + +@Dao +interface SearchHistoryDao { + @Query("SELECT * from searchHistory ORDER BY id DESC LIMIT 10") + fun getAll() : List + + @Query("SELECT * from searchHistory WHERE query COLLATE NOCASE ='%'||:keyword||'%'") + fun getAllByKeyword(keyword: String) : List + + @Insert + suspend fun insert(new: SearchHistoryItem) + + @Query("DELETE FROM searchHistory") + suspend fun deleteAll() +} \ No newline at end of file diff --git a/app/src/main/java/com/deniscerri/ytdlnis/database/models/SearchHistoryItem.kt b/app/src/main/java/com/deniscerri/ytdlnis/database/models/SearchHistoryItem.kt new file mode 100644 index 00000000..e7dfbd02 --- /dev/null +++ b/app/src/main/java/com/deniscerri/ytdlnis/database/models/SearchHistoryItem.kt @@ -0,0 +1,12 @@ +package com.deniscerri.ytdlnis.database.models + +import androidx.room.Entity +import androidx.room.PrimaryKey +import com.deniscerri.ytdlnis.database.viewmodel.DownloadViewModel + +@Entity(tableName = "searchHistory") +data class SearchHistoryItem( + @PrimaryKey(autoGenerate = true) + var id: Long, + val query: String +) \ No newline at end of file diff --git a/app/src/main/java/com/deniscerri/ytdlnis/database/repository/SearchHistoryRepository.kt b/app/src/main/java/com/deniscerri/ytdlnis/database/repository/SearchHistoryRepository.kt new file mode 100644 index 00000000..813e5042 --- /dev/null +++ b/app/src/main/java/com/deniscerri/ytdlnis/database/repository/SearchHistoryRepository.kt @@ -0,0 +1,22 @@ +package com.deniscerri.ytdlnis.database.repository + +import com.deniscerri.ytdlnis.database.dao.SearchHistoryDao +import com.deniscerri.ytdlnis.database.models.SearchHistoryItem + +class SearchHistoryRepository(private val searchHistoryDao: SearchHistoryDao) { + fun getAll() : List { + return searchHistoryDao.getAll() + } + + fun getAllByKeyword(keyword: String) : List { + return searchHistoryDao.getAllByKeyword(keyword) + } + + suspend fun insert(query: String){ + searchHistoryDao.insert(SearchHistoryItem(0, query)) + } + + suspend fun deleteAll(){ + searchHistoryDao.deleteAll() + } +} \ 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 7c60e222..b3968278 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 @@ -7,7 +7,9 @@ import com.deniscerri.ytdlnis.App import com.deniscerri.ytdlnis.R import com.deniscerri.ytdlnis.database.DBManager import com.deniscerri.ytdlnis.database.models.ResultItem +import com.deniscerri.ytdlnis.database.models.SearchHistoryItem import com.deniscerri.ytdlnis.database.repository.ResultRepository +import com.deniscerri.ytdlnis.database.repository.SearchHistoryRepository import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.launch import java.util.regex.Pattern @@ -15,6 +17,7 @@ import java.util.regex.Pattern class ResultViewModel(application: Application) : AndroidViewModel(application) { private val tag: String = "ResultViewModel" private val repository : ResultRepository + private val searchHistoryRepository : SearchHistoryRepository val items : LiveData> val loadingItems = MutableLiveData() var itemCount : LiveData @@ -23,6 +26,7 @@ class ResultViewModel(application: Application) : AndroidViewModel(application) val dao = DBManager.getInstance(application).resultDao val commandDao = DBManager.getInstance(application).commandTemplateDao repository = ResultRepository(dao, commandDao, getApplication().applicationContext) + searchHistoryRepository = SearchHistoryRepository(DBManager.getInstance(application).searchHistoryDao) items = repository.allResults loadingItems.postValue(false) itemCount = repository.itemCount @@ -99,4 +103,16 @@ class ResultViewModel(application: Application) : AndroidViewModel(application) fun getItemByURL(url: String) : ResultItem { return repository.getItemByURL(url) } + + fun addSearchQueryToHistory(query: String) = viewModelScope.launch(Dispatchers.IO) { + searchHistoryRepository.insert(query) + } + + fun deleteAllSearchQueryHistory() = viewModelScope.launch(Dispatchers.IO){ + searchHistoryRepository.deleteAll() + } + + fun getSearchHistory() : List { + return searchHistoryRepository.getAll() + } } \ No newline at end of file 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 7fdce1f9..1cab248c 100644 --- a/app/src/main/java/com/deniscerri/ytdlnis/ui/HomeFragment.kt +++ b/app/src/main/java/com/deniscerri/ytdlnis/ui/HomeFragment.kt @@ -251,6 +251,7 @@ class HomeFragment : Fragment(), HomeAdapter.OnItemClickListener, View.OnClickLi searchView!!.inputType = InputType.TYPE_TEXT_VARIATION_URI searchView.queryHint = getString(R.string.search_hint) infoUtil = InfoUtil(requireContext()) + searchView.setOnQueryTextListener(object : SearchView.OnQueryTextListener { override fun onQueryTextSubmit(query: String): Boolean { topAppBar!!.menu.findItem(R.id.search).collapseActionView() @@ -258,6 +259,9 @@ class HomeFragment : Fragment(), HomeAdapter.OnItemClickListener, View.OnClickLi downloadFabs!!.visibility = GONE selectedObjects = ArrayList() inputQuery = query.trim { it <= ' ' } + if(!sharedPreferences!!.getBoolean("incognito", false)){ + resultViewModel.addSearchQueryToHistory(inputQuery!!) + } resultViewModel.deleteAll() val thread = Thread { resultViewModel.parseQuery(inputQuery!!, true) @@ -268,9 +272,12 @@ class HomeFragment : Fragment(), HomeAdapter.OnItemClickListener, View.OnClickLi override fun onQueryTextChange(newText: String): Boolean { searchSuggestionsLinearLayout!!.removeAllViews() - if (newText.isEmpty()) return false val thread = Thread { - val suggestions = infoUtil!!.getSearchSuggestions(newText) + val suggestions = if (newText.isEmpty()) { + resultViewModel.getSearchHistory().map { it.query } + }else{ + infoUtil!!.getSearchSuggestions(newText) + } for (i in suggestions.indices) { val v = LayoutInflater.from(fragmentContext) .inflate(R.layout.search_suggestion_item, null) @@ -307,15 +314,9 @@ class HomeFragment : Fragment(), HomeAdapter.OnItemClickListener, View.OnClickLi try { mainActivity!!.cancelAllDownloads() topAppBar!!.menu.findItem(itemId).isVisible = false -// for (i in downloadInfo!!.downloadQueue.indices) { -// val vid = downloadInfo!!.downloadQueue[i] -// val type = vid.downloadedType -// updateDownloadingStatusOnResult(vid, type, false) -// } -// downloadQueue = ArrayList() -// downloading = false - } catch (ignored: Exception) { - } + } catch (ignored: Exception) {} + } else if (itemId == R.id.delete_search){ + resultViewModel.deleteAllSearchQueryHistory() } true } @@ -351,29 +352,11 @@ class HomeFragment : Fragment(), HomeAdapter.OnItemClickListener, View.OnClickLi 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") { -// mainActivity!!.removeItemFromDownloadQueue(vid, type) -// return -// } -// } catch (ignored: Exception) { -// } -// } if (sharedPreferences!!.getBoolean("download_card", true)) { -// selectedObjects!!.clear() -// selectedObjects!!.add(item!!) - //showConfigureSingleDownloadCard(createDownloadItem(item!!, type), item) showSingleDownloadSheet(item!!, type!!) } else { val downloadItem = downloadViewModel.createDownloadItemFromResult(item!!, type!!) downloadViewModel.queueDownloads(listOf(downloadItem)) -// downloadQueue!!.add(vid) -// updateDownloadingStatusOnResult(vid, type, true) -// if (isStoragePermissionGranted) { -// mainActivity!!.startDownloadService(downloadQueue, listener) -// downloadQueue!!.clear() -// } } } @@ -382,32 +365,6 @@ class HomeFragment : Fragment(), HomeAdapter.OnItemClickListener, View.OnClickLi bottomSheet.show(parentFragmentManager, "downloadSingleSheet") } - - fun updateDownloadStatusOnResult(v: ResultItem?, type: String?, downloaded: Boolean) { -// if (v != null) { -// databaseManager = DatabaseManager(context) -// try { -// databaseManager!!.updateDownloadStatusOnResult(v.videoId, type, downloaded) -// databaseManager!!.close() -// } catch (ignored: Exception) { -// } -// } - } - - fun updateDownloadingStatusOnResult(v: ResultItem?, type: String, isDownloading: Boolean) { -// if (v != null) { -// if (type == "audio") v.isDownloadingAudio = -// isDownloading else if (type == "video") v.isDownloadingVideo = isDownloading -// homeAdapter!!.updateVideoListItem(v, resultsList!!.indexOf(v)) -// databaseManager = DatabaseManager(context) -// try { -// databaseManager!!.updateDownloadingStatusOnResult(v.videoId, type, isDownloading) -// databaseManager!!.close() -// } catch (ignored: Exception) { -// } -// } - } - override fun onCardClick(videoURL: String, add: Boolean) { val item = resultsList?.find { it -> it?.url == videoURL } if (add) selectedObjects!!.add(item!!) else selectedObjects!!.remove(item) @@ -460,47 +417,6 @@ class HomeFragment : Fragment(), HomeAdapter.OnItemClickListener, View.OnClickLi } } - private fun initDownloadAll( - bottomSheet: BottomSheetDialog, - start: Int, - end: Int, - type: String - ) { -// var start = start -// var end = end -// if (start > end) { -// val first = bottomSheet.findViewById(R.id.first_textinput) -// first!!.error = getString(R.string.first_cant_be_larger_than_last) -// val last = bottomSheet.findViewById(R.id.last_textinput) -// last!!.error = getString(R.string.last_cant_be_smaller_than_first) -// return -// } -// bottomSheet.cancel() -// start-- -// end-- -// if (start <= 1) start = 0 -// val sharedPreferences = -// requireContext().getSharedPreferences("root_preferences", Activity.MODE_PRIVATE) -// if (sharedPreferences.getBoolean("download_card", true)) { -// selectedObjects!!.clear() -// selectedObjects!!.addAll(resultsList!!.subList(start, end + 1) as ArrayList) -// showConfigureDownloadCard(type) -// } else { -// for (i in start..end) { -// val vid = findVideo( -// resultsList!![i]!!.getURL() -// ) -// vid!!.downloadedType = type -// updateDownloadingStatusOnResult(vid, type, true) -// downloadQueue!!.add(vid) -// } -// if (isStoragePermissionGranted) { -// mainActivity!!.startDownloadService(downloadQueue, listener) -// downloadQueue!!.clear() -// } -// } - } - companion object { private const val TAG = "HomeFragment" } diff --git a/app/src/main/java/com/deniscerri/ytdlnis/util/InfoUtil.kt b/app/src/main/java/com/deniscerri/ytdlnis/util/InfoUtil.kt index 1b1b2f1b..2e044e05 100644 --- a/app/src/main/java/com/deniscerri/ytdlnis/util/InfoUtil.kt +++ b/app/src/main/java/com/deniscerri/ytdlnis/util/InfoUtil.kt @@ -4,8 +4,10 @@ import android.app.Activity import android.content.Context import android.util.Log import com.deniscerri.ytdlnis.R +import com.deniscerri.ytdlnis.database.DBManager import com.deniscerri.ytdlnis.database.models.Format import com.deniscerri.ytdlnis.database.models.ResultItem +import com.deniscerri.ytdlnis.database.repository.SearchHistoryRepository import com.google.gson.Gson import com.yausername.youtubedl_android.YoutubeDL import com.yausername.youtubedl_android.YoutubeDLRequest @@ -21,6 +23,7 @@ import java.util.* import kotlin.collections.ArrayList class InfoUtil(context: Context) { + private var searchHistoryRepository = SearchHistoryRepository(DBManager.getInstance(context).searchHistoryDao) private var items: ArrayList private var key: String? = null private var useInvidous = false @@ -532,7 +535,8 @@ class InfoUtil(context: Context) { val suggestionList = ArrayList() try { for (i in 0 until res.getJSONArray(1).length()) { - suggestionList.add(res.getJSONArray(1).getString(i)) + val item = res.getJSONArray(1).getString(i) + suggestionList.add(item) } } catch (ignored: Exception) { ignored.printStackTrace() diff --git a/app/src/main/res/menu/main_menu.xml b/app/src/main/res/menu/main_menu.xml index a8357749..6e744e30 100644 --- a/app/src/main/res/menu/main_menu.xml +++ b/app/src/main/res/menu/main_menu.xml @@ -15,6 +15,11 @@ android:title="@string/remove_results" app:showAsAction="never" /> + + Format Select Format Please Wait + Clear Search History \ No newline at end of file