mirror of
https://github.com/libre-tube/LibreTube.git
synced 2024-12-14 06:10:31 +05:30
replace globals with viewmodels
This commit is contained in:
parent
0819e58ddd
commit
4ec0a98caf
@ -4,19 +4,9 @@ package com.github.libretube
|
||||
* Global variables can be stored here
|
||||
*/
|
||||
object Globals {
|
||||
// for the player fragment
|
||||
var IS_FULL_SCREEN = false
|
||||
var MINI_PLAYER_VISIBLE = false
|
||||
|
||||
// for the data saver mode
|
||||
var DATA_SAVER_MODE_ENABLED = false
|
||||
|
||||
// for downloads
|
||||
var IS_DOWNLOAD_RUNNING = false
|
||||
|
||||
// for playlists
|
||||
var SELECTED_PLAYLIST_ID: String? = null
|
||||
|
||||
// history of played videos in the current lifecycle
|
||||
val playingQueue = mutableListOf<String>()
|
||||
}
|
||||
|
@ -9,14 +9,17 @@ import android.os.StrictMode
|
||||
import android.os.StrictMode.VmPolicy
|
||||
import androidx.preference.PreferenceManager
|
||||
import androidx.work.ExistingPeriodicWorkPolicy
|
||||
import coil.ImageLoader
|
||||
import com.fasterxml.jackson.core.type.TypeReference
|
||||
import com.fasterxml.jackson.databind.ObjectMapper
|
||||
import com.github.libretube.api.CronetHelper
|
||||
import com.github.libretube.api.RetrofitInstance
|
||||
import com.github.libretube.db.DatabaseHolder
|
||||
import com.github.libretube.db.obj.WatchHistoryItem
|
||||
import com.github.libretube.db.obj.WatchPosition
|
||||
import com.github.libretube.preferences.PreferenceHelper
|
||||
import com.github.libretube.preferences.PreferenceKeys
|
||||
import com.github.libretube.util.ConnectionHelper
|
||||
import com.github.libretube.util.ExceptionHandler
|
||||
import com.github.libretube.util.NotificationHelper
|
||||
|
||||
@ -30,7 +33,7 @@ class MyApp : Application() {
|
||||
initializeNotificationChannels()
|
||||
|
||||
/**
|
||||
* Set the applicationContext as context for the [PreferenceHelper]
|
||||
* Initialize the [PreferenceHelper]
|
||||
*/
|
||||
PreferenceHelper.setContext(applicationContext)
|
||||
|
||||
@ -40,7 +43,7 @@ class MyApp : Application() {
|
||||
DatabaseHolder.initializeDatabase(this)
|
||||
|
||||
/**
|
||||
* bypassing fileUriExposedException, see https://stackoverflow.com/questions/38200282/android-os-fileuriexposedexception-file-storage-emulated-0-test-txt-exposed
|
||||
* Bypassing fileUriExposedException, see https://stackoverflow.com/questions/38200282/android-os-fileuriexposedexception-file-storage-emulated-0-test-txt-exposed
|
||||
*/
|
||||
val builder = VmPolicy.Builder()
|
||||
StrictMode.setVmPolicy(builder.build())
|
||||
@ -48,7 +51,7 @@ class MyApp : Application() {
|
||||
/**
|
||||
* Set the api and the auth api url
|
||||
*/
|
||||
setRetrofitApiUrls()
|
||||
initializeRetrofit()
|
||||
|
||||
/**
|
||||
* Initialize the notification listener in the background
|
||||
@ -76,7 +79,7 @@ class MyApp : Application() {
|
||||
/**
|
||||
* Set the api urls needed for the [RetrofitInstance]
|
||||
*/
|
||||
private fun setRetrofitApiUrls() {
|
||||
private fun initializeRetrofit() {
|
||||
RetrofitInstance.url =
|
||||
PreferenceHelper.getString(PreferenceKeys.FETCH_INSTANCE, PIPED_API_URL)
|
||||
// set auth instance
|
||||
@ -89,6 +92,10 @@ class MyApp : Application() {
|
||||
} else {
|
||||
RetrofitInstance.url
|
||||
}
|
||||
CronetHelper.initCronet(this)
|
||||
ConnectionHelper.imageLoader = ImageLoader.Builder(this)
|
||||
.callFactory(CronetHelper.callFactory)
|
||||
.build()
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -25,15 +25,13 @@ import androidx.lifecycle.ViewModelProvider
|
||||
import androidx.navigation.NavController
|
||||
import androidx.navigation.findNavController
|
||||
import androidx.navigation.ui.setupWithNavController
|
||||
import coil.ImageLoader
|
||||
import com.github.libretube.Globals
|
||||
import com.github.libretube.R
|
||||
import com.github.libretube.api.CronetHelper
|
||||
import com.github.libretube.databinding.ActivityMainBinding
|
||||
import com.github.libretube.dialogs.ErrorDialog
|
||||
import com.github.libretube.extensions.BaseActivity
|
||||
import com.github.libretube.extensions.TAG
|
||||
import com.github.libretube.fragments.PlayerFragment
|
||||
import com.github.libretube.models.PlayerViewModel
|
||||
import com.github.libretube.models.SearchViewModel
|
||||
import com.github.libretube.preferences.PreferenceHelper
|
||||
import com.github.libretube.preferences.PreferenceKeys
|
||||
@ -74,17 +72,6 @@ class MainActivity : BaseActivity() {
|
||||
e.printStackTrace()
|
||||
}
|
||||
|
||||
CronetHelper.initCronet(this.applicationContext)
|
||||
ConnectionHelper.imageLoader = ImageLoader.Builder(this.applicationContext)
|
||||
.callFactory(CronetHelper.callFactory)
|
||||
.build()
|
||||
|
||||
// save whether the data saver mode is enabled
|
||||
Globals.DATA_SAVER_MODE_ENABLED = PreferenceHelper.getBoolean(
|
||||
PreferenceKeys.DATA_SAVER_MODE,
|
||||
false
|
||||
)
|
||||
|
||||
// show noInternet Activity if no internet available on app startup
|
||||
if (!ConnectionHelper.isNetworkAvailable(this)) {
|
||||
val noInternetIntent = Intent(this, NoInternetActivity::class.java)
|
||||
@ -456,7 +443,8 @@ class MainActivity : BaseActivity() {
|
||||
enableTransition(R.id.yt_transition, true)
|
||||
}
|
||||
findViewById<LinearLayout>(R.id.linLayout).visibility = View.VISIBLE
|
||||
Globals.IS_FULL_SCREEN = false
|
||||
val playerViewModel = ViewModelProvider(this)[PlayerViewModel::class.java]
|
||||
playerViewModel.isFullscreen.value = false
|
||||
requestedOrientation = if (autoRotationEnabled) ActivityInfo.SCREEN_ORIENTATION_USER
|
||||
else ActivityInfo.SCREEN_ORIENTATION_USER_PORTRAIT
|
||||
}
|
||||
|
@ -7,12 +7,13 @@ import android.widget.ArrayAdapter
|
||||
import android.widget.Toast
|
||||
import androidx.fragment.app.DialogFragment
|
||||
import androidx.fragment.app.Fragment
|
||||
import androidx.fragment.app.activityViewModels
|
||||
import androidx.lifecycle.lifecycleScope
|
||||
import com.github.libretube.Globals
|
||||
import com.github.libretube.R
|
||||
import com.github.libretube.api.RetrofitInstance
|
||||
import com.github.libretube.databinding.DialogAddtoplaylistBinding
|
||||
import com.github.libretube.extensions.TAG
|
||||
import com.github.libretube.models.PlaylistViewModel
|
||||
import com.github.libretube.obj.PlaylistId
|
||||
import com.github.libretube.preferences.PreferenceHelper
|
||||
import com.github.libretube.util.ThemeHelper
|
||||
@ -22,6 +23,7 @@ import java.io.IOException
|
||||
|
||||
class AddToPlaylistDialog : DialogFragment() {
|
||||
private lateinit var binding: DialogAddtoplaylistBinding
|
||||
private val viewModel: PlaylistViewModel by activityViewModels()
|
||||
|
||||
private lateinit var videoId: String
|
||||
private lateinit var token: String
|
||||
@ -67,17 +69,17 @@ class AddToPlaylistDialog : DialogFragment() {
|
||||
android.R.layout.simple_spinner_dropdown_item
|
||||
)
|
||||
binding.playlistsSpinner.adapter = arrayAdapter
|
||||
if (Globals.SELECTED_PLAYLIST_ID != null) {
|
||||
if (viewModel.lastSelectedPlaylistId != null) {
|
||||
var selectionIndex = 0
|
||||
response.forEachIndexed { index, playlist ->
|
||||
if (playlist.id == Globals.SELECTED_PLAYLIST_ID) selectionIndex = index
|
||||
if (playlist.id == viewModel.lastSelectedPlaylistId) selectionIndex = index
|
||||
}
|
||||
binding.playlistsSpinner.setSelection(selectionIndex)
|
||||
}
|
||||
runOnUiThread {
|
||||
binding.addToPlaylist.setOnClickListener {
|
||||
val index = binding.playlistsSpinner.selectedItemPosition
|
||||
Globals.SELECTED_PLAYLIST_ID = response[index].id!!
|
||||
viewModel.lastSelectedPlaylistId = response[index].id!!
|
||||
addToPlaylist(
|
||||
response[index].id!!
|
||||
)
|
||||
|
@ -6,11 +6,11 @@ import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import android.widget.Toast
|
||||
import androidx.fragment.app.activityViewModels
|
||||
import androidx.lifecycle.lifecycleScope
|
||||
import androidx.navigation.fragment.findNavController
|
||||
import androidx.recyclerview.widget.LinearLayoutManager
|
||||
import androidx.recyclerview.widget.RecyclerView
|
||||
import com.github.libretube.Globals
|
||||
import com.github.libretube.R
|
||||
import com.github.libretube.adapters.PlaylistsAdapter
|
||||
import com.github.libretube.api.RetrofitInstance
|
||||
@ -18,6 +18,7 @@ import com.github.libretube.databinding.FragmentLibraryBinding
|
||||
import com.github.libretube.dialogs.CreatePlaylistDialog
|
||||
import com.github.libretube.extensions.BaseFragment
|
||||
import com.github.libretube.extensions.TAG
|
||||
import com.github.libretube.models.PlayerViewModel
|
||||
import com.github.libretube.preferences.PreferenceHelper
|
||||
import com.github.libretube.preferences.PreferenceKeys
|
||||
import retrofit2.HttpException
|
||||
@ -27,6 +28,7 @@ class LibraryFragment : BaseFragment() {
|
||||
|
||||
lateinit var token: String
|
||||
private lateinit var binding: FragmentLibraryBinding
|
||||
val playerViewModel: PlayerViewModel by activityViewModels()
|
||||
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
@ -45,6 +47,12 @@ class LibraryFragment : BaseFragment() {
|
||||
|
||||
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||
super.onViewCreated(view, savedInstanceState)
|
||||
|
||||
// listen for the mini player state changing
|
||||
playerViewModel.isMiniPlayerVisible.observe(viewLifecycleOwner) {
|
||||
updateFABMargin()
|
||||
}
|
||||
|
||||
binding.playlistRecView.layoutManager = LinearLayoutManager(requireContext())
|
||||
token = PreferenceHelper.getToken()
|
||||
|
||||
@ -76,12 +84,12 @@ class LibraryFragment : BaseFragment() {
|
||||
}
|
||||
}
|
||||
|
||||
override fun onResume() {
|
||||
fun updateFABMargin() {
|
||||
// optimize CreatePlaylistFab bottom margin if miniPlayer active
|
||||
val bottomMargin = if (playerViewModel.isMiniPlayerVisible.value == true) 180 else 64
|
||||
val layoutParams = binding.createPlaylist.layoutParams as ViewGroup.MarginLayoutParams
|
||||
layoutParams.bottomMargin = if (Globals.MINI_PLAYER_VISIBLE) 180 else 64
|
||||
layoutParams.bottomMargin = bottomMargin
|
||||
binding.createPlaylist.layoutParams = layoutParams
|
||||
super.onResume()
|
||||
}
|
||||
|
||||
fun fetchPlaylists() {
|
||||
|
@ -28,6 +28,7 @@ import androidx.constraintlayout.widget.ConstraintLayout
|
||||
import androidx.core.net.toUri
|
||||
import androidx.core.os.bundleOf
|
||||
import androidx.core.view.isVisible
|
||||
import androidx.fragment.app.activityViewModels
|
||||
import androidx.lifecycle.lifecycleScope
|
||||
import androidx.recyclerview.widget.GridLayoutManager
|
||||
import androidx.recyclerview.widget.LinearLayoutManager
|
||||
@ -54,6 +55,7 @@ import com.github.libretube.extensions.TAG
|
||||
import com.github.libretube.extensions.await
|
||||
import com.github.libretube.interfaces.DoubleTapInterface
|
||||
import com.github.libretube.interfaces.PlayerOptionsInterface
|
||||
import com.github.libretube.models.PlayerViewModel
|
||||
import com.github.libretube.obj.ChapterSegment
|
||||
import com.github.libretube.obj.Segment
|
||||
import com.github.libretube.obj.Segments
|
||||
@ -107,6 +109,7 @@ class PlayerFragment : BaseFragment() {
|
||||
private lateinit var binding: FragmentPlayerBinding
|
||||
private lateinit var playerBinding: ExoStyledPlayerControlViewBinding
|
||||
private lateinit var doubleTapOverlayBinding: DoubleTapOverlayBinding
|
||||
private val viewModel: PlayerViewModel by activityViewModels()
|
||||
|
||||
/**
|
||||
* video information
|
||||
@ -378,11 +381,11 @@ class PlayerFragment : BaseFragment() {
|
||||
val mainMotionLayout =
|
||||
mainActivity.binding.mainMotionLayout
|
||||
if (currentId == eId) {
|
||||
Globals.MINI_PLAYER_VISIBLE = true
|
||||
viewModel.isMiniPlayerVisible.value = true
|
||||
exoPlayerView.useController = false
|
||||
mainMotionLayout.progress = 1F
|
||||
} else if (currentId == sId) {
|
||||
Globals.MINI_PLAYER_VISIBLE = false
|
||||
viewModel.isMiniPlayerVisible.value = false
|
||||
exoPlayerView.useController = true
|
||||
mainMotionLayout.progress = 0F
|
||||
}
|
||||
@ -561,7 +564,7 @@ class PlayerFragment : BaseFragment() {
|
||||
// actions that don't depend on video information
|
||||
private fun initializeOnClickActions(context: Context) {
|
||||
binding.closeImageView.setOnClickListener {
|
||||
Globals.MINI_PLAYER_VISIBLE = false
|
||||
viewModel.isMiniPlayerVisible.value = false
|
||||
binding.playerMotionLayout.transitionToEnd()
|
||||
val mainActivity = activity as MainActivity
|
||||
mainActivity.supportFragmentManager.beginTransaction()
|
||||
@ -569,7 +572,7 @@ class PlayerFragment : BaseFragment() {
|
||||
.commit()
|
||||
}
|
||||
playerBinding.closeImageButton.setOnClickListener {
|
||||
Globals.MINI_PLAYER_VISIBLE = false
|
||||
viewModel.isFullscreen.value = false
|
||||
binding.playerMotionLayout.transitionToEnd()
|
||||
val mainActivity = activity as MainActivity
|
||||
mainActivity.supportFragmentManager.beginTransaction()
|
||||
@ -644,7 +647,7 @@ class PlayerFragment : BaseFragment() {
|
||||
playerBinding.fullscreen.setOnClickListener {
|
||||
// hide player controller
|
||||
exoPlayerView.hideController()
|
||||
if (!Globals.IS_FULL_SCREEN) {
|
||||
if (viewModel.isFullscreen.value == false) {
|
||||
// go to fullscreen mode
|
||||
setFullscreen()
|
||||
} else {
|
||||
@ -737,7 +740,7 @@ class PlayerFragment : BaseFragment() {
|
||||
mainActivity.requestedOrientation = orientation
|
||||
}
|
||||
|
||||
Globals.IS_FULL_SCREEN = true
|
||||
viewModel.isFullscreen.value = true
|
||||
}
|
||||
|
||||
private fun unsetFullscreen() {
|
||||
@ -758,7 +761,7 @@ class PlayerFragment : BaseFragment() {
|
||||
mainActivity.requestedOrientation = ActivityInfo.SCREEN_ORIENTATION_USER_PORTRAIT
|
||||
}
|
||||
|
||||
Globals.IS_FULL_SCREEN = false
|
||||
viewModel.isFullscreen.value = false
|
||||
}
|
||||
|
||||
private fun toggleDescription() {
|
||||
@ -1301,7 +1304,7 @@ class PlayerFragment : BaseFragment() {
|
||||
}
|
||||
playerBinding.chapterLL.visibility = View.VISIBLE
|
||||
playerBinding.chapterLL.setOnClickListener {
|
||||
if (Globals.IS_FULL_SCREEN) {
|
||||
if (viewModel.isFullscreen.value!!) {
|
||||
MaterialAlertDialogBuilder(requireContext())
|
||||
.setTitle(R.string.chapters)
|
||||
.setItems(titles.toTypedArray()) { _, index ->
|
||||
@ -1527,7 +1530,7 @@ class PlayerFragment : BaseFragment() {
|
||||
playerBinding.closeImageButton.visibility = visibility
|
||||
playerBinding.exoTitle.visibility =
|
||||
if (isLocked &&
|
||||
Globals.IS_FULL_SCREEN
|
||||
viewModel.isFullscreen.value == true
|
||||
) View.VISIBLE else View.INVISIBLE
|
||||
|
||||
// disable double tap to seek when the player is locked
|
||||
@ -1627,7 +1630,7 @@ class PlayerFragment : BaseFragment() {
|
||||
}
|
||||
binding.linLayout.visibility = View.GONE
|
||||
|
||||
Globals.IS_FULL_SCREEN = false
|
||||
viewModel.isFullscreen.value = false
|
||||
} else {
|
||||
// enable exoPlayer controls again
|
||||
exoPlayerView.useController = true
|
||||
@ -1654,8 +1657,10 @@ class PlayerFragment : BaseFragment() {
|
||||
|
||||
val backgroundModeRunning = isServiceRunning(requireContext(), BackgroundMode::class.java)
|
||||
|
||||
return (binding.playerScrollView.getLocalVisibleRect(bounds) || Globals.IS_FULL_SCREEN) &&
|
||||
(exoPlayer.isPlaying || !backgroundModeRunning)
|
||||
return (
|
||||
binding.playerScrollView.getLocalVisibleRect(bounds) ||
|
||||
viewModel.isFullscreen.value == true
|
||||
) && (exoPlayer.isPlaying || !backgroundModeRunning)
|
||||
}
|
||||
|
||||
private fun isServiceRunning(context: Context, serviceClass: Class<*>): Boolean {
|
||||
|
@ -0,0 +1,13 @@
|
||||
package com.github.libretube.models
|
||||
|
||||
import androidx.lifecycle.MutableLiveData
|
||||
import androidx.lifecycle.ViewModel
|
||||
|
||||
class PlayerViewModel : ViewModel() {
|
||||
val isMiniPlayerVisible = MutableLiveData<Boolean>().apply {
|
||||
value = false
|
||||
}
|
||||
val isFullscreen = MutableLiveData<Boolean>().apply {
|
||||
value = false
|
||||
}
|
||||
}
|
@ -0,0 +1,7 @@
|
||||
package com.github.libretube.models
|
||||
|
||||
import androidx.lifecycle.ViewModel
|
||||
|
||||
class PlaylistViewModel : ViewModel() {
|
||||
var lastSelectedPlaylistId: String? = null
|
||||
}
|
@ -4,8 +4,7 @@ import androidx.lifecycle.MutableLiveData
|
||||
import androidx.lifecycle.ViewModel
|
||||
|
||||
class SearchViewModel : ViewModel() {
|
||||
var searchQuery = MutableLiveData<String>()
|
||||
|
||||
val searchQuery = MutableLiveData<String>()
|
||||
fun setQuery(query: String?) {
|
||||
this.searchQuery.value = query
|
||||
}
|
||||
|
@ -5,9 +5,12 @@ import android.net.ConnectivityManager
|
||||
import android.widget.ImageView
|
||||
import coil.ImageLoader
|
||||
import coil.load
|
||||
import com.github.libretube.Globals
|
||||
import com.github.libretube.preferences.PreferenceHelper
|
||||
import com.github.libretube.preferences.PreferenceKeys
|
||||
|
||||
object ConnectionHelper {
|
||||
lateinit var imageLoader: ImageLoader
|
||||
|
||||
fun isNetworkAvailable(context: Context): Boolean {
|
||||
val connectivityManager =
|
||||
context.getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager
|
||||
@ -38,13 +41,13 @@ object ConnectionHelper {
|
||||
return connectivityManager.activeNetworkInfo?.isConnected ?: false
|
||||
}
|
||||
|
||||
lateinit var imageLoader: ImageLoader
|
||||
|
||||
// load an image from a url into an imageView
|
||||
fun loadImage(url: String?, target: ImageView) {
|
||||
// only load the image if the data saver mode is disabled
|
||||
if (!Globals.DATA_SAVER_MODE_ENABLED) {
|
||||
target.load(url, imageLoader)
|
||||
}
|
||||
val dataSaverModeEnabled = PreferenceHelper.getBoolean(
|
||||
PreferenceKeys.DATA_SAVER_MODE,
|
||||
false
|
||||
)
|
||||
if (!dataSaverModeEnabled) target.load(url, imageLoader)
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user