convert fragments to viewbinding

This commit is contained in:
Bnyro 2022-07-01 11:11:24 +02:00
parent d120436d28
commit e6aefe3c93
12 changed files with 194 additions and 277 deletions

View File

@ -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())

View File

@ -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<TextView>(R.id.channel_name).text = channel_id
val recyclerView = view.findViewById<RecyclerView>(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<MaterialButton>(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<ScrollView>(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<ScrollView>(R.id.channel_scrollView).visibility = View.VISIBLE
val channelName = view.findViewById<TextView>(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<TextView>(R.id.channel_subs).text = resources.getString(
binding.channelSubs.text = resources.getString(
R.string.subscribers,
response.subscriberCount.formatShort()
)
val channelDescription = view.findViewById<TextView>(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<ImageView>(R.id.channel_banner)
val channelImage = view.findViewById<ImageView>(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<RecyclerView>(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<ScrollView>(R.id.channel_scrollView)
scrollView?.viewTreeObserver?.removeOnScrollChangedListener {
}
channelAdapter = null
view?.findViewById<RecyclerView>(R.id.channel_recView)?.adapter = null
super.onDestroyView()
}
}

View File

@ -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<RecyclerView>(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<ProgressBar>(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<RecyclerView>(R.id.recview)?.adapter = null
refreshLayout = null
Log.e(TAG, "destroyview")
super.onDestroyView()
}
}

View File

@ -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<ImageView>(R.id.boogh2).visibility = View.GONE
view.findViewById<TextView>(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<FloatingActionButton>(R.id.create_playlist)
createPlaylistButton.setOnClickListener {
binding.createPlaylist.setOnClickListener {
val newFragment = CreatePlaylistDialog()
newFragment.show(childFragmentManager, "Create Playlist")
}
} else {
refreshLayout.isEnabled = false
view.findViewById<FloatingActionButton>(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<FloatingActionButton>(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<ImageView>(R.id.boogh2)?.visibility = View.GONE
view?.findViewById<TextView>(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<ImageView>(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<TextView>(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)
}
}
}

View File

@ -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())
}

View File

@ -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<RecyclerView>(R.id.playlist_recView)
recyclerView.layoutManager = LinearLayoutManager(context)
binding.playlistRecView.layoutManager = LinearLayoutManager(context)
val progressBar = view.findViewById<ProgressBar>(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<ProgressBar>(R.id.playlist_progress).visibility = View.GONE
view.findViewById<TextView>(R.id.playlist_name).text = response.name
view.findViewById<TextView>(R.id.playlist_uploader).text = response.uploader
view.findViewById<TextView>(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<RecyclerView>(R.id.playlist_recView).adapter = playlistAdapter
val scrollView = view.findViewById<ScrollView>(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) {

View File

@ -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<ImageView>(R.id.clearSearch_imageView)
val filterImageView = view.findViewById<ImageView>(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
}
}

View File

@ -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<RelativeLayout>(R.id.loginOrRegister).visibility = View.GONE
refreshLayout?.isEnabled = true
binding.loginOrRegister.visibility = View.GONE
binding.subRefresh.isEnabled = true
var progressBar = view.findViewById<ProgressBar>(R.id.sub_progress)
progressBar.visibility = View.VISIBLE
binding.subProgress.visibility = View.VISIBLE
var channelRecView = view.findViewById<RecyclerView>(R.id.sub_channels)
var feedRecView = view.findViewById<RecyclerView>(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<RelativeLayout>(R.id.toggle_subs)
val arrowImageView = view.findViewById<ImageView>(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<ImageView>(R.id.toggle)
image.clearAnimation()
binding.subChannels.visibility = View.GONE
binding.subFeed.visibility = View.VISIBLE
}
}
val scrollView = view.findViewById<ScrollView>(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<ImageView>(R.id.boogh)) {
with(binding.boogh) {
visibility = View.VISIBLE
setImageResource(R.drawable.ic_list)
}
with(view.findViewById<TextView>(R.id.textLike)) {
with(binding.textLike) {
visibility = View.VISIBLE
text = getString(R.string.emptyList)
}
view.findViewById<RelativeLayout>(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<RecyclerView>(R.id.sub_feed)?.adapter = null
}
private fun Fragment?.runOnUiThread(action: () -> Unit) {
this ?: return
if (!isAdded) return // Fragment not attached to an Activity

View File

@ -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">
<ProgressBar
android:id="@+id/progressBar"

View File

@ -4,7 +4,7 @@
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".fragments.Library">
tools:context=".fragments.LibraryFragment">
<RelativeLayout
android:id="@+id/loginOrRegister2"
@ -14,7 +14,7 @@
android:layout_centerVertical="true">
<ImageView
android:id="@+id/boogh2"
android:id="@+id/boogh"
android:layout_width="100dp"
android:layout_height="100dp"
android:layout_centerInParent="true"
@ -22,10 +22,10 @@
android:src="@drawable/ic_login" />
<TextView
android:id="@+id/textLike2"
android:id="@+id/text_like"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="@id/boogh2"
android:layout_below="@id/boogh"
android:layout_centerHorizontal="true"
android:gravity="center"
android:text="@string/please_login"

View File

@ -3,7 +3,7 @@
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".fragments.Subscriptions">
tools:context=".fragments.SubscriptionsFragment">
<ProgressBar
android:id="@+id/sub_progress"

View File

@ -7,17 +7,17 @@
<fragment
android:id="@+id/home2"
android:name="com.github.libretube.fragments.Home"
android:name="com.github.libretube.fragments.HomeFragment"
android:label="fragment_home"
tools:layout="@layout/fragment_home" />
<fragment
android:id="@+id/subscriptions"
android:name="com.github.libretube.fragments.Subscriptions"
android:name="com.github.libretube.fragments.SubscriptionsFragment"
android:label="fragment_subscriptions"
tools:layout="@layout/fragment_subscriptions" />
<fragment
android:id="@+id/library"
android:name="com.github.libretube.fragments.Library"
android:name="com.github.libretube.fragments.LibraryFragment"
android:label="fragment_library"
tools:layout="@layout/fragment_library"></fragment>
<fragment