replace globals with viewmodels

This commit is contained in:
Bnyro 2022-08-15 09:41:30 +02:00
parent 0819e58ddd
commit 4ec0a98caf
10 changed files with 79 additions and 57 deletions

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -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 {

View File

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

View File

@ -0,0 +1,7 @@
package com.github.libretube.models
import androidx.lifecycle.ViewModel
class PlaylistViewModel : ViewModel() {
var lastSelectedPlaylistId: String? = null
}

View File

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

View File

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