()
- val data = JSONObject(response).getString("data")
- val decryptedData =
- decryptAES(
- data,
- preferences.secondKey.toString(),
- preferences.iv.toString(),
- ).replace(
- """o" {
+ val urls = mutableListOf()
+ val data = JSONObject(response).getString("data")
+ val decryptedData =
+ decryptAES(
+ data,
+ preferences.secondKey.toString(),
+ preferences.iv.toString(),
+ ).replace(
+ """o"
- binding.wrapper.isVisible = isConnected
- binding.noInternetStatus.noInternet.isVisible = !isConnected
- }
- }
private fun setBottomBarVisibility() {
navController.addOnDestinationChangedListener { _, destination, _ ->
@@ -209,6 +181,7 @@ class MainActivity : AppCompatActivity(), BottomNavScrollListener {
R.id.settingsFragment,
R.id.scheduleFragment,
R.id.theirProfile,
+ R.id.navigation_downloaded_episodes
)
) {
hideBottomNavBar()
@@ -219,6 +192,9 @@ class MainActivity : AppCompatActivity(), BottomNavScrollListener {
}
override fun onScrollDown() = hideBottomNavBar()
-
override fun onScrollUp() = showBottomNavBar()
+
+ companion object {
+ const val ANIMATION_DURATION = 200L
+ }
}
diff --git a/app/src/main/java/com/kl3jvi/animity/ui/activities/main/MainViewModel.kt b/app/src/main/java/com/kl3jvi/animity/ui/activities/main/MainViewModel.kt
index 86bf4082..31eeab03 100644
--- a/app/src/main/java/com/kl3jvi/animity/ui/activities/main/MainViewModel.kt
+++ b/app/src/main/java/com/kl3jvi/animity/ui/activities/main/MainViewModel.kt
@@ -18,45 +18,45 @@ import javax.inject.Inject
@ExperimentalCoroutinesApi
@HiltViewModel
class MainViewModel
- @Inject
- constructor(
- private val homeRepository: HomeRepository,
- private val userRepository: UserRepository,
- private val localStorage: PersistenceRepository,
- private val ioDispatcher: CoroutineDispatcher,
- network: NetworkMonitor,
- ) : ViewModel() {
- val isConnectedToNetwork = network.isConnected
+@Inject
+constructor(
+ private val homeRepository: HomeRepository,
+ private val userRepository: UserRepository,
+ private val localStorage: PersistenceRepository,
+ private val ioDispatcher: CoroutineDispatcher,
+ private val network: NetworkMonitor,
+) : ViewModel() {
- init {
- viewModelScope.launch(ioDispatcher) {
- launch { getUserSession() }
- launch { updateEncryptionKeys() }
- }
+ init {
+ viewModelScope.launch(ioDispatcher)
+ {
+ launch { getUserSession() }
+ launch { updateEncryptionKeys() }
}
+ }
- private fun getUserSession() {
- userRepository.getSessionForUser()
- .onEach { data ->
- if (!data.hasErrors()) {
- userRepository.setAniListUserId(data.data?.viewer?.id.toString())
- } else {
- Log.e("MainViewModel", "Error getting user session")
- }
- }.launchIn(viewModelScope)
- }
+ private fun getUserSession() {
+ userRepository.getSessionForUser()
+ .onEach { data ->
+ if (!data.hasErrors()) {
+ userRepository.setAniListUserId(data.data?.viewer?.id.toString())
+ } else {
+ Log.e("MainViewModel", "Error getting user session")
+ }
+ }.launchIn(viewModelScope)
+ }
- /**
- * > It gets the encryption keys from the server and saves them to the local storage
- */
- private fun updateEncryptionKeys() {
- homeRepository.getEncryptionKeys()
- .onEach { data ->
- with(localStorage) {
- iv = data.iv
- key = data.key
- secondKey = data.secondKey
- }
- }.launchIn(viewModelScope)
- }
+ /**
+ * > It gets the encryption keys from the server and saves them to the local storage
+ */
+ private fun updateEncryptionKeys() {
+ homeRepository.getEncryptionKeys()
+ .onEach { data ->
+ with(localStorage) {
+ iv = data.iv
+ key = data.key
+ secondKey = data.secondKey
+ }
+ }.launchIn(viewModelScope)
}
+}
diff --git a/app/src/main/java/com/kl3jvi/animity/ui/activities/player/PlayerActivity.kt b/app/src/main/java/com/kl3jvi/animity/ui/activities/player/PlayerActivity.kt
index 21e28383..d6d909f1 100644
--- a/app/src/main/java/com/kl3jvi/animity/ui/activities/player/PlayerActivity.kt
+++ b/app/src/main/java/com/kl3jvi/animity/ui/activities/player/PlayerActivity.kt
@@ -29,6 +29,7 @@ import com.google.android.exoplayer2.Player
import com.google.android.exoplayer2.audio.AudioAttributes
import com.google.android.exoplayer2.ext.okhttp.OkHttpDataSource
import com.google.android.exoplayer2.source.ConcatenatingMediaSource
+import com.google.android.exoplayer2.source.DefaultMediaSourceFactory
import com.google.android.exoplayer2.source.MediaSource
import com.google.android.exoplayer2.source.ProgressiveMediaSource
import com.google.android.exoplayer2.source.hls.HlsMediaSource
@@ -50,6 +51,7 @@ import com.kl3jvi.animity.utils.Constants
import com.kl3jvi.animity.utils.Constants.Companion.ANILIST_ID
import com.kl3jvi.animity.utils.Constants.Companion.ANIME_TITLE
import com.kl3jvi.animity.utils.Constants.Companion.EPISODE_DETAILS
+import com.kl3jvi.animity.utils.Constants.Companion.EPISODE_URL
import com.kl3jvi.animity.utils.Constants.Companion.REFERER
import com.kl3jvi.animity.utils.Constants.Companion.THUMBNAIL
import com.kl3jvi.animity.utils.Constants.Companion.showSnack
@@ -57,21 +59,25 @@ import com.kl3jvi.animity.utils.UiResult
import com.kl3jvi.animity.utils.collect
import com.kl3jvi.animity.utils.logError
import dagger.hilt.android.AndroidEntryPoint
+import java.io.File
+import java.net.InetAddress
+import javax.inject.Inject
import kotlinx.coroutines.ExperimentalCoroutinesApi
import okhttp3.Cache
import okhttp3.HttpUrl.Companion.toHttpUrl
import okhttp3.OkHttpClient
import okhttp3.dnsoverhttps.DnsOverHttps
-import java.io.File
-import java.net.InetAddress
-import javax.inject.Inject
+@Suppress("DEPRECATION")
@ExperimentalCoroutinesApi
@AndroidEntryPoint
class PlayerActivity : AppCompatActivity() {
@Inject
lateinit var settings: Settings
+ @Inject
+ lateinit var cacheDataSourceFactory: CacheDataSource.Factory
+
private val binding by lazy(LazyThreadSafetyMode.NONE) {
ActivityPlayerBinding.inflate(layoutInflater)
}
@@ -95,15 +101,17 @@ class PlayerActivity : AppCompatActivity() {
lateinit var episodeUrlLocal: String
lateinit var episodeEntity: EpisodeEntity
private var aniListId: Int = 0
+ private var episodeUrSavedInCache: String = ""
private var thumbnailUri: String = ""
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(binding.root)
- if (intent.hasExtra(EPISODE_DETAILS)) {
+ if (intent.hasExtra(EPISODE_DETAILS) || intent.hasExtra(EPISODE_URL)) {
val getIntentData = intent.getParcelableExtra(EPISODE_DETAILS)
aniListId = intent.getIntExtra(ANILIST_ID, 0)
+ episodeUrSavedInCache = intent.getStringExtra(EPISODE_URL).orEmpty()
animeTitlePassed = intent.getStringExtra(ANIME_TITLE).toString()
episodeNumberLocal = getIntentData?.episodeNumber.toString()
episodeUrlLocal = getIntentData?.episodeUrl.toString()
@@ -118,6 +126,15 @@ class PlayerActivity : AppCompatActivity() {
initialisePlayerLayout()
viewModel.episodeUrl.value = getIntentData?.episodeUrl.toString()
hideSystemUi()
+ initializeVideoPlayback()
+ }
+ }
+
+ private fun initializeVideoPlayback() {
+ if (episodeUrSavedInCache.isNotEmpty()) {
+ playLocally(listOf(listOf(episodeUrSavedInCache)))
+ } else {
+ initializePlayer()
}
}
@@ -178,15 +195,27 @@ class PlayerActivity : AppCompatActivity() {
public override fun onStart() {
super.onStart()
if (Util.SDK_INT > 23 && player == null) {
- initializePlayer()
+// initializePlayer()
onIsPlayingChanged(isPlaying = true)
}
}
+ private fun playLocally(passedUrl: List>) {
+ try {
+ setupPlayer(passedUrl)
+ handlePlayerListener()
+ handleSkipIntro()
+ } catch (e: Exception) {
+ e.printStackTrace()
+ showSnack(binding.root, e.localizedMessage)
+ }
+ binding.loadingOverlay.visibility = View.GONE
+ }
+
public override fun onResume() {
super.onResume()
if (Util.SDK_INT <= 23 && player == null) {
- initializePlayer()
+// initializePlayer()
onIsPlayingChanged(isPlaying = true)
}
player?.playWhenReady = true
@@ -212,6 +241,10 @@ class PlayerActivity : AppCompatActivity() {
@ExperimentalCoroutinesApi
private fun initializePlayer() {
+ if (episodeUrSavedInCache.isNotEmpty()) {
+ playLocally(listOf(listOf(episodeUrSavedInCache)))
+ return
+ }
collect(viewModel.episodeMediaUrl) { res ->
when (res) {
is UiResult.Error, UiResult.Loading -> {
@@ -262,17 +295,25 @@ class PlayerActivity : AppCompatActivity() {
.setSeekForwardIncrementMs(settings.seekForwardTime)
.build().apply {
binding.videoView.player = this
- val mediaItems =
- listOfEpisodesWithQualities.map { episodeWithQualities ->
- MediaItem.fromUri(episodeWithQualities.last())
- }
+ val mediaItems = listOfEpisodesWithQualities.map { episodeWithQualities ->
+ MediaItem.fromUri(episodeWithQualities.last())
+ }
val concatenatedSource = ConcatenatingMediaSource()
+
mediaItems.forEach { mediaItem ->
val videoSource =
- buildMediaSource(mediaItem, mediaItem.localConfiguration?.uri.toString())
+ buildMediaSource(
+ mediaItem,
+ mediaItem.localConfiguration?.uri.toString()
+ )
concatenatedSource.addMediaSource(videoSource)
}
- setMediaSource(concatenatedSource)
+
+ setMediaSource(
+ DefaultMediaSourceFactory(this@PlayerActivity)
+ .setDataSourceFactory(cacheDataSourceFactory)
+ .createMediaSource(mediaItems.first())
+ )
playWhenReady = true
prepare()
}
@@ -289,7 +330,7 @@ class PlayerActivity : AppCompatActivity() {
val realDurationMillis = player?.duration ?: 0
episodeEntity =
EpisodeEntity().apply {
- aniListId = aniListId
+ aniListId = this@PlayerActivity.aniListId
episodeUrl = episodeUrlLocal
watchedDuration = 0
duration = realDurationMillis
diff --git a/app/src/main/java/com/kl3jvi/animity/ui/activities/player/PlayerViewModel.kt b/app/src/main/java/com/kl3jvi/animity/ui/activities/player/PlayerViewModel.kt
index 4282a254..cdb1c260 100644
--- a/app/src/main/java/com/kl3jvi/animity/ui/activities/player/PlayerViewModel.kt
+++ b/app/src/main/java/com/kl3jvi/animity/ui/activities/player/PlayerViewModel.kt
@@ -8,6 +8,7 @@ import com.kl3jvi.animity.domain.repositories.PlayerRepository
import com.kl3jvi.animity.utils.Constants.Companion.Empty
import com.kl3jvi.animity.utils.mapToUiState
import dagger.hilt.android.lifecycle.HiltViewModel
+import javax.inject.Inject
import kotlinx.coroutines.CoroutineDispatcher
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.ExperimentalCoroutinesApi
@@ -19,55 +20,54 @@ import kotlinx.coroutines.flow.flow
import kotlinx.coroutines.flow.flowOn
import kotlinx.coroutines.launch
import kotlinx.coroutines.plus
-import javax.inject.Inject
@HiltViewModel
@ExperimentalCoroutinesApi
class PlayerViewModel
- @Inject
- constructor(
- private val playerRepository: PlayerRepository,
- private val ioDispatcher: CoroutineDispatcher,
- ) : ViewModel() {
- var episodeUrl = MutableStateFlow(String.Empty)
+@Inject
+constructor(
+ private val playerRepository: PlayerRepository,
+ private val ioDispatcher: CoroutineDispatcher,
+) : ViewModel() {
+ var episodeUrl = MutableStateFlow(String.Empty)
- private var _playBackPosition = MutableStateFlow(0)
- var playBackPosition = _playBackPosition.asStateFlow()
+ private var _playBackPosition = MutableStateFlow(0)
+ var playBackPosition = _playBackPosition.asStateFlow()
- /**
- * It creates a flow that emits the current position of the exoPlayer every second.
- *
- * @param exoPlayer ExoPlayer? - The ExoPlayer instance
- */
- fun progress(exoPlayer: ExoPlayer?) =
- flow {
- exoPlayer?.currentPosition?.let {
- while (it < 200000) {
- emit(exoPlayer.currentPosition)
- delay(1000)
- }
+ /**
+ * It creates a flow that emits the current position of the exoPlayer every second.
+ *
+ * @param exoPlayer ExoPlayer? - The ExoPlayer instance
+ */
+ fun progress(exoPlayer: ExoPlayer?) =
+ flow {
+ exoPlayer?.currentPosition?.let {
+ while (it < 200000) {
+ emit(exoPlayer.currentPosition)
+ delay(1000)
}
- }.flowOn(Dispatchers.Main)
+ }
+ }.flowOn(Dispatchers.Main)
- val episodeMediaUrl =
- episodeUrl.flatMapLatest {
- val mapToUiState =
- playerRepository.getMediaUrl(
- url = it,
- extra = listOf("naruto"),
- ).mapToUiState(viewModelScope + ioDispatcher)
- mapToUiState
- } // List of episodes which have a list of qualities
+ val episodeMediaUrl =
+ episodeUrl.flatMapLatest {
+ val mapToUiState =
+ playerRepository.getMediaUrl(
+ url = it,
+ extra = listOf("naruto"),
+ ).mapToUiState(viewModelScope + ioDispatcher)
+ mapToUiState
+ } // List of episodes which have a list of qualities
- fun upsertEpisode(episodeEntity: EpisodeEntity) {
- viewModelScope.launch(ioDispatcher) { playerRepository.upsertEpisode(episodeEntity) }
- }
+ fun upsertEpisode(episodeEntity: EpisodeEntity) {
+ viewModelScope.launch(ioDispatcher) { playerRepository.upsertEpisode(episodeEntity) }
+ }
- fun getPlaybackPosition(episodeUrl: String) {
- viewModelScope.launch(ioDispatcher) {
- playerRepository.getPlaybackPosition(episodeUrl).collect { content ->
- _playBackPosition.value = content.watchedDuration
- }
+ fun getPlaybackPosition(episodeUrl: String) {
+ viewModelScope.launch(ioDispatcher) {
+ playerRepository.getPlaybackPosition(episodeUrl).collect { content ->
+ _playBackPosition.value = content.watchedDuration
}
}
}
+}
diff --git a/app/src/main/java/com/kl3jvi/animity/ui/fragments/StateManager.kt b/app/src/main/java/com/kl3jvi/animity/ui/fragments/StateManager.kt
index e3e837ee..ec79d6a4 100644
--- a/app/src/main/java/com/kl3jvi/animity/ui/fragments/StateManager.kt
+++ b/app/src/main/java/com/kl3jvi/animity/ui/fragments/StateManager.kt
@@ -1,7 +1,29 @@
package com.kl3jvi.animity.ui.fragments
-interface StateManager {
- fun showLoading(show: Boolean)
+import androidx.lifecycle.Lifecycle
+import androidx.lifecycle.coroutineScope
+import androidx.lifecycle.flowWithLifecycle
+import kotlinx.coroutines.flow.Flow
+import kotlinx.coroutines.flow.launchIn
+import kotlinx.coroutines.flow.onEach
- fun handleError(e: Throwable)
+abstract class StateManager {
+ abstract fun showLoadingState(show: Boolean)
+
+ abstract fun handleErrorState(e: Throwable)
+
+ fun handleNetworkChanges(
+ networkConnection: Flow,
+ lifecycle: Lifecycle,
+ callback: (isConnected: Boolean) -> Unit,
+ ) {
+ networkConnection.flowWithLifecycle(lifecycle,Lifecycle.State.RESUMED)
+ .onEach { isConnected ->
+ callback(isConnected)
+ }.launchIn(lifecycle.coroutineScope)
+ }
+}
+
+interface StateManagerFactory {
+ fun create(): StateManager
}
diff --git a/app/src/main/java/com/kl3jvi/animity/ui/fragments/base/AnimityFragment.kt b/app/src/main/java/com/kl3jvi/animity/ui/fragments/base/AnimityFragment.kt
new file mode 100644
index 00000000..c4c82d8a
--- /dev/null
+++ b/app/src/main/java/com/kl3jvi/animity/ui/fragments/base/AnimityFragment.kt
@@ -0,0 +1,48 @@
+package com.kl3jvi.animity.ui.fragments.base
+
+import androidx.annotation.LayoutRes
+import androidx.fragment.app.Fragment
+import androidx.fragment.app.activityViewModels
+import com.kl3jvi.animity.ui.activities.main.MainViewModel
+import com.kl3jvi.animity.ui.fragments.StateManager
+import com.kl3jvi.animity.ui.fragments.StateManagerFactory
+import kotlinx.coroutines.ExperimentalCoroutinesApi
+import kotlinx.coroutines.flow.emptyFlow
+
+abstract class AnimityFragment(@LayoutRes contentLayoutId: Int) : Fragment(contentLayoutId),
+ StateManagerFactory {
+
+ private val stateManager by lazy { create() }
+ private val mainViewModel by activityViewModels()
+
+ abstract fun showLoading(show: Boolean)
+ abstract fun handleError(e: Throwable)
+ abstract fun handleNetworkChanges(isConnected: Boolean)
+
+ override fun create(): StateManager {
+ return object : StateManager() {
+ override fun showLoadingState(show: Boolean) = showLoading(show)
+ override fun handleErrorState(e: Throwable) = handleError(e)
+ }
+ }
+
+ @OptIn(ExperimentalCoroutinesApi::class)
+ override fun onStart() {
+ super.onStart()
+ stateManager.handleNetworkChanges(
+ emptyFlow(),
+ lifecycle,
+ ::handleNetworkChanges
+ )
+ }
+
+
+ override fun onResume() {
+ super.onResume()
+ stateManager.handleNetworkChanges(
+ emptyFlow(),
+ lifecycle,
+ ::handleNetworkChanges
+ )
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/kl3jvi/animity/ui/fragments/details/animeDetails/DetailsFragment.kt b/app/src/main/java/com/kl3jvi/animity/ui/fragments/details/animeDetails/DetailsFragment.kt
index 291cae57..1725f42d 100644
--- a/app/src/main/java/com/kl3jvi/animity/ui/fragments/details/animeDetails/DetailsFragment.kt
+++ b/app/src/main/java/com/kl3jvi/animity/ui/fragments/details/animeDetails/DetailsFragment.kt
@@ -37,6 +37,11 @@ import com.kl3jvi.animity.utils.launchActivity
import com.kl3jvi.animity.utils.parseTime
import com.kl3jvi.animity.utils.setHtmlText
import dagger.hilt.android.AndroidEntryPoint
+import java.text.SimpleDateFormat
+import java.util.Date
+import java.util.Locale
+import javax.inject.Inject
+import kotlin.properties.Delegates
import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.channels.awaitClose
import kotlinx.coroutines.delay
@@ -44,11 +49,6 @@ import kotlinx.coroutines.flow.callbackFlow
import kotlinx.coroutines.flow.launchIn
import kotlinx.coroutines.flow.onEach
import kotlinx.coroutines.launch
-import java.text.SimpleDateFormat
-import java.util.Date
-import java.util.Locale
-import javax.inject.Inject
-import kotlin.properties.Delegates
@Suppress("DEPRECATION")
@ExperimentalCoroutinesApi
diff --git a/app/src/main/java/com/kl3jvi/animity/ui/fragments/details/animeDetails/DetailsViewModel.kt b/app/src/main/java/com/kl3jvi/animity/ui/fragments/details/animeDetails/DetailsViewModel.kt
index 51fe7a6a..afa04d7d 100644
--- a/app/src/main/java/com/kl3jvi/animity/ui/fragments/details/animeDetails/DetailsViewModel.kt
+++ b/app/src/main/java/com/kl3jvi/animity/ui/fragments/details/animeDetails/DetailsViewModel.kt
@@ -35,6 +35,7 @@ import kotlinx.coroutines.flow.flowOf
import kotlinx.coroutines.flow.flowOn
import kotlinx.coroutines.flow.launchIn
import kotlinx.coroutines.flow.map
+import kotlinx.coroutines.flow.onEach
import kotlinx.coroutines.flow.stateIn
import kotlinx.coroutines.launch
import kotlinx.coroutines.plus
@@ -105,22 +106,20 @@ constructor(
}
fun downloadEpisode(episodeModel: EpisodeModel, aniListMedia: AniListMedia) {
- viewModelScope.launch(
- ioDispatcher + CoroutineExceptionHandler { _, throwable ->
- Log.e("Error", "Download error: ${throwable.message}", throwable)
- }
- ) {
- playerRepository.getMediaUrl(url = episodeModel.episodeUrl, extra = listOf("naruto"))
- .asResult()
- .ifChanged()
- .collect { result ->
- when (result) {
- is Result.Error -> handleError(result)
- is Result.Success -> handleSuccess(result, episodeModel, aniListMedia)
- else -> {}
- }
+ playerRepository.getMediaUrl(url = episodeModel.episodeUrl, extra = listOf("naruto"))
+ .asResult()
+ .ifChanged()
+ .onEach { result ->
+ when (result) {
+ is Result.Error -> handleError(result)
+ is Result.Success -> handleSuccess(result, episodeModel, aniListMedia)
+ else -> {}
}
- }
+ }.launchIn(
+ viewModelScope + ioDispatcher + CoroutineExceptionHandler { _, throwable ->
+ Log.e("Error", "Download error: ${throwable.message}", throwable)
+ }
+ )
}
private fun handleError(result: Result.Error) {
@@ -135,18 +134,14 @@ constructor(
val videoUrls = result.data
if (videoUrls.isNotEmpty()) {
val videoUrl = videoUrls.first().first()
-
checkAndInsertAnime(aniListMedia)
-
- val localEpisode = createLocalEpisode(episodeModel, aniListMedia)
-
+ val localEpisode = createLocalEpisode(videoUrl, episodeModel, aniListMedia)
downloader.downloadVideoUrl(
videoUrl,
DownloadListener(localEpisode)
)
- } else {
- Log.e("Error", "No video URLs found.")
- }
+ } else return
+
}
private suspend fun checkAndInsertAnime(aniListMedia: AniListMedia) {
@@ -165,11 +160,12 @@ constructor(
}
private fun createLocalEpisode(
+ videoUrl: String,
episodeModel: EpisodeModel,
aniListMedia: AniListMedia
): LocalEpisode {
return LocalEpisode(
- episodeUrl = episodeModel.episodeUrl,
+ episodeUrl = videoUrl,
animeId = aniListMedia.idAniList,
episodeNumber = episodeModel.getEpisodeNumberAsString(),
downloaded = true
@@ -192,7 +188,6 @@ constructor(
}
}
-
fun changeAnimeStatus(status: MediaListStatus) {
passedAniListMedia.flatMapLatest {
detailsRepository.changeAnimeStatus(it.idAniList, status)
diff --git a/app/src/main/java/com/kl3jvi/animity/ui/fragments/details/animeDetails/EpisodeContainer.kt b/app/src/main/java/com/kl3jvi/animity/ui/fragments/details/animeDetails/EpisodeContainer.kt
index 3b57f54d..ba93c792 100644
--- a/app/src/main/java/com/kl3jvi/animity/ui/fragments/details/animeDetails/EpisodeContainer.kt
+++ b/app/src/main/java/com/kl3jvi/animity/ui/fragments/details/animeDetails/EpisodeContainer.kt
@@ -69,6 +69,7 @@ class EpisodeContainer : Fragment(R.layout.fragment_episode_container) {
}
}
showTitle(episodeModel.episodeName.isNotEmpty())
+ isDownloaded(episodeModel.isDownloaded)
isFiller(episodeModel.isFiller)
downloadStatus(DownloadState.STATE_QUEUED)
imageUrl(
diff --git a/app/src/main/java/com/kl3jvi/animity/ui/fragments/downloads/DownloadFragment.kt b/app/src/main/java/com/kl3jvi/animity/ui/fragments/downloads/DownloadFragment.kt
index 0f255faa..0f0dfec8 100644
--- a/app/src/main/java/com/kl3jvi/animity/ui/fragments/downloads/DownloadFragment.kt
+++ b/app/src/main/java/com/kl3jvi/animity/ui/fragments/downloads/DownloadFragment.kt
@@ -3,9 +3,6 @@ package com.kl3jvi.animity.ui.fragments.downloads
import android.os.Bundle
import android.util.Log
import android.view.View
-import android.view.animation.Animation
-import android.view.animation.AnimationUtils
-import android.widget.ImageButton
import androidx.fragment.app.Fragment
import androidx.fragment.app.viewModels
import androidx.recyclerview.widget.LinearLayoutManager
@@ -16,6 +13,7 @@ import com.kl3jvi.animity.utils.BottomNavScrollListener
import com.kl3jvi.animity.utils.UiResult
import com.kl3jvi.animity.utils.collect
import com.kl3jvi.animity.utils.epoxy.setupBottomNavScrollListener
+import com.kl3jvi.animity.utils.navigateSafe
import dagger.hilt.android.AndroidEntryPoint
@AndroidEntryPoint
@@ -52,40 +50,12 @@ class DownloadFragment : Fragment(R.layout.fragment_download) {
id(anime.id)
anime(anime)
clickListener { a ->
- val deleteButton =
- a?.findViewById(R.id.delete_button)
-
- if (deleteButton?.visibility == View.VISIBLE) {
- // Create a fade out animation and then set visibility to GONE
- val fadeOut =
- AnimationUtils.loadAnimation(
- deleteButton.context,
- android.R.anim.fade_out,
- )
- fadeOut.setAnimationListener(
- object :
- Animation.AnimationListener {
- override fun onAnimationStart(animation: Animation?) {}
-
- override fun onAnimationRepeat(animation: Animation?) {}
-
- override fun onAnimationEnd(animation: Animation?) {
- deleteButton.visibility = View.GONE
- }
- },
- )
- deleteButton.startAnimation(fadeOut)
- } else {
- // Set visibility to VISIBLE and then create a fade in animation
- deleteButton?.visibility = View.VISIBLE
- val fadeIn =
- AnimationUtils.loadAnimation(
- deleteButton?.context,
- android.R.anim.fade_in,
- )
- deleteButton?.startAnimation(fadeIn)
- }
- true
+ a.navigateSafe(
+ DownloadFragmentDirections.actionNavigationDownloadsToDownloadedEpisodesFragment(
+ anime.id,
+ anime.title
+ ),
+ )
}
}
}
diff --git a/app/src/main/java/com/kl3jvi/animity/ui/fragments/downloads/DownloadViewModel.kt b/app/src/main/java/com/kl3jvi/animity/ui/fragments/downloads/DownloadViewModel.kt
index 530310a3..33aa5e06 100644
--- a/app/src/main/java/com/kl3jvi/animity/ui/fragments/downloads/DownloadViewModel.kt
+++ b/app/src/main/java/com/kl3jvi/animity/ui/fragments/downloads/DownloadViewModel.kt
@@ -8,12 +8,10 @@ import dagger.hilt.android.lifecycle.HiltViewModel
import javax.inject.Inject
@HiltViewModel
-class DownloadViewModel
- @Inject
- constructor(
- persistenceRepository: PersistenceRepository,
- ) : ViewModel() {
- val listOfAnimes =
- persistenceRepository.getAllAnimesThatHasDownloadedEpisodes()
- .mapToUiState(viewModelScope)
- }
+class DownloadViewModel @Inject constructor(
+ persistenceRepository: PersistenceRepository,
+) : ViewModel() {
+ val listOfAnimes =
+ persistenceRepository.getAllAnimesThatHasDownloadedEpisodes()
+ .mapToUiState(viewModelScope)
+}
diff --git a/app/src/main/java/com/kl3jvi/animity/ui/fragments/downloads/episodes/DownloadedEpisodesFragment.kt b/app/src/main/java/com/kl3jvi/animity/ui/fragments/downloads/episodes/DownloadedEpisodesFragment.kt
new file mode 100644
index 00000000..3976c5ef
--- /dev/null
+++ b/app/src/main/java/com/kl3jvi/animity/ui/fragments/downloads/episodes/DownloadedEpisodesFragment.kt
@@ -0,0 +1,63 @@
+package com.kl3jvi.animity.ui.fragments.downloads.episodes
+
+import android.os.Bundle
+import android.view.View
+import androidx.fragment.app.Fragment
+import androidx.fragment.app.viewModels
+import androidx.navigation.fragment.navArgs
+import com.kl3jvi.animity.R
+import com.kl3jvi.animity.databinding.FragmentDownloadedEpisodesBinding
+import com.kl3jvi.animity.episodeList
+import com.kl3jvi.animity.ui.activities.player.PlayerActivity
+import com.kl3jvi.animity.utils.Constants
+import com.kl3jvi.animity.utils.collect
+import com.kl3jvi.animity.utils.launchActivity
+import dagger.hilt.android.AndroidEntryPoint
+import kotlinx.coroutines.ExperimentalCoroutinesApi
+
+@AndroidEntryPoint
+class DownloadedEpisodesFragment : Fragment(R.layout.fragment_downloaded_episodes) {
+
+ companion object {
+ fun newInstance() = DownloadedEpisodesFragment()
+ }
+
+ private val viewModel: DownloadedEpisodesViewModel by viewModels()
+
+ private val args: DownloadedEpisodesFragmentArgs by navArgs()
+ private var binding: FragmentDownloadedEpisodesBinding? = null
+
+ override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
+ super.onViewCreated(view, savedInstanceState)
+ binding = FragmentDownloadedEpisodesBinding.bind(view)
+ initViews()
+ }
+
+ @OptIn(ExperimentalCoroutinesApi::class)
+ private fun initViews() {
+ viewModel.setAnimeId(args.animePassId)
+ collect(viewModel.downloadedEpisodes) { downloadList ->
+ binding?.epoxyRecyclerView?.withModels {
+ downloadList.sortedBy { it.episodeNumber }.forEach { animeDetails ->
+ episodeList {
+ id(animeDetails.episodeUrl)
+ episodeInfo(animeDetails)
+ clickListener { view ->
+ // navigate to player
+ requireContext().launchActivity {
+ putExtra(Constants.EPISODE_URL, animeDetails.episodeUrl)
+ putExtra(Constants.ANILIST_ID, animeDetails.animeId)
+ putExtra(Constants.ANIME_TITLE, animeDetails.episodeNumber)
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+
+ override fun onDestroyView() {
+ super.onDestroyView()
+ binding = null
+ }
+}
diff --git a/app/src/main/java/com/kl3jvi/animity/ui/fragments/downloads/episodes/DownloadedEpisodesViewModel.kt b/app/src/main/java/com/kl3jvi/animity/ui/fragments/downloads/episodes/DownloadedEpisodesViewModel.kt
new file mode 100644
index 00000000..94166ffa
--- /dev/null
+++ b/app/src/main/java/com/kl3jvi/animity/ui/fragments/downloads/episodes/DownloadedEpisodesViewModel.kt
@@ -0,0 +1,25 @@
+package com.kl3jvi.animity.ui.fragments.downloads.episodes
+
+import androidx.lifecycle.ViewModel
+import com.kl3jvi.animity.domain.repositories.PersistenceRepository
+import dagger.hilt.android.lifecycle.HiltViewModel
+import javax.inject.Inject
+import kotlinx.coroutines.flow.MutableStateFlow
+import kotlinx.coroutines.flow.emptyFlow
+import kotlinx.coroutines.flow.flatMapLatest
+
+@HiltViewModel
+class DownloadedEpisodesViewModel @Inject constructor(
+ private val persistenceRepository: PersistenceRepository
+) : ViewModel() {
+ private val animeId: MutableStateFlow = MutableStateFlow(-1)
+ val downloadedEpisodes = animeId.flatMapLatest {
+ if (it != -1)
+ persistenceRepository.getDownloadedEpisodesForAnime(it)
+ else emptyFlow()
+ }
+
+ fun setAnimeId(id: Int) {
+ animeId.value = id
+ }
+}
diff --git a/app/src/main/java/com/kl3jvi/animity/ui/fragments/favorites/FavoritesFragment.kt b/app/src/main/java/com/kl3jvi/animity/ui/fragments/favorites/FavoritesFragment.kt
index 4c656fd0..ae58183a 100644
--- a/app/src/main/java/com/kl3jvi/animity/ui/fragments/favorites/FavoritesFragment.kt
+++ b/app/src/main/java/com/kl3jvi/animity/ui/fragments/favorites/FavoritesFragment.kt
@@ -11,7 +11,6 @@ import androidx.recyclerview.widget.GridLayoutManager
import com.kl3jvi.animity.R
import com.kl3jvi.animity.analytics.Analytics
import com.kl3jvi.animity.databinding.FragmentFavoritesBinding
-import com.kl3jvi.animity.ui.fragments.StateManager
import com.kl3jvi.animity.utils.BottomNavScrollListener
import com.kl3jvi.animity.utils.Constants.Companion.showSnack
import com.kl3jvi.animity.utils.collect
@@ -25,7 +24,7 @@ import javax.inject.Inject
@Suppress("SameParameterValue")
@ExperimentalCoroutinesApi
@AndroidEntryPoint
-class FavoritesFragment : Fragment(R.layout.fragment_favorites), StateManager {
+class FavoritesFragment : Fragment(R.layout.fragment_favorites) {
private val viewModel: FavoritesViewModel by viewModels()
private var binding: FragmentFavoritesBinding? = null
private lateinit var pagingController: FavoritesSearchController
@@ -100,7 +99,7 @@ class FavoritesFragment : Fragment(R.layout.fragment_favorites), StateManager {
binding = null
}
- override fun showLoading(show: Boolean) = Unit
+ fun showLoading(show: Boolean) = Unit
- override fun handleError(e: Throwable) = showSnack(binding?.root, e.message)
+ fun handleError(e: Throwable) = showSnack(binding?.root, e.message)
}
diff --git a/app/src/main/java/com/kl3jvi/animity/ui/fragments/favorites/FavoritesViewModel.kt b/app/src/main/java/com/kl3jvi/animity/ui/fragments/favorites/FavoritesViewModel.kt
index 39121bc2..f4cd86bf 100644
--- a/app/src/main/java/com/kl3jvi/animity/ui/fragments/favorites/FavoritesViewModel.kt
+++ b/app/src/main/java/com/kl3jvi/animity/ui/fragments/favorites/FavoritesViewModel.kt
@@ -9,6 +9,7 @@ import com.kl3jvi.animity.data.model.ui_models.AniListMedia
import com.kl3jvi.animity.domain.repositories.FavoriteRepository
import com.kl3jvi.animity.domain.repositories.PersistenceRepository
import dagger.hilt.android.lifecycle.HiltViewModel
+import javax.inject.Inject
import kotlinx.coroutines.CoroutineDispatcher
import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.Job
@@ -20,37 +21,36 @@ import kotlinx.coroutines.flow.launchIn
import kotlinx.coroutines.flow.onEach
import kotlinx.coroutines.flow.onStart
import kotlinx.coroutines.plus
-import javax.inject.Inject
@ExperimentalCoroutinesApi
@HiltViewModel
class FavoritesViewModel
- @Inject
- constructor(
- private val favoriteRepository: FavoriteRepository,
- private val localStorage: PersistenceRepository,
- private val ioDispatcher: CoroutineDispatcher,
- ) : ViewModel() {
- private var _favoritesList = MutableStateFlow(FavouriteState.Loading)
- val favoritesList = _favoritesList.asStateFlow()
- private var job: Job? = null
+@Inject
+constructor(
+ private val favoriteRepository: FavoriteRepository,
+ private val localStorage: PersistenceRepository,
+ private val ioDispatcher: CoroutineDispatcher,
+) : ViewModel() {
+ private var _favoritesList = MutableStateFlow(FavouriteState.Loading)
+ val favoritesList = _favoritesList.asStateFlow()
+ private var job: Job? = null
- init {
- refreshFavorites()
- }
+ init {
+ refreshFavorites()
+ }
- fun refreshFavorites() {
- favoriteRepository.getFavoriteAnimesFromAniList(localStorage.aniListUserId?.toInt())
- .cachedIn(viewModelScope)
- .onStart { _favoritesList.value = FavouriteState.Loading }
- .catch { _favoritesList.value = FavouriteState.Error(it) }
- .buffer(0)
- .onEach {
- Log.e("FAVORITES", it.toString())
- _favoritesList.value = FavouriteState.Success(it)
- }.launchIn(viewModelScope + ioDispatcher)
- }
+ fun refreshFavorites() {
+ favoriteRepository.getFavoriteAnimesFromAniList(localStorage.aniListUserId?.toInt())
+ .cachedIn(viewModelScope)
+ .onStart { _favoritesList.value = FavouriteState.Loading }
+ .catch { _favoritesList.value = FavouriteState.Error(it) }
+ .buffer(0)
+ .onEach {
+ Log.e("FAVORITES", it.toString())
+ _favoritesList.value = FavouriteState.Success(it)
+ }.launchIn(viewModelScope + ioDispatcher)
}
+}
sealed interface FavouriteState {
data class Success(val data: PagingData) : FavouriteState
diff --git a/app/src/main/java/com/kl3jvi/animity/ui/fragments/home/HomeFragment.kt b/app/src/main/java/com/kl3jvi/animity/ui/fragments/home/HomeFragment.kt
index 366e9ef7..171daa2c 100644
--- a/app/src/main/java/com/kl3jvi/animity/ui/fragments/home/HomeFragment.kt
+++ b/app/src/main/java/com/kl3jvi/animity/ui/fragments/home/HomeFragment.kt
@@ -3,13 +3,13 @@ package com.kl3jvi.animity.ui.fragments.home
import android.os.Bundle
import android.view.View
import androidx.core.view.isVisible
-import androidx.fragment.app.Fragment
import androidx.fragment.app.activityViewModels
import androidx.fragment.app.viewModels
import com.kl3jvi.animity.R
import com.kl3jvi.animity.analytics.Analytics
import com.kl3jvi.animity.databinding.FragmentHomeBinding
-import com.kl3jvi.animity.ui.fragments.StateManager
+import com.kl3jvi.animity.ui.activities.main.MainActivity
+import com.kl3jvi.animity.ui.fragments.base.AnimityFragment
import com.kl3jvi.animity.ui.fragments.notifications.NotificationBottomSheetFragment
import com.kl3jvi.animity.ui.fragments.schedule.ScheduleViewModel
import com.kl3jvi.animity.utils.BottomNavScrollListener
@@ -25,10 +25,12 @@ import javax.inject.Inject
@ExperimentalCoroutinesApi
@AndroidEntryPoint
-class HomeFragment : Fragment(R.layout.fragment_home), StateManager {
+class HomeFragment : AnimityFragment(R.layout.fragment_home) {
private val viewModel: HomeViewModel by viewModels()
private var binding: FragmentHomeBinding? = null
private val scheduleViewModel by activityViewModels()
+ private val stateManager by lazy { create() }
+
private val listener: BottomNavScrollListener by lazy {
requireActivity() as BottomNavScrollListener
@@ -98,16 +100,18 @@ class HomeFragment : Fragment(R.layout.fragment_home), StateManager {
}
}
+ override fun showLoading(show: Boolean) = Unit
+ override fun handleError(e: Throwable) = showSnack(binding?.root, e.message)
+ override fun handleNetworkChanges(isConnected: Boolean) {
+// val activityBinding = (activity as MainActivity).binding
+// activityBinding.wrapper.isVisible = isConnected
+// activityBinding.noInternetStatus.noInternet.isVisible = !isConnected
+ }
+
override fun onDestroyView() {
super.onDestroyView()
binding = null
}
- override fun showLoading(show: Boolean) =
- with(binding) {
- this?.mainRv?.isVisible = !show
- this?.loading?.isVisible = show
- }
- override fun handleError(e: Throwable) = showSnack(binding?.root, e.message)
}
diff --git a/app/src/main/java/com/kl3jvi/animity/ui/fragments/home/HomeViewModel.kt b/app/src/main/java/com/kl3jvi/animity/ui/fragments/home/HomeViewModel.kt
index bbf0af0c..5df5df5a 100644
--- a/app/src/main/java/com/kl3jvi/animity/ui/fragments/home/HomeViewModel.kt
+++ b/app/src/main/java/com/kl3jvi/animity/ui/fragments/home/HomeViewModel.kt
@@ -5,6 +5,7 @@ import androidx.lifecycle.viewModelScope
import com.kl3jvi.animity.analytics.Analytics
import com.kl3jvi.animity.domain.repositories.HomeRepository
import com.kl3jvi.animity.utils.mapToUiState
+import com.kl3jvi.animity.utils.network.NetworkMonitor
import dagger.hilt.android.lifecycle.HiltViewModel
import kotlinx.coroutines.CoroutineDispatcher
import kotlinx.coroutines.plus
@@ -12,13 +13,13 @@ import javax.inject.Inject
@HiltViewModel
class HomeViewModel
- @Inject
- constructor(
- homeRepository: HomeRepository,
- val analytics: Analytics,
- ioDispatcher: CoroutineDispatcher,
- ) : ViewModel() {
- val homeDataUiState =
- homeRepository.getHomeData()
- .mapToUiState(viewModelScope + ioDispatcher)
- }
+@Inject
+constructor(
+ homeRepository: HomeRepository,
+ val analytics: Analytics,
+ ioDispatcher: CoroutineDispatcher,
+ network: NetworkMonitor
+) : ViewModel() {
+ val homeDataUiState = homeRepository.getHomeData()
+ .mapToUiState(viewModelScope + ioDispatcher, network.isConnected)
+}
diff --git a/app/src/main/java/com/kl3jvi/animity/ui/fragments/notifications/NotificationBottomSheetFragment.kt b/app/src/main/java/com/kl3jvi/animity/ui/fragments/notifications/NotificationBottomSheetFragment.kt
index b405bc68..ef25a5a1 100644
--- a/app/src/main/java/com/kl3jvi/animity/ui/fragments/notifications/NotificationBottomSheetFragment.kt
+++ b/app/src/main/java/com/kl3jvi/animity/ui/fragments/notifications/NotificationBottomSheetFragment.kt
@@ -15,7 +15,6 @@ import com.kl3jvi.animity.analytics.Analytics
import com.kl3jvi.animity.data.enums.NotificationType
import com.kl3jvi.animity.data.model.ui_models.AniListMedia
import com.kl3jvi.animity.databinding.NotificationsBottomSheetBinding
-import com.kl3jvi.animity.ui.fragments.StateManager
import com.kl3jvi.animity.ui.fragments.home.HomeFragmentDirections
import com.kl3jvi.animity.utils.Constants.Companion.showSnack
import com.kl3jvi.animity.utils.collectLatest
@@ -25,7 +24,7 @@ import dagger.hilt.android.AndroidEntryPoint
import javax.inject.Inject
@AndroidEntryPoint
-class NotificationBottomSheetFragment : BottomSheetDialogFragment(), StateManager {
+class NotificationBottomSheetFragment : BottomSheetDialogFragment() {
private var binding: NotificationsBottomSheetBinding? = null
private val viewModel by activityViewModels()
private lateinit var pagingController: NotificationsController
@@ -118,10 +117,10 @@ class NotificationBottomSheetFragment : BottomSheetDialogFragment(), StateManage
showLoading(show)
}
- override fun showLoading(show: Boolean) {
+ fun showLoading(show: Boolean) {
binding?.progress?.isVisible = show
binding?.notificationsRv?.isVisible = !show
}
- override fun handleError(e: Throwable) = showSnack(binding?.root, e.message)
+ fun handleError(e: Throwable) = showSnack(binding?.root, e.message)
}
diff --git a/app/src/main/java/com/kl3jvi/animity/ui/fragments/notifications/NotificationViewModel.kt b/app/src/main/java/com/kl3jvi/animity/ui/fragments/notifications/NotificationViewModel.kt
index bbd6ced9..7e1c44bb 100644
--- a/app/src/main/java/com/kl3jvi/animity/ui/fragments/notifications/NotificationViewModel.kt
+++ b/app/src/main/java/com/kl3jvi/animity/ui/fragments/notifications/NotificationViewModel.kt
@@ -9,12 +9,12 @@ import javax.inject.Inject
@HiltViewModel
class NotificationViewModel
- @Inject
- constructor(
- notificationsRepository: NotificationsRepository,
- ) : ViewModel() {
- val notifications =
- notificationsRepository
- .getNotifications()
- .cachedIn(viewModelScope)
- }
+@Inject
+constructor(
+ notificationsRepository: NotificationsRepository,
+) : ViewModel() {
+ val notifications =
+ notificationsRepository
+ .getNotifications()
+ .cachedIn(viewModelScope)
+}
diff --git a/app/src/main/java/com/kl3jvi/animity/ui/fragments/profile/my/ProfileFragment.kt b/app/src/main/java/com/kl3jvi/animity/ui/fragments/profile/my/ProfileFragment.kt
index bc3cff31..39227096 100644
--- a/app/src/main/java/com/kl3jvi/animity/ui/fragments/profile/my/ProfileFragment.kt
+++ b/app/src/main/java/com/kl3jvi/animity/ui/fragments/profile/my/ProfileFragment.kt
@@ -19,12 +19,12 @@ import com.kl3jvi.animity.utils.createFragmentMenu
import com.kl3jvi.animity.utils.epoxy.setupBottomNavScrollListener
import com.kl3jvi.animity.utils.launchActivity
import dagger.hilt.android.AndroidEntryPoint
-import kotlinx.coroutines.ExperimentalCoroutinesApi
import javax.inject.Inject
+import kotlinx.coroutines.ExperimentalCoroutinesApi
@ExperimentalCoroutinesApi
@AndroidEntryPoint
-class ProfileFragment : Fragment(R.layout.fragment_profile), StateManager {
+class ProfileFragment : Fragment(R.layout.fragment_profile) {
private val viewModel: ProfileViewModel by viewModels()
private var binding: FragmentProfileBinding? = null
private lateinit var listener: BottomNavScrollListener
@@ -94,10 +94,10 @@ class ProfileFragment : Fragment(R.layout.fragment_profile), StateManager {
analytics.logCurrentScreen("Profile")
}
- override fun showLoading(show: Boolean) {
+ fun showLoading(show: Boolean) {
binding?.loading?.isVisible = show
binding?.profileRv?.isVisible = !show
}
- override fun handleError(e: Throwable) = showSnack(binding?.root, e.message)
+ fun handleError(e: Throwable) = showSnack(binding?.root, e.message)
}
diff --git a/app/src/main/java/com/kl3jvi/animity/ui/fragments/profile/my/ProfileViewModel.kt b/app/src/main/java/com/kl3jvi/animity/ui/fragments/profile/my/ProfileViewModel.kt
index d7f914db..b55cdfa9 100644
--- a/app/src/main/java/com/kl3jvi/animity/ui/fragments/profile/my/ProfileViewModel.kt
+++ b/app/src/main/java/com/kl3jvi/animity/ui/fragments/profile/my/ProfileViewModel.kt
@@ -6,6 +6,7 @@ import com.kl3jvi.animity.domain.repositories.PersistenceRepository
import com.kl3jvi.animity.domain.repositories.ProfileRepository
import com.kl3jvi.animity.domain.repositories.UserRepository
import com.kl3jvi.animity.utils.mapToUiState
+import com.kl3jvi.animity.utils.network.NetworkMonitor
import dagger.hilt.android.lifecycle.HiltViewModel
import kotlinx.coroutines.CoroutineDispatcher
import kotlinx.coroutines.ExperimentalCoroutinesApi
@@ -15,17 +16,18 @@ import javax.inject.Inject
@ExperimentalCoroutinesApi
@HiltViewModel
class ProfileViewModel
- @Inject
- constructor(
- private val userRepository: UserRepository,
- profileRepository: ProfileRepository,
- localStorage: PersistenceRepository,
- ioDispatcher: CoroutineDispatcher,
- ) : ViewModel() {
- val profileData =
- profileRepository
- .getProfileData(localStorage.aniListUserId?.toInt())
- .mapToUiState(viewModelScope + ioDispatcher)
+@Inject
+constructor(
+ private val userRepository: UserRepository,
+ profileRepository: ProfileRepository,
+ localStorage: PersistenceRepository,
+ ioDispatcher: CoroutineDispatcher,
+ networkMonitor: NetworkMonitor
+) : ViewModel() {
+ val profileData =
+ profileRepository
+ .getProfileData(localStorage.aniListUserId?.toInt())
+ .mapToUiState(viewModelScope + ioDispatcher, networkMonitor.isConnected)
- fun clearStorage(triggered: () -> Unit) = userRepository.clearStorage(triggered)
- }
+ fun clearStorage(triggered: () -> Unit) = userRepository.clearStorage(triggered)
+}
diff --git a/app/src/main/java/com/kl3jvi/animity/ui/fragments/profile/their/TheirProfile.kt b/app/src/main/java/com/kl3jvi/animity/ui/fragments/profile/their/TheirProfile.kt
index 9fed2680..0bcfa875 100644
--- a/app/src/main/java/com/kl3jvi/animity/ui/fragments/profile/their/TheirProfile.kt
+++ b/app/src/main/java/com/kl3jvi/animity/ui/fragments/profile/their/TheirProfile.kt
@@ -18,7 +18,7 @@ import com.kl3jvi.animity.utils.collect
import dagger.hilt.android.AndroidEntryPoint
@AndroidEntryPoint
-class TheirProfile : Fragment(R.layout.fragment_their_profile), StateManager {
+class TheirProfile : Fragment(R.layout.fragment_their_profile) {
private val viewModel: TheirProfileViewModel by viewModels()
private var binding: FragmentTheirProfileBinding? = null
@@ -71,10 +71,10 @@ class TheirProfile : Fragment(R.layout.fragment_their_profile), StateManager {
binding = null
}
- override fun showLoading(show: Boolean) {
+ fun showLoading(show: Boolean) {
binding?.loading?.isVisible = show
binding?.theirProfileRv?.isVisible = !show
}
- override fun handleError(e: Throwable) = showSnack(binding?.root, e.message)
+ fun handleError(e: Throwable) = showSnack(binding?.root, e.message)
}
diff --git a/app/src/main/java/com/kl3jvi/animity/ui/fragments/profile/their/TheirProfileViewModel.kt b/app/src/main/java/com/kl3jvi/animity/ui/fragments/profile/their/TheirProfileViewModel.kt
index bad9e158..187c60eb 100644
--- a/app/src/main/java/com/kl3jvi/animity/ui/fragments/profile/their/TheirProfileViewModel.kt
+++ b/app/src/main/java/com/kl3jvi/animity/ui/fragments/profile/their/TheirProfileViewModel.kt
@@ -7,41 +7,41 @@ import com.kl3jvi.animity.data.model.ui_models.User
import com.kl3jvi.animity.domain.repositories.ProfileRepository
import com.kl3jvi.animity.utils.mapToUiState
import dagger.hilt.android.lifecycle.HiltViewModel
+import javax.inject.Inject
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.combine
import kotlinx.coroutines.flow.flatMapLatest
import kotlinx.coroutines.launch
-import javax.inject.Inject
@HiltViewModel
class TheirProfileViewModel
- @Inject
- constructor(
- private val profileRepository: ProfileRepository,
- private val savedStateHandle: SavedStateHandle,
- ) : ViewModel() {
- private val followState: MutableStateFlow> =
- MutableStateFlow(Pair("Follow", ""))
+@Inject
+constructor(
+ private val profileRepository: ProfileRepository,
+ private val savedStateHandle: SavedStateHandle,
+) : ViewModel() {
+ private val followState: MutableStateFlow> =
+ MutableStateFlow(Pair("Follow", ""))
- val theirProfileData =
- savedStateHandle.getStateFlow("user", User())
- .flatMapLatest { user ->
- profileRepository.getProfileData(user.id)
- }.combine(followState) { profileData, followState ->
- profileData.copy(
- userData = profileData.userData,
- profileRow = profileData.profileRow,
- followState = followState,
- )
- }.mapToUiState(viewModelScope)
+ val theirProfileData =
+ savedStateHandle.getStateFlow("user", User())
+ .flatMapLatest { user ->
+ profileRepository.getProfileData(user.id)
+ }.combine(followState) { profileData, followState ->
+ profileData.copy(
+ userData = profileData.userData,
+ profileRow = profileData.profileRow,
+ followState = followState,
+ )
+ }.mapToUiState(viewModelScope)
- fun followUser() {
- val id = savedStateHandle.get("user")?.id ?: return
- viewModelScope.launch(Dispatchers.IO) {
- profileRepository.followUser(id).collect { newFollowState ->
- followState.value = newFollowState
- }
+ fun followUser() {
+ val id = savedStateHandle.get("user")?.id ?: return
+ viewModelScope.launch(Dispatchers.IO) {
+ profileRepository.followUser(id).collect { newFollowState ->
+ followState.value = newFollowState
}
}
}
+}
diff --git a/app/src/main/java/com/kl3jvi/animity/ui/fragments/schedule/DayPagerAdapter.kt b/app/src/main/java/com/kl3jvi/animity/ui/fragments/schedule/DayPagerAdapter.kt
index d9a27d6e..db3903a7 100644
--- a/app/src/main/java/com/kl3jvi/animity/ui/fragments/schedule/DayPagerAdapter.kt
+++ b/app/src/main/java/com/kl3jvi/animity/ui/fragments/schedule/DayPagerAdapter.kt
@@ -12,9 +12,9 @@ class DayPagerAdapter(
fragmentManager: FragmentManager,
lifecycle: Lifecycle,
) : FragmentStateAdapter(
- fragmentManager,
- lifecycle,
- ) {
+ fragmentManager,
+ lifecycle,
+) {
private val weekDays = WeekName.values()
private var scheduleMap: Map> = emptyMap()
diff --git a/app/src/main/java/com/kl3jvi/animity/ui/fragments/schedule/ScheduleViewModel.kt b/app/src/main/java/com/kl3jvi/animity/ui/fragments/schedule/ScheduleViewModel.kt
index 022044b2..ff1fc0dd 100644
--- a/app/src/main/java/com/kl3jvi/animity/ui/fragments/schedule/ScheduleViewModel.kt
+++ b/app/src/main/java/com/kl3jvi/animity/ui/fragments/schedule/ScheduleViewModel.kt
@@ -6,6 +6,7 @@ import com.kl3jvi.animity.data.enums.WeekName
import com.kl3jvi.animity.data.mapper.AiringInfo
import com.kl3jvi.animity.domain.repositories.NotificationsRepository
import dagger.hilt.android.lifecycle.HiltViewModel
+import javax.inject.Inject
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.async
import kotlinx.coroutines.coroutineScope
@@ -13,42 +14,36 @@ import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.flow.firstOrNull
import kotlinx.coroutines.launch
-import javax.inject.Inject
@HiltViewModel
-class ScheduleViewModel
- @Inject
- constructor(
- private val notificationsRepository: NotificationsRepository,
- ) : ViewModel() {
- private val _airingAnimeSchedule = MutableStateFlow