diff --git a/app/src/main/java/com/github/libretube/dialogs/CreatePlaylistDialog.kt b/app/src/main/java/com/github/libretube/dialogs/CreatePlaylistDialog.kt index c08a9096a..57c7db895 100644 --- a/app/src/main/java/com/github/libretube/dialogs/CreatePlaylistDialog.kt +++ b/app/src/main/java/com/github/libretube/dialogs/CreatePlaylistDialog.kt @@ -10,7 +10,7 @@ import androidx.fragment.app.DialogFragment import androidx.lifecycle.lifecycleScope import com.github.libretube.R import com.github.libretube.databinding.DialogCreatePlaylistBinding -import com.github.libretube.fragments.Library +import com.github.libretube.fragments.LibraryFragment import com.github.libretube.obj.Playlists import com.github.libretube.util.PreferenceHelper import com.github.libretube.util.RetrofitInstance @@ -82,7 +82,7 @@ class CreatePlaylistDialog : DialogFragment() { } // refresh the playlists in the library try { - val parent = parentFragment as Library + val parent = parentFragment as LibraryFragment parent.fetchPlaylists() } catch (e: Exception) { Log.e(TAG, e.toString()) diff --git a/app/src/main/java/com/github/libretube/fragments/ChannelFragment.kt b/app/src/main/java/com/github/libretube/fragments/ChannelFragment.kt index a45f80c71..d6f1e8355 100644 --- a/app/src/main/java/com/github/libretube/fragments/ChannelFragment.kt +++ b/app/src/main/java/com/github/libretube/fragments/ChannelFragment.kt @@ -6,16 +6,12 @@ import android.util.Log import android.view.LayoutInflater import android.view.View import android.view.ViewGroup -import android.widget.ImageView -import android.widget.ScrollView -import android.widget.TextView import androidx.fragment.app.Fragment import androidx.lifecycle.lifecycleScope import androidx.recyclerview.widget.LinearLayoutManager -import androidx.recyclerview.widget.RecyclerView -import androidx.swiperefreshlayout.widget.SwipeRefreshLayout import com.github.libretube.R import com.github.libretube.adapters.ChannelAdapter +import com.github.libretube.databinding.FragmentChannelBinding import com.github.libretube.obj.Subscribe import com.github.libretube.util.PreferenceHelper import com.github.libretube.util.RetrofitInstance @@ -26,19 +22,19 @@ import retrofit2.HttpException import java.io.IOException class ChannelFragment : Fragment() { - - private var channel_id: String? = null private val TAG = "ChannelFragment" + private lateinit var binding: FragmentChannelBinding + + private var channelId: String? = null var nextPage: String? = null - var channelAdapter: ChannelAdapter? = null - var isLoading = true - var isSubscribed: Boolean = false - private var refreshLayout: SwipeRefreshLayout? = null + private var channelAdapter: ChannelAdapter? = null + private var isLoading = true + private var isSubscribed: Boolean = false override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) arguments?.let { - channel_id = it.getString("channel_id") + channelId = it.getString("channel_id") } } @@ -46,43 +42,39 @@ class ChannelFragment : Fragment() { inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle? - ): View? { - // Inflate the layout for this fragment - return inflater.inflate(R.layout.fragment_channel, container, false) + ): View { + binding = FragmentChannelBinding.inflate(layoutInflater, container, false) + return binding.root } override fun onViewCreated(view: View, savedInstanceState: Bundle?) { super.onViewCreated(view, savedInstanceState) - channel_id = channel_id!!.replace("/channel/", "") - view.findViewById(R.id.channel_name).text = channel_id - val recyclerView = view.findViewById(R.id.channel_recView) - recyclerView.layoutManager = LinearLayoutManager(context) - refreshLayout = view.findViewById(R.id.channel_refresh) + channelId = channelId!!.replace("/channel/", "") + binding.channelName.text = channelId + binding.channelRecView.layoutManager = LinearLayoutManager(context) val refreshChannel = { - refreshLayout?.isRefreshing = true - fetchChannel(view) - val subButton = view.findViewById(R.id.channel_subscribe) + binding.channelRefresh.isRefreshing = true + fetchChannel() if (PreferenceHelper.getToken(requireContext()) != "") { - isSubscribed(subButton) + isSubscribed(binding.channelSubscribe) } } refreshChannel() - refreshLayout?.setOnRefreshListener { + binding.channelRefresh.setOnRefreshListener { refreshChannel() } - val scrollView = view.findViewById(R.id.channel_scrollView) - scrollView.viewTreeObserver + binding.channelScrollView.viewTreeObserver .addOnScrollChangedListener { - if (scrollView.getChildAt(0).bottom - == (scrollView.height + scrollView.scrollY) + if (binding.channelScrollView.getChildAt(0).bottom + == (binding.channelScrollView.height + binding.channelScrollView.scrollY) ) { // scroll view is at bottom if (nextPage != null && !isLoading) { isLoading = true - refreshLayout?.isRefreshing = true + binding.channelRefresh.isRefreshing = true fetchNextPage() } } @@ -96,7 +88,7 @@ class ChannelFragment : Fragment() { val response = try { val token = PreferenceHelper.getToken(requireContext()) RetrofitInstance.api.isSubscribed( - channel_id!!, + channelId!!, token ) } catch (e: IOException) { @@ -137,7 +129,7 @@ class ChannelFragment : Fragment() { val token = PreferenceHelper.getToken(requireContext()) RetrofitInstance.api.subscribe( token, - Subscribe(channel_id) + Subscribe(channelId) ) } catch (e: IOException) { println(e) @@ -160,7 +152,7 @@ class ChannelFragment : Fragment() { val token = PreferenceHelper.getToken(requireContext()) RetrofitInstance.api.unsubscribe( token, - Subscribe(channel_id) + Subscribe(channelId) ) } catch (e: IOException) { println(e) @@ -176,55 +168,52 @@ class ChannelFragment : Fragment() { run() } - private fun fetchChannel(view: View) { + private fun fetchChannel() { fun run() { lifecycleScope.launchWhenCreated { val response = try { - RetrofitInstance.api.getChannel(channel_id!!) + RetrofitInstance.api.getChannel(channelId!!) } catch (e: IOException) { - refreshLayout?.isRefreshing = false + binding.channelRefresh.isRefreshing = false println(e) Log.e(TAG, "IOException, you might not have internet connection") return@launchWhenCreated } catch (e: HttpException) { - refreshLayout?.isRefreshing = false + binding.channelRefresh.isRefreshing = false Log.e(TAG, "HttpException, unexpected response") return@launchWhenCreated } nextPage = response.nextpage isLoading = false - refreshLayout?.isRefreshing = false + binding.channelRefresh.isRefreshing = false runOnUiThread { - view.findViewById(R.id.channel_scrollView).visibility = View.VISIBLE - val channelName = view.findViewById(R.id.channel_name) - channelName.text = response.name + binding.channelScrollView.visibility = View.VISIBLE + binding.channelName.text = response.name if (response.verified) { - channelName.setCompoundDrawablesWithIntrinsicBounds( + binding.channelName.setCompoundDrawablesWithIntrinsicBounds( 0, 0, R.drawable.ic_verified, 0 ) } - view.findViewById(R.id.channel_subs).text = resources.getString( + binding.channelSubs.text = resources.getString( R.string.subscribers, response.subscriberCount.formatShort() ) - val channelDescription = view.findViewById(R.id.channel_description) if (response.description?.trim() == "") { - channelDescription.visibility = View.GONE + binding.channelDescription.visibility = View.GONE } else { - channelDescription.text = response.description?.trim() + binding.channelDescription.text = response.description?.trim() } - val bannerImage = view.findViewById(R.id.channel_banner) - val channelImage = view.findViewById(R.id.channel_image) - Picasso.get().load(response.bannerUrl).into(bannerImage) - Picasso.get().load(response.avatarUrl).into(channelImage) + + Picasso.get().load(response.bannerUrl).into(binding.channelBanner) + Picasso.get().load(response.avatarUrl).into(binding.channelImage) channelAdapter = ChannelAdapter( response.relatedStreams!!.toMutableList(), childFragmentManager ) - view.findViewById(R.id.channel_recView).adapter = channelAdapter + binding.channelRecView.adapter = channelAdapter } } } @@ -235,21 +224,21 @@ class ChannelFragment : Fragment() { fun run() { lifecycleScope.launchWhenCreated { val response = try { - RetrofitInstance.api.getChannelNextPage(channel_id!!, nextPage!!) + RetrofitInstance.api.getChannelNextPage(channelId!!, nextPage!!) } catch (e: IOException) { - refreshLayout?.isRefreshing = false + binding.channelRefresh.isRefreshing = false println(e) Log.e(TAG, "IOException, you might not have internet connection") return@launchWhenCreated } catch (e: HttpException) { - refreshLayout?.isRefreshing = false + binding.channelRefresh.isRefreshing = false Log.e(TAG, "HttpException, unexpected response," + e.response()) return@launchWhenCreated } nextPage = response.nextpage channelAdapter?.updateItems(response.relatedStreams!!) isLoading = false - refreshLayout?.isRefreshing = false + binding.channelRefresh.isRefreshing = false } } run() @@ -260,13 +249,4 @@ class ChannelFragment : Fragment() { if (!isAdded) return // Fragment not attached to an Activity activity?.runOnUiThread(action) } - - override fun onDestroyView() { - val scrollView = view?.findViewById(R.id.channel_scrollView) - scrollView?.viewTreeObserver?.removeOnScrollChangedListener { - } - channelAdapter = null - view?.findViewById(R.id.channel_recView)?.adapter = null - super.onDestroyView() - } } diff --git a/app/src/main/java/com/github/libretube/fragments/Home.kt b/app/src/main/java/com/github/libretube/fragments/HomeFragment.kt similarity index 72% rename from app/src/main/java/com/github/libretube/fragments/Home.kt rename to app/src/main/java/com/github/libretube/fragments/HomeFragment.kt index 573d1ad41..43c5d3369 100644 --- a/app/src/main/java/com/github/libretube/fragments/Home.kt +++ b/app/src/main/java/com/github/libretube/fragments/HomeFragment.kt @@ -11,18 +11,18 @@ import androidx.fragment.app.Fragment import androidx.lifecycle.lifecycleScope import androidx.recyclerview.widget.GridLayoutManager import androidx.recyclerview.widget.RecyclerView -import androidx.swiperefreshlayout.widget.SwipeRefreshLayout import com.github.libretube.R import com.github.libretube.adapters.TrendingAdapter +import com.github.libretube.databinding.FragmentHomeBinding import com.github.libretube.util.PreferenceHelper import com.github.libretube.util.RetrofitInstance import retrofit2.HttpException import java.io.IOException -class Home : Fragment() { - +class HomeFragment : Fragment() { private val TAG = "HomeFragment" - private var refreshLayout: SwipeRefreshLayout? = null + private lateinit var binding: FragmentHomeBinding + override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) arguments?.let { @@ -33,27 +33,24 @@ class Home : Fragment() { inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle? - ): View? { - // Inflate the layout for this fragment - return inflater.inflate(R.layout.fragment_home, container, false) + ): View { + binding = FragmentHomeBinding.inflate(layoutInflater, container, false) + return binding.root } override fun onViewCreated(view: View, savedInstanceState: Bundle?) { super.onViewCreated(view, savedInstanceState) - val recyclerView = view.findViewById(R.id.recview) val grid = PreferenceHelper.getString( requireContext(), "grid", resources.getInteger(R.integer.grid_items).toString() )!! - recyclerView.layoutManager = GridLayoutManager(view.context, grid.toInt()) - val progressbar = view.findViewById(R.id.progressBar) - fetchJson(progressbar, recyclerView) - refreshLayout = view.findViewById(R.id.home_refresh) - refreshLayout?.isEnabled = true - refreshLayout?.setOnRefreshListener { + binding.recview.layoutManager = GridLayoutManager(view.context, grid.toInt()) + fetchJson(binding.progressBar, binding.recview) + binding.homeRefresh.isEnabled = true + binding.homeRefresh.setOnRefreshListener { Log.d(TAG, "hmm") - fetchJson(progressbar, recyclerView) + fetchJson(binding.progressBar, binding.recview) } } @@ -73,7 +70,7 @@ class Home : Fragment() { Toast.makeText(context, R.string.server_error, Toast.LENGTH_SHORT).show() return@launchWhenCreated } finally { - refreshLayout?.isRefreshing = false + binding.homeRefresh.isRefreshing = false } runOnUiThread { progressBar.visibility = View.GONE @@ -89,11 +86,4 @@ class Home : Fragment() { if (!isAdded) return // Fragment not attached to an Activity activity?.runOnUiThread(action) } - - override fun onDestroyView() { - view?.findViewById(R.id.recview)?.adapter = null - refreshLayout = null - Log.e(TAG, "destroyview") - super.onDestroyView() - } } diff --git a/app/src/main/java/com/github/libretube/fragments/Library.kt b/app/src/main/java/com/github/libretube/fragments/LibraryFragment.kt similarity index 57% rename from app/src/main/java/com/github/libretube/fragments/Library.kt rename to app/src/main/java/com/github/libretube/fragments/LibraryFragment.kt index 4c844066e..b66ce1fc3 100644 --- a/app/src/main/java/com/github/libretube/fragments/Library.kt +++ b/app/src/main/java/com/github/libretube/fragments/LibraryFragment.kt @@ -5,29 +5,24 @@ import android.util.Log import android.view.LayoutInflater import android.view.View import android.view.ViewGroup -import android.widget.ImageView -import android.widget.TextView import android.widget.Toast import androidx.fragment.app.Fragment import androidx.lifecycle.lifecycleScope import androidx.recyclerview.widget.LinearLayoutManager -import androidx.recyclerview.widget.RecyclerView -import androidx.swiperefreshlayout.widget.SwipeRefreshLayout import com.github.libretube.R import com.github.libretube.adapters.PlaylistsAdapter +import com.github.libretube.databinding.FragmentLibraryBinding import com.github.libretube.dialogs.CreatePlaylistDialog import com.github.libretube.util.PreferenceHelper import com.github.libretube.util.RetrofitInstance -import com.google.android.material.floatingactionbutton.FloatingActionButton import retrofit2.HttpException import java.io.IOException -class Library : Fragment() { +class LibraryFragment : Fragment() { private val TAG = "LibraryFragment" lateinit var token: String - private lateinit var playlistRecyclerView: RecyclerView - private lateinit var refreshLayout: SwipeRefreshLayout + private lateinit var binding: FragmentLibraryBinding override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) @@ -39,48 +34,44 @@ class Library : Fragment() { inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle? - ): View? { - // Inflate the layout for this fragment - return inflater.inflate(R.layout.fragment_library, container, false) + ): View { + binding = FragmentLibraryBinding.inflate(layoutInflater, container, false) + return binding.root } override fun onViewCreated(view: View, savedInstanceState: Bundle?) { super.onViewCreated(view, savedInstanceState) - playlistRecyclerView = view.findViewById(R.id.playlist_recView) - playlistRecyclerView.layoutManager = LinearLayoutManager(view.context) + binding.playlistRecView.layoutManager = LinearLayoutManager(view.context) token = PreferenceHelper.getToken(requireContext()) - refreshLayout = view.findViewById(R.id.playlist_refresh) if (token != "") { - view.findViewById(R.id.boogh2).visibility = View.GONE - view.findViewById(R.id.textLike2).visibility = View.GONE + binding.boogh.visibility = View.GONE + binding.textLike.visibility = View.GONE fetchPlaylists() - refreshLayout.isEnabled = true - refreshLayout.setOnRefreshListener { + binding.playlistRefresh.isEnabled = true + binding.playlistRefresh.setOnRefreshListener { fetchPlaylists() } - val createPlaylistButton = view.findViewById(R.id.create_playlist) - createPlaylistButton.setOnClickListener { + binding.createPlaylist.setOnClickListener { val newFragment = CreatePlaylistDialog() newFragment.show(childFragmentManager, "Create Playlist") } } else { - refreshLayout.isEnabled = false - view.findViewById(R.id.create_playlist).visibility = View.GONE + binding.playlistRefresh.isEnabled = false + binding.createPlaylist.visibility = View.GONE } } override fun onResume() { // optimize CreatePlaylistFab bottom margin if miniPlayer active - val createPlaylistButton = view?.findViewById(R.id.create_playlist) - val layoutParams = createPlaylistButton?.layoutParams as ViewGroup.MarginLayoutParams + val layoutParams = binding.createPlaylist.layoutParams as ViewGroup.MarginLayoutParams layoutParams.bottomMargin = if (isMiniPlayerVisible) 180 else 64 - createPlaylistButton?.layoutParams = layoutParams + binding.createPlaylist.layoutParams = layoutParams super.onResume() } fun fetchPlaylists() { fun run() { - refreshLayout.isRefreshing = true + binding.playlistRefresh.isRefreshing = true lifecycleScope.launchWhenCreated { val response = try { RetrofitInstance.api.playlists(token) @@ -94,27 +85,27 @@ class Library : Fragment() { Toast.makeText(context, R.string.server_error, Toast.LENGTH_SHORT).show() return@launchWhenCreated } finally { - refreshLayout.isRefreshing = false + binding.playlistRefresh.isRefreshing = false } if (response.isNotEmpty()) { runOnUiThread { - view?.findViewById(R.id.boogh2)?.visibility = View.GONE - view?.findViewById(R.id.textLike2)?.visibility = View.GONE + binding.boogh.visibility = View.GONE + binding.textLike.visibility = View.GONE } val playlistsAdapter = PlaylistsAdapter( response.toMutableList(), requireActivity() ) - playlistRecyclerView.adapter = playlistsAdapter + binding.playlistRecView.adapter = playlistsAdapter } else { runOnUiThread { - view?.findViewById(R.id.boogh2).apply { - this?.visibility = View.VISIBLE - this?.setImageResource(R.drawable.ic_list) + binding.boogh.apply { + visibility = View.VISIBLE + setImageResource(R.drawable.ic_list) } - view?.findViewById(R.id.textLike2).apply { - this?.visibility = View.VISIBLE - this?.text = getString(R.string.emptyList) + binding.textLike.apply { + visibility = View.VISIBLE + text = getString(R.string.emptyList) } } } diff --git a/app/src/main/java/com/github/libretube/fragments/PlayerFragment.kt b/app/src/main/java/com/github/libretube/fragments/PlayerFragment.kt index 263352f56..6e7b0186e 100644 --- a/app/src/main/java/com/github/libretube/fragments/PlayerFragment.kt +++ b/app/src/main/java/com/github/libretube/fragments/PlayerFragment.kt @@ -369,10 +369,7 @@ class PlayerFragment : Fragment() { // pause player if screen off and setting enabled if ( - this::exoPlayer.isInitialized && - exoPlayer != null && - !isScreenOn && - pausePlayerOnScreenOffEnabled + this::exoPlayer.isInitialized && !isScreenOn && pausePlayerOnScreenOffEnabled ) { exoPlayer.pause() } @@ -518,7 +515,7 @@ class PlayerFragment : Fragment() { // if it's not a playlist then use the next related video } else if (relatedStreams != null && relatedStreams!!.isNotEmpty()) { // save next video from related streams for autoplay - nextStreamId = relatedStreams!![0].url!!.replace("/watch?v=", "")!! + nextStreamId = relatedStreams!![0].url!!.replace("/watch?v=", "") } } } @@ -792,7 +789,7 @@ class PlayerFragment : Fragment() { val videoSource: MediaSource = DefaultMediaSourceFactory(dataSourceFactory) .createMediaSource(videoItem) - var audioSource: MediaSource = + val audioSource: MediaSource = ProgressiveMediaSource.Factory(dataSourceFactory) .createMediaSource(fromUri(audioUrl)) val mergeSource: MediaSource = @@ -1178,10 +1175,7 @@ class PlayerFragment : Fragment() { binding.playerScrollView.getHitRect(bounds) if (SDK_INT >= Build.VERSION_CODES.O && - exoPlayer.isPlaying && ( - binding.playerScrollView.getLocalVisibleRect(bounds) == true || - isFullScreen - ) + exoPlayer.isPlaying && (binding.playerScrollView.getLocalVisibleRect(bounds) || isFullScreen) ) { activity?.enterPictureInPictureMode(updatePipParams()) } diff --git a/app/src/main/java/com/github/libretube/fragments/PlaylistFragment.kt b/app/src/main/java/com/github/libretube/fragments/PlaylistFragment.kt index 4e8c20dab..e85c6aaf9 100644 --- a/app/src/main/java/com/github/libretube/fragments/PlaylistFragment.kt +++ b/app/src/main/java/com/github/libretube/fragments/PlaylistFragment.kt @@ -5,15 +5,12 @@ import android.util.Log import android.view.LayoutInflater import android.view.View import android.view.ViewGroup -import android.widget.ProgressBar -import android.widget.ScrollView -import android.widget.TextView import androidx.fragment.app.Fragment import androidx.lifecycle.lifecycleScope import androidx.recyclerview.widget.LinearLayoutManager -import androidx.recyclerview.widget.RecyclerView import com.github.libretube.R import com.github.libretube.adapters.PlaylistAdapter +import com.github.libretube.databinding.FragmentPlaylistBinding import com.github.libretube.util.PreferenceHelper import com.github.libretube.util.RetrofitInstance import retrofit2.HttpException @@ -21,11 +18,13 @@ import java.io.IOException class PlaylistFragment : Fragment() { private val TAG = "PlaylistFragment" + private lateinit var binding: FragmentPlaylistBinding private var playlistId: String? = null var nextPage: String? = null - var playlistAdapter: PlaylistAdapter? = null - var isLoading = true + private var playlistAdapter: PlaylistAdapter? = null + private var isLoading = true + override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) arguments?.let { @@ -37,24 +36,22 @@ class PlaylistFragment : Fragment() { inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle? - ): View? { - // Inflate the layout for this fragment - return inflater.inflate(R.layout.fragment_playlist, container, false) + ): View { + binding = FragmentPlaylistBinding.inflate(layoutInflater, container, false) + return binding.root } override fun onViewCreated(view: View, savedInstanceState: Bundle?) { super.onViewCreated(view, savedInstanceState) playlistId = playlistId!!.replace("/playlist?list=", "") - val recyclerView = view.findViewById(R.id.playlist_recView) - recyclerView.layoutManager = LinearLayoutManager(context) + binding.playlistRecView.layoutManager = LinearLayoutManager(context) - val progressBar = view.findViewById(R.id.playlist_progress) - progressBar.visibility = View.VISIBLE - fetchPlaylist(view) + binding.playlistProgress.visibility = View.VISIBLE + fetchPlaylist() } - private fun fetchPlaylist(view: View) { + private fun fetchPlaylist() { fun run() { lifecycleScope.launchWhenCreated { val response = try { @@ -70,10 +67,10 @@ class PlaylistFragment : Fragment() { nextPage = response.nextpage isLoading = false runOnUiThread { - view.findViewById(R.id.playlist_progress).visibility = View.GONE - view.findViewById(R.id.playlist_name).text = response.name - view.findViewById(R.id.playlist_uploader).text = response.uploader - view.findViewById(R.id.playlist_totVideos).text = + binding.playlistProgress.visibility = View.GONE + binding.playlistName.text = response.name + binding.playlistUploader.text = response.uploader + binding.playlistTotVideos.text = getString(R.string.videoCount, response.videos.toString()) val user = PreferenceHelper.getUsername(requireContext()) var isOwner = false @@ -87,12 +84,11 @@ class PlaylistFragment : Fragment() { requireActivity(), childFragmentManager ) - view.findViewById(R.id.playlist_recView).adapter = playlistAdapter - val scrollView = view.findViewById(R.id.playlist_scrollview) - scrollView.viewTreeObserver + binding.playlistRecView.adapter = playlistAdapter + binding.playlistScrollview.viewTreeObserver .addOnScrollChangedListener { - if (scrollView.getChildAt(0).bottom - == (scrollView.height + scrollView.scrollY) + if (binding.playlistScrollview.getChildAt(0).bottom + == (binding.playlistScrollview.height + binding.playlistScrollview.scrollY) ) { // scroll view is at bottom if (nextPage != null && !isLoading) { diff --git a/app/src/main/java/com/github/libretube/fragments/SearchFragment.kt b/app/src/main/java/com/github/libretube/fragments/SearchFragment.kt index cfe515d71..c81a8ec87 100644 --- a/app/src/main/java/com/github/libretube/fragments/SearchFragment.kt +++ b/app/src/main/java/com/github/libretube/fragments/SearchFragment.kt @@ -12,7 +12,6 @@ import android.view.WindowManager.LayoutParams.SOFT_INPUT_STATE_ALWAYS_HIDDEN import android.view.inputmethod.EditorInfo import android.view.inputmethod.InputMethodManager import android.widget.EditText -import android.widget.ImageView import android.widget.TextView.GONE import android.widget.TextView.OnEditorActionListener import android.widget.TextView.VISIBLE @@ -20,28 +19,26 @@ import androidx.fragment.app.Fragment import androidx.lifecycle.lifecycleScope import androidx.recyclerview.widget.GridLayoutManager import androidx.recyclerview.widget.LinearLayoutManager -import androidx.recyclerview.widget.RecyclerView import com.github.libretube.R import com.github.libretube.adapters.SearchAdapter import com.github.libretube.adapters.SearchHistoryAdapter import com.github.libretube.adapters.SearchSuggestionsAdapter +import com.github.libretube.databinding.FragmentSearchBinding import com.github.libretube.hideKeyboard import com.github.libretube.util.PreferenceHelper import com.github.libretube.util.RetrofitInstance import com.google.android.material.dialog.MaterialAlertDialogBuilder -import kotlinx.coroutines.GlobalScope -import kotlinx.coroutines.launch import retrofit2.HttpException import java.io.IOException class SearchFragment : Fragment() { private val TAG = "SearchFragment" + private lateinit var binding: FragmentSearchBinding + private var selectedFilter = 0 private var apiSearchFilter = "all" private var nextPage: String? = null - private lateinit var searchRecView: RecyclerView - private lateinit var historyRecView: RecyclerView - private lateinit var autoTextView: EditText + private var searchAdapter: SearchAdapter? = null private var isLoading: Boolean = true private var isFetchingSearch: Boolean = false @@ -56,27 +53,21 @@ class SearchFragment : Fragment() { inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle? - ): View? { - // Inflate the layout for this fragment - return inflater.inflate(R.layout.fragment_search, container, false) + ): View { + binding = FragmentSearchBinding.inflate(layoutInflater, container, false) + return binding.root } override fun onViewCreated(view: View, savedInstanceState: Bundle?) { super.onViewCreated(view, savedInstanceState) - searchRecView = view.findViewById(R.id.search_recycler) - historyRecView = view.findViewById(R.id.history_recycler) - autoTextView = view.findViewById(R.id.autoCompleteTextView) - - val clearSearchButton = view.findViewById(R.id.clearSearch_imageView) - val filterImageView = view.findViewById(R.id.filterMenu_imageView) var tempSelectedItem = 0 - clearSearchButton.setOnClickListener { - autoTextView.text.clear() + binding.clearSearchImageView.setOnClickListener { + binding.autoCompleteTextView.text.clear() } - filterImageView.setOnClickListener { + binding.filterMenuImageView.setOnClickListener { val filterOptions = arrayOf( getString(R.string.all), getString(R.string.videos), @@ -108,7 +99,7 @@ class SearchFragment : Fragment() { 7 -> "music_playlists" else -> "all" } - fetchSearch(autoTextView.text.toString()) + fetchSearch(binding.autoCompleteTextView.text.toString()) } .setNegativeButton(getString(R.string.cancel), null) .create() @@ -116,16 +107,16 @@ class SearchFragment : Fragment() { } // show search history - historyRecView.layoutManager = LinearLayoutManager(view.context) + binding.historyRecycler.layoutManager = LinearLayoutManager(view.context) showHistory() - searchRecView.layoutManager = GridLayoutManager(view.context, 1) - autoTextView.requestFocus() + binding.searchRecycler.layoutManager = GridLayoutManager(view.context, 1) + binding.autoCompleteTextView.requestFocus() val imm = requireContext().getSystemService(Context.INPUT_METHOD_SERVICE) as InputMethodManager - imm.showSoftInput(autoTextView, InputMethodManager.SHOW_IMPLICIT) + imm.showSoftInput(binding.autoCompleteTextView, InputMethodManager.SHOW_IMPLICIT) - autoTextView.addTextChangedListener(object : TextWatcher { + binding.autoCompleteTextView.addTextChangedListener(object : TextWatcher { override fun beforeTextChanged( s: CharSequence?, start: Int, @@ -136,18 +127,15 @@ class SearchFragment : Fragment() { override fun onTextChanged(s: CharSequence?, start: Int, before: Int, count: Int) { if (s!! != "") { - searchRecView.adapter = null + binding.searchRecycler.adapter = null - searchRecView.viewTreeObserver + binding.searchRecycler.viewTreeObserver .addOnScrollChangedListener { - if (!searchRecView.canScrollVertically(1)) { - fetchNextSearchItems(autoTextView.text.toString()) + if (!binding.searchRecycler.canScrollVertically(1)) { + fetchNextSearchItems(binding.autoCompleteTextView.text.toString()) } } - - GlobalScope.launch { - fetchSuggestions(s.toString(), autoTextView) - } + fetchSuggestions(s.toString(), binding.autoCompleteTextView) } } @@ -157,13 +145,13 @@ class SearchFragment : Fragment() { } } }) - autoTextView.setOnEditorActionListener( + binding.autoCompleteTextView.setOnEditorActionListener( OnEditorActionListener { _, actionId, _ -> if (actionId == EditorInfo.IME_ACTION_SEARCH) { hideKeyboard() - searchRecView.visibility = VISIBLE - historyRecView.visibility = GONE - fetchSearch(autoTextView.text.toString()) + binding.searchRecycler.visibility = VISIBLE + binding.historyRecycler.visibility = GONE + fetchSearch(binding.autoCompleteTextView.text.toString()) return@OnEditorActionListener true } false @@ -174,8 +162,8 @@ class SearchFragment : Fragment() { private fun fetchSuggestions(query: String, autoTextView: EditText) { fun run() { lifecycleScope.launchWhenCreated { - searchRecView.visibility = GONE - historyRecView.visibility = VISIBLE + binding.searchRecycler.visibility = GONE + binding.historyRecycler.visibility = VISIBLE val response = try { RetrofitInstance.api.getSuggestions(query) } catch (e: IOException) { @@ -188,7 +176,7 @@ class SearchFragment : Fragment() { } val suggestionsAdapter = SearchSuggestionsAdapter(response, autoTextView, this@SearchFragment) - historyRecView.adapter = suggestionsAdapter + binding.historyRecycler.adapter = suggestionsAdapter } } if (!isFetchingSearch) run() @@ -211,10 +199,10 @@ class SearchFragment : Fragment() { nextPage = response.nextpage if (response.items!!.isNotEmpty()) { runOnUiThread { - historyRecView.visibility = GONE - searchRecView.visibility = VISIBLE + binding.historyRecycler.visibility = GONE + binding.searchRecycler.visibility = VISIBLE searchAdapter = SearchAdapter(response.items, childFragmentManager) - searchRecView.adapter = searchAdapter + binding.searchRecycler.adapter = searchAdapter } } addToHistory(query) @@ -265,12 +253,12 @@ class SearchFragment : Fragment() { } private fun showHistory() { - searchRecView.visibility = GONE + binding.searchRecycler.visibility = GONE val historyList = PreferenceHelper.getHistory(requireContext()) if (historyList.isNotEmpty()) { - historyRecView.adapter = - SearchHistoryAdapter(requireContext(), historyList, autoTextView, this) - historyRecView.visibility = VISIBLE + binding.historyRecycler.adapter = + SearchHistoryAdapter(requireContext(), historyList, binding.autoCompleteTextView, this) + binding.historyRecycler.visibility = VISIBLE } } diff --git a/app/src/main/java/com/github/libretube/fragments/Subscriptions.kt b/app/src/main/java/com/github/libretube/fragments/SubscriptionsFragment.kt similarity index 60% rename from app/src/main/java/com/github/libretube/fragments/Subscriptions.kt rename to app/src/main/java/com/github/libretube/fragments/SubscriptionsFragment.kt index d502a7cf3..fa8ef8ee1 100644 --- a/app/src/main/java/com/github/libretube/fragments/Subscriptions.kt +++ b/app/src/main/java/com/github/libretube/fragments/SubscriptionsFragment.kt @@ -5,11 +5,7 @@ import android.util.Log import android.view.LayoutInflater import android.view.View import android.view.ViewGroup -import android.widget.ImageView import android.widget.ProgressBar -import android.widget.RelativeLayout -import android.widget.ScrollView -import android.widget.TextView import android.widget.Toast import androidx.core.view.isVisible import androidx.fragment.app.Fragment @@ -17,21 +13,23 @@ import androidx.lifecycle.lifecycleScope import androidx.recyclerview.widget.GridLayoutManager import androidx.recyclerview.widget.LinearLayoutManager import androidx.recyclerview.widget.RecyclerView -import androidx.swiperefreshlayout.widget.SwipeRefreshLayout import com.github.libretube.R import com.github.libretube.adapters.SubscriptionAdapter import com.github.libretube.adapters.SubscriptionChannelAdapter +import com.github.libretube.databinding.FragmentSubscriptionsBinding import com.github.libretube.util.PreferenceHelper import com.github.libretube.util.RetrofitInstance import retrofit2.HttpException import java.io.IOException -class Subscriptions : Fragment() { +class SubscriptionsFragment : Fragment() { val TAG = "SubFragment" + private lateinit var binding: FragmentSubscriptionsBinding + lateinit var token: String - var isLoaded = false + private var isLoaded = false private var subscriptionAdapter: SubscriptionAdapter? = null - private var refreshLayout: SwipeRefreshLayout? = null + override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) arguments?.let { @@ -42,84 +40,72 @@ class Subscriptions : Fragment() { inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle? - ): View? { - // Inflate the layout for this fragment - return inflater.inflate(R.layout.fragment_subscriptions, container, false) + ): View { + binding = FragmentSubscriptionsBinding.inflate(layoutInflater, container, false) + return binding.root } override fun onViewCreated(view: View, savedInstanceState: Bundle?) { super.onViewCreated(view, savedInstanceState) token = PreferenceHelper.getToken(requireContext()) - refreshLayout = view.findViewById(R.id.sub_refresh) + if (token != "") { - view.findViewById(R.id.loginOrRegister).visibility = View.GONE - refreshLayout?.isEnabled = true + binding.loginOrRegister.visibility = View.GONE + binding.subRefresh.isEnabled = true - var progressBar = view.findViewById(R.id.sub_progress) - progressBar.visibility = View.VISIBLE + binding.subProgress.visibility = View.VISIBLE - var channelRecView = view.findViewById(R.id.sub_channels) - - var feedRecView = view.findViewById(R.id.sub_feed) val grid = PreferenceHelper.getString( requireContext(), "grid", resources.getInteger(R.integer.grid_items).toString() )!! - feedRecView.layoutManager = GridLayoutManager(view.context, grid.toInt()) - fetchFeed(feedRecView, progressBar, view) + binding.subFeed.layoutManager = GridLayoutManager(view.context, grid.toInt()) + fetchFeed(binding.subFeed, binding.subProgress) - refreshLayout?.setOnRefreshListener { - fetchChannels(channelRecView) - fetchFeed(feedRecView, progressBar, view) + binding.subRefresh.setOnRefreshListener { + fetchChannels(binding.subChannels) + fetchFeed(binding.subFeed, binding.subProgress) } - var toggleSubs = view.findViewById(R.id.toggle_subs) - val arrowImageView = view.findViewById(R.id.toggle) - - toggleSubs.visibility = View.VISIBLE + binding.toggleSubs.visibility = View.VISIBLE var loadedSubbedChannels = false - toggleSubs.setOnClickListener { - arrowImageView.animate().rotationBy(180F).setDuration(100).start() - if (!channelRecView.isVisible) { + binding.toggleSubs.setOnClickListener { + binding.toggle.animate().rotationBy(180F).setDuration(100).start() + if (!binding.subChannels.isVisible) { if (!loadedSubbedChannels) { - channelRecView?.layoutManager = LinearLayoutManager(context) - fetchChannels(channelRecView) + binding.subChannels.layoutManager = LinearLayoutManager(context) + fetchChannels(binding.subChannels) loadedSubbedChannels = true } - channelRecView.visibility = View.VISIBLE - feedRecView.visibility = View.GONE + binding.subChannels.visibility = View.VISIBLE + binding.subFeed.visibility = View.GONE } else { - channelRecView.visibility = View.GONE - feedRecView.visibility = View.VISIBLE - - // toggle button - val image = view.findViewById(R.id.toggle) - image.clearAnimation() + binding.subChannels.visibility = View.GONE + binding.subFeed.visibility = View.VISIBLE } } - val scrollView = view.findViewById(R.id.scrollview_sub) - scrollView.viewTreeObserver + binding.scrollviewSub.viewTreeObserver .addOnScrollChangedListener { - if (scrollView.getChildAt(0).bottom - == (scrollView.height + scrollView.scrollY) + if (binding.scrollviewSub.getChildAt(0).bottom + == (binding.scrollviewSub.height + binding.scrollviewSub.scrollY) ) { // scroll view is at bottom if (isLoaded) { - refreshLayout?.isRefreshing = true + binding.subRefresh.isRefreshing = true subscriptionAdapter?.updateItems() - refreshLayout?.isRefreshing = false + binding.subRefresh.isRefreshing = false } } } } else { - refreshLayout?.isEnabled = false + binding.subRefresh.isEnabled = false } } - private fun fetchFeed(feedRecView: RecyclerView, progressBar: ProgressBar, view: View) { + private fun fetchFeed(feedRecView: RecyclerView, progressBar: ProgressBar) { fun run() { lifecycleScope.launchWhenCreated { val response = try { @@ -132,7 +118,7 @@ class Subscriptions : Fragment() { Log.e(TAG, "HttpException, unexpected response") return@launchWhenCreated } finally { - refreshLayout?.isRefreshing = false + binding.subRefresh.isRefreshing = false } if (response.isNotEmpty()) { subscriptionAdapter = SubscriptionAdapter(response, childFragmentManager) @@ -140,16 +126,15 @@ class Subscriptions : Fragment() { subscriptionAdapter?.updateItems() } else { runOnUiThread { - with(view.findViewById(R.id.boogh)) { + with(binding.boogh) { visibility = View.VISIBLE setImageResource(R.drawable.ic_list) } - with(view.findViewById(R.id.textLike)) { + with(binding.textLike) { visibility = View.VISIBLE text = getString(R.string.emptyList) } - view.findViewById(R.id.loginOrRegister) - .visibility = View.VISIBLE + binding.loginOrRegister.visibility = View.VISIBLE } } progressBar.visibility = View.GONE @@ -172,7 +157,7 @@ class Subscriptions : Fragment() { Log.e(TAG, "HttpException, unexpected response") return@launchWhenCreated } finally { - refreshLayout?.isRefreshing = false + binding.subRefresh.isRefreshing = false } if (response.isNotEmpty()) { channelRecView.adapter = SubscriptionChannelAdapter(response.toMutableList()) @@ -184,13 +169,6 @@ class Subscriptions : Fragment() { run() } - override fun onDestroy() { - Log.e(TAG, "Destroyed") - super.onDestroy() - subscriptionAdapter = null - view?.findViewById(R.id.sub_feed)?.adapter = null - } - private fun Fragment?.runOnUiThread(action: () -> Unit) { this ?: return if (!isAdded) return // Fragment not attached to an Activity diff --git a/app/src/main/res/layout/fragment_home.xml b/app/src/main/res/layout/fragment_home.xml index 2e240e5db..4b859beac 100644 --- a/app/src/main/res/layout/fragment_home.xml +++ b/app/src/main/res/layout/fragment_home.xml @@ -4,7 +4,7 @@ xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" - tools:context=".fragments.Home"> + tools:context=".fragments.HomeFragment"> + tools:context=".fragments.LibraryFragment"> + tools:context=".fragments.SubscriptionsFragment">