From 8ff87e5108fb28dac0e2a340807db85f72d92393 Mon Sep 17 00:00:00 2001 From: LagradOst Date: Wed, 28 Jul 2021 03:04:32 +0200 Subject: [PATCH] found memory leak that is not fixed but fixes search --- .../lagradost/cloudstream3/MainActivity.kt | 24 +++----------- .../com/lagradost/cloudstream3/UIHelper.kt | 9 +++++ .../ui/download/DownloadButtonSetup.kt | 22 +++++++++---- .../cloudstream3/ui/result/EpisodeAdapter.kt | 5 +-- .../cloudstream3/ui/result/ResultFragment.kt | 7 ++++ .../cloudstream3/ui/search/SearchAdaptor.kt | 23 ++++++------- .../cloudstream3/ui/search/SearchFragment.kt | 25 +++++++++++--- .../cloudstream3/ui/search/SearchViewModel.kt | 12 +++++++ .../cloudstream3/utils/ExoPlayerHelper.kt | 33 ------------------- .../utils/VideoDownloadManager.kt | 12 +++++-- app/src/main/res/menu/bottom_nav_menu.xml | 4 +-- .../main/res/navigation/mobile_navigation.xml | 12 +++---- 12 files changed, 100 insertions(+), 88 deletions(-) delete mode 100644 app/src/main/java/com/lagradost/cloudstream3/utils/ExoPlayerHelper.kt diff --git a/app/src/main/java/com/lagradost/cloudstream3/MainActivity.kt b/app/src/main/java/com/lagradost/cloudstream3/MainActivity.kt index 955191c7..4c2ff50a 100644 --- a/app/src/main/java/com/lagradost/cloudstream3/MainActivity.kt +++ b/app/src/main/java/com/lagradost/cloudstream3/MainActivity.kt @@ -7,29 +7,23 @@ import android.content.pm.PackageManager import android.content.res.ColorStateList import android.os.Build import android.os.Bundle -import android.widget.Toast +import android.view.WindowManager import androidx.appcompat.app.AppCompatActivity import androidx.navigation.NavOptions import androidx.navigation.findNavController import androidx.navigation.fragment.NavHostFragment -import androidx.navigation.ui.AppBarConfiguration -import androidx.navigation.ui.setupWithNavController import com.google.android.gms.cast.framework.CastButtonFactory import com.google.android.material.bottomnavigation.BottomNavigationView import com.lagradost.cloudstream3.UIHelper.checkWrite import com.lagradost.cloudstream3.UIHelper.getResourceColor import com.lagradost.cloudstream3.UIHelper.hasPIPPermission -import com.lagradost.cloudstream3.UIHelper.isUsingMobileData import com.lagradost.cloudstream3.UIHelper.requestRW import com.lagradost.cloudstream3.UIHelper.shouldShowPIPMode import com.lagradost.cloudstream3.receivers.VideoDownloadRestartReceiver import com.lagradost.cloudstream3.ui.download.DownloadChildFragment import com.lagradost.cloudstream3.utils.DataStore.getKey -import com.lagradost.cloudstream3.utils.DataStore.getKeys import com.lagradost.cloudstream3.utils.DataStore.removeKey -import com.lagradost.cloudstream3.utils.DataStore.removeKeys import com.lagradost.cloudstream3.utils.DataStoreHelper.setViewPos -import com.lagradost.cloudstream3.utils.VideoDownloadManager import kotlinx.android.synthetic.main.fragment_result.* const val VLC_PACKAGE = "org.videolan.vlc" @@ -57,14 +51,7 @@ class MainActivity : AppCompatActivity() { var isInPlayer: Boolean = false var canShowPipMode: Boolean = false var isInPIPMode: Boolean = false - lateinit var mainContext: MainActivity lateinit var navOptions: NavOptions - - //https://github.com/anggrayudi/SimpleStorage/blob/4eb6306efb6cdfae4e34f170c8b9d4e135b04d51/sample/src/main/java/com/anggrayudi/storage/sample/activity/MainActivity.kt#L624 - const val REQUEST_CODE_STORAGE_ACCESS = 1 - const val REQUEST_CODE_PICK_FOLDER = 2 - const val REQUEST_CODE_PICK_FILE = 3 - const val REQUEST_CODE_ASK_PERMISSIONS = 4 } private fun enterPIPMode() { @@ -149,7 +136,7 @@ class MainActivity : AppCompatActivity() { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) - mainContext = this + window.setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_ALWAYS_HIDDEN) setContentView(R.layout.activity_main) val navView: BottomNavigationView = findViewById(R.id.nav_view) @@ -174,9 +161,9 @@ class MainActivity : AppCompatActivity() { navView.setOnNavigationItemSelectedListener { item -> when (item.itemId) { - // R.id.navigation_home -> { - // navController.navigate(R.id.navigation_home, null, navOptions) - //} + R.id.navigation_home -> { + navController.navigate(R.id.navigation_home, null, navOptions) + } R.id.navigation_search -> { navController.navigate(R.id.navigation_search, null, navOptions) } @@ -232,7 +219,6 @@ class MainActivity : AppCompatActivity() { }*/ - /* val castContext = CastContext.getSharedInstance(applicationContext) fun buildMediaQueueItem(video: String): MediaQueueItem { diff --git a/app/src/main/java/com/lagradost/cloudstream3/UIHelper.kt b/app/src/main/java/com/lagradost/cloudstream3/UIHelper.kt index e0af59db..38dd69a8 100644 --- a/app/src/main/java/com/lagradost/cloudstream3/UIHelper.kt +++ b/app/src/main/java/com/lagradost/cloudstream3/UIHelper.kt @@ -31,6 +31,7 @@ import androidx.core.graphics.alpha import androidx.core.graphics.blue import androidx.core.graphics.green import androidx.core.graphics.red +import androidx.fragment.app.Fragment import androidx.fragment.app.FragmentActivity import androidx.preference.PreferenceManager import com.google.android.gms.cast.framework.CastContext @@ -68,6 +69,14 @@ object UIHelper { ) } + fun Fragment.hideKeyboard() { + view.let { + if (it != null) { + activity?.hideKeyboard(it) + } + } + } + @ColorInt fun Context.getResourceColor(@AttrRes resource: Int, alphaFactor: Float = 1f): Int { val typedArray = obtainStyledAttributes(intArrayOf(resource)) diff --git a/app/src/main/java/com/lagradost/cloudstream3/ui/download/DownloadButtonSetup.kt b/app/src/main/java/com/lagradost/cloudstream3/ui/download/DownloadButtonSetup.kt index 42024a9c..26235c8c 100644 --- a/app/src/main/java/com/lagradost/cloudstream3/ui/download/DownloadButtonSetup.kt +++ b/app/src/main/java/com/lagradost/cloudstream3/ui/download/DownloadButtonSetup.kt @@ -105,7 +105,7 @@ object DownloadButtonSetup { downloadView: View, downloadImageChangeCallback: (Pair) -> Unit, clickCallback: (DownloadClickEvent) -> Unit, - ) { + ): () -> Unit { var lastState: VideoDownloadManager.DownloadType? = null var currentBytes = setupCurrentBytes ?: 0 var totalBytes = setupTotalBytes ?: 0 @@ -174,7 +174,7 @@ object DownloadButtonSetup { fixDownloadedBytes(currentBytes, totalBytes, false) changeDownloadImage(VideoDownloadManager.getDownloadState(data.id)) - VideoDownloadManager.downloadProgressEvent += { downloadData -> + val downloadProgressEventListener = { downloadData: Triple -> if (data.id == downloadData.first) { if (downloadData.second != currentBytes || downloadData.third != totalBytes) { // TO PREVENT WASTING UI TIME Coroutines.runOnMainThread { @@ -184,7 +184,7 @@ object DownloadButtonSetup { } } - VideoDownloadManager.downloadStatusEvent += { downloadData -> + val downloadStatusEventListener = { downloadData: Pair -> if (data.id == downloadData.first) { if (lastState != downloadData.second || needImageUpdate) { // TO PREVENT WASTING UI TIME Coroutines.runOnMainThread { @@ -194,6 +194,9 @@ object DownloadButtonSetup { } } + VideoDownloadManager.downloadProgressEvent += downloadProgressEventListener + VideoDownloadManager.downloadStatusEvent += downloadStatusEventListener + downloadView.setOnClickListener { if (currentBytes <= 0) { clickCallback.invoke(DownloadClickEvent(DOWNLOAD_ACTION_DOWNLOAD, data)) @@ -220,6 +223,11 @@ object DownloadButtonSetup { } } } + + return { + VideoDownloadManager.downloadProgressEvent -= downloadProgressEventListener + VideoDownloadManager.downloadStatusEvent -= downloadStatusEventListener + } } fun setUpMaterialButton( @@ -230,8 +238,8 @@ object DownloadButtonSetup { textView: TextView?, data: VideoDownloadHelper.DownloadEpisodeCached, clickCallback: (DownloadClickEvent) -> Unit, - ) { - setUpDownloadButton(setupCurrentBytes, setupTotalBytes, progressBar, textView, data, downloadButton, { + ): () -> Unit { + return setUpDownloadButton(setupCurrentBytes, setupTotalBytes, progressBar, textView, data, downloadButton, { downloadButton?.setIconResource(it.first) downloadButton?.text = it.second }, clickCallback) @@ -245,8 +253,8 @@ object DownloadButtonSetup { textView: TextView?, data: VideoDownloadHelper.DownloadEpisodeCached, clickCallback: (DownloadClickEvent) -> Unit, - ) { - setUpDownloadButton(setupCurrentBytes, setupTotalBytes, progressBar, textView, data, downloadImage, { + ): () -> Unit { + return setUpDownloadButton(setupCurrentBytes, setupTotalBytes, progressBar, textView, data, downloadImage, { downloadImage?.setImageResource(it.first) }, clickCallback) } diff --git a/app/src/main/java/com/lagradost/cloudstream3/ui/result/EpisodeAdapter.kt b/app/src/main/java/com/lagradost/cloudstream3/ui/result/EpisodeAdapter.kt index ee412963..ce2bcdf4 100644 --- a/app/src/main/java/com/lagradost/cloudstream3/ui/result/EpisodeAdapter.kt +++ b/app/src/main/java/com/lagradost/cloudstream3/ui/result/EpisodeAdapter.kt @@ -16,6 +16,7 @@ import com.lagradost.cloudstream3.ui.download.DOWNLOAD_ACTION_DOWNLOAD import com.lagradost.cloudstream3.ui.download.DownloadButtonSetup import com.lagradost.cloudstream3.ui.download.DownloadButtonSetup.handleDownloadClick import com.lagradost.cloudstream3.ui.download.DownloadClickEvent +import com.lagradost.cloudstream3.utils.Event import com.lagradost.cloudstream3.utils.VideoDownloadHelper import com.lagradost.cloudstream3.utils.VideoDownloadManager import kotlinx.android.synthetic.main.result_episode.view.episode_holder @@ -46,8 +47,8 @@ class EpisodeAdapter( private val hasDownloadSupport: Boolean, private val clickCallback: (EpisodeClickEvent) -> Unit, private val downloadClickCallback: (DownloadClickEvent) -> Unit, -) : - RecyclerView.Adapter() { +) : RecyclerView.Adapter() { + @LayoutRes private var layout: Int = 0 fun updateLayout() { diff --git a/app/src/main/java/com/lagradost/cloudstream3/ui/result/ResultFragment.kt b/app/src/main/java/com/lagradost/cloudstream3/ui/result/ResultFragment.kt index 4161f49c..8c7d2ec5 100644 --- a/app/src/main/java/com/lagradost/cloudstream3/ui/result/ResultFragment.kt +++ b/app/src/main/java/com/lagradost/cloudstream3/ui/result/ResultFragment.kt @@ -38,6 +38,7 @@ import com.lagradost.cloudstream3.UIHelper.checkWrite import com.lagradost.cloudstream3.UIHelper.colorFromAttribute import com.lagradost.cloudstream3.UIHelper.fixPaddingStatusbar import com.lagradost.cloudstream3.UIHelper.getStatusBarHeight +import com.lagradost.cloudstream3.UIHelper.hideKeyboard import com.lagradost.cloudstream3.UIHelper.isAppInstalled import com.lagradost.cloudstream3.UIHelper.isCastApiAvailable import com.lagradost.cloudstream3.UIHelper.isConnectedToChromecast @@ -65,6 +66,9 @@ import jp.wasabeef.glide.transformations.BlurTransformation import kotlinx.android.synthetic.main.fragment_result.* import kotlinx.coroutines.Job import java.io.File +import java.util.* +import kotlin.collections.ArrayList +import kotlin.collections.HashMap const val MAX_SYNO_LENGH = 300 @@ -220,6 +224,9 @@ class ResultFragment : Fragment() { @SuppressLint("SetTextI18n") override fun onViewCreated(view: View, savedInstanceState: Bundle?) { super.onViewCreated(view, savedInstanceState) + activity?.window?.decorView?.clearFocus() + hideKeyboard() + activity?.fixPaddingStatusbar(result_scroll) activity?.fixPaddingStatusbar(result_barstatus) diff --git a/app/src/main/java/com/lagradost/cloudstream3/ui/search/SearchAdaptor.kt b/app/src/main/java/com/lagradost/cloudstream3/ui/search/SearchAdaptor.kt index b235a43a..3a78f811 100644 --- a/app/src/main/java/com/lagradost/cloudstream3/ui/search/SearchAdaptor.kt +++ b/app/src/main/java/com/lagradost/cloudstream3/ui/search/SearchAdaptor.kt @@ -8,6 +8,7 @@ import android.widget.FrameLayout import android.widget.ImageView import android.widget.TextView import androidx.appcompat.app.AppCompatActivity +import androidx.cardview.widget.CardView import androidx.recyclerview.widget.RecyclerView import com.bumptech.glide.Glide import com.bumptech.glide.load.model.GlideUrl @@ -56,17 +57,17 @@ class SearchAdapter( constructor(itemView: View, _activity: Activity, resView: AutofitRecyclerView) : RecyclerView.ViewHolder(itemView) { val activity = _activity val cardView: ImageView = itemView.imageView - val cardText: TextView = itemView.imageText - val text_type: TextView? = itemView.text_type + private val cardText: TextView = itemView.imageText + private val textType: TextView? = itemView.text_type // val search_result_lang: ImageView? = itemView.search_result_lang - val text_is_dub: View? = itemView.text_is_dub - val text_is_sub: View? = itemView.text_is_sub + private val textIsDub: View? = itemView.text_is_dub + private val textIsSub: View? = itemView.text_is_sub //val cardTextExtra: TextView? = itemView.imageTextExtra //val imageTextProvider: TextView? = itemView.imageTextProvider - val bg = itemView.backgroundCard - val compactView = itemView.context.getGridIsCompact() + private val bg: CardView = itemView.backgroundCard + private val compactView = itemView.context.getGridIsCompact() private val coverHeight: Int = if (compactView) 80.toPx else (resView.itemWidth / 0.68).roundToInt() fun bind(card: Any) { @@ -80,7 +81,7 @@ class SearchAdapter( } } - text_type?.text = when (card.type) { + textType?.text = when (card.type) { TvType.Anime -> "Anime" TvType.Movie -> "Movie" TvType.ONA -> "ONA" @@ -88,8 +89,8 @@ class SearchAdapter( } // search_result_lang?.visibility = View.GONE - text_is_dub?.visibility = View.GONE - text_is_sub?.visibility = View.GONE + textIsDub?.visibility = View.GONE + textIsSub?.visibility = View.GONE cardText.text = card.name @@ -114,11 +115,11 @@ class SearchAdapter( if (card.dubStatus?.size == 1) { //search_result_lang?.visibility = View.VISIBLE if (card.dubStatus.contains(DubStatus.Dubbed)) { - text_is_dub?.visibility = View.VISIBLE + textIsDub?.visibility = View.VISIBLE //search_result_lang?.setColorFilter(ContextCompat.getColor(activity, R.color.dubColor)) } else if (card.dubStatus.contains(DubStatus.Subbed)) { //search_result_lang?.setColorFilter(ContextCompat.getColor(activity, R.color.subColor)) - text_is_sub?.visibility = View.VISIBLE + textIsSub?.visibility = View.VISIBLE } } } diff --git a/app/src/main/java/com/lagradost/cloudstream3/ui/search/SearchFragment.kt b/app/src/main/java/com/lagradost/cloudstream3/ui/search/SearchFragment.kt index fb00c8b7..891cd46c 100644 --- a/app/src/main/java/com/lagradost/cloudstream3/ui/search/SearchFragment.kt +++ b/app/src/main/java/com/lagradost/cloudstream3/ui/search/SearchFragment.kt @@ -1,10 +1,13 @@ package com.lagradost.cloudstream3.ui.search +import android.content.Context import android.content.res.Configuration import android.os.Bundle import android.view.LayoutInflater import android.view.View import android.view.ViewGroup +import android.view.WindowManager +import android.view.inputmethod.InputMethodManager import android.widget.ImageView import android.widget.Toast import androidx.appcompat.app.AlertDialog @@ -36,7 +39,9 @@ class SearchFragment : Fragment() { ): View? { searchViewModel = ViewModelProvider(this).get(SearchViewModel::class.java) - + activity?.window?.setSoftInputMode( + WindowManager.LayoutParams.SOFT_INPUT_STATE_VISIBLE + ) return inflater.inflate(R.layout.fragment_search, container, false) } @@ -125,9 +130,9 @@ class SearchFragment : Fragment() { observe(searchViewModel.searchResponse) { when (it) { is Resource.Success -> { - it?.value?.let { data -> - (cardSpace.adapter as SearchAdapter).cardList = data - (cardSpace.adapter as SearchAdapter).notifyDataSetChanged() + it.value.let { data -> + (cardSpace?.adapter as SearchAdapter?)?.cardList = data + cardSpace?.adapter?.notifyDataSetChanged() } searchExitIcon.alpha = 1f search_loading_bar.alpha = 0f @@ -144,6 +149,18 @@ class SearchFragment : Fragment() { } } allApi.providersActive = requireActivity().getApiSettings() + + main_search.setOnQueryTextFocusChangeListener { searchView, b -> + if (b) { + // https://stackoverflow.com/questions/12022715/unable-to-show-keyboard-automatically-in-the-searchview + searchView?.postDelayed({ + val imm: InputMethodManager? = + requireActivity().getSystemService(Context.INPUT_METHOD_SERVICE) as? InputMethodManager? + imm?.showSoftInput(view.findFocus(), 0) + }, 200) + } + } + main_search.onActionViewExpanded() //searchViewModel.search("iron man") //(activity as AppCompatActivity).loadResult("https://shiro.is/overlord-dubbed", "overlord-dubbed", "Shiro") /* diff --git a/app/src/main/java/com/lagradost/cloudstream3/ui/search/SearchViewModel.kt b/app/src/main/java/com/lagradost/cloudstream3/ui/search/SearchViewModel.kt index 1e0304b9..31b9c1d5 100644 --- a/app/src/main/java/com/lagradost/cloudstream3/ui/search/SearchViewModel.kt +++ b/app/src/main/java/com/lagradost/cloudstream3/ui/search/SearchViewModel.kt @@ -14,8 +14,16 @@ class SearchViewModel : ViewModel() { val searchResponse: LiveData>> get() = _searchResponse var searchCounter = 0 + private fun clearSearch() { + _searchResponse.postValue(Resource.Success(ArrayList())) + } + fun search(query: String) = viewModelScope.launch { searchCounter++ + if(query.length <= 1) { + clearSearch() + return@launch + } val localSearchCounter = searchCounter _searchResponse.postValue(Resource.Loading()) val data = safeApiCall { @@ -27,6 +35,10 @@ class SearchViewModel : ViewModel() { fun quickSearch(query: String) = viewModelScope.launch { searchCounter++ + if(query.length <= 1) { + clearSearch() + return@launch + } val localSearchCounter = searchCounter _searchResponse.postValue(Resource.Loading()) val data = safeApiCall { diff --git a/app/src/main/java/com/lagradost/cloudstream3/utils/ExoPlayerHelper.kt b/app/src/main/java/com/lagradost/cloudstream3/utils/ExoPlayerHelper.kt deleted file mode 100644 index 960fac6c..00000000 --- a/app/src/main/java/com/lagradost/cloudstream3/utils/ExoPlayerHelper.kt +++ /dev/null @@ -1,33 +0,0 @@ -package com.lagradost.cloudstream3.utils - -import com.google.android.exoplayer2.database.ExoDatabaseProvider -import com.google.android.exoplayer2.offline.DownloadManager -import com.google.android.exoplayer2.upstream.DefaultHttpDataSourceFactory -import com.google.android.exoplayer2.upstream.cache.LeastRecentlyUsedCacheEvictor -import com.google.android.exoplayer2.upstream.cache.SimpleCache -import com.lagradost.cloudstream3.MainActivity -import java.util.concurrent.Executor - -object ExoPlayerHelper { - private val context = MainActivity.mainContext - val databaseProvider = ExoDatabaseProvider(context) - val downloadExecutor = Executor { obj: Runnable -> obj.run() } - val dataSourceFactory = DefaultHttpDataSourceFactory() - - val downloadCache: SimpleCache by lazy { - SimpleCache( - context.cacheDir, - LeastRecentlyUsedCacheEvictor(20 * 1024 * 1024), - databaseProvider - ) - } - - val downloadManager: DownloadManager by lazy { - DownloadManager(context, - databaseProvider, - downloadCache, - dataSourceFactory, - downloadExecutor) - } - -} \ No newline at end of file diff --git a/app/src/main/java/com/lagradost/cloudstream3/utils/VideoDownloadManager.kt b/app/src/main/java/com/lagradost/cloudstream3/utils/VideoDownloadManager.kt index 10a07e66..1f15d9d2 100644 --- a/app/src/main/java/com/lagradost/cloudstream3/utils/VideoDownloadManager.kt +++ b/app/src/main/java/com/lagradost/cloudstream3/utils/VideoDownloadManager.kt @@ -526,7 +526,6 @@ object VideoDownloadManager { var count: Int var bytesDownloaded = resumeLength - var isPaused = false var isStopped = false var isDone = false @@ -561,7 +560,8 @@ object VideoDownloadManager { ) } - downloadEvent += { event -> + + val downloadEventListener = { event: Pair -> if (event.first == ep.id) { when (event.second) { DownloadActionType.Pause -> { @@ -579,6 +579,8 @@ object VideoDownloadManager { } } + downloadEvent += downloadEventListener + // UPDATE DOWNLOAD NOTIFICATION val notificationCoroutine = main { while (true) { @@ -620,6 +622,12 @@ object VideoDownloadManager { connectionInputStream.close() notificationCoroutine.cancel() + try { + downloadEvent -= downloadEventListener + } catch (e: Exception) { + e.printStackTrace() + } + try { downloadStatus.remove(ep.id) } catch (e: Exception) { diff --git a/app/src/main/res/menu/bottom_nav_menu.xml b/app/src/main/res/menu/bottom_nav_menu.xml index 11d11cf5..ab5759e1 100644 --- a/app/src/main/res/menu/bottom_nav_menu.xml +++ b/app/src/main/res/menu/bottom_nav_menu.xml @@ -1,16 +1,14 @@ - - + app:startDestination="@+id/navigation_home"> - + + android:label="@string/title_settings"/> + android:label="@string/title_settings"/> \ No newline at end of file