diff --git a/app/build.gradle b/app/build.gradle index 4129b5cd..1ad47e5d 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -25,8 +25,8 @@ android { applicationId "com.kl3jvi.animity" minSdk 21 targetSdk 32 - versionCode 9 - versionName "1.0.8" + versionCode 10 + versionName "1.0.9" archivesBaseName = "Animity-v$versionName" testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" } @@ -47,11 +47,11 @@ android { } compileOptions { - sourceCompatibility JavaVersion.VERSION_1_8 - targetCompatibility JavaVersion.VERSION_1_8 + sourceCompatibility JavaVersion.VERSION_11 + targetCompatibility JavaVersion.VERSION_11 } kotlinOptions { - jvmTarget = '1.8' + jvmTarget = '11' } buildFeatures { viewBinding true @@ -211,6 +211,9 @@ dependencies { // def brainTree = "6.0.2" // implementation "com.braintreepayments.api:drop-in:$brainTree" + implementation 'org.mozilla:rhino:1.7.13' + + def epoxyVersion = "5.0.0-beta03" implementation "com.airbnb.android:epoxy:$epoxyVersion" implementation "com.airbnb.android:epoxy-databinding:$epoxyVersion" diff --git a/app/release/output-metadata.json b/app/release/output-metadata.json index 04758318..91843cca 100644 --- a/app/release/output-metadata.json +++ b/app/release/output-metadata.json @@ -11,9 +11,9 @@ "type": "UNIVERSAL", "filters": [], "attributes": [], - "versionCode": 9, - "versionName": "1.0.8", - "outputFile": "Animity-v1.0.8-universal-release.apk" + "versionCode": 10, + "versionName": "1.0.9", + "outputFile": "Animity-v1.0.9-universal-release.apk" }, { "type": "ONE_OF_MANY", @@ -24,9 +24,9 @@ } ], "attributes": [], - "versionCode": 9, - "versionName": "1.0.8", - "outputFile": "Animity-v1.0.8-x86_64-release.apk" + "versionCode": 10, + "versionName": "1.0.9", + "outputFile": "Animity-v1.0.9-x86_64-release.apk" }, { "type": "ONE_OF_MANY", @@ -37,35 +37,35 @@ } ], "attributes": [], - "versionCode": 9, - "versionName": "1.0.8", - "outputFile": "Animity-v1.0.8-x86-release.apk" + "versionCode": 10, + "versionName": "1.0.9", + "outputFile": "Animity-v1.0.9-x86-release.apk" }, { "type": "ONE_OF_MANY", "filters": [ { "filterType": "ABI", - "value": "armeabi-v7a" + "value": "arm64-v8a" } ], "attributes": [], - "versionCode": 9, - "versionName": "1.0.8", - "outputFile": "Animity-v1.0.8-armeabi-v7a-release.apk" + "versionCode": 10, + "versionName": "1.0.9", + "outputFile": "Animity-v1.0.9-arm64-v8a-release.apk" }, { "type": "ONE_OF_MANY", "filters": [ { "filterType": "ABI", - "value": "arm64-v8a" + "value": "armeabi-v7a" } ], "attributes": [], - "versionCode": 9, - "versionName": "1.0.8", - "outputFile": "Animity-v1.0.8-arm64-v8a-release.apk" + "versionCode": 10, + "versionName": "1.0.9", + "outputFile": "Animity-v1.0.9-armeabi-v7a-release.apk" } ], "elementType": "File" diff --git a/app/src/main/graphql/Query.graphql b/app/src/main/graphql/Query.graphql index 9151a5d9..38d66324 100644 --- a/app/src/main/graphql/Query.graphql +++ b/app/src/main/graphql/Query.graphql @@ -394,20 +394,6 @@ fragment HomeMedia on Media { large medium } - # recommendations( - # page: 1 - # perPage: 25 - # sort:ID - # ){ - # edges { - # node { - # media { - # - # } - # } - # } - # - # } streamingEpisodes { title thumbnail diff --git a/app/src/main/java/com/kl3jvi/animity/data/model/ui_models/EpisodeModel.kt b/app/src/main/java/com/kl3jvi/animity/data/model/ui_models/EpisodeModel.kt index 3c0b0632..9b5e6bb4 100644 --- a/app/src/main/java/com/kl3jvi/animity/data/model/ui_models/EpisodeModel.kt +++ b/app/src/main/java/com/kl3jvi/animity/data/model/ui_models/EpisodeModel.kt @@ -12,7 +12,7 @@ data class EpisodeModel( var episodeName: String = "", var episodeNumber: String, var episodeUrl: String, - var episodeType: String, + var episodeType: String = "", var percentage: Int = 0, var isFiller: Boolean = false ) : Parcelable diff --git a/app/src/main/java/com/kl3jvi/animity/di/NetworkModule.kt b/app/src/main/java/com/kl3jvi/animity/di/NetworkModule.kt index 272858e7..dc0d9265 100644 --- a/app/src/main/java/com/kl3jvi/animity/di/NetworkModule.kt +++ b/app/src/main/java/com/kl3jvi/animity/di/NetworkModule.kt @@ -1,7 +1,6 @@ package com.kl3jvi.animity.di -import android.content.Context import com.apollographql.apollo3.ApolloClient import com.apollographql.apollo3.network.okHttpClient import com.kl3jvi.animity.data.network.anilist_service.AniListClient @@ -11,29 +10,28 @@ import com.kl3jvi.animity.data.network.anime_service.AnimeService import com.kl3jvi.animity.data.network.interceptor.HeaderInterceptor import com.kl3jvi.animity.domain.repositories.activity_repositories.LoginRepository import com.kl3jvi.animity.domain.repositories.persistence_repositories.LocalStorage +import com.kl3jvi.animity.utils.Apollo import com.kl3jvi.animity.utils.Constants.Companion.ANILIST_API_URL import com.kl3jvi.animity.utils.Constants.Companion.BASE_URL +import com.kl3jvi.animity.utils.RetrofitClient import dagger.Module import dagger.Provides import dagger.hilt.InstallIn -import dagger.hilt.android.qualifiers.ApplicationContext import dagger.hilt.components.SingletonComponent import okhttp3.OkHttpClient import okhttp3.logging.HttpLoggingInterceptor import retrofit2.Retrofit import retrofit2.converter.gson.GsonConverterFactory import java.util.concurrent.TimeUnit -import javax.inject.Named import javax.inject.Singleton -import kotlin.reflect.KParameter @InstallIn(SingletonComponent::class) @Module object NetworkModule { - /* Providing an OkHttpClient to the dagger. */ @Provides @Singleton + @Apollo fun provideOkHttpClient( localStorage: LocalStorage, loginRepository: LoginRepository, @@ -49,10 +47,9 @@ object NetworkModule { .build() } - @Provides @Singleton - @Named("RetrofitOkHttp") + @RetrofitClient fun provideRetrofitOkHttpClient(): OkHttpClient { return OkHttpClient.Builder() .addInterceptor(HttpLoggingInterceptor().apply { @@ -68,7 +65,7 @@ object NetworkModule { @Provides @Singleton fun provideRetrofit( - @Named("RetrofitOkHttp") okHttpClient: OkHttpClient + @RetrofitClient okHttpClient: OkHttpClient ): Retrofit { return Retrofit.Builder() .baseUrl(BASE_URL) @@ -86,7 +83,7 @@ object NetworkModule { @Provides @Singleton fun provideApolloClient( - okHttpClient: OkHttpClient, + @Apollo okHttpClient: OkHttpClient, ): ApolloClient { return ApolloClient.Builder() .serverUrl(ANILIST_API_URL) diff --git a/app/src/main/java/com/kl3jvi/animity/di/RepositoryModule.kt b/app/src/main/java/com/kl3jvi/animity/di/RepositoryModule.kt index 05933cca..8475d616 100644 --- a/app/src/main/java/com/kl3jvi/animity/di/RepositoryModule.kt +++ b/app/src/main/java/com/kl3jvi/animity/di/RepositoryModule.kt @@ -16,9 +16,11 @@ import dagger.Binds import dagger.Module import dagger.hilt.InstallIn import dagger.hilt.components.SingletonComponent +import kotlinx.coroutines.ExperimentalCoroutinesApi @Module @InstallIn(SingletonComponent::class) +@ExperimentalCoroutinesApi abstract class RepositoryModule { @Binds diff --git a/app/src/main/java/com/kl3jvi/animity/domain/repositories/persistence_repositories/LocalStorage.kt b/app/src/main/java/com/kl3jvi/animity/domain/repositories/persistence_repositories/LocalStorage.kt index ae3091bf..f8a40013 100644 --- a/app/src/main/java/com/kl3jvi/animity/domain/repositories/persistence_repositories/LocalStorage.kt +++ b/app/src/main/java/com/kl3jvi/animity/domain/repositories/persistence_repositories/LocalStorage.kt @@ -3,14 +3,19 @@ package com.kl3jvi.animity.domain.repositories.persistence_repositories /* It's an interface that defines the properties that are used to store data in the local storage */ interface LocalStorage { + /* It's a property that is used to store the bearer token in the local storage. */ var bearerToken: String? var refreshToken: String? var guestToken: String? var aniListUserId: String? + /* It's a part of the encryption algorithm. */ var iv: String? var key: String? var secondKey: String? + /** + * Clears the storage and logs out + */ fun clearStorage() } \ No newline at end of file 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 e13191e6..5e8c99d6 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 @@ -2,7 +2,6 @@ package com.kl3jvi.animity.ui.activities.player import android.annotation.SuppressLint import android.os.Bundle -import android.util.Log import android.view.View import android.widget.ImageButton import android.widget.ImageView @@ -47,7 +46,6 @@ import okhttp3.OkHttpClient import okhttp3.dnsoverhttps.DnsOverHttps import java.io.File import java.net.InetAddress -import kotlin.math.pow @ExperimentalCoroutinesApi @@ -98,7 +96,7 @@ class PlayerActivity : AppCompatActivity() { initialisePlayerLayout() viewModel.updateEpisodeUrl(getIntentData?.episodeUrl.toString()) - Log.e("Playback position", playbackPosition.toString()) + hideSystemUi() } } @@ -116,7 +114,6 @@ class PlayerActivity : AppCompatActivity() { public override fun onResume() { super.onResume() - hideSystemUi() if (Util.SDK_INT <= 23 && player == null) { initializePlayer() onIsPlayingChanged(isPlaying = true) @@ -318,6 +315,7 @@ class PlayerActivity : AppCompatActivity() { .setAllowChunklessPreparation(true) .createMediaSource(mediaItem) } else { + /* Creating a data source factory. */ val dataSource = { val dataSource: DataSource.Factory = DefaultHttpDataSource.Factory() .setUserAgent(Constants.USER_AGENT) 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 4c87395e..11e8d0b0 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 @@ -6,20 +6,18 @@ import android.view.View import android.view.ViewGroup import androidx.core.view.isVisible import androidx.fragment.app.viewModels -import com.airbnb.epoxy.EpoxyModel -import com.airbnb.epoxy.preload.EpoxyModelPreloader -import com.airbnb.epoxy.preload.PreloadRequestHolder -import com.airbnb.epoxy.preload.ViewMetadata +import androidx.lifecycle.lifecycleScope import com.kl3jvi.animity.databinding.FragmentHomeBinding -import com.kl3jvi.animity.episodeLarge -import com.kl3jvi.animity.title import com.kl3jvi.animity.ui.activities.main.MainActivity import com.kl3jvi.animity.ui.base.BaseFragment import com.kl3jvi.animity.utils.NetworkUtils.isConnectedToInternet -import com.kl3jvi.animity.utils.observeLiveData +import com.kl3jvi.animity.utils.collectFlow import dagger.hilt.android.AndroidEntryPoint +import kotlinx.coroutines.ExperimentalCoroutinesApi +import kotlinx.coroutines.launch +@ExperimentalCoroutinesApi @AndroidEntryPoint class HomeFragment : BaseFragment() { override val viewModel: HomeViewModel by viewModels() @@ -33,7 +31,7 @@ class HomeFragment : BaseFragment() { } private fun fetchHomeData() { - observeLiveData(viewModel.homeData, viewLifecycleOwner) { result -> + collectFlow(viewModel.homeData) { result -> binding.mainRv.withModels { binding.loadingIndicator.isVisible = result.newAnime.isEmpty() buildHome(result, firebaseAnalytics) @@ -48,8 +46,9 @@ class HomeFragment : BaseFragment() { private fun handleNetworkChanges() { requireActivity().isConnectedToInternet(viewLifecycleOwner) { isConnected -> + /* Checking if the user is connected to the internet and if so, it will fetch the data from + the server. */ if (isConnected) fetchHomeData() - binding.apply { mainRv.isVisible = isConnected loadingIndicator.isVisible = isConnected @@ -58,6 +57,9 @@ class HomeFragment : BaseFragment() { } } + /** + * It handles network changes. + */ override fun onStart() { super.onStart() handleNetworkChanges() @@ -67,27 +69,14 @@ class HomeFragment : BaseFragment() { override fun initViews() { -// binding.button2.setOnClickListener { -// requireContext().launchActivity { -// val dropInRequest = DropInRequest() -// dropInClient = DropInClient( -// requireContext(), -// "sandbox_ykvmgk4j_fssw4nqtc2phhht8", -// dropInRequest -// ) -// dropInClient.launchDropInForResult( -// requireActivity(), -// PaymentActivity.DROP_IN_REQUEST_CODE -// ) -// } -// } + lifecycleScope.launch { + + } } override fun getViewBinding(): FragmentHomeBinding = FragmentHomeBinding.inflate(layoutInflater) - companion object { - const val DROP_IN_REQUEST_CODE = 800 - } + } 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 30f13a9c..ab795713 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 @@ -1,20 +1,16 @@ package com.kl3jvi.animity.ui.fragments.home -import androidx.lifecycle.LiveData -import androidx.lifecycle.MutableLiveData import androidx.lifecycle.ViewModel import androidx.lifecycle.viewModelScope import com.kl3jvi.animity.data.model.ui_models.HomeData import com.kl3jvi.animity.domain.use_cases.GetAnimesUseCase import com.kl3jvi.animity.utils.NetworkResource -import com.kl3jvi.animity.utils.logError import com.kl3jvi.animity.utils.logMessage import dagger.hilt.android.lifecycle.HiltViewModel import kotlinx.coroutines.CoroutineDispatcher -import kotlinx.coroutines.flow.catch -import kotlinx.coroutines.flow.flowOn -import kotlinx.coroutines.flow.launchIn -import kotlinx.coroutines.flow.onEach +import kotlinx.coroutines.flow.MutableStateFlow +import kotlinx.coroutines.flow.asStateFlow +import kotlinx.coroutines.launch import javax.inject.Inject @HiltViewModel @@ -23,8 +19,8 @@ class HomeViewModel @Inject constructor( private val ioDispatcher: CoroutineDispatcher ) : ViewModel() { - private var _homeData = MutableLiveData() - var homeData: LiveData = _homeData + private var _homeData = MutableStateFlow(HomeData()) + var homeData = _homeData.asStateFlow() init { getHomePageData() @@ -34,17 +30,18 @@ class HomeViewModel @Inject constructor( * It fetches data from the server and updates the UI. */ private fun getHomePageData() { - getAnimesUseCase().flowOn(ioDispatcher).catch { e -> - logError(e) - }.onEach { - when (it) { - is NetworkResource.Failed -> { - logMessage(it.message) - } - is NetworkResource.Success -> { - _homeData.value = it.data ?: HomeData() + viewModelScope.launch(ioDispatcher) { + getAnimesUseCase().collect { + when (it) { + is NetworkResource.Failed -> { + /* A function that logs the message to the console. */ + logMessage(it.message) + } + is NetworkResource.Success -> { + _homeData.value = it.data + } } } - }.launchIn(viewModelScope) + } } } diff --git a/app/src/main/java/com/kl3jvi/animity/utils/Annotations.kt b/app/src/main/java/com/kl3jvi/animity/utils/Annotations.kt new file mode 100644 index 00000000..9cc0b238 --- /dev/null +++ b/app/src/main/java/com/kl3jvi/animity/utils/Annotations.kt @@ -0,0 +1,11 @@ +package com.kl3jvi.animity.utils + +import javax.inject.Qualifier + +@Qualifier +@Retention(AnnotationRetention.RUNTIME) +annotation class RetrofitClient + +@Qualifier +@Retention(AnnotationRetention.RUNTIME) +annotation class Apollo \ No newline at end of file diff --git a/app/src/main/java/com/kl3jvi/animity/utils/Constants.kt b/app/src/main/java/com/kl3jvi/animity/utils/Constants.kt index 3d3d0195..a1c8d2aa 100644 --- a/app/src/main/java/com/kl3jvi/animity/utils/Constants.kt +++ b/app/src/main/java/com/kl3jvi/animity/utils/Constants.kt @@ -5,6 +5,8 @@ import android.graphics.Color import android.view.View import com.google.android.exoplayer2.upstream.DefaultHttpDataSource import com.google.android.material.snackbar.Snackbar +import com.google.gson.Gson +import com.google.gson.GsonBuilder import com.kl3jvi.animity.BuildConfig import java.util.* @@ -33,11 +35,14 @@ class Constants { const val SIGNUP_URL = "https://anilist.co/signup" const val MAL_SYNC_URL = "https://raw.githubusercontent.com/MALSync/MAL-Sync-Backup/master/data/anilist/anime" - const val EPISODE_TITLES = "https://raw.githubusercontent.com/saikou-app/mal-id-filler-list/main/fillers" + const val EPISODE_TITLES = + "https://raw.githubusercontent.com/saikou-app/mal-id-filler-list/main/fillers" /* Used to get the gogoanime keys from the github repo. Thanks to https://github.com/justfoolingaround */ - const val GOGO_KEYS_URL ="https://raw.githubusercontent.com/justfoolingaround/animdl-provider-benchmarks/master/api/gogoanime.json" + const val GOGO_KEYS_URL = + "https://raw.githubusercontent.com/justfoolingaround/animdl-provider-benchmarks/master/api/gogoanime.json" + /* The default cover image for the profile. */ const val DEFAULT_COVER = "https://bit.ly/3p6DE28" @@ -61,7 +66,7 @@ class Constants { "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/80.0.3987.132 Safari/537.36" const val ORIGIN = "https://gogoanime.gg/" - const val REFERER = "https://goload.pro/" + const val REFERER = "https://goload.pro/" // fun getHeader(): Map { // return mapOf( @@ -161,6 +166,11 @@ class Constants { return UUID.randomUUID().toString() } + val mapper = GsonBuilder().create() + + inline fun Gson.readValue(content: String): T = + this.fromJson(content, T::class.java) + } } diff --git a/app/src/main/java/com/kl3jvi/animity/utils/parser/HtmlParser.kt b/app/src/main/java/com/kl3jvi/animity/utils/parser/HtmlParser.kt index 5b749ecc..48600976 100644 --- a/app/src/main/java/com/kl3jvi/animity/utils/parser/HtmlParser.kt +++ b/app/src/main/java/com/kl3jvi/animity/utils/parser/HtmlParser.kt @@ -17,7 +17,6 @@ class HtmlParser @Inject constructor( private val preferences: LocalStorage ) : Parser { - /** * It takes a response from a network request, parses it, and returns a list of AnimeMetaModel * objects