From 450cf3f7283efdfeea2b5f6b31c106d197753713 Mon Sep 17 00:00:00 2001 From: Kamalesh Reddy Paluru Date: Sat, 6 Jan 2024 03:37:32 -0500 Subject: [PATCH 01/30] I think I fixed navigation https://github.com/raamcosta/compose-destinations/blob/46099dc0f6066a1fb343b1f107445bfa29cbca15/sample/src/main/java/com/ramcosta/destinations/sample/ui/composables/BottomBar.kt#L33-L58 --- .../animite/features/navigationbar/NavigationBar.kt | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/app/src/main/java/com/imashnake/animite/features/navigationbar/NavigationBar.kt b/app/src/main/java/com/imashnake/animite/features/navigationbar/NavigationBar.kt index 6d8c6abc..44535e6a 100644 --- a/app/src/main/java/com/imashnake/animite/features/navigationbar/NavigationBar.kt +++ b/app/src/main/java/com/imashnake/animite/features/navigationbar/NavigationBar.kt @@ -1,6 +1,7 @@ package com.imashnake.animite.features.navigationbar import android.content.res.Configuration +import android.util.Log import androidx.compose.foundation.layout.WindowInsets import androidx.compose.foundation.layout.asPaddingValues import androidx.compose.foundation.layout.displayCutout @@ -30,6 +31,7 @@ import com.imashnake.animite.profile.ProfileNavGraph import com.imashnake.animite.rslash.RslashNavGraph import com.ramcosta.composedestinations.spec.DestinationSpec import com.ramcosta.composedestinations.utils.currentDestinationAsState +import com.ramcosta.composedestinations.utils.isRouteOnBackStack import com.ramcosta.composedestinations.utils.startDestination import com.imashnake.animite.R as Res @@ -52,12 +54,19 @@ fun NavigationBar( ) { WindowInsets.displayCutout } else { WindowInsets(0.dp) } ) { val currentDestination by navController.currentDestinationAsState() - - NavigationBarPaths.values().forEach { destination -> + NavigationBarPaths.entries.forEach { destination -> + val isCurrentDestOnBackStack = navController.isRouteOnBackStack(destination.route) NavigationBarItem( modifier = Modifier.navigationBarsPadding(), selected = currentDestination?.startDestination == destination.route, onClick = { + Log.d("FuniNavGraphs", "${currentDestination?.startDestination}, ${destination.route}") + + if (isCurrentDestOnBackStack) { + navController.popBackStack(destination.route.route, false) + return@NavigationBarItem + } + navController.navigate(destination.route.route) { popUpTo(navController.graph.findStartDestination().id) { saveState = true From 17c0b6984c792283ade50705cda7d47e6f4014ec Mon Sep 17 00:00:00 2001 From: Kamalesh Reddy Paluru Date: Sat, 6 Jan 2024 04:08:28 -0500 Subject: [PATCH 02/30] Access access token https://anilist.gitbook.io/anilist-apiv2-docs/overview/oauth/implicit-grant#making-authenticated-requests --- app/src/main/AndroidManifest.xml | 8 +++++ .../features/navigationbar/NavigationBar.kt | 3 -- profile/build.gradle.kts | 4 +++ .../animite/profile/ProfileScreen.kt | 29 +++++++++++++++++-- .../animite/profile/dev/internal/Constants.kt | 6 ++++ 5 files changed, 44 insertions(+), 6 deletions(-) create mode 100644 profile/src/main/kotlin/com/imashnake/animite/profile/dev/internal/Constants.kt diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index 1caca10c..fdcec69d 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -23,6 +23,14 @@ + + + + + + diff --git a/app/src/main/java/com/imashnake/animite/features/navigationbar/NavigationBar.kt b/app/src/main/java/com/imashnake/animite/features/navigationbar/NavigationBar.kt index 44535e6a..0310d86e 100644 --- a/app/src/main/java/com/imashnake/animite/features/navigationbar/NavigationBar.kt +++ b/app/src/main/java/com/imashnake/animite/features/navigationbar/NavigationBar.kt @@ -1,7 +1,6 @@ package com.imashnake.animite.features.navigationbar import android.content.res.Configuration -import android.util.Log import androidx.compose.foundation.layout.WindowInsets import androidx.compose.foundation.layout.asPaddingValues import androidx.compose.foundation.layout.displayCutout @@ -60,8 +59,6 @@ fun NavigationBar( modifier = Modifier.navigationBarsPadding(), selected = currentDestination?.startDestination == destination.route, onClick = { - Log.d("FuniNavGraphs", "${currentDestination?.startDestination}, ${destination.route}") - if (isCurrentDestOnBackStack) { navController.popBackStack(destination.route.route, false) return@NavigationBarItem diff --git a/profile/build.gradle.kts b/profile/build.gradle.kts index b0ccc33a..ab3080c4 100644 --- a/profile/build.gradle.kts +++ b/profile/build.gradle.kts @@ -6,15 +6,19 @@ plugins { alias(libs.plugins.ksp) } +android.buildFeatures.buildConfig = true + android { defaultConfig { testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner" + buildConfigField("int", "CLIENT_ID", "10678") } buildTypes { release { isMinifyEnabled = false proguardFiles(getDefaultProguardFile("proguard-android-optimize.txt"), "proguard-rules.pro") + buildConfigField("int", "CLIENT_ID", "10678") } } diff --git a/profile/src/main/kotlin/com/imashnake/animite/profile/ProfileScreen.kt b/profile/src/main/kotlin/com/imashnake/animite/profile/ProfileScreen.kt index 749cbcc5..5fc23f0f 100644 --- a/profile/src/main/kotlin/com/imashnake/animite/profile/ProfileScreen.kt +++ b/profile/src/main/kotlin/com/imashnake/animite/profile/ProfileScreen.kt @@ -4,23 +4,39 @@ import androidx.compose.foundation.background import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.Spacer import androidx.compose.foundation.layout.fillMaxSize +import androidx.compose.foundation.layout.size +import androidx.compose.material3.Button import androidx.compose.material3.MaterialTheme import androidx.compose.material3.Text import androidx.compose.runtime.Composable import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier +import androidx.compose.ui.platform.LocalUriHandler import androidx.compose.ui.res.stringResource -import com.imashnake.animite.core.R as coreR import com.imashnake.animite.core.ui.LocalPaddings import com.imashnake.animite.core.ui.ProgressIndicator +import com.imashnake.animite.profile.dev.internal.ANILIST_AUTH_DEEPLINK +import com.imashnake.animite.profile.dev.internal.ANILIST_AUTH_URL +import com.ramcosta.composedestinations.annotation.DeepLink import com.ramcosta.composedestinations.annotation.Destination import com.ramcosta.composedestinations.annotation.RootNavGraph +import com.imashnake.animite.core.R as coreR -@Destination(route = "profile-screen") +@Destination( + route = "user", + deepLinks = [ + DeepLink( + uriPattern = ANILIST_AUTH_DEEPLINK + ) + ] +) @RootNavGraph(start = true) @Composable -fun ProfileScreen() { +fun ProfileScreen( + accessToken: String? = null +) { Box( contentAlignment = Alignment.Center, modifier = Modifier @@ -33,12 +49,19 @@ fun ProfileScreen() { LocalPaddings.current.tiny ) ) { + val uriHandler = LocalUriHandler.current Text( text = stringResource(coreR.string.coming_soon), color = MaterialTheme.colorScheme.onSurfaceVariant, style = MaterialTheme.typography.labelLarge ) ProgressIndicator() + + Spacer(modifier = Modifier.size(LocalPaddings.current.large)) + + Button(onClick = { uriHandler.openUri(ANILIST_AUTH_URL) }) { + Text(text = "Log in") + } } } } diff --git a/profile/src/main/kotlin/com/imashnake/animite/profile/dev/internal/Constants.kt b/profile/src/main/kotlin/com/imashnake/animite/profile/dev/internal/Constants.kt new file mode 100644 index 00000000..d1afe51f --- /dev/null +++ b/profile/src/main/kotlin/com/imashnake/animite/profile/dev/internal/Constants.kt @@ -0,0 +1,6 @@ +package com.imashnake.animite.profile.dev.internal + +import com.imashnake.animite.profile.BuildConfig + +const val ANILIST_AUTH_DEEPLINK = "jinnah://animite#access_token={accessToken}&token_type=Bearer&expires_in=31622400" +const val ANILIST_AUTH_URL = "https://anilist.co/api/v2/oauth/authorize?client_id={${BuildConfig.CLIENT_ID}}&response_type=token" From 5d11d2366f8189fa99d790a8d2ee7dc92484565d Mon Sep 17 00:00:00 2001 From: Kamalesh Reddy Paluru Date: Sun, 7 Jan 2024 00:45:10 -0500 Subject: [PATCH 03/30] Cleanup --- .../com/imashnake/animite/api/anilist/AnilistApiModule.kt | 2 +- profile/build.gradle.kts | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/api/anilist/src/main/kotlin/com/imashnake/animite/api/anilist/AnilistApiModule.kt b/api/anilist/src/main/kotlin/com/imashnake/animite/api/anilist/AnilistApiModule.kt index 8cd22844..76eae2b9 100644 --- a/api/anilist/src/main/kotlin/com/imashnake/animite/api/anilist/AnilistApiModule.kt +++ b/api/anilist/src/main/kotlin/com/imashnake/animite/api/anilist/AnilistApiModule.kt @@ -18,7 +18,7 @@ import javax.inject.Singleton @InstallIn(SingletonComponent::class) object AnilistApiModule { - // TODO name this so we can have other apollo clients for different APIs + // TODO: Name this so we can have other apollo clients for different APIs. @Provides @Singleton fun provideApolloClient( diff --git a/profile/build.gradle.kts b/profile/build.gradle.kts index ab3080c4..389d1d69 100644 --- a/profile/build.gradle.kts +++ b/profile/build.gradle.kts @@ -44,6 +44,7 @@ ksp { dependencies { implementation(project(":core")) + // AndroidX implementation(libs.androidx.activityCompose) implementation(libs.androidx.coreKtx) From c4640f73ddf723019ba855ce441abc7b23818746 Mon Sep 17 00:00:00 2001 From: Kamalesh Reddy Paluru Date: Sun, 7 Jan 2024 00:57:07 -0500 Subject: [PATCH 04/30] Added DataStore https://developer.android.com/topic/libraries/architecture/datastore#preferences-datastore-dependencies --- api/anilist/build.gradle.kts | 3 +++ gradle/libs.versions.toml | 5 +++++ 2 files changed, 8 insertions(+) diff --git a/api/anilist/build.gradle.kts b/api/anilist/build.gradle.kts index 8feab45a..be9766b2 100644 --- a/api/anilist/build.gradle.kts +++ b/api/anilist/build.gradle.kts @@ -37,6 +37,9 @@ dependencies { implementation(libs.hilt.android) implementation(libs.hilt.navigationCompose) ksp(libs.hilt.android.compiler) + + // DataStore + implementation(libs.datastore) } apollo { diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 0f9d6c6f..e9d6045d 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -32,6 +32,10 @@ espresso = "3.6.0-alpha02" # https://github.com/apollographql/apollo-kotlin/releases. apollo = "3.8.2" +# DataStore +# https://developer.android.com/jetpack/androidx/releases/datastore +datastore = "1.0.0" + # COIL # https://github.com/coil-kt/coil/blob/main/CHANGELOG.md. coil = "2.5.0" @@ -102,6 +106,7 @@ apollo-cache-sqlite = { group = "com.apollographql.apollo3", name = "apollo-norm coil-compose = { group = "io.coil-kt", name = "coil-compose", version.ref = "coil" } kotlin-coroutines-android = { group = "org.jetbrains.kotlinx", name = "kotlinx-coroutines-android", version.ref = "coroutines" } kotlin-coroutines-core = { group = "org.jetbrains.kotlinx", name = "kotlinx-coroutines-core", version.ref = "coroutines" } +datastore = { group = "androidx.datastore", name = "datastore-preferences", version.ref = "datastore" } hilt-android = { group = "com.google.dagger", name = "hilt-android", version.ref = "dagger" } hilt-android-compiler = { group = "com.google.dagger", name = "hilt-android-compiler", version.ref = "dagger" } hilt-navigationCompose = { group = "androidx.hilt", name = "hilt-navigation-compose", version.ref = "hilt" } From 4c64f40f43d44684e71a4ebeb709fc8767a7f2e4 Mon Sep 17 00:00:00 2001 From: Kamalesh Reddy Paluru Date: Sun, 7 Jan 2024 01:39:12 -0500 Subject: [PATCH 05/30] Setup preferences data source --- .../imashnake/animite/api/DataStoreModule.kt | 25 +++++++++++++++++++ .../animite/api/PreferencesRepository.kt | 13 ++++++++++ 2 files changed, 38 insertions(+) create mode 100644 api/anilist/src/main/kotlin/com/imashnake/animite/api/DataStoreModule.kt create mode 100644 api/anilist/src/main/kotlin/com/imashnake/animite/api/PreferencesRepository.kt diff --git a/api/anilist/src/main/kotlin/com/imashnake/animite/api/DataStoreModule.kt b/api/anilist/src/main/kotlin/com/imashnake/animite/api/DataStoreModule.kt new file mode 100644 index 00000000..1877682d --- /dev/null +++ b/api/anilist/src/main/kotlin/com/imashnake/animite/api/DataStoreModule.kt @@ -0,0 +1,25 @@ +package com.imashnake.animite.api + +import android.content.Context +import androidx.datastore.core.DataStore +import androidx.datastore.preferences.core.PreferenceDataStoreFactory +import androidx.datastore.preferences.core.Preferences +import androidx.datastore.preferences.preferencesDataStoreFile +import dagger.Module +import dagger.Provides +import dagger.hilt.InstallIn +import dagger.hilt.android.qualifiers.ApplicationContext +import dagger.hilt.components.SingletonComponent +import javax.inject.Singleton + +@Module +@InstallIn(SingletonComponent::class) +object DataStoreModule { + @Singleton + @Provides + fun providePreferencesDataStore(@ApplicationContext appContext: Context): DataStore { + return PreferenceDataStoreFactory.create( + produceFile = { appContext.preferencesDataStoreFile("default") } + ) + } +} diff --git a/api/anilist/src/main/kotlin/com/imashnake/animite/api/PreferencesRepository.kt b/api/anilist/src/main/kotlin/com/imashnake/animite/api/PreferencesRepository.kt new file mode 100644 index 00000000..a7757a3c --- /dev/null +++ b/api/anilist/src/main/kotlin/com/imashnake/animite/api/PreferencesRepository.kt @@ -0,0 +1,13 @@ +package com.imashnake.animite.api + +import androidx.datastore.core.DataStore +import androidx.datastore.preferences.core.Preferences +import androidx.datastore.preferences.core.stringPreferencesKey +import kotlinx.coroutines.flow.map +import javax.inject.Inject + +class PreferencesRepository @Inject constructor( + private val dataStore: DataStore +) { + val accessToken = dataStore.data.map { it[stringPreferencesKey("access_token")] } +} From e350a7b6f59186789950cb6a40189fbe36b10e28 Mon Sep 17 00:00:00 2001 From: Kamalesh Reddy Paluru Date: Sun, 7 Jan 2024 02:11:07 -0500 Subject: [PATCH 06/30] Created `:api:preferences` module --- api/anilist/build.gradle.kts | 3 -- api/preferences/build.gradle.kts | 35 +++++++++++++++++++ api/preferences/src/main/AndroidManifest.xml | 1 + .../api/preferences}/DataStoreModule.kt | 2 +- .../api/preferences}/PreferencesRepository.kt | 2 +- settings.gradle.kts | 1 + 6 files changed, 39 insertions(+), 5 deletions(-) create mode 100644 api/preferences/build.gradle.kts create mode 100644 api/preferences/src/main/AndroidManifest.xml rename api/{anilist/src/main/kotlin/com/imashnake/animite/api => preferences/src/main/kotlin/com/imashnake/animite/api/preferences}/DataStoreModule.kt (94%) rename api/{anilist/src/main/kotlin/com/imashnake/animite/api => preferences/src/main/kotlin/com/imashnake/animite/api/preferences}/PreferencesRepository.kt (90%) diff --git a/api/anilist/build.gradle.kts b/api/anilist/build.gradle.kts index be9766b2..8feab45a 100644 --- a/api/anilist/build.gradle.kts +++ b/api/anilist/build.gradle.kts @@ -37,9 +37,6 @@ dependencies { implementation(libs.hilt.android) implementation(libs.hilt.navigationCompose) ksp(libs.hilt.android.compiler) - - // DataStore - implementation(libs.datastore) } apollo { diff --git a/api/preferences/build.gradle.kts b/api/preferences/build.gradle.kts new file mode 100644 index 00000000..e4ff4d44 --- /dev/null +++ b/api/preferences/build.gradle.kts @@ -0,0 +1,35 @@ +plugins { + alias(libs.plugins.android.library) + alias(libs.plugins.kotlin) + alias(libs.plugins.hilt) + alias(libs.plugins.ksp) +} + +android { + defaultConfig { + testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner" + } + + buildTypes { + release { + isMinifyEnabled = false + proguardFiles(getDefaultProguardFile("proguard-android-optimize.txt"), "proguard-rules.pro") + } + } + + namespace = "com.imashnake.animite.api.preferences" +} + +kotlin { + jvmToolchain(17) +} + +dependencies { + // Hilt + implementation(libs.hilt.android) + implementation(libs.hilt.navigationCompose) + ksp(libs.hilt.android.compiler) + + // DataStore + implementation(libs.datastore) +} diff --git a/api/preferences/src/main/AndroidManifest.xml b/api/preferences/src/main/AndroidManifest.xml new file mode 100644 index 00000000..cc947c56 --- /dev/null +++ b/api/preferences/src/main/AndroidManifest.xml @@ -0,0 +1 @@ + diff --git a/api/anilist/src/main/kotlin/com/imashnake/animite/api/DataStoreModule.kt b/api/preferences/src/main/kotlin/com/imashnake/animite/api/preferences/DataStoreModule.kt similarity index 94% rename from api/anilist/src/main/kotlin/com/imashnake/animite/api/DataStoreModule.kt rename to api/preferences/src/main/kotlin/com/imashnake/animite/api/preferences/DataStoreModule.kt index 1877682d..6d763089 100644 --- a/api/anilist/src/main/kotlin/com/imashnake/animite/api/DataStoreModule.kt +++ b/api/preferences/src/main/kotlin/com/imashnake/animite/api/preferences/DataStoreModule.kt @@ -1,4 +1,4 @@ -package com.imashnake.animite.api +package com.imashnake.animite.api.preferences import android.content.Context import androidx.datastore.core.DataStore diff --git a/api/anilist/src/main/kotlin/com/imashnake/animite/api/PreferencesRepository.kt b/api/preferences/src/main/kotlin/com/imashnake/animite/api/preferences/PreferencesRepository.kt similarity index 90% rename from api/anilist/src/main/kotlin/com/imashnake/animite/api/PreferencesRepository.kt rename to api/preferences/src/main/kotlin/com/imashnake/animite/api/preferences/PreferencesRepository.kt index a7757a3c..bf0bfcda 100644 --- a/api/anilist/src/main/kotlin/com/imashnake/animite/api/PreferencesRepository.kt +++ b/api/preferences/src/main/kotlin/com/imashnake/animite/api/preferences/PreferencesRepository.kt @@ -1,4 +1,4 @@ -package com.imashnake.animite.api +package com.imashnake.animite.api.preferences import androidx.datastore.core.DataStore import androidx.datastore.preferences.core.Preferences diff --git a/settings.gradle.kts b/settings.gradle.kts index b65f64bf..fae925ea 100644 --- a/settings.gradle.kts +++ b/settings.gradle.kts @@ -24,6 +24,7 @@ plugins { rootProject.name = "Animite" include( ":api:anilist", + ":api:preferences", ":material-color-utilities", ":core", ":profile", From caadae15207a5ba3a156c57f8fce71d614797599 Mon Sep 17 00:00:00 2001 From: Kamalesh Reddy Paluru Date: Sun, 7 Jan 2024 14:09:24 -0500 Subject: [PATCH 07/30] Moved Resource to core --- app/src/main/java/com/imashnake/animite/features/home/Home.kt | 2 +- .../java/com/imashnake/animite/features/home/HomeViewModel.kt | 4 ++-- .../imashnake/animite/features/searchbar/SearchViewModel.kt | 4 ++-- .../main/kotlin/com/imashnake/animite/core}/data/Resource.kt | 2 +- 4 files changed, 6 insertions(+), 6 deletions(-) rename {app/src/main/java/com/imashnake/animite => core/src/main/kotlin/com/imashnake/animite/core}/data/Resource.kt (97%) diff --git a/app/src/main/java/com/imashnake/animite/features/home/Home.kt b/app/src/main/java/com/imashnake/animite/features/home/Home.kt index 556f3ab2..efdb4b7d 100644 --- a/app/src/main/java/com/imashnake/animite/features/home/Home.kt +++ b/app/src/main/java/com/imashnake/animite/features/home/Home.kt @@ -51,7 +51,7 @@ import com.imashnake.animite.core.extensions.bannerParallax import com.imashnake.animite.core.extensions.landscapeCutoutPadding import com.imashnake.animite.core.ui.ProgressIndicator import com.imashnake.animite.core.ui.TranslucentStatusBarLayout -import com.imashnake.animite.data.Resource +import com.imashnake.animite.core.data.Resource import com.imashnake.animite.features.destinations.MediaPageDestination import com.imashnake.animite.features.media.MediaPageArgs import com.imashnake.animite.features.ui.MediaSmall diff --git a/app/src/main/java/com/imashnake/animite/features/home/HomeViewModel.kt b/app/src/main/java/com/imashnake/animite/features/home/HomeViewModel.kt index 8ceb7a1e..463e2123 100644 --- a/app/src/main/java/com/imashnake/animite/features/home/HomeViewModel.kt +++ b/app/src/main/java/com/imashnake/animite/features/home/HomeViewModel.kt @@ -6,8 +6,8 @@ import androidx.lifecycle.viewModelScope import com.imashnake.animite.api.anilist.AnilistMediaRepository import com.imashnake.animite.api.anilist.type.MediaSort import com.imashnake.animite.api.anilist.type.MediaType -import com.imashnake.animite.data.Resource -import com.imashnake.animite.data.Resource.Companion.asResource +import com.imashnake.animite.core.data.Resource +import com.imashnake.animite.core.data.Resource.Companion.asResource import com.imashnake.animite.dev.ext.nextSeason import com.imashnake.animite.dev.ext.season import com.imashnake.animite.dev.internal.Constants diff --git a/app/src/main/java/com/imashnake/animite/features/searchbar/SearchViewModel.kt b/app/src/main/java/com/imashnake/animite/features/searchbar/SearchViewModel.kt index b328cf7b..0a77f773 100644 --- a/app/src/main/java/com/imashnake/animite/features/searchbar/SearchViewModel.kt +++ b/app/src/main/java/com/imashnake/animite/features/searchbar/SearchViewModel.kt @@ -5,8 +5,8 @@ import androidx.lifecycle.ViewModel import androidx.lifecycle.viewModelScope import com.imashnake.animite.api.anilist.AnilistSearchRepository import com.imashnake.animite.api.anilist.type.MediaType -import com.imashnake.animite.data.Resource -import com.imashnake.animite.data.Resource.Companion.asResource +import com.imashnake.animite.core.data.Resource +import com.imashnake.animite.core.data.Resource.Companion.asResource import com.imashnake.animite.dev.internal.Constants import dagger.hilt.android.lifecycle.HiltViewModel import kotlinx.coroutines.ExperimentalCoroutinesApi diff --git a/app/src/main/java/com/imashnake/animite/data/Resource.kt b/core/src/main/kotlin/com/imashnake/animite/core/data/Resource.kt similarity index 97% rename from app/src/main/java/com/imashnake/animite/data/Resource.kt rename to core/src/main/kotlin/com/imashnake/animite/core/data/Resource.kt index ff9e8c00..784cbbeb 100644 --- a/app/src/main/java/com/imashnake/animite/data/Resource.kt +++ b/core/src/main/kotlin/com/imashnake/animite/core/data/Resource.kt @@ -1,4 +1,4 @@ -package com.imashnake.animite.data +package com.imashnake.animite.core.data import kotlinx.coroutines.ExperimentalCoroutinesApi import kotlinx.coroutines.flow.Flow From d9f9b55f0f6f83967eacdd9ea3f4f3e0ccc1d98a Mon Sep 17 00:00:00 2001 From: Kamalesh Reddy Paluru Date: Sun, 7 Jan 2024 14:10:36 -0500 Subject: [PATCH 08/30] Add Hilt --- profile/build.gradle.kts | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/profile/build.gradle.kts b/profile/build.gradle.kts index 389d1d69..3f4f803f 100644 --- a/profile/build.gradle.kts +++ b/profile/build.gradle.kts @@ -44,6 +44,7 @@ ksp { dependencies { implementation(project(":core")) + implementation(project(":api:preferences")) // AndroidX implementation(libs.androidx.activityCompose) @@ -64,6 +65,11 @@ dependencies { implementation(libs.kotlin.coroutines.android) implementation(libs.kotlin.coroutines.core) + // Hilt + implementation(libs.hilt.android) + implementation(libs.hilt.navigationCompose) + ksp(libs.hilt.android.compiler) + // Compose Destinations implementation(libs.compose.destinations) ksp(libs.compose.destinations.ksp) From 52b3090f639ede48b6a7ac4b803d8e737da25643 Mon Sep 17 00:00:00 2001 From: Kamalesh Reddy Paluru Date: Sun, 7 Jan 2024 14:10:47 -0500 Subject: [PATCH 09/30] Fix URL --- .../com/imashnake/animite/profile/dev/internal/Constants.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/profile/src/main/kotlin/com/imashnake/animite/profile/dev/internal/Constants.kt b/profile/src/main/kotlin/com/imashnake/animite/profile/dev/internal/Constants.kt index d1afe51f..b7124610 100644 --- a/profile/src/main/kotlin/com/imashnake/animite/profile/dev/internal/Constants.kt +++ b/profile/src/main/kotlin/com/imashnake/animite/profile/dev/internal/Constants.kt @@ -3,4 +3,4 @@ package com.imashnake.animite.profile.dev.internal import com.imashnake.animite.profile.BuildConfig const val ANILIST_AUTH_DEEPLINK = "jinnah://animite#access_token={accessToken}&token_type=Bearer&expires_in=31622400" -const val ANILIST_AUTH_URL = "https://anilist.co/api/v2/oauth/authorize?client_id={${BuildConfig.CLIENT_ID}}&response_type=token" +const val ANILIST_AUTH_URL = "https://anilist.co/api/v2/oauth/authorize?client_id=${BuildConfig.CLIENT_ID}&response_type=token" From 8dc5f5efb8f587c219ab13400417a7cb6006334f Mon Sep 17 00:00:00 2001 From: Kamalesh Reddy Paluru Date: Sun, 7 Jan 2024 16:06:51 -0500 Subject: [PATCH 10/30] Saved access token to DataStore --- .../api/preferences/PreferencesRepository.kt | 12 +++++-- .../api/preferences/ext/DataStoreExt.kt | 21 ++++++++++++ .../animite/profile/ProfileScreen.kt | 34 ++++++------------- .../animite/profile/ProfileViewModel.kt | 25 ++++++++++++++ 4 files changed, 67 insertions(+), 25 deletions(-) create mode 100644 api/preferences/src/main/kotlin/com/imashnake/animite/api/preferences/ext/DataStoreExt.kt create mode 100644 profile/src/main/kotlin/com/imashnake/animite/profile/ProfileViewModel.kt diff --git a/api/preferences/src/main/kotlin/com/imashnake/animite/api/preferences/PreferencesRepository.kt b/api/preferences/src/main/kotlin/com/imashnake/animite/api/preferences/PreferencesRepository.kt index bf0bfcda..8006935e 100644 --- a/api/preferences/src/main/kotlin/com/imashnake/animite/api/preferences/PreferencesRepository.kt +++ b/api/preferences/src/main/kotlin/com/imashnake/animite/api/preferences/PreferencesRepository.kt @@ -3,11 +3,19 @@ package com.imashnake.animite.api.preferences import androidx.datastore.core.DataStore import androidx.datastore.preferences.core.Preferences import androidx.datastore.preferences.core.stringPreferencesKey -import kotlinx.coroutines.flow.map +import com.imashnake.animite.api.preferences.ext.getValue +import com.imashnake.animite.api.preferences.ext.setValue import javax.inject.Inject +private const val ACCESS_TOKEN = "access_token" + class PreferencesRepository @Inject constructor( private val dataStore: DataStore ) { - val accessToken = dataStore.data.map { it[stringPreferencesKey("access_token")] } + private val accessTokenKey = stringPreferencesKey(ACCESS_TOKEN) + val accessToken = dataStore.getValue(accessTokenKey, null) + + suspend fun setAccessToken(accessToken: String?) { + dataStore.setValue(accessTokenKey, accessToken) + } } diff --git a/api/preferences/src/main/kotlin/com/imashnake/animite/api/preferences/ext/DataStoreExt.kt b/api/preferences/src/main/kotlin/com/imashnake/animite/api/preferences/ext/DataStoreExt.kt new file mode 100644 index 00000000..c20beb45 --- /dev/null +++ b/api/preferences/src/main/kotlin/com/imashnake/animite/api/preferences/ext/DataStoreExt.kt @@ -0,0 +1,21 @@ +package com.imashnake.animite.api.preferences.ext + +import androidx.datastore.core.DataStore +import androidx.datastore.preferences.core.Preferences +import androidx.datastore.preferences.core.edit +import kotlinx.coroutines.flow.map + +fun DataStore.getValue( + key: Preferences.Key, + default: T? = null +) = data.map { + it[key] ?: default +} + +suspend fun DataStore.setValue( + key: Preferences.Key, + value: T? +) = edit { + if (value != null) it[key] = value + else it.remove(key) +} diff --git a/profile/src/main/kotlin/com/imashnake/animite/profile/ProfileScreen.kt b/profile/src/main/kotlin/com/imashnake/animite/profile/ProfileScreen.kt index 5fc23f0f..b9981d41 100644 --- a/profile/src/main/kotlin/com/imashnake/animite/profile/ProfileScreen.kt +++ b/profile/src/main/kotlin/com/imashnake/animite/profile/ProfileScreen.kt @@ -1,28 +1,23 @@ package com.imashnake.animite.profile import androidx.compose.foundation.background -import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.Box -import androidx.compose.foundation.layout.Column -import androidx.compose.foundation.layout.Spacer import androidx.compose.foundation.layout.fillMaxSize -import androidx.compose.foundation.layout.size import androidx.compose.material3.Button import androidx.compose.material3.MaterialTheme import androidx.compose.material3.Text import androidx.compose.runtime.Composable +import androidx.compose.runtime.collectAsState +import androidx.compose.runtime.getValue import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.platform.LocalUriHandler -import androidx.compose.ui.res.stringResource -import com.imashnake.animite.core.ui.LocalPaddings -import com.imashnake.animite.core.ui.ProgressIndicator +import androidx.hilt.navigation.compose.hiltViewModel import com.imashnake.animite.profile.dev.internal.ANILIST_AUTH_DEEPLINK import com.imashnake.animite.profile.dev.internal.ANILIST_AUTH_URL import com.ramcosta.composedestinations.annotation.DeepLink import com.ramcosta.composedestinations.annotation.Destination import com.ramcosta.composedestinations.annotation.RootNavGraph -import com.imashnake.animite.core.R as coreR @Destination( route = "user", @@ -35,33 +30,26 @@ import com.imashnake.animite.core.R as coreR @RootNavGraph(start = true) @Composable fun ProfileScreen( + viewModel: ProfileViewModel = hiltViewModel(), accessToken: String? = null ) { + accessToken?.let { viewModel.setAccessToken(it) } + val actualAccessToken by viewModel.accessToken.collectAsState() + Box( contentAlignment = Alignment.Center, modifier = Modifier .fillMaxSize() .background(MaterialTheme.colorScheme.background) ) { - Column( - horizontalAlignment = Alignment.CenterHorizontally, - verticalArrangement = Arrangement.spacedBy( - LocalPaddings.current.tiny - ) - ) { - val uriHandler = LocalUriHandler.current - Text( - text = stringResource(coreR.string.coming_soon), - color = MaterialTheme.colorScheme.onSurfaceVariant, - style = MaterialTheme.typography.labelLarge - ) - ProgressIndicator() - - Spacer(modifier = Modifier.size(LocalPaddings.current.large)) + val uriHandler = LocalUriHandler.current + if (actualAccessToken == null) { Button(onClick = { uriHandler.openUri(ANILIST_AUTH_URL) }) { Text(text = "Log in") } + } else { + Text(text = "Saved access token!") } } } diff --git a/profile/src/main/kotlin/com/imashnake/animite/profile/ProfileViewModel.kt b/profile/src/main/kotlin/com/imashnake/animite/profile/ProfileViewModel.kt new file mode 100644 index 00000000..296d7bd2 --- /dev/null +++ b/profile/src/main/kotlin/com/imashnake/animite/profile/ProfileViewModel.kt @@ -0,0 +1,25 @@ +package com.imashnake.animite.profile + +import androidx.lifecycle.ViewModel +import androidx.lifecycle.viewModelScope +import com.imashnake.animite.api.preferences.PreferencesRepository +import com.imashnake.animite.core.data.Resource +import dagger.hilt.android.lifecycle.HiltViewModel +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.flow.SharingStarted +import kotlinx.coroutines.flow.stateIn +import kotlinx.coroutines.launch +import javax.inject.Inject + +@HiltViewModel +class ProfileViewModel @Inject constructor( + private val preferencesRepository: PreferencesRepository +) : ViewModel() { + fun setAccessToken(accessToken: String?) = viewModelScope.launch(Dispatchers.IO) { + preferencesRepository.setAccessToken(accessToken) + } + + val accessToken = preferencesRepository + .accessToken + .stateIn(viewModelScope, SharingStarted.WhileSubscribed(1000), Resource.loading()) +} From 1ee020bd45253b1c08198cb2de87189f480fe8fd Mon Sep 17 00:00:00 2001 From: Kamalesh Reddy Paluru Date: Sun, 7 Jan 2024 17:01:43 -0500 Subject: [PATCH 11/30] Added interceptor --- api/anilist/build.gradle.kts | 2 ++ .../animite/api/anilist/AnilistApiModule.kt | 21 ++++++++++++++++++- api/preferences/build.gradle.kts | 2 ++ .../api/preferences/DataStoreModule.kt | 7 +++++++ .../imashnake/animite/core/GlobalVariables.kt | 5 +++++ .../animite/profile/ProfileViewModel.kt | 14 ++++++++++++- 6 files changed, 49 insertions(+), 2 deletions(-) create mode 100644 core/src/main/kotlin/com/imashnake/animite/core/GlobalVariables.kt diff --git a/api/anilist/build.gradle.kts b/api/anilist/build.gradle.kts index 8feab45a..bd7738ab 100644 --- a/api/anilist/build.gradle.kts +++ b/api/anilist/build.gradle.kts @@ -28,6 +28,8 @@ kotlin { } dependencies { + implementation(project(":core")) + // Apollo Kotlin implementation(libs.apollo.runtime) implementation(libs.apollo.cache.memory) diff --git a/api/anilist/src/main/kotlin/com/imashnake/animite/api/anilist/AnilistApiModule.kt b/api/anilist/src/main/kotlin/com/imashnake/animite/api/anilist/AnilistApiModule.kt index 76eae2b9..6f8e9002 100644 --- a/api/anilist/src/main/kotlin/com/imashnake/animite/api/anilist/AnilistApiModule.kt +++ b/api/anilist/src/main/kotlin/com/imashnake/animite/api/anilist/AnilistApiModule.kt @@ -2,10 +2,15 @@ package com.imashnake.animite.api.anilist import android.content.Context import com.apollographql.apollo3.ApolloClient +import com.apollographql.apollo3.api.http.HttpRequest +import com.apollographql.apollo3.api.http.HttpResponse import com.apollographql.apollo3.cache.normalized.api.MemoryCacheFactory import com.apollographql.apollo3.cache.normalized.normalizedCache import com.apollographql.apollo3.cache.normalized.sql.SqlNormalizedCacheFactory +import com.apollographql.apollo3.network.http.HttpInterceptor +import com.apollographql.apollo3.network.http.HttpInterceptorChain import com.apollographql.apollo3.network.http.LoggingInterceptor +import com.imashnake.animite.core.GlobalVariables import dagger.Module import dagger.Provides import dagger.hilt.InstallIn @@ -22,7 +27,8 @@ object AnilistApiModule { @Provides @Singleton fun provideApolloClient( - @ApplicationContext context: Context + @ApplicationContext context: Context, + globalVariables: GlobalVariables ): ApolloClient { // Cache is hit in order, so check in-memory -> check sqlite // We have an in-memory cache first for speed, then a SQLite cache for persistence. @@ -31,8 +37,21 @@ object AnilistApiModule { return ApolloClient.Builder() .dispatcher(Dispatchers.IO) .serverUrl("https://graphql.anilist.co/") + .addHttpInterceptor(AuthorizationInterceptor(globalVariables.accessToken)) .addHttpInterceptor(LoggingInterceptor(LoggingInterceptor.Level.BODY)) .normalizedCache(cacheFactory) .build() } + + class AuthorizationInterceptor(private val token: String?) : HttpInterceptor { + override suspend fun intercept(request: HttpRequest, chain: HttpInterceptorChain): HttpResponse { + return chain.proceed( + request.newBuilder().apply { + token?.let { + addHeader("Authorization", "Bearer $it") + } + }.build() + ) + } + } } diff --git a/api/preferences/build.gradle.kts b/api/preferences/build.gradle.kts index e4ff4d44..ffefe59f 100644 --- a/api/preferences/build.gradle.kts +++ b/api/preferences/build.gradle.kts @@ -25,6 +25,8 @@ kotlin { } dependencies { + implementation(project(":core")) + // Hilt implementation(libs.hilt.android) implementation(libs.hilt.navigationCompose) diff --git a/api/preferences/src/main/kotlin/com/imashnake/animite/api/preferences/DataStoreModule.kt b/api/preferences/src/main/kotlin/com/imashnake/animite/api/preferences/DataStoreModule.kt index 6d763089..61f7a497 100644 --- a/api/preferences/src/main/kotlin/com/imashnake/animite/api/preferences/DataStoreModule.kt +++ b/api/preferences/src/main/kotlin/com/imashnake/animite/api/preferences/DataStoreModule.kt @@ -5,6 +5,7 @@ import androidx.datastore.core.DataStore import androidx.datastore.preferences.core.PreferenceDataStoreFactory import androidx.datastore.preferences.core.Preferences import androidx.datastore.preferences.preferencesDataStoreFile +import com.imashnake.animite.core.GlobalVariables import dagger.Module import dagger.Provides import dagger.hilt.InstallIn @@ -22,4 +23,10 @@ object DataStoreModule { produceFile = { appContext.preferencesDataStoreFile("default") } ) } + + @Singleton + @Provides + fun provideGlobalVariables(): GlobalVariables { + return GlobalVariables() + } } diff --git a/core/src/main/kotlin/com/imashnake/animite/core/GlobalVariables.kt b/core/src/main/kotlin/com/imashnake/animite/core/GlobalVariables.kt new file mode 100644 index 00000000..f022f864 --- /dev/null +++ b/core/src/main/kotlin/com/imashnake/animite/core/GlobalVariables.kt @@ -0,0 +1,5 @@ +package com.imashnake.animite.core + +class GlobalVariables { + var accessToken: String? = null +} diff --git a/profile/src/main/kotlin/com/imashnake/animite/profile/ProfileViewModel.kt b/profile/src/main/kotlin/com/imashnake/animite/profile/ProfileViewModel.kt index 296d7bd2..0003cc31 100644 --- a/profile/src/main/kotlin/com/imashnake/animite/profile/ProfileViewModel.kt +++ b/profile/src/main/kotlin/com/imashnake/animite/profile/ProfileViewModel.kt @@ -3,17 +3,23 @@ package com.imashnake.animite.profile import androidx.lifecycle.ViewModel import androidx.lifecycle.viewModelScope import com.imashnake.animite.api.preferences.PreferencesRepository +import com.imashnake.animite.core.GlobalVariables import com.imashnake.animite.core.data.Resource import dagger.hilt.android.lifecycle.HiltViewModel import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.flow.SharingStarted +import kotlinx.coroutines.flow.launchIn +import kotlinx.coroutines.flow.map +import kotlinx.coroutines.flow.onEach +import kotlinx.coroutines.flow.single import kotlinx.coroutines.flow.stateIn import kotlinx.coroutines.launch import javax.inject.Inject @HiltViewModel class ProfileViewModel @Inject constructor( - private val preferencesRepository: PreferencesRepository + private val preferencesRepository: PreferencesRepository, + private val globalVariables: GlobalVariables, ) : ViewModel() { fun setAccessToken(accessToken: String?) = viewModelScope.launch(Dispatchers.IO) { preferencesRepository.setAccessToken(accessToken) @@ -22,4 +28,10 @@ class ProfileViewModel @Inject constructor( val accessToken = preferencesRepository .accessToken .stateIn(viewModelScope, SharingStarted.WhileSubscribed(1000), Resource.loading()) + + init { + preferencesRepository.accessToken.onEach { + globalVariables.accessToken = it + }.launchIn(viewModelScope) + } } From ca02677d5085a722525a22927cfa61b961e2a32c Mon Sep 17 00:00:00 2001 From: Kamalesh Reddy Paluru Date: Sun, 7 Jan 2024 17:05:08 -0500 Subject: [PATCH 12/30] Cleanup --- .../kotlin/com/imashnake/animite/profile/ProfileViewModel.kt | 2 -- 1 file changed, 2 deletions(-) diff --git a/profile/src/main/kotlin/com/imashnake/animite/profile/ProfileViewModel.kt b/profile/src/main/kotlin/com/imashnake/animite/profile/ProfileViewModel.kt index 0003cc31..76cab394 100644 --- a/profile/src/main/kotlin/com/imashnake/animite/profile/ProfileViewModel.kt +++ b/profile/src/main/kotlin/com/imashnake/animite/profile/ProfileViewModel.kt @@ -9,9 +9,7 @@ import dagger.hilt.android.lifecycle.HiltViewModel import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.flow.SharingStarted import kotlinx.coroutines.flow.launchIn -import kotlinx.coroutines.flow.map import kotlinx.coroutines.flow.onEach -import kotlinx.coroutines.flow.single import kotlinx.coroutines.flow.stateIn import kotlinx.coroutines.launch import javax.inject.Inject From 207a679572fbc3c98ccdde3a9f206262c328f878 Mon Sep 17 00:00:00 2001 From: Kamalesh Reddy Paluru Date: Mon, 8 Jan 2024 01:12:08 -0500 Subject: [PATCH 13/30] Added UserQuery --- .../src/main/graphql/MediaQuery.graphql | 2 +- .../src/main/graphql/UserQuery.graphql | 24 +++++++++++++++++++ .../api/anilist/AnilistUserRepository.kt | 18 ++++++++++++++ profile/build.gradle.kts | 1 + .../animite/profile/ProfileScreen.kt | 18 +++++++++++++- .../animite/profile/ProfileViewModel.kt | 8 +++++++ 6 files changed, 69 insertions(+), 2 deletions(-) create mode 100644 api/anilist/src/main/graphql/UserQuery.graphql create mode 100644 api/anilist/src/main/kotlin/com/imashnake/animite/api/anilist/AnilistUserRepository.kt diff --git a/api/anilist/src/main/graphql/MediaQuery.graphql b/api/anilist/src/main/graphql/MediaQuery.graphql index 29b2ee75..639d23bb 100644 --- a/api/anilist/src/main/graphql/MediaQuery.graphql +++ b/api/anilist/src/main/graphql/MediaQuery.graphql @@ -2,7 +2,7 @@ query MediaQuery( $id: Int, $type: MediaType ) { - media: Media (id: $id, type: $type) { + media: Media(id: $id, type: $type) { bannerImage coverImage { extraLarge diff --git a/api/anilist/src/main/graphql/UserQuery.graphql b/api/anilist/src/main/graphql/UserQuery.graphql new file mode 100644 index 00000000..f660416b --- /dev/null +++ b/api/anilist/src/main/graphql/UserQuery.graphql @@ -0,0 +1,24 @@ +query UserQuery { +# TODO: Get this to work. +# viewer: Viewer { +# id +# name +# about +# avatar { +# large +# } +# bannerImage +# } + # TODO: Make `name` a parameter. + user: User( + name: "imashnake0" + ) { + id + name + about + avatar { + large + } + bannerImage + } +} diff --git a/api/anilist/src/main/kotlin/com/imashnake/animite/api/anilist/AnilistUserRepository.kt b/api/anilist/src/main/kotlin/com/imashnake/animite/api/anilist/AnilistUserRepository.kt new file mode 100644 index 00000000..4e6c94ee --- /dev/null +++ b/api/anilist/src/main/kotlin/com/imashnake/animite/api/anilist/AnilistUserRepository.kt @@ -0,0 +1,18 @@ +package com.imashnake.animite.api.anilist + +import com.apollographql.apollo3.ApolloClient +import com.apollographql.apollo3.cache.normalized.FetchPolicy +import com.apollographql.apollo3.cache.normalized.fetchPolicy +import kotlinx.coroutines.flow.Flow +import javax.inject.Inject + +class AnilistUserRepository @Inject constructor( + private val apolloClient: ApolloClient +) { + fun fetchViewer(): Flow> { + return apolloClient + .query(UserQuery()) + .fetchPolicy(FetchPolicy.CacheAndNetwork).toFlow() + .asResult { it.user } + } +} diff --git a/profile/build.gradle.kts b/profile/build.gradle.kts index 3f4f803f..5ebba8ff 100644 --- a/profile/build.gradle.kts +++ b/profile/build.gradle.kts @@ -44,6 +44,7 @@ ksp { dependencies { implementation(project(":core")) + implementation(project(":api:anilist")) implementation(project(":api:preferences")) // AndroidX diff --git a/profile/src/main/kotlin/com/imashnake/animite/profile/ProfileScreen.kt b/profile/src/main/kotlin/com/imashnake/animite/profile/ProfileScreen.kt index b9981d41..942e519e 100644 --- a/profile/src/main/kotlin/com/imashnake/animite/profile/ProfileScreen.kt +++ b/profile/src/main/kotlin/com/imashnake/animite/profile/ProfileScreen.kt @@ -1,8 +1,11 @@ package com.imashnake.animite.profile +import android.util.Log import androidx.compose.foundation.background import androidx.compose.foundation.layout.Box +import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.fillMaxSize +import androidx.compose.foundation.layout.padding import androidx.compose.material3.Button import androidx.compose.material3.MaterialTheme import androidx.compose.material3.Text @@ -12,7 +15,9 @@ import androidx.compose.runtime.getValue import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.platform.LocalUriHandler +import androidx.compose.ui.res.dimensionResource import androidx.hilt.navigation.compose.hiltViewModel +import com.imashnake.animite.core.ui.LocalPaddings import com.imashnake.animite.profile.dev.internal.ANILIST_AUTH_DEEPLINK import com.imashnake.animite.profile.dev.internal.ANILIST_AUTH_URL import com.ramcosta.composedestinations.annotation.DeepLink @@ -35,6 +40,7 @@ fun ProfileScreen( ) { accessToken?.let { viewModel.setAccessToken(it) } val actualAccessToken by viewModel.accessToken.collectAsState() + val viewer by viewModel.viewer.collectAsState() Box( contentAlignment = Alignment.Center, @@ -49,7 +55,17 @@ fun ProfileScreen( Text(text = "Log in") } } else { - Text(text = "Saved access token!") + viewer.data?.let { viewer -> + with(viewer) { + Column(Modifier.padding(LocalPaddings.current.large)) { + Text(text = "ID: $id") + Text(text = "Name: $name") + about?.let { Text(text = "About: $it") } + avatar?.large?.let { Text(text = "Avatar: $it") } + bannerImage?.let { Text(text = "Banner Image: $it") } + } + } + } } } } diff --git a/profile/src/main/kotlin/com/imashnake/animite/profile/ProfileViewModel.kt b/profile/src/main/kotlin/com/imashnake/animite/profile/ProfileViewModel.kt index 76cab394..63f8813e 100644 --- a/profile/src/main/kotlin/com/imashnake/animite/profile/ProfileViewModel.kt +++ b/profile/src/main/kotlin/com/imashnake/animite/profile/ProfileViewModel.kt @@ -2,9 +2,11 @@ package com.imashnake.animite.profile import androidx.lifecycle.ViewModel import androidx.lifecycle.viewModelScope +import com.imashnake.animite.api.anilist.AnilistUserRepository import com.imashnake.animite.api.preferences.PreferencesRepository import com.imashnake.animite.core.GlobalVariables import com.imashnake.animite.core.data.Resource +import com.imashnake.animite.core.data.Resource.Companion.asResource import dagger.hilt.android.lifecycle.HiltViewModel import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.flow.SharingStarted @@ -16,6 +18,7 @@ import javax.inject.Inject @HiltViewModel class ProfileViewModel @Inject constructor( + userRepository: AnilistUserRepository, private val preferencesRepository: PreferencesRepository, private val globalVariables: GlobalVariables, ) : ViewModel() { @@ -27,6 +30,11 @@ class ProfileViewModel @Inject constructor( .accessToken .stateIn(viewModelScope, SharingStarted.WhileSubscribed(1000), Resource.loading()) + val viewer = userRepository + .fetchViewer() + .asResource() + .stateIn(viewModelScope, SharingStarted.WhileSubscribed(1000), Resource.loading()) + init { preferencesRepository.accessToken.onEach { globalVariables.accessToken = it From 99b0cbac4d7111e57651913355ac5603f1b1c0fb Mon Sep 17 00:00:00 2001 From: Kamalesh Reddy Paluru Date: Mon, 8 Jan 2024 01:12:29 -0500 Subject: [PATCH 14/30] Cleanup --- .../main/kotlin/com/imashnake/animite/profile/ProfileScreen.kt | 2 -- 1 file changed, 2 deletions(-) diff --git a/profile/src/main/kotlin/com/imashnake/animite/profile/ProfileScreen.kt b/profile/src/main/kotlin/com/imashnake/animite/profile/ProfileScreen.kt index 942e519e..c30627cd 100644 --- a/profile/src/main/kotlin/com/imashnake/animite/profile/ProfileScreen.kt +++ b/profile/src/main/kotlin/com/imashnake/animite/profile/ProfileScreen.kt @@ -1,6 +1,5 @@ package com.imashnake.animite.profile -import android.util.Log import androidx.compose.foundation.background import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.Column @@ -15,7 +14,6 @@ import androidx.compose.runtime.getValue import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.platform.LocalUriHandler -import androidx.compose.ui.res.dimensionResource import androidx.hilt.navigation.compose.hiltViewModel import com.imashnake.animite.core.ui.LocalPaddings import com.imashnake.animite.profile.dev.internal.ANILIST_AUTH_DEEPLINK From 2ae64b2ef8f19b23893f6bf5fc474c918374ffd9 Mon Sep 17 00:00:00 2001 From: Kamalesh Reddy Paluru Date: Mon, 8 Jan 2024 01:48:03 -0500 Subject: [PATCH 15/30] Injected `authorizationInterceptor` --- .../src/main/graphql/UserQuery.graphql | 37 ++++++++++++------- .../animite/api/anilist/AnilistApiModule.kt | 23 +++++++++--- .../api/anilist/AnilistUserRepository.kt | 6 +-- 3 files changed, 45 insertions(+), 21 deletions(-) diff --git a/api/anilist/src/main/graphql/UserQuery.graphql b/api/anilist/src/main/graphql/UserQuery.graphql index f660416b..6706ea38 100644 --- a/api/anilist/src/main/graphql/UserQuery.graphql +++ b/api/anilist/src/main/graphql/UserQuery.graphql @@ -1,17 +1,16 @@ -query UserQuery { -# TODO: Get this to work. -# viewer: Viewer { -# id -# name -# about -# avatar { -# large -# } -# bannerImage -# } - # TODO: Make `name` a parameter. +query UserQuery( + $id: Int, + $name: String, + $isModerator: Boolean, + $search: String, + $sort: [UserSort], +) { user: User( - name: "imashnake0" + id: $id, + name: $name + isModerator: $isModerator + search: $search + sort: $sort ) { id name @@ -22,3 +21,15 @@ query UserQuery { bannerImage } } + +query Viewer { + viewer: Viewer { + id + name + about + avatar { + large + } + bannerImage + } +} diff --git a/api/anilist/src/main/kotlin/com/imashnake/animite/api/anilist/AnilistApiModule.kt b/api/anilist/src/main/kotlin/com/imashnake/animite/api/anilist/AnilistApiModule.kt index 6f8e9002..f65f28cf 100644 --- a/api/anilist/src/main/kotlin/com/imashnake/animite/api/anilist/AnilistApiModule.kt +++ b/api/anilist/src/main/kotlin/com/imashnake/animite/api/anilist/AnilistApiModule.kt @@ -28,7 +28,7 @@ object AnilistApiModule { @Singleton fun provideApolloClient( @ApplicationContext context: Context, - globalVariables: GlobalVariables + authorizationInterceptor: AuthorizationInterceptor ): ApolloClient { // Cache is hit in order, so check in-memory -> check sqlite // We have an in-memory cache first for speed, then a SQLite cache for persistence. @@ -37,21 +37,34 @@ object AnilistApiModule { return ApolloClient.Builder() .dispatcher(Dispatchers.IO) .serverUrl("https://graphql.anilist.co/") - .addHttpInterceptor(AuthorizationInterceptor(globalVariables.accessToken)) + .addHttpInterceptor(authorizationInterceptor) .addHttpInterceptor(LoggingInterceptor(LoggingInterceptor.Level.BODY)) .normalizedCache(cacheFactory) .build() } - class AuthorizationInterceptor(private val token: String?) : HttpInterceptor { - override suspend fun intercept(request: HttpRequest, chain: HttpInterceptorChain): HttpResponse { + class AuthorizationInterceptor( + private val globalVariables: GlobalVariables, + ) : HttpInterceptor { + override suspend fun intercept( + request: HttpRequest, + chain: HttpInterceptorChain + ): HttpResponse { return chain.proceed( request.newBuilder().apply { - token?.let { + globalVariables.accessToken?.let { addHeader("Authorization", "Bearer $it") } }.build() ) } } + + @Singleton + @Provides + fun provideAuthorizationInterceptor( + globalVariables: GlobalVariables + ): AuthorizationInterceptor { + return AuthorizationInterceptor(globalVariables) + } } diff --git a/api/anilist/src/main/kotlin/com/imashnake/animite/api/anilist/AnilistUserRepository.kt b/api/anilist/src/main/kotlin/com/imashnake/animite/api/anilist/AnilistUserRepository.kt index 4e6c94ee..d21165bd 100644 --- a/api/anilist/src/main/kotlin/com/imashnake/animite/api/anilist/AnilistUserRepository.kt +++ b/api/anilist/src/main/kotlin/com/imashnake/animite/api/anilist/AnilistUserRepository.kt @@ -9,10 +9,10 @@ import javax.inject.Inject class AnilistUserRepository @Inject constructor( private val apolloClient: ApolloClient ) { - fun fetchViewer(): Flow> { + fun fetchViewer(): Flow> { return apolloClient - .query(UserQuery()) + .query(ViewerQuery()) .fetchPolicy(FetchPolicy.CacheAndNetwork).toFlow() - .asResult { it.user } + .asResult { it.viewer } } } From 83dc508f5df96239661c05f662280a4190d9fd48 Mon Sep 17 00:00:00 2001 From: imashnake0 Date: Wed, 10 Jan 2024 05:25:03 -0500 Subject: [PATCH 16/30] Remove intermediate class --- .../animite/api/anilist/AnilistApiModule.kt | 20 +++++++------------ 1 file changed, 7 insertions(+), 13 deletions(-) diff --git a/api/anilist/src/main/kotlin/com/imashnake/animite/api/anilist/AnilistApiModule.kt b/api/anilist/src/main/kotlin/com/imashnake/animite/api/anilist/AnilistApiModule.kt index f65f28cf..f7af16ee 100644 --- a/api/anilist/src/main/kotlin/com/imashnake/animite/api/anilist/AnilistApiModule.kt +++ b/api/anilist/src/main/kotlin/com/imashnake/animite/api/anilist/AnilistApiModule.kt @@ -28,7 +28,7 @@ object AnilistApiModule { @Singleton fun provideApolloClient( @ApplicationContext context: Context, - authorizationInterceptor: AuthorizationInterceptor + httpInterceptor: HttpInterceptor ): ApolloClient { // Cache is hit in order, so check in-memory -> check sqlite // We have an in-memory cache first for speed, then a SQLite cache for persistence. @@ -37,15 +37,17 @@ object AnilistApiModule { return ApolloClient.Builder() .dispatcher(Dispatchers.IO) .serverUrl("https://graphql.anilist.co/") - .addHttpInterceptor(authorizationInterceptor) + .addHttpInterceptor(httpInterceptor) .addHttpInterceptor(LoggingInterceptor(LoggingInterceptor.Level.BODY)) .normalizedCache(cacheFactory) .build() } - class AuthorizationInterceptor( - private val globalVariables: GlobalVariables, - ) : HttpInterceptor { + @Singleton + @Provides + fun provideHttpInterceptor( + globalVariables: GlobalVariables + ): HttpInterceptor = object : HttpInterceptor { override suspend fun intercept( request: HttpRequest, chain: HttpInterceptorChain @@ -59,12 +61,4 @@ object AnilistApiModule { ) } } - - @Singleton - @Provides - fun provideAuthorizationInterceptor( - globalVariables: GlobalVariables - ): AuthorizationInterceptor { - return AuthorizationInterceptor(globalVariables) - } } From fe95cccf11bd54aa71beb88741a80c23496d00c2 Mon Sep 17 00:00:00 2001 From: imashnake0 Date: Sat, 13 Jan 2024 21:01:08 -0500 Subject: [PATCH 17/30] Stop exposing access token --- .../kotlin/com/imashnake/animite/profile/ProfileScreen.kt | 4 ++-- .../kotlin/com/imashnake/animite/profile/ProfileViewModel.kt | 5 +++-- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/profile/src/main/kotlin/com/imashnake/animite/profile/ProfileScreen.kt b/profile/src/main/kotlin/com/imashnake/animite/profile/ProfileScreen.kt index c30627cd..3d3f9258 100644 --- a/profile/src/main/kotlin/com/imashnake/animite/profile/ProfileScreen.kt +++ b/profile/src/main/kotlin/com/imashnake/animite/profile/ProfileScreen.kt @@ -37,7 +37,7 @@ fun ProfileScreen( accessToken: String? = null ) { accessToken?.let { viewModel.setAccessToken(it) } - val actualAccessToken by viewModel.accessToken.collectAsState() + val isLoggedIn by viewModel.isLoggedIn.collectAsState(initial = false) val viewer by viewModel.viewer.collectAsState() Box( @@ -48,7 +48,7 @@ fun ProfileScreen( ) { val uriHandler = LocalUriHandler.current - if (actualAccessToken == null) { + if (!isLoggedIn) { Button(onClick = { uriHandler.openUri(ANILIST_AUTH_URL) }) { Text(text = "Log in") } diff --git a/profile/src/main/kotlin/com/imashnake/animite/profile/ProfileViewModel.kt b/profile/src/main/kotlin/com/imashnake/animite/profile/ProfileViewModel.kt index 63f8813e..c7d3a267 100644 --- a/profile/src/main/kotlin/com/imashnake/animite/profile/ProfileViewModel.kt +++ b/profile/src/main/kotlin/com/imashnake/animite/profile/ProfileViewModel.kt @@ -11,6 +11,7 @@ import dagger.hilt.android.lifecycle.HiltViewModel import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.flow.SharingStarted import kotlinx.coroutines.flow.launchIn +import kotlinx.coroutines.flow.map import kotlinx.coroutines.flow.onEach import kotlinx.coroutines.flow.stateIn import kotlinx.coroutines.launch @@ -26,9 +27,9 @@ class ProfileViewModel @Inject constructor( preferencesRepository.setAccessToken(accessToken) } - val accessToken = preferencesRepository + val isLoggedIn = preferencesRepository .accessToken - .stateIn(viewModelScope, SharingStarted.WhileSubscribed(1000), Resource.loading()) + .map { !it.isNullOrEmpty() } val viewer = userRepository .fetchViewer() From 52a4f31d9cc40791a833623e47d4912d7b02b652 Mon Sep 17 00:00:00 2001 From: imashnake0 Date: Sat, 13 Jan 2024 22:10:58 -0500 Subject: [PATCH 18/30] Viewer is non-nullable --- .../imashnake/animite/api/anilist/AnilistUserRepository.kt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/api/anilist/src/main/kotlin/com/imashnake/animite/api/anilist/AnilistUserRepository.kt b/api/anilist/src/main/kotlin/com/imashnake/animite/api/anilist/AnilistUserRepository.kt index d21165bd..043f1d27 100644 --- a/api/anilist/src/main/kotlin/com/imashnake/animite/api/anilist/AnilistUserRepository.kt +++ b/api/anilist/src/main/kotlin/com/imashnake/animite/api/anilist/AnilistUserRepository.kt @@ -9,10 +9,10 @@ import javax.inject.Inject class AnilistUserRepository @Inject constructor( private val apolloClient: ApolloClient ) { - fun fetchViewer(): Flow> { + fun fetchViewer(): Flow> { return apolloClient .query(ViewerQuery()) .fetchPolicy(FetchPolicy.CacheAndNetwork).toFlow() - .asResult { it.viewer } + .asResult { it.viewer!! } } } From 39edf8cc91866346fa1789200a6b33479929eac3 Mon Sep 17 00:00:00 2001 From: imashnake0 Date: Sun, 14 Jan 2024 07:36:11 -0500 Subject: [PATCH 19/30] Use access token from DataStore --- api/anilist/build.gradle.kts | 1 + .../com/imashnake/animite/api/anilist/AnilistApiModule.kt | 7 ++++--- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/api/anilist/build.gradle.kts b/api/anilist/build.gradle.kts index bd7738ab..cd65615d 100644 --- a/api/anilist/build.gradle.kts +++ b/api/anilist/build.gradle.kts @@ -29,6 +29,7 @@ kotlin { dependencies { implementation(project(":core")) + implementation(project(":api:preferences")) // Apollo Kotlin implementation(libs.apollo.runtime) diff --git a/api/anilist/src/main/kotlin/com/imashnake/animite/api/anilist/AnilistApiModule.kt b/api/anilist/src/main/kotlin/com/imashnake/animite/api/anilist/AnilistApiModule.kt index f7af16ee..40cc3278 100644 --- a/api/anilist/src/main/kotlin/com/imashnake/animite/api/anilist/AnilistApiModule.kt +++ b/api/anilist/src/main/kotlin/com/imashnake/animite/api/anilist/AnilistApiModule.kt @@ -10,13 +10,14 @@ import com.apollographql.apollo3.cache.normalized.sql.SqlNormalizedCacheFactory import com.apollographql.apollo3.network.http.HttpInterceptor import com.apollographql.apollo3.network.http.HttpInterceptorChain import com.apollographql.apollo3.network.http.LoggingInterceptor -import com.imashnake.animite.core.GlobalVariables +import com.imashnake.animite.api.preferences.PreferencesRepository import dagger.Module import dagger.Provides import dagger.hilt.InstallIn import dagger.hilt.android.qualifiers.ApplicationContext import dagger.hilt.components.SingletonComponent import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.flow.first import javax.inject.Singleton @Module @@ -46,7 +47,7 @@ object AnilistApiModule { @Singleton @Provides fun provideHttpInterceptor( - globalVariables: GlobalVariables + preferencesRepository: PreferencesRepository ): HttpInterceptor = object : HttpInterceptor { override suspend fun intercept( request: HttpRequest, @@ -54,7 +55,7 @@ object AnilistApiModule { ): HttpResponse { return chain.proceed( request.newBuilder().apply { - globalVariables.accessToken?.let { + preferencesRepository.accessToken.first()?.let { addHeader("Authorization", "Bearer $it") } }.build() From b8e9b73930e59d394a19114b11b50f29d2fe4889 Mon Sep 17 00:00:00 2001 From: imashnake0 Date: Sun, 14 Jan 2024 07:43:25 -0500 Subject: [PATCH 20/30] Purge `GlobalVariables` --- .../animite/api/preferences/DataStoreModule.kt | 7 ------- .../com/imashnake/animite/core/GlobalVariables.kt | 5 ----- .../imashnake/animite/profile/ProfileViewModel.kt | 12 +----------- 3 files changed, 1 insertion(+), 23 deletions(-) delete mode 100644 core/src/main/kotlin/com/imashnake/animite/core/GlobalVariables.kt diff --git a/api/preferences/src/main/kotlin/com/imashnake/animite/api/preferences/DataStoreModule.kt b/api/preferences/src/main/kotlin/com/imashnake/animite/api/preferences/DataStoreModule.kt index 61f7a497..6d763089 100644 --- a/api/preferences/src/main/kotlin/com/imashnake/animite/api/preferences/DataStoreModule.kt +++ b/api/preferences/src/main/kotlin/com/imashnake/animite/api/preferences/DataStoreModule.kt @@ -5,7 +5,6 @@ import androidx.datastore.core.DataStore import androidx.datastore.preferences.core.PreferenceDataStoreFactory import androidx.datastore.preferences.core.Preferences import androidx.datastore.preferences.preferencesDataStoreFile -import com.imashnake.animite.core.GlobalVariables import dagger.Module import dagger.Provides import dagger.hilt.InstallIn @@ -23,10 +22,4 @@ object DataStoreModule { produceFile = { appContext.preferencesDataStoreFile("default") } ) } - - @Singleton - @Provides - fun provideGlobalVariables(): GlobalVariables { - return GlobalVariables() - } } diff --git a/core/src/main/kotlin/com/imashnake/animite/core/GlobalVariables.kt b/core/src/main/kotlin/com/imashnake/animite/core/GlobalVariables.kt deleted file mode 100644 index f022f864..00000000 --- a/core/src/main/kotlin/com/imashnake/animite/core/GlobalVariables.kt +++ /dev/null @@ -1,5 +0,0 @@ -package com.imashnake.animite.core - -class GlobalVariables { - var accessToken: String? = null -} diff --git a/profile/src/main/kotlin/com/imashnake/animite/profile/ProfileViewModel.kt b/profile/src/main/kotlin/com/imashnake/animite/profile/ProfileViewModel.kt index c7d3a267..026a5298 100644 --- a/profile/src/main/kotlin/com/imashnake/animite/profile/ProfileViewModel.kt +++ b/profile/src/main/kotlin/com/imashnake/animite/profile/ProfileViewModel.kt @@ -4,15 +4,12 @@ import androidx.lifecycle.ViewModel import androidx.lifecycle.viewModelScope import com.imashnake.animite.api.anilist.AnilistUserRepository import com.imashnake.animite.api.preferences.PreferencesRepository -import com.imashnake.animite.core.GlobalVariables import com.imashnake.animite.core.data.Resource import com.imashnake.animite.core.data.Resource.Companion.asResource import dagger.hilt.android.lifecycle.HiltViewModel import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.flow.SharingStarted -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 javax.inject.Inject @@ -20,8 +17,7 @@ import javax.inject.Inject @HiltViewModel class ProfileViewModel @Inject constructor( userRepository: AnilistUserRepository, - private val preferencesRepository: PreferencesRepository, - private val globalVariables: GlobalVariables, + private val preferencesRepository: PreferencesRepository ) : ViewModel() { fun setAccessToken(accessToken: String?) = viewModelScope.launch(Dispatchers.IO) { preferencesRepository.setAccessToken(accessToken) @@ -35,10 +31,4 @@ class ProfileViewModel @Inject constructor( .fetchViewer() .asResource() .stateIn(viewModelScope, SharingStarted.WhileSubscribed(1000), Resource.loading()) - - init { - preferencesRepository.accessToken.onEach { - globalVariables.accessToken = it - }.launchIn(viewModelScope) - } } From bd6434da65315267f1a4991313824fe7d2b66553 Mon Sep 17 00:00:00 2001 From: imashnake0 Date: Sun, 14 Jan 2024 08:29:47 -0500 Subject: [PATCH 21/30] Removed deps --- api/anilist/build.gradle.kts | 2 -- api/preferences/build.gradle.kts | 3 --- 2 files changed, 5 deletions(-) diff --git a/api/anilist/build.gradle.kts b/api/anilist/build.gradle.kts index cd65615d..fa1561ea 100644 --- a/api/anilist/build.gradle.kts +++ b/api/anilist/build.gradle.kts @@ -28,7 +28,6 @@ kotlin { } dependencies { - implementation(project(":core")) implementation(project(":api:preferences")) // Apollo Kotlin @@ -38,7 +37,6 @@ dependencies { // Hilt implementation(libs.hilt.android) - implementation(libs.hilt.navigationCompose) ksp(libs.hilt.android.compiler) } diff --git a/api/preferences/build.gradle.kts b/api/preferences/build.gradle.kts index ffefe59f..8040355e 100644 --- a/api/preferences/build.gradle.kts +++ b/api/preferences/build.gradle.kts @@ -25,11 +25,8 @@ kotlin { } dependencies { - implementation(project(":core")) - // Hilt implementation(libs.hilt.android) - implementation(libs.hilt.navigationCompose) ksp(libs.hilt.android.compiler) // DataStore From dfc702033e14b70429543b7b3ee77d3ae55a004b Mon Sep 17 00:00:00 2001 From: imashnake0 Date: Sun, 14 Jan 2024 20:43:12 -0500 Subject: [PATCH 22/30] Use unauthorized client by default --- .../animite/api/anilist/AnilistApiModule.kt | 22 +++++++++++++++++-- .../api/anilist/AnilistMediaRepository.kt | 3 ++- .../api/anilist/AnilistSearchRepository.kt | 3 ++- .../api/anilist/AnilistUserRepository.kt | 3 ++- 4 files changed, 26 insertions(+), 5 deletions(-) diff --git a/api/anilist/src/main/kotlin/com/imashnake/animite/api/anilist/AnilistApiModule.kt b/api/anilist/src/main/kotlin/com/imashnake/animite/api/anilist/AnilistApiModule.kt index 40cc3278..987d54c0 100644 --- a/api/anilist/src/main/kotlin/com/imashnake/animite/api/anilist/AnilistApiModule.kt +++ b/api/anilist/src/main/kotlin/com/imashnake/animite/api/anilist/AnilistApiModule.kt @@ -18,6 +18,7 @@ import dagger.hilt.android.qualifiers.ApplicationContext import dagger.hilt.components.SingletonComponent import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.flow.first +import javax.inject.Named import javax.inject.Singleton @Module @@ -27,12 +28,29 @@ object AnilistApiModule { // TODO: Name this so we can have other apollo clients for different APIs. @Provides @Singleton + @Named("unauthorized") fun provideApolloClient( - @ApplicationContext context: Context, - httpInterceptor: HttpInterceptor + @ApplicationContext context: Context ): ApolloClient { // Cache is hit in order, so check in-memory -> check sqlite // We have an in-memory cache first for speed, then a SQLite cache for persistence. + val cacheFactory = MemoryCacheFactory(maxSizeBytes = 10 * 1024 * 1024) + .chain(SqlNormalizedCacheFactory(context, "apollo.db")) + return ApolloClient.Builder() + .dispatcher(Dispatchers.IO) + .serverUrl("https://graphql.anilist.co/") + .addHttpInterceptor(LoggingInterceptor(LoggingInterceptor.Level.BODY)) + .normalizedCache(cacheFactory) + .build() + } + + @Provides + @Singleton + @Named("authorized") + fun provideApolloClient( + @ApplicationContext context: Context, + httpInterceptor: HttpInterceptor + ): ApolloClient { val cacheFactory = MemoryCacheFactory(maxSizeBytes = 10 * 1024 * 1024) .chain(SqlNormalizedCacheFactory(context, "apollo.db")) return ApolloClient.Builder() diff --git a/api/anilist/src/main/kotlin/com/imashnake/animite/api/anilist/AnilistMediaRepository.kt b/api/anilist/src/main/kotlin/com/imashnake/animite/api/anilist/AnilistMediaRepository.kt index d2f0b7d7..f1f479f7 100644 --- a/api/anilist/src/main/kotlin/com/imashnake/animite/api/anilist/AnilistMediaRepository.kt +++ b/api/anilist/src/main/kotlin/com/imashnake/animite/api/anilist/AnilistMediaRepository.kt @@ -10,9 +10,10 @@ import com.imashnake.animite.api.anilist.type.MediaSort import com.imashnake.animite.api.anilist.type.MediaType import kotlinx.coroutines.flow.Flow import javax.inject.Inject +import javax.inject.Named class AnilistMediaRepository @Inject constructor( - private val apolloClient: ApolloClient + @Named("unauthorized") private val apolloClient: ApolloClient ) { fun fetchMediaList( diff --git a/api/anilist/src/main/kotlin/com/imashnake/animite/api/anilist/AnilistSearchRepository.kt b/api/anilist/src/main/kotlin/com/imashnake/animite/api/anilist/AnilistSearchRepository.kt index 562ef372..245f1f63 100644 --- a/api/anilist/src/main/kotlin/com/imashnake/animite/api/anilist/AnilistSearchRepository.kt +++ b/api/anilist/src/main/kotlin/com/imashnake/animite/api/anilist/AnilistSearchRepository.kt @@ -8,9 +8,10 @@ import com.imashnake.animite.api.anilist.sanitize.search.Search import com.imashnake.animite.api.anilist.type.MediaType import kotlinx.coroutines.flow.Flow import javax.inject.Inject +import javax.inject.Named class AnilistSearchRepository @Inject constructor( - private val apolloClient: ApolloClient + @Named("unauthorized") private val apolloClient: ApolloClient ) { fun fetchSearch( type: MediaType, diff --git a/api/anilist/src/main/kotlin/com/imashnake/animite/api/anilist/AnilistUserRepository.kt b/api/anilist/src/main/kotlin/com/imashnake/animite/api/anilist/AnilistUserRepository.kt index 043f1d27..aac87705 100644 --- a/api/anilist/src/main/kotlin/com/imashnake/animite/api/anilist/AnilistUserRepository.kt +++ b/api/anilist/src/main/kotlin/com/imashnake/animite/api/anilist/AnilistUserRepository.kt @@ -5,9 +5,10 @@ import com.apollographql.apollo3.cache.normalized.FetchPolicy import com.apollographql.apollo3.cache.normalized.fetchPolicy import kotlinx.coroutines.flow.Flow import javax.inject.Inject +import javax.inject.Named class AnilistUserRepository @Inject constructor( - private val apolloClient: ApolloClient + @Named("authorized") private val apolloClient: ApolloClient ) { fun fetchViewer(): Flow> { return apolloClient From 6e1bd6f91581af4bee0e42be2f2316b9837aa57f Mon Sep 17 00:00:00 2001 From: imashnake0 Date: Sun, 14 Jan 2024 20:44:08 -0500 Subject: [PATCH 23/30] Oops --- .../com/imashnake/animite/api/anilist/AnilistApiModule.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/api/anilist/src/main/kotlin/com/imashnake/animite/api/anilist/AnilistApiModule.kt b/api/anilist/src/main/kotlin/com/imashnake/animite/api/anilist/AnilistApiModule.kt index 987d54c0..00c50d55 100644 --- a/api/anilist/src/main/kotlin/com/imashnake/animite/api/anilist/AnilistApiModule.kt +++ b/api/anilist/src/main/kotlin/com/imashnake/animite/api/anilist/AnilistApiModule.kt @@ -47,7 +47,7 @@ object AnilistApiModule { @Provides @Singleton @Named("authorized") - fun provideApolloClient( + fun provideAuthorizedApolloClient( @ApplicationContext context: Context, httpInterceptor: HttpInterceptor ): ApolloClient { From 8a6561025efcd445e2265c00aa47208ebed6f350 Mon Sep 17 00:00:00 2001 From: imashnake0 Date: Sun, 14 Jan 2024 22:53:31 -0500 Subject: [PATCH 24/30] Added a login button --- core/src/main/res/drawable/ic_anilist.xml | 15 ++++++ .../com/imashnake/animite/profile/Login.kt | 49 +++++++++++++++++++ .../animite/profile/ProfileScreen.kt | 37 +++++++------- 3 files changed, 81 insertions(+), 20 deletions(-) create mode 100644 core/src/main/res/drawable/ic_anilist.xml create mode 100644 profile/src/main/kotlin/com/imashnake/animite/profile/Login.kt diff --git a/core/src/main/res/drawable/ic_anilist.xml b/core/src/main/res/drawable/ic_anilist.xml new file mode 100644 index 00000000..aa99a100 --- /dev/null +++ b/core/src/main/res/drawable/ic_anilist.xml @@ -0,0 +1,15 @@ + + + + + diff --git a/profile/src/main/kotlin/com/imashnake/animite/profile/Login.kt b/profile/src/main/kotlin/com/imashnake/animite/profile/Login.kt new file mode 100644 index 00000000..42527629 --- /dev/null +++ b/profile/src/main/kotlin/com/imashnake/animite/profile/Login.kt @@ -0,0 +1,49 @@ +package com.imashnake.animite.profile + +import androidx.compose.foundation.layout.Row +import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.layout.size +import androidx.compose.foundation.layout.wrapContentWidth +import androidx.compose.material3.ButtonDefaults +import androidx.compose.material3.Icon +import androidx.compose.material3.OutlinedButton +import androidx.compose.material3.Text +import androidx.compose.runtime.Composable +import androidx.compose.ui.Alignment +import androidx.compose.ui.Modifier +import androidx.compose.ui.graphics.Color +import androidx.compose.ui.graphics.vector.ImageVector +import androidx.compose.ui.platform.LocalUriHandler +import androidx.compose.ui.res.vectorResource +import androidx.compose.ui.unit.dp +import com.imashnake.animite.core.ui.LocalPaddings +import com.imashnake.animite.profile.dev.internal.ANILIST_AUTH_URL +import com.imashnake.animite.core.R as coreR + +@Composable +fun Login(modifier: Modifier = Modifier) { + val uriHandler = LocalUriHandler.current + OutlinedButton( + onClick = { uriHandler.openUri(ANILIST_AUTH_URL) }, + colors = ButtonDefaults.buttonColors( + containerColor = Color(0xFF1E2630), + contentColor = Color.White + ), + modifier = modifier + ) { + Row(Modifier.wrapContentWidth()) { + Icon( + imageVector = ImageVector.vectorResource(coreR.drawable.ic_anilist), + contentDescription = "AniList icon", + tint = Color.Unspecified, + modifier = Modifier.size(24.dp) + ) + Text( + text = "Log in", + modifier = Modifier + .align(Alignment.CenterVertically) + .padding(start = LocalPaddings.current.tiny) + ) + } + } +} diff --git a/profile/src/main/kotlin/com/imashnake/animite/profile/ProfileScreen.kt b/profile/src/main/kotlin/com/imashnake/animite/profile/ProfileScreen.kt index 3d3f9258..b0ad65f0 100644 --- a/profile/src/main/kotlin/com/imashnake/animite/profile/ProfileScreen.kt +++ b/profile/src/main/kotlin/com/imashnake/animite/profile/ProfileScreen.kt @@ -2,10 +2,7 @@ package com.imashnake.animite.profile import androidx.compose.foundation.background import androidx.compose.foundation.layout.Box -import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.fillMaxSize -import androidx.compose.foundation.layout.padding -import androidx.compose.material3.Button import androidx.compose.material3.MaterialTheme import androidx.compose.material3.Text import androidx.compose.runtime.Composable @@ -13,11 +10,12 @@ import androidx.compose.runtime.collectAsState import androidx.compose.runtime.getValue import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier -import androidx.compose.ui.platform.LocalUriHandler +import androidx.compose.ui.text.SpanStyle +import androidx.compose.ui.text.buildAnnotatedString +import androidx.compose.ui.text.font.FontWeight +import androidx.compose.ui.text.withStyle import androidx.hilt.navigation.compose.hiltViewModel -import com.imashnake.animite.core.ui.LocalPaddings import com.imashnake.animite.profile.dev.internal.ANILIST_AUTH_DEEPLINK -import com.imashnake.animite.profile.dev.internal.ANILIST_AUTH_URL import com.ramcosta.composedestinations.annotation.DeepLink import com.ramcosta.composedestinations.annotation.Destination import com.ramcosta.composedestinations.annotation.RootNavGraph @@ -46,23 +44,22 @@ fun ProfileScreen( .fillMaxSize() .background(MaterialTheme.colorScheme.background) ) { - val uriHandler = LocalUriHandler.current - if (!isLoggedIn) { - Button(onClick = { uriHandler.openUri(ANILIST_AUTH_URL) }) { - Text(text = "Log in") - } + Login() } else { - viewer.data?.let { viewer -> - with(viewer) { - Column(Modifier.padding(LocalPaddings.current.large)) { - Text(text = "ID: $id") - Text(text = "Name: $name") - about?.let { Text(text = "About: $it") } - avatar?.large?.let { Text(text = "Avatar: $it") } - bannerImage?.let { Text(text = "Banner Image: $it") } + viewer.data?.let { + Text(text = buildAnnotatedString { + append("Logged in as ") + withStyle( + SpanStyle( + fontWeight = FontWeight.Bold, + color = MaterialTheme.colorScheme.primary + ) + ) { + append(it.name) } - } + append(" \uD83D\uDE33") + }) } } } From fbbdab474edb04c36cd2983cb11c0d7e647c8747 Mon Sep 17 00:00:00 2001 From: imashnake0 Date: Sun, 14 Jan 2024 23:08:54 -0500 Subject: [PATCH 25/30] Removed sus --- profile/build.gradle.kts | 4 ---- .../com/imashnake/animite/profile/dev/internal/Constants.kt | 4 +--- 2 files changed, 1 insertion(+), 7 deletions(-) diff --git a/profile/build.gradle.kts b/profile/build.gradle.kts index 5ebba8ff..a65fec95 100644 --- a/profile/build.gradle.kts +++ b/profile/build.gradle.kts @@ -6,19 +6,15 @@ plugins { alias(libs.plugins.ksp) } -android.buildFeatures.buildConfig = true - android { defaultConfig { testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner" - buildConfigField("int", "CLIENT_ID", "10678") } buildTypes { release { isMinifyEnabled = false proguardFiles(getDefaultProguardFile("proguard-android-optimize.txt"), "proguard-rules.pro") - buildConfigField("int", "CLIENT_ID", "10678") } } diff --git a/profile/src/main/kotlin/com/imashnake/animite/profile/dev/internal/Constants.kt b/profile/src/main/kotlin/com/imashnake/animite/profile/dev/internal/Constants.kt index b7124610..69e81706 100644 --- a/profile/src/main/kotlin/com/imashnake/animite/profile/dev/internal/Constants.kt +++ b/profile/src/main/kotlin/com/imashnake/animite/profile/dev/internal/Constants.kt @@ -1,6 +1,4 @@ package com.imashnake.animite.profile.dev.internal -import com.imashnake.animite.profile.BuildConfig - const val ANILIST_AUTH_DEEPLINK = "jinnah://animite#access_token={accessToken}&token_type=Bearer&expires_in=31622400" -const val ANILIST_AUTH_URL = "https://anilist.co/api/v2/oauth/authorize?client_id=${BuildConfig.CLIENT_ID}&response_type=token" +const val ANILIST_AUTH_URL = "https://anilist.co/api/v2/oauth/authorize?client_id=10678&response_type=token" From 457e3cf21a24d631f832e94e4e0e04d9d2e15fd1 Mon Sep 17 00:00:00 2001 From: imashnake0 Date: Sun, 14 Jan 2024 23:15:08 -0500 Subject: [PATCH 26/30] Cleanup I think they fixed this now. --- api/anilist/build.gradle.kts | 2 -- app/build.gradle.kts | 2 -- core/build.gradle.kts | 2 -- material-color-utilities/build.gradle.kts | 2 -- profile/build.gradle.kts | 2 -- rslash/build.gradle.kts | 2 -- 6 files changed, 12 deletions(-) diff --git a/api/anilist/build.gradle.kts b/api/anilist/build.gradle.kts index fa1561ea..a9a9f6b4 100644 --- a/api/anilist/build.gradle.kts +++ b/api/anilist/build.gradle.kts @@ -1,5 +1,3 @@ -@file:Suppress("UnstableApiUsage") - plugins { alias(libs.plugins.android.library) alias(libs.plugins.kotlin) diff --git a/app/build.gradle.kts b/app/build.gradle.kts index f705ea23..d1eab698 100644 --- a/app/build.gradle.kts +++ b/app/build.gradle.kts @@ -1,5 +1,3 @@ -@file:Suppress("UnstableApiUsage") - plugins { alias(libs.plugins.android.application) alias(libs.plugins.kotlin) diff --git a/core/build.gradle.kts b/core/build.gradle.kts index f5ccf047..f841b1b4 100644 --- a/core/build.gradle.kts +++ b/core/build.gradle.kts @@ -1,5 +1,3 @@ -@file:Suppress("UnstableApiUsage") - plugins { alias(libs.plugins.android.library) alias(libs.plugins.kotlin) diff --git a/material-color-utilities/build.gradle.kts b/material-color-utilities/build.gradle.kts index 2c585ff0..4b0c9932 100644 --- a/material-color-utilities/build.gradle.kts +++ b/material-color-utilities/build.gradle.kts @@ -1,5 +1,3 @@ -@file:Suppress("UnstableApiUsage") - plugins { alias(libs.plugins.android.library) alias(libs.plugins.kotlin) diff --git a/profile/build.gradle.kts b/profile/build.gradle.kts index a65fec95..dc8acdf7 100644 --- a/profile/build.gradle.kts +++ b/profile/build.gradle.kts @@ -1,5 +1,3 @@ -@file:Suppress("UnstableApiUsage") - plugins { alias(libs.plugins.android.library) alias(libs.plugins.kotlin) diff --git a/rslash/build.gradle.kts b/rslash/build.gradle.kts index 7a8a10b8..f5626350 100644 --- a/rslash/build.gradle.kts +++ b/rslash/build.gradle.kts @@ -1,5 +1,3 @@ -@file:Suppress("UnstableApiUsage") - plugins { alias(libs.plugins.android.library) alias(libs.plugins.kotlin) From 9851b237de22755dd6b46f061d2b52a75c992ade Mon Sep 17 00:00:00 2001 From: imashnake0 Date: Sun, 14 Jan 2024 23:46:02 -0500 Subject: [PATCH 27/30] Resolved comments - Inlined `ACESS_TOKEN`. - Removed TODO. - Fixed annotations. --- .../imashnake/animite/api/anilist/AnilistApiModule.kt | 10 ++++++---- .../animite/api/anilist/AnilistMediaRepository.kt | 2 +- .../animite/api/anilist/AnilistSearchRepository.kt | 2 +- .../animite/api/anilist/AnilistUserRepository.kt | 2 +- .../animite/api/preferences/PreferencesRepository.kt | 4 +--- 5 files changed, 10 insertions(+), 10 deletions(-) diff --git a/api/anilist/src/main/kotlin/com/imashnake/animite/api/anilist/AnilistApiModule.kt b/api/anilist/src/main/kotlin/com/imashnake/animite/api/anilist/AnilistApiModule.kt index 00c50d55..748b316c 100644 --- a/api/anilist/src/main/kotlin/com/imashnake/animite/api/anilist/AnilistApiModule.kt +++ b/api/anilist/src/main/kotlin/com/imashnake/animite/api/anilist/AnilistApiModule.kt @@ -19,16 +19,14 @@ import dagger.hilt.components.SingletonComponent import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.flow.first import javax.inject.Named +import javax.inject.Qualifier import javax.inject.Singleton @Module @InstallIn(SingletonComponent::class) object AnilistApiModule { - - // TODO: Name this so we can have other apollo clients for different APIs. @Provides @Singleton - @Named("unauthorized") fun provideApolloClient( @ApplicationContext context: Context ): ApolloClient { @@ -46,7 +44,7 @@ object AnilistApiModule { @Provides @Singleton - @Named("authorized") + @Authorized fun provideAuthorizedApolloClient( @ApplicationContext context: Context, httpInterceptor: HttpInterceptor @@ -81,3 +79,7 @@ object AnilistApiModule { } } } + +@Qualifier +@Retention(AnnotationRetention.BINARY) +annotation class Authorized diff --git a/api/anilist/src/main/kotlin/com/imashnake/animite/api/anilist/AnilistMediaRepository.kt b/api/anilist/src/main/kotlin/com/imashnake/animite/api/anilist/AnilistMediaRepository.kt index f1f479f7..d0fcfd1b 100644 --- a/api/anilist/src/main/kotlin/com/imashnake/animite/api/anilist/AnilistMediaRepository.kt +++ b/api/anilist/src/main/kotlin/com/imashnake/animite/api/anilist/AnilistMediaRepository.kt @@ -13,7 +13,7 @@ import javax.inject.Inject import javax.inject.Named class AnilistMediaRepository @Inject constructor( - @Named("unauthorized") private val apolloClient: ApolloClient + private val apolloClient: ApolloClient ) { fun fetchMediaList( diff --git a/api/anilist/src/main/kotlin/com/imashnake/animite/api/anilist/AnilistSearchRepository.kt b/api/anilist/src/main/kotlin/com/imashnake/animite/api/anilist/AnilistSearchRepository.kt index 245f1f63..4ffb00cf 100644 --- a/api/anilist/src/main/kotlin/com/imashnake/animite/api/anilist/AnilistSearchRepository.kt +++ b/api/anilist/src/main/kotlin/com/imashnake/animite/api/anilist/AnilistSearchRepository.kt @@ -11,7 +11,7 @@ import javax.inject.Inject import javax.inject.Named class AnilistSearchRepository @Inject constructor( - @Named("unauthorized") private val apolloClient: ApolloClient + private val apolloClient: ApolloClient ) { fun fetchSearch( type: MediaType, diff --git a/api/anilist/src/main/kotlin/com/imashnake/animite/api/anilist/AnilistUserRepository.kt b/api/anilist/src/main/kotlin/com/imashnake/animite/api/anilist/AnilistUserRepository.kt index aac87705..03403fd9 100644 --- a/api/anilist/src/main/kotlin/com/imashnake/animite/api/anilist/AnilistUserRepository.kt +++ b/api/anilist/src/main/kotlin/com/imashnake/animite/api/anilist/AnilistUserRepository.kt @@ -8,7 +8,7 @@ import javax.inject.Inject import javax.inject.Named class AnilistUserRepository @Inject constructor( - @Named("authorized") private val apolloClient: ApolloClient + @Authorized private val apolloClient: ApolloClient ) { fun fetchViewer(): Flow> { return apolloClient diff --git a/api/preferences/src/main/kotlin/com/imashnake/animite/api/preferences/PreferencesRepository.kt b/api/preferences/src/main/kotlin/com/imashnake/animite/api/preferences/PreferencesRepository.kt index 8006935e..ddb5b36f 100644 --- a/api/preferences/src/main/kotlin/com/imashnake/animite/api/preferences/PreferencesRepository.kt +++ b/api/preferences/src/main/kotlin/com/imashnake/animite/api/preferences/PreferencesRepository.kt @@ -7,12 +7,10 @@ import com.imashnake.animite.api.preferences.ext.getValue import com.imashnake.animite.api.preferences.ext.setValue import javax.inject.Inject -private const val ACCESS_TOKEN = "access_token" - class PreferencesRepository @Inject constructor( private val dataStore: DataStore ) { - private val accessTokenKey = stringPreferencesKey(ACCESS_TOKEN) + private val accessTokenKey = stringPreferencesKey("access_token") val accessToken = dataStore.getValue(accessTokenKey, null) suspend fun setAccessToken(accessToken: String?) { From 5b532b39f0f9d541c19eb7ae76cb89336bcdab6a Mon Sep 17 00:00:00 2001 From: imashnake0 Date: Sun, 14 Jan 2024 23:51:00 -0500 Subject: [PATCH 28/30] Docs and cleanup --- .../com/imashnake/animite/api/anilist/AnilistApiModule.kt | 1 - .../animite/api/anilist/AnilistMediaRepository.kt | 1 - .../animite/api/anilist/AnilistSearchRepository.kt | 1 - .../imashnake/animite/api/anilist/AnilistUserRepository.kt | 7 ++++++- 4 files changed, 6 insertions(+), 4 deletions(-) diff --git a/api/anilist/src/main/kotlin/com/imashnake/animite/api/anilist/AnilistApiModule.kt b/api/anilist/src/main/kotlin/com/imashnake/animite/api/anilist/AnilistApiModule.kt index 748b316c..e42dae8d 100644 --- a/api/anilist/src/main/kotlin/com/imashnake/animite/api/anilist/AnilistApiModule.kt +++ b/api/anilist/src/main/kotlin/com/imashnake/animite/api/anilist/AnilistApiModule.kt @@ -18,7 +18,6 @@ import dagger.hilt.android.qualifiers.ApplicationContext import dagger.hilt.components.SingletonComponent import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.flow.first -import javax.inject.Named import javax.inject.Qualifier import javax.inject.Singleton diff --git a/api/anilist/src/main/kotlin/com/imashnake/animite/api/anilist/AnilistMediaRepository.kt b/api/anilist/src/main/kotlin/com/imashnake/animite/api/anilist/AnilistMediaRepository.kt index d0fcfd1b..d2f0b7d7 100644 --- a/api/anilist/src/main/kotlin/com/imashnake/animite/api/anilist/AnilistMediaRepository.kt +++ b/api/anilist/src/main/kotlin/com/imashnake/animite/api/anilist/AnilistMediaRepository.kt @@ -10,7 +10,6 @@ import com.imashnake.animite.api.anilist.type.MediaSort import com.imashnake.animite.api.anilist.type.MediaType import kotlinx.coroutines.flow.Flow import javax.inject.Inject -import javax.inject.Named class AnilistMediaRepository @Inject constructor( private val apolloClient: ApolloClient diff --git a/api/anilist/src/main/kotlin/com/imashnake/animite/api/anilist/AnilistSearchRepository.kt b/api/anilist/src/main/kotlin/com/imashnake/animite/api/anilist/AnilistSearchRepository.kt index 4ffb00cf..562ef372 100644 --- a/api/anilist/src/main/kotlin/com/imashnake/animite/api/anilist/AnilistSearchRepository.kt +++ b/api/anilist/src/main/kotlin/com/imashnake/animite/api/anilist/AnilistSearchRepository.kt @@ -8,7 +8,6 @@ import com.imashnake.animite.api.anilist.sanitize.search.Search import com.imashnake.animite.api.anilist.type.MediaType import kotlinx.coroutines.flow.Flow import javax.inject.Inject -import javax.inject.Named class AnilistSearchRepository @Inject constructor( private val apolloClient: ApolloClient diff --git a/api/anilist/src/main/kotlin/com/imashnake/animite/api/anilist/AnilistUserRepository.kt b/api/anilist/src/main/kotlin/com/imashnake/animite/api/anilist/AnilistUserRepository.kt index 03403fd9..538b0ff1 100644 --- a/api/anilist/src/main/kotlin/com/imashnake/animite/api/anilist/AnilistUserRepository.kt +++ b/api/anilist/src/main/kotlin/com/imashnake/animite/api/anilist/AnilistUserRepository.kt @@ -5,8 +5,13 @@ import com.apollographql.apollo3.cache.normalized.FetchPolicy import com.apollographql.apollo3.cache.normalized.fetchPolicy import kotlinx.coroutines.flow.Flow import javax.inject.Inject -import javax.inject.Named +/** + * Repository for anything user related. Including the [ViewerQuery.Viewer]. + * + * @param apolloClient Client with the [`Authorization` header](https://anilist.gitbook.io/anilist-apiv2-docs/overview/oauth/implicit-grant#making-authenticated-requests).' + * @property fetchViewer Fetches the current user with an authorized [apolloClient]. + */ class AnilistUserRepository @Inject constructor( @Authorized private val apolloClient: ApolloClient ) { From 577740d450820bd6ab37cc2709a007d68d99381d Mon Sep 17 00:00:00 2001 From: imashnake0 Date: Sun, 14 Jan 2024 23:52:19 -0500 Subject: [PATCH 29/30] :i_: --- .../com/imashnake/animite/api/anilist/AnilistUserRepository.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/api/anilist/src/main/kotlin/com/imashnake/animite/api/anilist/AnilistUserRepository.kt b/api/anilist/src/main/kotlin/com/imashnake/animite/api/anilist/AnilistUserRepository.kt index 538b0ff1..52ef8624 100644 --- a/api/anilist/src/main/kotlin/com/imashnake/animite/api/anilist/AnilistUserRepository.kt +++ b/api/anilist/src/main/kotlin/com/imashnake/animite/api/anilist/AnilistUserRepository.kt @@ -9,7 +9,7 @@ import javax.inject.Inject /** * Repository for anything user related. Including the [ViewerQuery.Viewer]. * - * @param apolloClient Client with the [`Authorization` header](https://anilist.gitbook.io/anilist-apiv2-docs/overview/oauth/implicit-grant#making-authenticated-requests).' + * @param apolloClient Client with the [`Authorization` header](https://anilist.gitbook.io/anilist-apiv2-docs/overview/oauth/implicit-grant#making-authenticated-requests). * @property fetchViewer Fetches the current user with an authorized [apolloClient]. */ class AnilistUserRepository @Inject constructor( From b19f774197dc83d40bf140697513685acb44928c Mon Sep 17 00:00:00 2001 From: imashnake0 Date: Mon, 15 Jan 2024 00:08:10 -0500 Subject: [PATCH 30/30] More docs and renamed annotation Co-Authored-By: Jack Boswell --- .../com/imashnake/animite/api/anilist/AnilistApiModule.kt | 4 ++-- .../animite/api/anilist/AnilistMediaRepository.kt | 7 +++++++ .../animite/api/anilist/AnilistSearchRepository.kt | 6 ++++++ .../imashnake/animite/api/anilist/AnilistUserRepository.kt | 2 +- 4 files changed, 16 insertions(+), 3 deletions(-) diff --git a/api/anilist/src/main/kotlin/com/imashnake/animite/api/anilist/AnilistApiModule.kt b/api/anilist/src/main/kotlin/com/imashnake/animite/api/anilist/AnilistApiModule.kt index e42dae8d..e7641d40 100644 --- a/api/anilist/src/main/kotlin/com/imashnake/animite/api/anilist/AnilistApiModule.kt +++ b/api/anilist/src/main/kotlin/com/imashnake/animite/api/anilist/AnilistApiModule.kt @@ -43,7 +43,7 @@ object AnilistApiModule { @Provides @Singleton - @Authorized + @AuthorizedClient fun provideAuthorizedApolloClient( @ApplicationContext context: Context, httpInterceptor: HttpInterceptor @@ -81,4 +81,4 @@ object AnilistApiModule { @Qualifier @Retention(AnnotationRetention.BINARY) -annotation class Authorized +annotation class AuthorizedClient diff --git a/api/anilist/src/main/kotlin/com/imashnake/animite/api/anilist/AnilistMediaRepository.kt b/api/anilist/src/main/kotlin/com/imashnake/animite/api/anilist/AnilistMediaRepository.kt index d2f0b7d7..7929947a 100644 --- a/api/anilist/src/main/kotlin/com/imashnake/animite/api/anilist/AnilistMediaRepository.kt +++ b/api/anilist/src/main/kotlin/com/imashnake/animite/api/anilist/AnilistMediaRepository.kt @@ -11,6 +11,13 @@ import com.imashnake.animite.api.anilist.type.MediaType import kotlinx.coroutines.flow.Flow import javax.inject.Inject +/** + * Repository for fetching [MediaQuery.Media] or a list of [MediaListQuery.Medium]. + * + * @param apolloClient Default apollo client. + * @property fetchMediaList Fetches a list of [MediaListQuery.Medium]. + * @property fetchMedia Fetches detailed media: [MediaQuery.Media]. + */ class AnilistMediaRepository @Inject constructor( private val apolloClient: ApolloClient ) { diff --git a/api/anilist/src/main/kotlin/com/imashnake/animite/api/anilist/AnilistSearchRepository.kt b/api/anilist/src/main/kotlin/com/imashnake/animite/api/anilist/AnilistSearchRepository.kt index 562ef372..6dabf2e4 100644 --- a/api/anilist/src/main/kotlin/com/imashnake/animite/api/anilist/AnilistSearchRepository.kt +++ b/api/anilist/src/main/kotlin/com/imashnake/animite/api/anilist/AnilistSearchRepository.kt @@ -9,6 +9,12 @@ import com.imashnake.animite.api.anilist.type.MediaType import kotlinx.coroutines.flow.Flow import javax.inject.Inject +/** + * Repository for fetching media search results (e.g., search bar). + * + * @param apolloClient Default apollo client. + * @property fetchSearch Fetch a list of `search`es. + */ class AnilistSearchRepository @Inject constructor( private val apolloClient: ApolloClient ) { diff --git a/api/anilist/src/main/kotlin/com/imashnake/animite/api/anilist/AnilistUserRepository.kt b/api/anilist/src/main/kotlin/com/imashnake/animite/api/anilist/AnilistUserRepository.kt index 52ef8624..386e9434 100644 --- a/api/anilist/src/main/kotlin/com/imashnake/animite/api/anilist/AnilistUserRepository.kt +++ b/api/anilist/src/main/kotlin/com/imashnake/animite/api/anilist/AnilistUserRepository.kt @@ -13,7 +13,7 @@ import javax.inject.Inject * @property fetchViewer Fetches the current user with an authorized [apolloClient]. */ class AnilistUserRepository @Inject constructor( - @Authorized private val apolloClient: ApolloClient + @AuthorizedClient private val apolloClient: ApolloClient ) { fun fetchViewer(): Flow> { return apolloClient