diff --git a/.gitignore b/.gitignore index aa724b7..9ff96f7 100644 --- a/.gitignore +++ b/.gitignore @@ -1,15 +1,13 @@ *.iml -.gradle /local.properties -/.idea/caches -/.idea/libraries -/.idea/modules.xml -/.idea/workspace.xml -/.idea/navEditor.xml -/.idea/assetWizardSettings.xml +.idea/ .DS_Store -/build /captures .externalNativeBuild .cxx local.properties +*.klib +.kotlinc/ +.kotlin/ +.gradle/ +build/ diff --git a/.idea/.name b/.idea/.name deleted file mode 100644 index b4ebe73..0000000 --- a/.idea/.name +++ /dev/null @@ -1 +0,0 @@ -Song Quest \ No newline at end of file diff --git a/apk/song-quest-1.0.0.apk b/apk/song-quest-1.0.0.apk deleted file mode 100644 index 227a319..0000000 Binary files a/apk/song-quest-1.0.0.apk and /dev/null differ diff --git a/app/build.gradle.kts b/app/build.gradle.kts deleted file mode 100644 index 78f35ba..0000000 --- a/app/build.gradle.kts +++ /dev/null @@ -1,101 +0,0 @@ -plugins { - id("com.android.application") - id("org.jetbrains.kotlin.android") - id("org.jetbrains.kotlin.plugin.serialization") - kotlin("kapt") - id("com.google.dagger.hilt.android") - id("org.jetbrains.compose") - id("org.jetbrains.kotlin.plugin.compose") -} - -android { - namespace = "com.spongycode.songquest" - compileSdk = 36 - - defaultConfig { - applicationId = "com.spongycode.songquest" - minSdk = 24 - targetSdk = 36 - versionCode = 1 - versionName = "1.0" - - testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner" - } - - buildTypes { - release { - isMinifyEnabled = false - proguardFiles( - getDefaultProguardFile("proguard-android-optimize.txt"), - "proguard-rules.pro" - ) - } - } - - compileOptions { - sourceCompatibility = JavaVersion.VERSION_17 - targetCompatibility = JavaVersion.VERSION_17 - } - - kotlin { - jvmToolchain(17) - } - - buildFeatures { - compose = true - } - - composeOptions { - kotlinCompilerExtensionVersion = "1.5.1" - } - - packaging { - resources { - excludes += "/META-INF/{AL2.0,LGPL2.1}" - } - } -} - -dependencies { - - // Core - implementation("androidx.core:core-ktx:1.17.0") - implementation("androidx.lifecycle:lifecycle-runtime-ktx:2.9.4") - implementation("androidx.activity:activity-compose:1.11.0") - - // Compose BOM - implementation(platform("androidx.compose:compose-bom:2025.09.00")) - implementation("androidx.compose.ui:ui") - implementation("androidx.compose.ui:ui-graphics") - implementation("androidx.compose.ui:ui-tooling-preview") - implementation("androidx.compose.material3:material3") - implementation("androidx.compose.material3:material3-window-size-class") - implementation("androidx.compose.runtime:runtime-livedata:1.9.1") - - // Navigation - implementation("androidx.navigation:navigation-compose:2.9.4") - - // Datastore - implementation("androidx.datastore:datastore-preferences:1.1.7") - - // Serialization - implementation("org.jetbrains.kotlinx:kotlinx-serialization-json:1.9.0") - - // Ktor - implementation("io.ktor:ktor-client-core:3.3.0") - implementation("io.ktor:ktor-client-cio:3.3.0") - implementation("io.ktor:ktor-client-content-negotiation:3.3.0") - implementation("io.ktor:ktor-serialization-kotlinx-json:3.3.0") - implementation("io.ktor:ktor-client-logging:3.3.0") - - // Hilt - implementation("com.google.dagger:hilt-android:2.57.1") - kapt("com.google.dagger:hilt-android-compiler:2.57.1") - kapt("androidx.hilt:hilt-compiler:1.3.0") - implementation("androidx.hilt:hilt-navigation-fragment:1.3.0") - implementation("androidx.hilt:hilt-navigation-compose:1.3.0") -} - -kapt { - correctErrorTypes = true -} diff --git a/app/src/androidTest/java/com/spongycode/songquest/ExampleInstrumentedTest.kt b/app/src/androidTest/java/com/spongycode/songquest/ExampleInstrumentedTest.kt deleted file mode 100644 index c266baf..0000000 --- a/app/src/androidTest/java/com/spongycode/songquest/ExampleInstrumentedTest.kt +++ /dev/null @@ -1,24 +0,0 @@ -package com.spongycode.songquest - -import androidx.test.platform.app.InstrumentationRegistry -import androidx.test.ext.junit.runners.AndroidJUnit4 - -import org.junit.Test -import org.junit.runner.RunWith - -import org.junit.Assert.* - -/** - * Instrumented test, which will execute on an Android device. - * - * See [testing documentation](http://d.android.com/tools/testing). - */ -@RunWith(AndroidJUnit4::class) -class ExampleInstrumentedTest { - @Test - fun useAppContext() { - // Context of the app under test. - val appContext = InstrumentationRegistry.getInstrumentation().targetContext - assertEquals("com.spongycode.songquest", appContext.packageName) - } -} \ No newline at end of file diff --git a/app/src/main/java/com/spongycode/songquest/MainActivity.kt b/app/src/main/java/com/spongycode/songquest/MainActivity.kt deleted file mode 100644 index e0a21de..0000000 --- a/app/src/main/java/com/spongycode/songquest/MainActivity.kt +++ /dev/null @@ -1,31 +0,0 @@ -package com.spongycode.songquest - -import android.os.Bundle -import androidx.activity.ComponentActivity -import androidx.activity.compose.setContent -import androidx.compose.foundation.layout.fillMaxSize -import androidx.compose.material3.MaterialTheme -import androidx.compose.material3.Surface -import androidx.compose.ui.Modifier -import com.spongycode.songquest.ui.navigation.NavContainer -import com.spongycode.songquest.ui.theme.SongQuestTheme -import com.spongycode.songquest.util.Constants.SPLASH_SCREEN -import dagger.hilt.android.AndroidEntryPoint - -@AndroidEntryPoint -class MainActivity : ComponentActivity() { - override fun onCreate(savedInstanceState: Bundle?) { - setTheme(R.style.Theme_SongQuest) - super.onCreate(savedInstanceState) - setContent { - SongQuestTheme { - Surface( - modifier = Modifier.fillMaxSize(), - color = MaterialTheme.colorScheme.background - ) { - NavContainer(startDestination = SPLASH_SCREEN) - } - } - } - } -} \ No newline at end of file diff --git a/app/src/main/java/com/spongycode/songquest/SongApp.kt b/app/src/main/java/com/spongycode/songquest/SongApp.kt deleted file mode 100644 index e8b5876..0000000 --- a/app/src/main/java/com/spongycode/songquest/SongApp.kt +++ /dev/null @@ -1,7 +0,0 @@ -package com.spongycode.songquest - -import android.app.Application -import dagger.hilt.android.HiltAndroidApp - -@HiltAndroidApp -class SongApp : Application() \ No newline at end of file diff --git a/app/src/main/java/com/spongycode/songquest/data/repository/DatastoreRepositoryImpl.kt b/app/src/main/java/com/spongycode/songquest/data/repository/DatastoreRepositoryImpl.kt deleted file mode 100644 index b508848..0000000 --- a/app/src/main/java/com/spongycode/songquest/data/repository/DatastoreRepositoryImpl.kt +++ /dev/null @@ -1,53 +0,0 @@ -package com.spongycode.songquest.data.repository - -import android.content.Context -import androidx.datastore.core.DataStore -import androidx.datastore.preferences.core.Preferences -import androidx.datastore.preferences.core.edit -import androidx.datastore.preferences.core.stringPreferencesKey -import androidx.datastore.preferences.preferencesDataStore -import com.spongycode.songquest.domain.repository.DatastoreRepository -import com.spongycode.songquest.util.Constants -import com.spongycode.songquest.util.Constants.PREFERENCES_NAME -import kotlinx.coroutines.flow.first -import javax.inject.Inject - -class DatastoreRepositoryImpl @Inject constructor( - private val context: Context -) : DatastoreRepository { - - override suspend fun getString(key: Preferences.Key): String? { - val preferences = context.preferencesDataStore.data.first() - val tokenExists = preferences[key] != null - return if (tokenExists) { - preferences[key] ?: "" - } else { - null - } - } - - override suspend fun storeString(key: Preferences.Key, value: String) { - context.preferencesDataStore.edit { setting -> - setting[key] = value - } - } - - override suspend fun storeListString(list: List, String>>) { - list.map { - context.preferencesDataStore.edit { setting -> - setting[it.first] = it.second - } - } - } - - companion object { - private val Context.preferencesDataStore: DataStore by preferencesDataStore( - name = PREFERENCES_NAME - ) - val accessTokenSession = stringPreferencesKey(Constants.ACCESS_TOKEN_SESSION) - val refreshTokenSession = stringPreferencesKey(Constants.REFRESH_TOKEN_SESSION) - val usernameSession = stringPreferencesKey(Constants.USERNAME_SESSION) - val emailSession = stringPreferencesKey(Constants.EMAIL_SESSION) - val gamesPlayedSession = stringPreferencesKey(Constants.GAMES_PLAYED_SESSION) - } -} \ No newline at end of file diff --git a/app/src/main/java/com/spongycode/songquest/di/AppModule.kt b/app/src/main/java/com/spongycode/songquest/di/AppModule.kt deleted file mode 100644 index 1297e34..0000000 --- a/app/src/main/java/com/spongycode/songquest/di/AppModule.kt +++ /dev/null @@ -1,51 +0,0 @@ -package com.spongycode.songquest.di - -import android.content.Context -import android.util.Log -import com.spongycode.songquest.data.repository.DatastoreRepositoryImpl -import com.spongycode.songquest.domain.repository.DatastoreRepository -import dagger.Module -import dagger.Provides -import dagger.hilt.InstallIn -import dagger.hilt.android.qualifiers.ApplicationContext -import dagger.hilt.components.SingletonComponent -import io.ktor.client.HttpClient -import io.ktor.client.engine.cio.CIO -import io.ktor.client.plugins.contentnegotiation.ContentNegotiation -import io.ktor.client.plugins.logging.LogLevel -import io.ktor.client.plugins.logging.Logger -import io.ktor.client.plugins.logging.Logging -import io.ktor.serialization.kotlinx.json.json -import kotlinx.serialization.json.Json -import javax.inject.Singleton - -@Module -@InstallIn(SingletonComponent::class) -object AppModule { - @Provides - @Singleton - fun provideClient(): HttpClient { - return HttpClient(CIO) { - install(ContentNegotiation) { - json(Json { - ignoreUnknownKeys = true - coerceInputValues = true - }) - } - install(Logging) { - logger = object : Logger { - override fun log(message: String) { - Log.d("http", message) - } - } - level = LogLevel.ALL - } - } - } - - @Singleton - @Provides - fun provideDataStoreRepository( - @ApplicationContext app: Context - ): DatastoreRepository = DatastoreRepositoryImpl(app) -} \ No newline at end of file diff --git a/app/src/main/java/com/spongycode/songquest/di/RepositoryModule.kt b/app/src/main/java/com/spongycode/songquest/di/RepositoryModule.kt deleted file mode 100644 index d09aef0..0000000 --- a/app/src/main/java/com/spongycode/songquest/di/RepositoryModule.kt +++ /dev/null @@ -1,28 +0,0 @@ -package com.spongycode.songquest.di - -import com.spongycode.songquest.data.repository.AuthRepositoryImpl -import com.spongycode.songquest.data.repository.GameplayRepositoryImpl -import com.spongycode.songquest.domain.repository.AuthRepository -import com.spongycode.songquest.domain.repository.GameplayRepository -import dagger.Binds -import dagger.Module -import dagger.hilt.InstallIn -import dagger.hilt.components.SingletonComponent -import javax.inject.Singleton - -@Module -@InstallIn(SingletonComponent::class) -abstract class RepositoryModule { - - @Binds - @Singleton - abstract fun bindAuthRepository( - authRepositoryImpl: AuthRepositoryImpl - ): AuthRepository - - @Binds - @Singleton - abstract fun bindGameplayRepository( - gameplayRepositoryImpl: GameplayRepositoryImpl - ): GameplayRepository -} diff --git a/app/src/main/java/com/spongycode/songquest/domain/repository/DatastoreRepository.kt b/app/src/main/java/com/spongycode/songquest/domain/repository/DatastoreRepository.kt deleted file mode 100644 index de340f2..0000000 --- a/app/src/main/java/com/spongycode/songquest/domain/repository/DatastoreRepository.kt +++ /dev/null @@ -1,9 +0,0 @@ -package com.spongycode.songquest.domain.repository - -import androidx.datastore.preferences.core.Preferences - -interface DatastoreRepository { - suspend fun getString(key: Preferences.Key): String? - suspend fun storeString(key: Preferences.Key, value: String) - suspend fun storeListString(list: List, String>>) -} \ No newline at end of file diff --git a/app/src/main/java/com/spongycode/songquest/ui/navigation/NavContainer.kt b/app/src/main/java/com/spongycode/songquest/ui/navigation/NavContainer.kt deleted file mode 100644 index d5fd85c..0000000 --- a/app/src/main/java/com/spongycode/songquest/ui/navigation/NavContainer.kt +++ /dev/null @@ -1,144 +0,0 @@ -package com.spongycode.songquest.ui.navigation - -import androidx.compose.animation.AnimatedContentTransitionScope -import androidx.compose.animation.EnterTransition -import androidx.compose.animation.core.tween -import androidx.compose.runtime.Composable -import androidx.compose.runtime.CompositionLocalProvider -import androidx.compose.runtime.compositionLocalOf -import androidx.navigation.NavHostController -import androidx.navigation.compose.NavHost -import androidx.navigation.compose.composable -import androidx.navigation.compose.rememberNavController -import com.spongycode.songquest.ui.screen.auth.forgot_password.ForgotPasswordScreenRoot -import com.spongycode.songquest.ui.screen.auth.login.LoginScreenRoot -import com.spongycode.songquest.ui.screen.auth.register.RegisterScreenRoot -import com.spongycode.songquest.ui.screen.gameplay.gameover.GameOverScreenRoot -import com.spongycode.songquest.ui.screen.gameplay.history.HistoryScreenRoot -import com.spongycode.songquest.ui.screen.gameplay.home.HomeScreenRoot -import com.spongycode.songquest.ui.screen.gameplay.leaderboard.LeaderboardScreenRoot -import com.spongycode.songquest.ui.screen.gameplay.playing.PlayingScreenRoot -import com.spongycode.songquest.ui.screen.gameplay.profile.ProfileScreenRoot -import com.spongycode.songquest.ui.screen.starter.SplashScreenRoot -import com.spongycode.songquest.util.Constants.CATEGORY -import com.spongycode.songquest.util.Constants.FORGOT_PASSWORD_SCREEN -import com.spongycode.songquest.util.Constants.GAME_ID -import com.spongycode.songquest.util.Constants.GAME_OVER_SCREEN -import com.spongycode.songquest.util.Constants.HISTORY_SCREEN -import com.spongycode.songquest.util.Constants.HOME_SCREEN -import com.spongycode.songquest.util.Constants.LEADERBOARD_SCREEN -import com.spongycode.songquest.util.Constants.LOGIN_SCREEN -import com.spongycode.songquest.util.Constants.PLAYING_SCREEN -import com.spongycode.songquest.util.Constants.PROFILE_SCREEN -import com.spongycode.songquest.util.Constants.REGISTER_SCREEN -import com.spongycode.songquest.util.Constants.SPLASH_SCREEN - -val LocalNavController = compositionLocalOf { error("No NavController") } - -@Composable -fun NavContainer(startDestination: String) { - val navController = rememberNavController() - CompositionLocalProvider(LocalNavController provides navController) { - NavHost(navController = navController, startDestination = startDestination) { - composable(route = SPLASH_SCREEN) { - SplashScreenRoot() - } - composable(route = REGISTER_SCREEN) { - RegisterScreenRoot() - } - composable(route = LOGIN_SCREEN, - enterTransition = { - slideIntoContainer( - AnimatedContentTransitionScope.SlideDirection.Start, tween(300) - ) - }, - popEnterTransition = { - EnterTransition.None - }, - exitTransition = { - slideOutOfContainer( - AnimatedContentTransitionScope.SlideDirection.End, tween(300) - ) - } - ) { - LoginScreenRoot() - } - composable(route = FORGOT_PASSWORD_SCREEN, - enterTransition = { - slideIntoContainer( - AnimatedContentTransitionScope.SlideDirection.Start, tween(300) - ) - }, - popEnterTransition = { - EnterTransition.None - }, - exitTransition = { - slideOutOfContainer( - AnimatedContentTransitionScope.SlideDirection.End, tween(300) - ) - } - ) { - ForgotPasswordScreenRoot() - } - composable(route = HOME_SCREEN) { - HomeScreenRoot() - } - composable(route = "$PLAYING_SCREEN/{$CATEGORY}") { - val category = it.arguments?.getString(CATEGORY) - PlayingScreenRoot(category = category!!) - } - composable(route = "$GAME_OVER_SCREEN/{$GAME_ID}") { - val gameId = it.arguments?.getString(GAME_ID) - GameOverScreenRoot(gameId = gameId!!) - } - composable(route = PROFILE_SCREEN, - enterTransition = { - slideIntoContainer( - AnimatedContentTransitionScope.SlideDirection.Start, tween(100) - ) - }, - popEnterTransition = { - EnterTransition.None - }, - exitTransition = { - slideOutOfContainer( - AnimatedContentTransitionScope.SlideDirection.End, tween(100) - ) - }) { - ProfileScreenRoot() - } - composable(route = HISTORY_SCREEN, - enterTransition = { - slideIntoContainer( - AnimatedContentTransitionScope.SlideDirection.Start, tween(100) - ) - }, - popEnterTransition = { - EnterTransition.None - }, - exitTransition = { - slideOutOfContainer( - AnimatedContentTransitionScope.SlideDirection.End, tween(100) - ) - }) { - HistoryScreenRoot() - } - composable(route = LEADERBOARD_SCREEN, - enterTransition = { - slideIntoContainer( - AnimatedContentTransitionScope.SlideDirection.Start, tween(100) - ) - }, - popEnterTransition = { - EnterTransition.None - }, - exitTransition = { - slideOutOfContainer( - AnimatedContentTransitionScope.SlideDirection.End, tween(100) - ) - }) { - LeaderboardScreenRoot() - } - } - } -} \ No newline at end of file diff --git a/app/src/main/java/com/spongycode/songquest/ui/theme/Theme.kt b/app/src/main/java/com/spongycode/songquest/ui/theme/Theme.kt deleted file mode 100644 index 02d150b..0000000 --- a/app/src/main/java/com/spongycode/songquest/ui/theme/Theme.kt +++ /dev/null @@ -1,69 +0,0 @@ -package com.spongycode.songquest.ui.theme - -import android.app.Activity -import androidx.compose.foundation.isSystemInDarkTheme -import androidx.compose.material3.MaterialTheme -import androidx.compose.material3.darkColorScheme -import androidx.compose.material3.lightColorScheme -import androidx.compose.runtime.Composable -import androidx.compose.runtime.SideEffect -import androidx.compose.ui.graphics.Color -import androidx.compose.ui.graphics.toArgb -import androidx.compose.ui.platform.LocalView -import androidx.core.view.WindowCompat - -private val DarkColorScheme = darkColorScheme( - primary = Color.White, - primaryContainer = Color(0xFF1D1C1C), - secondaryContainer = Color(0xFF353434), - inversePrimary = Color(0xFFD8D3D3), - secondary = PurpleGrey80, - tertiary = Pink80, - background = Color.Black, -) - -private val LightColorScheme = lightColorScheme( - primary = Color.Black, - primaryContainer = Color(0xFFF1ECEC), - secondaryContainer = Color(0xFFE2D8D8), - inversePrimary = Color(0xFF777373), - secondary = PurpleGrey40, - tertiary = Pink40, - background = Color.White, - /* Other default colors to override - background = Color(0xFFFFFBFE), - surface = Color(0xFFFFFBFE), - onPrimary = Color.White, - onSecondary = Color.White, - onTertiary = Color.White, - onBackground = Color(0xFF1C1B1F), - onSurface = Color(0xFF1C1B1F), - */ -) - -@Composable -fun SongQuestTheme( - darkTheme: Boolean = false, - // Dynamic color is available on Android 12+ - dynamicColor: Boolean = true, - content: @Composable () -> Unit -) { - val colorScheme = when { - darkTheme -> DarkColorScheme - else -> LightColorScheme - } - val view = LocalView.current - if (!view.isInEditMode) { - SideEffect { - val window = (view.context as Activity).window - window.statusBarColor =Color.Black.toArgb() - WindowCompat.getInsetsController(window, view).isAppearanceLightStatusBars = darkTheme - } - } - - MaterialTheme( - colorScheme = colorScheme, - typography = Typography, - content = content - ) -} \ No newline at end of file diff --git a/app/src/main/java/com/spongycode/songquest/ui/theme/Type.kt b/app/src/main/java/com/spongycode/songquest/ui/theme/Type.kt deleted file mode 100644 index cc29943..0000000 --- a/app/src/main/java/com/spongycode/songquest/ui/theme/Type.kt +++ /dev/null @@ -1,34 +0,0 @@ -package com.spongycode.songquest.ui.theme - -import androidx.compose.material3.Typography -import androidx.compose.ui.text.TextStyle -import androidx.compose.ui.text.font.FontFamily -import androidx.compose.ui.text.font.FontWeight -import androidx.compose.ui.unit.sp - -// Set of Material typography styles to start with -val Typography = Typography( - bodyLarge = TextStyle( - fontFamily = FontFamily.Default, - fontWeight = FontWeight.Normal, - fontSize = 16.sp, - lineHeight = 24.sp, - letterSpacing = 0.5.sp - ) - /* Other default text styles to override - titleLarge = TextStyle( - fontFamily = FontFamily.Default, - fontWeight = FontWeight.Normal, - fontSize = 22.sp, - lineHeight = 28.sp, - letterSpacing = 0.sp - ), - labelSmall = TextStyle( - fontFamily = FontFamily.Default, - fontWeight = FontWeight.Medium, - fontSize = 11.sp, - lineHeight = 16.sp, - letterSpacing = 0.5.sp - ) - */ -) \ No newline at end of file diff --git a/app/src/main/java/com/spongycode/songquest/util/Fonts.kt b/app/src/main/java/com/spongycode/songquest/util/Fonts.kt deleted file mode 100644 index b3234ce..0000000 --- a/app/src/main/java/com/spongycode/songquest/util/Fonts.kt +++ /dev/null @@ -1,15 +0,0 @@ -package com.spongycode.songquest.util - -import androidx.compose.ui.text.font.Font -import androidx.compose.ui.text.font.FontFamily -import androidx.compose.ui.text.font.FontWeight -import com.spongycode.songquest.R - -object Fonts { - val poppinsFamily = FontFamily( - Font(R.font.poppins_extra_bold, FontWeight.W800), - Font(R.font.poppins_bold, FontWeight.W600), - Font(R.font.poppins_medium, FontWeight.Medium), - Font(R.font.poppins_regular, FontWeight.Normal) - ) -} diff --git a/app/src/main/java/com/spongycode/songquest/util/TimesAgo.kt b/app/src/main/java/com/spongycode/songquest/util/TimesAgo.kt deleted file mode 100644 index a4fd212..0000000 --- a/app/src/main/java/com/spongycode/songquest/util/TimesAgo.kt +++ /dev/null @@ -1,41 +0,0 @@ -package com.spongycode.songquest.util - -import java.text.SimpleDateFormat -import java.util.Calendar -import java.util.Locale -import java.util.TimeZone - -object TimesAgo { - fun getTimeAgo(time: String): String { - try { - val inputFormat = SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss", Locale.getDefault()) - inputFormat.timeZone = TimeZone.getTimeZone("UTC") - val serverDate = inputFormat.parse(time) - - val now = Calendar.getInstance() - val serverTime = Calendar.getInstance() - serverTime.time = serverDate!! - - val diffInMillis = now.timeInMillis - serverTime.timeInMillis - val seconds = diffInMillis / 1000 - val minutes = seconds / 60 - val hours = minutes / 60 - val days = hours / 24 - - return when { - days > 2 -> { - val outputFormat = SimpleDateFormat("MMM d 'at' HH:mm", Locale.getDefault()) - outputFormat.timeZone = TimeZone.getDefault() - outputFormat.format(serverDate) - } - - days >= 1 -> if (days > 1) "$days days ago" else "yesterday" - hours >= 1 -> "$hours hour${if (hours > 1) "s" else ""} ago" - minutes >= 1 -> "$minutes min${if (minutes > 1) "s" else ""} ago" - else -> "$seconds sec${if (seconds > 1) "s" else ""} ago" - } - } catch (e: Exception) { - return "just now" - } - } -} \ No newline at end of file diff --git a/app/src/main/res/drawable/baseline_account_circle_24.xml b/app/src/main/res/drawable/baseline_account_circle_24.xml deleted file mode 100644 index 93ce250..0000000 --- a/app/src/main/res/drawable/baseline_account_circle_24.xml +++ /dev/null @@ -1,5 +0,0 @@ - - - diff --git a/app/src/main/res/drawable/baseline_cancel_24.xml b/app/src/main/res/drawable/baseline_cancel_24.xml deleted file mode 100644 index a0a94e3..0000000 --- a/app/src/main/res/drawable/baseline_cancel_24.xml +++ /dev/null @@ -1,5 +0,0 @@ - - - diff --git a/app/src/main/res/drawable/baseline_check_circle_24.xml b/app/src/main/res/drawable/baseline_check_circle_24.xml deleted file mode 100644 index b83d1bc..0000000 --- a/app/src/main/res/drawable/baseline_check_circle_24.xml +++ /dev/null @@ -1,5 +0,0 @@ - - - diff --git a/app/src/main/res/drawable/baseline_visibility_24.xml b/app/src/main/res/drawable/baseline_visibility_24.xml deleted file mode 100644 index b923c39..0000000 --- a/app/src/main/res/drawable/baseline_visibility_24.xml +++ /dev/null @@ -1,5 +0,0 @@ - - - diff --git a/app/src/main/res/drawable/baseline_visibility_off_24.xml b/app/src/main/res/drawable/baseline_visibility_off_24.xml deleted file mode 100644 index 00c8a20..0000000 --- a/app/src/main/res/drawable/baseline_visibility_off_24.xml +++ /dev/null @@ -1,5 +0,0 @@ - - - diff --git a/app/src/main/res/drawable/ic_launcher_background.xml b/app/src/main/res/drawable/ic_launcher_background.xml deleted file mode 100644 index 07d5da9..0000000 --- a/app/src/main/res/drawable/ic_launcher_background.xml +++ /dev/null @@ -1,170 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/app/src/main/res/drawable/ic_launcher_foreground.xml b/app/src/main/res/drawable/ic_launcher_foreground.xml deleted file mode 100644 index 2b068d1..0000000 --- a/app/src/main/res/drawable/ic_launcher_foreground.xml +++ /dev/null @@ -1,30 +0,0 @@ - - - - - - - - - - - \ No newline at end of file diff --git a/app/src/main/res/font/poppins_bold.ttf b/app/src/main/res/font/poppins_bold.ttf deleted file mode 100644 index 00559ee..0000000 Binary files a/app/src/main/res/font/poppins_bold.ttf and /dev/null differ diff --git a/app/src/main/res/font/poppins_extra_bold.ttf b/app/src/main/res/font/poppins_extra_bold.ttf deleted file mode 100644 index df70936..0000000 Binary files a/app/src/main/res/font/poppins_extra_bold.ttf and /dev/null differ diff --git a/app/src/main/res/font/poppins_light.ttf b/app/src/main/res/font/poppins_light.ttf deleted file mode 100644 index bc36bcc..0000000 Binary files a/app/src/main/res/font/poppins_light.ttf and /dev/null differ diff --git a/app/src/main/res/font/poppins_medium.ttf b/app/src/main/res/font/poppins_medium.ttf deleted file mode 100644 index 6bcdcc2..0000000 Binary files a/app/src/main/res/font/poppins_medium.ttf and /dev/null differ diff --git a/app/src/main/res/font/poppins_regular.ttf b/app/src/main/res/font/poppins_regular.ttf deleted file mode 100644 index 9f0c71b..0000000 Binary files a/app/src/main/res/font/poppins_regular.ttf and /dev/null differ diff --git a/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml b/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml deleted file mode 100644 index 6f3b755..0000000 --- a/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml +++ /dev/null @@ -1,6 +0,0 @@ - - - - - - \ No newline at end of file diff --git a/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml b/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml deleted file mode 100644 index 6f3b755..0000000 --- a/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml +++ /dev/null @@ -1,6 +0,0 @@ - - - - - - \ No newline at end of file diff --git a/app/src/main/res/mipmap-hdpi/ic_launcher.webp b/app/src/main/res/mipmap-hdpi/ic_launcher.webp deleted file mode 100644 index c209e78..0000000 Binary files a/app/src/main/res/mipmap-hdpi/ic_launcher.webp and /dev/null differ diff --git a/app/src/main/res/mipmap-hdpi/ic_launcher_round.webp b/app/src/main/res/mipmap-hdpi/ic_launcher_round.webp deleted file mode 100644 index b2dfe3d..0000000 Binary files a/app/src/main/res/mipmap-hdpi/ic_launcher_round.webp and /dev/null differ diff --git a/app/src/main/res/mipmap-mdpi/ic_launcher.webp b/app/src/main/res/mipmap-mdpi/ic_launcher.webp deleted file mode 100644 index 4f0f1d6..0000000 Binary files a/app/src/main/res/mipmap-mdpi/ic_launcher.webp and /dev/null differ diff --git a/app/src/main/res/mipmap-mdpi/ic_launcher_round.webp b/app/src/main/res/mipmap-mdpi/ic_launcher_round.webp deleted file mode 100644 index 62b611d..0000000 Binary files a/app/src/main/res/mipmap-mdpi/ic_launcher_round.webp and /dev/null differ diff --git a/app/src/main/res/mipmap-xhdpi/ic_launcher.webp b/app/src/main/res/mipmap-xhdpi/ic_launcher.webp deleted file mode 100644 index 948a307..0000000 Binary files a/app/src/main/res/mipmap-xhdpi/ic_launcher.webp and /dev/null differ diff --git a/app/src/main/res/mipmap-xhdpi/ic_launcher_round.webp b/app/src/main/res/mipmap-xhdpi/ic_launcher_round.webp deleted file mode 100644 index 1b9a695..0000000 Binary files a/app/src/main/res/mipmap-xhdpi/ic_launcher_round.webp and /dev/null differ diff --git a/app/src/main/res/mipmap-xxhdpi/ic_launcher.webp b/app/src/main/res/mipmap-xxhdpi/ic_launcher.webp deleted file mode 100644 index 28d4b77..0000000 Binary files a/app/src/main/res/mipmap-xxhdpi/ic_launcher.webp and /dev/null differ diff --git a/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.webp b/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.webp deleted file mode 100644 index 9287f50..0000000 Binary files a/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.webp and /dev/null differ diff --git a/app/src/main/res/mipmap-xxxhdpi/ic_launcher.webp b/app/src/main/res/mipmap-xxxhdpi/ic_launcher.webp deleted file mode 100644 index aa7d642..0000000 Binary files a/app/src/main/res/mipmap-xxxhdpi/ic_launcher.webp and /dev/null differ diff --git a/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.webp b/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.webp deleted file mode 100644 index 9126ae3..0000000 Binary files a/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.webp and /dev/null differ diff --git a/app/src/main/res/values/colors.xml b/app/src/main/res/values/colors.xml deleted file mode 100644 index f8c6127..0000000 --- a/app/src/main/res/values/colors.xml +++ /dev/null @@ -1,10 +0,0 @@ - - - #FFBB86FC - #FF6200EE - #FF3700B3 - #FF03DAC5 - #FF018786 - #FF000000 - #FFFFFFFF - \ No newline at end of file diff --git a/app/src/test/java/com/spongycode/songquest/ExampleUnitTest.kt b/app/src/test/java/com/spongycode/songquest/ExampleUnitTest.kt deleted file mode 100644 index 8484cc2..0000000 --- a/app/src/test/java/com/spongycode/songquest/ExampleUnitTest.kt +++ /dev/null @@ -1,17 +0,0 @@ -package com.spongycode.songquest - -import org.junit.Test - -import org.junit.Assert.* - -/** - * Example local unit test, which will execute on the development machine (host). - * - * See [testing documentation](http://d.android.com/tools/testing). - */ -class ExampleUnitTest { - @Test - fun addition_isCorrect() { - assertEquals(4, 2 + 2) - } -} \ No newline at end of file diff --git a/build.gradle.kts b/build.gradle.kts index 0dbceb2..fdb077a 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -1,12 +1,12 @@ plugins { id("com.android.application") version "8.13.0" apply false + id("com.android.library") version "8.13.0" apply false id("org.jetbrains.kotlin.android") version "2.2.20" apply false id("org.jetbrains.kotlin.plugin.serialization") version "2.2.20" apply false id("com.google.dagger.hilt.android") version "2.57.1" apply false id("org.jetbrains.compose") version "1.9.0" apply false id("org.jetbrains.kotlin.plugin.compose") version "2.2.20" apply false -} - -tasks.register("clean", Delete::class) { - delete(rootProject.buildDir) + id("org.jetbrains.kotlin.multiplatform") version "2.2.20" apply false + id("com.android.kotlin.multiplatform.library") version "8.13.0" apply false + id("com.android.lint") version "8.13.0" apply false } \ No newline at end of file diff --git a/app/.gitignore b/composeApp/.gitignore similarity index 100% rename from app/.gitignore rename to composeApp/.gitignore diff --git a/composeApp/build.gradle.kts b/composeApp/build.gradle.kts new file mode 100644 index 0000000..dcf7c99 --- /dev/null +++ b/composeApp/build.gradle.kts @@ -0,0 +1,160 @@ +@file:OptIn(ExperimentalKotlinGradlePluginApi::class) + +import org.jetbrains.kotlin.gradle.ExperimentalKotlinGradlePluginApi +import org.jetbrains.kotlin.gradle.ExperimentalWasmDsl +import org.jetbrains.kotlin.gradle.dsl.JvmTarget +import org.jetbrains.kotlin.gradle.plugin.mpp.apple.XCFramework +import org.jetbrains.kotlin.gradle.targets.js.webpack.KotlinWebpackConfig + +plugins { + alias(libs.plugins.kotlinMultiplatform) + alias(libs.plugins.androidApplication) + alias(libs.plugins.composeMultiplatform) + alias(libs.plugins.composeCompiler) + alias(libs.plugins.composeHotReload) + id("org.jetbrains.kotlin.plugin.serialization") +} + +compose.resources { + publicResClass = true + generateResClass = auto +} + + +kotlin { + @OptIn(ExperimentalKotlinGradlePluginApi::class) compilerOptions { + freeCompilerArgs.add("-Xexpect-actual-classes") + } + + androidTarget { + @OptIn(ExperimentalKotlinGradlePluginApi::class) + compilerOptions { + jvmTarget.set(JvmTarget.JVM_11) + } + } + + val xcf = XCFramework() + listOf( + iosX64(), + iosArm64(), + iosSimulatorArm64() + ).forEach { iosTarget -> + iosTarget.binaries.framework { + baseName = "composeApp" + xcf.add(this) + isStatic = true + } + } + + @OptIn(ExperimentalWasmDsl::class) + wasmJs { + outputModuleName.set(provider { "composeApp" }) + browser { + val rootDirPath = project.rootDir.path + val projectDirPath = project.projectDir.path + commonWebpackConfig { + outputFileName = "composeApp.js" + devServer = (devServer ?: KotlinWebpackConfig.DevServer()).apply { + static = (static ?: mutableListOf()).apply { + // Serve sources to debug inside browser + add(rootDirPath) + add(projectDirPath) + } + } + } + } + binaries.executable() + } + + sourceSets { + + commonMain.dependencies { + implementation(compose.runtime) + implementation(compose.foundation) + implementation(compose.material3) + implementation(compose.ui) + implementation(compose.components.resources) + implementation(libs.material.icons.core) + implementation(compose.components.uiToolingPreview) + implementation(libs.androidx.lifecycle.viewmodel) + implementation(libs.androidx.lifecycle.runtimeCompose) + implementation(libs.kotlin.stdlib) + implementation(libs.kotlinx.datetime) + + + implementation(libs.multiplatform.settings.no.arg) + implementation(libs.multiplatform.settings) + + implementation(libs.kotlinx.serialization.json) + implementation(libs.navigation.compose) + + implementation(project.dependencies.platform(libs.ktor.bom)) + implementation(libs.bundles.ktor.common) + + } + + androidMain.dependencies { + implementation(libs.androidx.activity.compose) + implementation(compose.preview) + implementation(project.dependencies.platform(libs.ktor.bom)) + implementation(libs.ktor.client.okhttp) + } + + iosMain.dependencies { + implementation(project.dependencies.platform(libs.ktor.bom)) + implementation(libs.ktor.client.darwin) + } + + wasmJsMain.dependencies { + implementation(project.dependencies.platform(libs.ktor.bom)) + implementation(libs.ktor.client.js) + } + } +} + + +android { + namespace = "com.spongycode.songquest" + compileSdk = 36 + + defaultConfig { + applicationId = "com.spongycode.songquest" + minSdk = 24 + targetSdk = 36 + versionCode = 1 + versionName = "1.0" + } + + buildTypes { + release { + isMinifyEnabled = false + proguardFiles( + getDefaultProguardFile("proguard-android-optimize.txt"), + "proguard-rules.pro" + ) + } + } + + compileOptions { + sourceCompatibility = JavaVersion.VERSION_21 + targetCompatibility = JavaVersion.VERSION_21 + } + + kotlin { + jvmToolchain(21) + } + + buildFeatures { + compose = true + } + + composeOptions { + kotlinCompilerExtensionVersion = "1.5.1" + } + + packaging { + resources { + excludes += "/META-INF/{AL2.0,LGPL2.1}" + } + } +} \ No newline at end of file diff --git a/app/proguard-rules.pro b/composeApp/proguard-rules.pro similarity index 100% rename from app/proguard-rules.pro rename to composeApp/proguard-rules.pro diff --git a/app/src/main/AndroidManifest.xml b/composeApp/src/androidMain/AndroidManifest.xml similarity index 94% rename from app/src/main/AndroidManifest.xml rename to composeApp/src/androidMain/AndroidManifest.xml index d663dfe..6dbe7e7 100644 --- a/app/src/main/AndroidManifest.xml +++ b/composeApp/src/androidMain/AndroidManifest.xml @@ -4,7 +4,6 @@ diff --git a/composeApp/src/androidMain/kotlin/com/spongycode/songquest/AudioPlayer.android.kt b/composeApp/src/androidMain/kotlin/com/spongycode/songquest/AudioPlayer.android.kt new file mode 100644 index 0000000..26ff076 --- /dev/null +++ b/composeApp/src/androidMain/kotlin/com/spongycode/songquest/AudioPlayer.android.kt @@ -0,0 +1,31 @@ +package com.spongycode.songquest + +import android.media.MediaPlayer + +actual class AudioPlayer { + private var mediaPlayer: MediaPlayer? = null + private var sourceUrl: String? = null + + actual fun setSource(url: String) { + sourceUrl = url + } + + actual fun prepareAndPlay(looping: Boolean) { + mediaPlayer?.release() + mediaPlayer = MediaPlayer().apply { + setDataSource(sourceUrl) + isLooping = looping + setOnPreparedListener { start() } + prepareAsync() + } + } + + actual fun stop() { + mediaPlayer?.stop() + } + + actual fun release() { + mediaPlayer?.release() + mediaPlayer = null + } +} diff --git a/app/src/main/java/com/spongycode/songquest/util/Image.kt b/composeApp/src/androidMain/kotlin/com/spongycode/songquest/BitmapShare.android.kt similarity index 58% rename from app/src/main/java/com/spongycode/songquest/util/Image.kt rename to composeApp/src/androidMain/kotlin/com/spongycode/songquest/BitmapShare.android.kt index 8a87f2f..824bbf8 100644 --- a/app/src/main/java/com/spongycode/songquest/util/Image.kt +++ b/composeApp/src/androidMain/kotlin/com/spongycode/songquest/BitmapShare.android.kt @@ -1,11 +1,31 @@ -package com.spongycode.songquest.util +package com.spongycode.songquest import android.content.Context import android.content.Intent import android.graphics.Bitmap import android.net.Uri +import androidx.compose.ui.graphics.ImageBitmap +import androidx.compose.ui.graphics.asAndroidBitmap import androidx.core.content.FileProvider +import com.spongycode.songquest.Image.saveBitmapAndGetUri +import com.spongycode.songquest.Image.shareImageUriWithText +import com.spongycode.songquest.util.Constants.BASE_URL import java.io.File +import kotlin.io.outputStream +import kotlin.use + +actual fun ImageBitmap.share( + context: PlatformContext, + score: Int?, + category: String? +) { + val ctx = context.getContext() as Context + val bitmap = asAndroidBitmap() + val uri = saveBitmapAndGetUri(ctx, bitmap) + val message = + "I scored $score in #$category Quiz! Think you can beat me?\nDownload the app: $BASE_URL" + shareImageUriWithText(ctx, uri, message) +} object Image { fun saveBitmapAndGetUri(context: Context, bitmap: Bitmap): Uri { diff --git a/composeApp/src/androidMain/kotlin/com/spongycode/songquest/MainActivity.kt b/composeApp/src/androidMain/kotlin/com/spongycode/songquest/MainActivity.kt new file mode 100644 index 0000000..2107c4e --- /dev/null +++ b/composeApp/src/androidMain/kotlin/com/spongycode/songquest/MainActivity.kt @@ -0,0 +1,16 @@ +package com.spongycode.songquest + +import android.os.Bundle +import androidx.activity.ComponentActivity +import androidx.activity.compose.setContent +import com.spongycode.songquest.ui.theme.SongQuestTheme + +class MainActivity : ComponentActivity() { + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + PlatformContext.setContext(applicationContext) + setContent { + App() + } + } +} \ No newline at end of file diff --git a/composeApp/src/androidMain/kotlin/com/spongycode/songquest/Platform.android.kt b/composeApp/src/androidMain/kotlin/com/spongycode/songquest/Platform.android.kt new file mode 100644 index 0000000..2ecabd7 --- /dev/null +++ b/composeApp/src/androidMain/kotlin/com/spongycode/songquest/Platform.android.kt @@ -0,0 +1,27 @@ +package com.spongycode.songquest + +import android.content.Context +import android.content.res.Resources + +actual fun platform(): String = "Android" +actual fun getScreenWidth(): Float { + val configuration = Resources.getSystem().configuration + return configuration.screenWidthDp.toFloat() +} + +actual fun getScreenHeight(): Float { + val configuration = Resources.getSystem().configuration + return configuration.screenHeightDp.toFloat() +} + +actual object PlatformContext { + private var appContext: Context? = null + + actual fun setContext(context: Any) { + appContext = context as? Context + } + + actual fun getContext(): Any? { + return appContext + } +} \ No newline at end of file diff --git a/app/src/main/res/drawable/logo.xml b/composeApp/src/androidMain/res/drawable/logo.xml similarity index 100% rename from app/src/main/res/drawable/logo.xml rename to composeApp/src/androidMain/res/drawable/logo.xml diff --git a/app/src/main/res/drawable/logo_text.xml b/composeApp/src/androidMain/res/drawable/logo_text.xml similarity index 100% rename from app/src/main/res/drawable/logo_text.xml rename to composeApp/src/androidMain/res/drawable/logo_text.xml diff --git a/app/src/main/res/drawable/splash_screen.xml b/composeApp/src/androidMain/res/drawable/splash_screen.xml similarity index 100% rename from app/src/main/res/drawable/splash_screen.xml rename to composeApp/src/androidMain/res/drawable/splash_screen.xml diff --git a/composeApp/src/androidMain/res/values/strings.xml b/composeApp/src/androidMain/res/values/strings.xml new file mode 100644 index 0000000..08814bc --- /dev/null +++ b/composeApp/src/androidMain/res/values/strings.xml @@ -0,0 +1,3 @@ + + Song Quest + \ No newline at end of file diff --git a/app/src/main/res/values/themes.xml b/composeApp/src/androidMain/res/values/themes.xml similarity index 100% rename from app/src/main/res/values/themes.xml rename to composeApp/src/androidMain/res/values/themes.xml diff --git a/app/src/main/res/xml/backup_rules.xml b/composeApp/src/androidMain/res/xml/backup_rules.xml similarity index 100% rename from app/src/main/res/xml/backup_rules.xml rename to composeApp/src/androidMain/res/xml/backup_rules.xml diff --git a/app/src/main/res/xml/data_extraction_rules.xml b/composeApp/src/androidMain/res/xml/data_extraction_rules.xml similarity index 100% rename from app/src/main/res/xml/data_extraction_rules.xml rename to composeApp/src/androidMain/res/xml/data_extraction_rules.xml diff --git a/app/src/main/res/xml/file_paths.xml b/composeApp/src/androidMain/res/xml/file_paths.xml similarity index 100% rename from app/src/main/res/xml/file_paths.xml rename to composeApp/src/androidMain/res/xml/file_paths.xml diff --git a/composeApp/src/commonMain/composeResources/drawable/baseline_account_circle_24.xml b/composeApp/src/commonMain/composeResources/drawable/baseline_account_circle_24.xml new file mode 100644 index 0000000..7c880f6 --- /dev/null +++ b/composeApp/src/commonMain/composeResources/drawable/baseline_account_circle_24.xml @@ -0,0 +1,5 @@ + + + diff --git a/composeApp/src/commonMain/composeResources/drawable/baseline_cancel_24.xml b/composeApp/src/commonMain/composeResources/drawable/baseline_cancel_24.xml new file mode 100644 index 0000000..32cfdb5 --- /dev/null +++ b/composeApp/src/commonMain/composeResources/drawable/baseline_cancel_24.xml @@ -0,0 +1,5 @@ + + + diff --git a/app/src/main/res/drawable/baseline_music_note_24.xml b/composeApp/src/commonMain/composeResources/drawable/baseline_check_circle_24.xml similarity index 53% rename from app/src/main/res/drawable/baseline_music_note_24.xml rename to composeApp/src/commonMain/composeResources/drawable/baseline_check_circle_24.xml index 4bd8b20..79d3959 100644 --- a/app/src/main/res/drawable/baseline_music_note_24.xml +++ b/composeApp/src/commonMain/composeResources/drawable/baseline_check_circle_24.xml @@ -1,5 +1,5 @@ - + diff --git a/composeApp/src/commonMain/composeResources/drawable/baseline_visibility_24.xml b/composeApp/src/commonMain/composeResources/drawable/baseline_visibility_24.xml new file mode 100644 index 0000000..5c7a589 --- /dev/null +++ b/composeApp/src/commonMain/composeResources/drawable/baseline_visibility_24.xml @@ -0,0 +1,5 @@ + + + diff --git a/composeApp/src/commonMain/composeResources/drawable/baseline_visibility_off_24.xml b/composeApp/src/commonMain/composeResources/drawable/baseline_visibility_off_24.xml new file mode 100644 index 0000000..ac47fa6 --- /dev/null +++ b/composeApp/src/commonMain/composeResources/drawable/baseline_visibility_off_24.xml @@ -0,0 +1,5 @@ + + + diff --git a/app/src/main/res/drawable/bollywood_banner.png b/composeApp/src/commonMain/composeResources/drawable/bollywood_banner.png similarity index 100% rename from app/src/main/res/drawable/bollywood_banner.png rename to composeApp/src/commonMain/composeResources/drawable/bollywood_banner.png diff --git a/composeApp/src/commonMain/composeResources/drawable/compose-multiplatform.xml b/composeApp/src/commonMain/composeResources/drawable/compose-multiplatform.xml new file mode 100644 index 0000000..1ffc948 --- /dev/null +++ b/composeApp/src/commonMain/composeResources/drawable/compose-multiplatform.xml @@ -0,0 +1,44 @@ + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/desi_hip_hop_banner.png b/composeApp/src/commonMain/composeResources/drawable/desi_hip_hop_banner.png similarity index 100% rename from app/src/main/res/drawable/desi_hip_hop_banner.png rename to composeApp/src/commonMain/composeResources/drawable/desi_hip_hop_banner.png diff --git a/app/src/main/res/drawable/gameplay_count.xml b/composeApp/src/commonMain/composeResources/drawable/gameplay_count.xml similarity index 100% rename from app/src/main/res/drawable/gameplay_count.xml rename to composeApp/src/commonMain/composeResources/drawable/gameplay_count.xml diff --git a/app/src/main/res/drawable/heart.xml b/composeApp/src/commonMain/composeResources/drawable/heart.xml similarity index 100% rename from app/src/main/res/drawable/heart.xml rename to composeApp/src/commonMain/composeResources/drawable/heart.xml diff --git a/app/src/main/res/drawable/hip_hop_banner.png b/composeApp/src/commonMain/composeResources/drawable/hip_hop_banner.png similarity index 100% rename from app/src/main/res/drawable/hip_hop_banner.png rename to composeApp/src/commonMain/composeResources/drawable/hip_hop_banner.png diff --git a/app/src/main/res/drawable/hollywood_banner.png b/composeApp/src/commonMain/composeResources/drawable/hollywood_banner.png similarity index 100% rename from app/src/main/res/drawable/hollywood_banner.png rename to composeApp/src/commonMain/composeResources/drawable/hollywood_banner.png diff --git a/app/src/main/res/drawable/leader_board_icon.xml b/composeApp/src/commonMain/composeResources/drawable/leader_board_icon.xml similarity index 100% rename from app/src/main/res/drawable/leader_board_icon.xml rename to composeApp/src/commonMain/composeResources/drawable/leader_board_icon.xml diff --git a/composeApp/src/commonMain/composeResources/drawable/logo_text.xml b/composeApp/src/commonMain/composeResources/drawable/logo_text.xml new file mode 100644 index 0000000..e53b882 --- /dev/null +++ b/composeApp/src/commonMain/composeResources/drawable/logo_text.xml @@ -0,0 +1,70 @@ + + + + + + + + + + + + + + + + + + diff --git a/composeApp/src/commonMain/composeResources/font/poppins_bold.ttf b/composeApp/src/commonMain/composeResources/font/poppins_bold.ttf new file mode 100644 index 0000000..e69de29 diff --git a/composeApp/src/commonMain/composeResources/font/poppins_extra_bold.ttf b/composeApp/src/commonMain/composeResources/font/poppins_extra_bold.ttf new file mode 100644 index 0000000..e69de29 diff --git a/composeApp/src/commonMain/composeResources/font/poppins_light.ttf b/composeApp/src/commonMain/composeResources/font/poppins_light.ttf new file mode 100644 index 0000000..e69de29 diff --git a/composeApp/src/commonMain/composeResources/font/poppins_medium.ttf b/composeApp/src/commonMain/composeResources/font/poppins_medium.ttf new file mode 100644 index 0000000..e69de29 diff --git a/composeApp/src/commonMain/composeResources/font/poppins_regular.ttf b/composeApp/src/commonMain/composeResources/font/poppins_regular.ttf new file mode 100644 index 0000000..e69de29 diff --git a/app/src/main/res/values/strings.xml b/composeApp/src/commonMain/composeResources/values/strings.xml similarity index 88% rename from app/src/main/res/values/strings.xml rename to composeApp/src/commonMain/composeResources/values/strings.xml index e8856e0..49e9665 100644 --- a/app/src/main/res/values/strings.xml +++ b/composeApp/src/commonMain/composeResources/values/strings.xml @@ -1,5 +1,4 @@ - Song Quest Registering... Register Error 😖 diff --git a/composeApp/src/commonMain/kotlin/com/spongycode/songquest/App.kt b/composeApp/src/commonMain/kotlin/com/spongycode/songquest/App.kt new file mode 100644 index 0000000..b96c66e --- /dev/null +++ b/composeApp/src/commonMain/kotlin/com/spongycode/songquest/App.kt @@ -0,0 +1,27 @@ +package com.spongycode.songquest + +import androidx.compose.foundation.layout.fillMaxSize +import androidx.compose.material3.MaterialTheme +import androidx.compose.material3.Surface +import androidx.compose.runtime.Composable +import androidx.compose.ui.Modifier +import com.spongycode.songquest.di.AppContainer +import com.spongycode.songquest.ui.navigation.NavContainer +import com.spongycode.songquest.ui.theme.SongQuestTheme +import com.spongycode.songquest.util.Constants.SPLASH_SCREEN + +@Composable +fun App() { + AppContainer.init() + SongQuestTheme { + Surface( + modifier = Modifier.fillMaxSize(), + color = MaterialTheme.colorScheme.background + ) { + NavContainer( + startDestination = SPLASH_SCREEN, + appContainer = AppContainer + ) + } + } +} \ No newline at end of file diff --git a/composeApp/src/commonMain/kotlin/com/spongycode/songquest/AudioPlayer.kt b/composeApp/src/commonMain/kotlin/com/spongycode/songquest/AudioPlayer.kt new file mode 100644 index 0000000..226bafa --- /dev/null +++ b/composeApp/src/commonMain/kotlin/com/spongycode/songquest/AudioPlayer.kt @@ -0,0 +1,8 @@ +package com.spongycode.songquest + +expect class AudioPlayer() { + fun setSource(url: String) + fun prepareAndPlay(looping: Boolean = true) + fun stop() + fun release() +} \ No newline at end of file diff --git a/composeApp/src/commonMain/kotlin/com/spongycode/songquest/BitmapShare.kt b/composeApp/src/commonMain/kotlin/com/spongycode/songquest/BitmapShare.kt new file mode 100644 index 0000000..730ccb1 --- /dev/null +++ b/composeApp/src/commonMain/kotlin/com/spongycode/songquest/BitmapShare.kt @@ -0,0 +1,5 @@ +package com.spongycode.songquest + +import androidx.compose.ui.graphics.ImageBitmap + +expect fun ImageBitmap.share(context: PlatformContext, score: Int?, category: String?) diff --git a/composeApp/src/commonMain/kotlin/com/spongycode/songquest/Platform.kt b/composeApp/src/commonMain/kotlin/com/spongycode/songquest/Platform.kt new file mode 100644 index 0000000..b43159b --- /dev/null +++ b/composeApp/src/commonMain/kotlin/com/spongycode/songquest/Platform.kt @@ -0,0 +1,10 @@ +package com.spongycode.songquest + +expect fun platform(): String +expect fun getScreenWidth(): Float +expect fun getScreenHeight(): Float + +expect object PlatformContext { + fun setContext(context: Any) + fun getContext(): Any? +} \ No newline at end of file diff --git a/app/src/main/java/com/spongycode/songquest/data/model/ApiResponse.kt b/composeApp/src/commonMain/kotlin/com/spongycode/songquest/data/model/ApiResponse.kt similarity index 100% rename from app/src/main/java/com/spongycode/songquest/data/model/ApiResponse.kt rename to composeApp/src/commonMain/kotlin/com/spongycode/songquest/data/model/ApiResponse.kt diff --git a/app/src/main/java/com/spongycode/songquest/data/model/auth/AuthModel.kt b/composeApp/src/commonMain/kotlin/com/spongycode/songquest/data/model/auth/AuthModel.kt similarity index 100% rename from app/src/main/java/com/spongycode/songquest/data/model/auth/AuthModel.kt rename to composeApp/src/commonMain/kotlin/com/spongycode/songquest/data/model/auth/AuthModel.kt diff --git a/app/src/main/java/com/spongycode/songquest/data/model/auth/UserModel.kt b/composeApp/src/commonMain/kotlin/com/spongycode/songquest/data/model/auth/UserModel.kt similarity index 100% rename from app/src/main/java/com/spongycode/songquest/data/model/auth/UserModel.kt rename to composeApp/src/commonMain/kotlin/com/spongycode/songquest/data/model/auth/UserModel.kt diff --git a/app/src/main/java/com/spongycode/songquest/data/model/gameplay/CheckAnswerModel.kt b/composeApp/src/commonMain/kotlin/com/spongycode/songquest/data/model/gameplay/CheckAnswerModel.kt similarity index 100% rename from app/src/main/java/com/spongycode/songquest/data/model/gameplay/CheckAnswerModel.kt rename to composeApp/src/commonMain/kotlin/com/spongycode/songquest/data/model/gameplay/CheckAnswerModel.kt diff --git a/app/src/main/java/com/spongycode/songquest/data/model/gameplay/CreateGameModel.kt b/composeApp/src/commonMain/kotlin/com/spongycode/songquest/data/model/gameplay/CreateGameModel.kt similarity index 100% rename from app/src/main/java/com/spongycode/songquest/data/model/gameplay/CreateGameModel.kt rename to composeApp/src/commonMain/kotlin/com/spongycode/songquest/data/model/gameplay/CreateGameModel.kt diff --git a/app/src/main/java/com/spongycode/songquest/data/model/gameplay/GameModel.kt b/composeApp/src/commonMain/kotlin/com/spongycode/songquest/data/model/gameplay/GameModel.kt similarity index 100% rename from app/src/main/java/com/spongycode/songquest/data/model/gameplay/GameModel.kt rename to composeApp/src/commonMain/kotlin/com/spongycode/songquest/data/model/gameplay/GameModel.kt diff --git a/app/src/main/java/com/spongycode/songquest/data/model/gameplay/HistoryModel.kt b/composeApp/src/commonMain/kotlin/com/spongycode/songquest/data/model/gameplay/HistoryModel.kt similarity index 100% rename from app/src/main/java/com/spongycode/songquest/data/model/gameplay/HistoryModel.kt rename to composeApp/src/commonMain/kotlin/com/spongycode/songquest/data/model/gameplay/HistoryModel.kt diff --git a/app/src/main/java/com/spongycode/songquest/data/model/gameplay/LeaderboardModel.kt b/composeApp/src/commonMain/kotlin/com/spongycode/songquest/data/model/gameplay/LeaderboardModel.kt similarity index 100% rename from app/src/main/java/com/spongycode/songquest/data/model/gameplay/LeaderboardModel.kt rename to composeApp/src/commonMain/kotlin/com/spongycode/songquest/data/model/gameplay/LeaderboardModel.kt diff --git a/app/src/main/java/com/spongycode/songquest/data/model/gameplay/OptionModel.kt b/composeApp/src/commonMain/kotlin/com/spongycode/songquest/data/model/gameplay/OptionModel.kt similarity index 100% rename from app/src/main/java/com/spongycode/songquest/data/model/gameplay/OptionModel.kt rename to composeApp/src/commonMain/kotlin/com/spongycode/songquest/data/model/gameplay/OptionModel.kt diff --git a/app/src/main/java/com/spongycode/songquest/data/model/gameplay/PlayingModel.kt b/composeApp/src/commonMain/kotlin/com/spongycode/songquest/data/model/gameplay/PlayingModel.kt similarity index 100% rename from app/src/main/java/com/spongycode/songquest/data/model/gameplay/PlayingModel.kt rename to composeApp/src/commonMain/kotlin/com/spongycode/songquest/data/model/gameplay/PlayingModel.kt diff --git a/app/src/main/java/com/spongycode/songquest/data/model/gameplay/QuestionModel.kt b/composeApp/src/commonMain/kotlin/com/spongycode/songquest/data/model/gameplay/QuestionModel.kt similarity index 100% rename from app/src/main/java/com/spongycode/songquest/data/model/gameplay/QuestionModel.kt rename to composeApp/src/commonMain/kotlin/com/spongycode/songquest/data/model/gameplay/QuestionModel.kt diff --git a/composeApp/src/commonMain/kotlin/com/spongycode/songquest/di/AppContainer.kt b/composeApp/src/commonMain/kotlin/com/spongycode/songquest/di/AppContainer.kt new file mode 100644 index 0000000..2d385ff --- /dev/null +++ b/composeApp/src/commonMain/kotlin/com/spongycode/songquest/di/AppContainer.kt @@ -0,0 +1,69 @@ +package com.spongycode.songquest.di + +import com.spongycode.songquest.repository.AuthRepositoryImpl +import com.spongycode.songquest.repository.GameplayRepositoryImpl +import com.spongycode.songquest.repository.SettingsRepository +import com.spongycode.songquest.repository.SettingsRepositoryImpl +import com.spongycode.songquest.ui.screen.auth.forgot_password.ForgotPasswordViewModel +import com.spongycode.songquest.ui.screen.auth.login.LoginViewModel +import com.spongycode.songquest.ui.screen.auth.register.RegisterViewModel +import com.spongycode.songquest.ui.screen.gameplay.gameover.GameOverViewModel +import com.spongycode.songquest.ui.screen.gameplay.history.HistoryViewModel +import com.spongycode.songquest.ui.screen.gameplay.home.HomeViewModel +import com.spongycode.songquest.ui.screen.gameplay.leaderboard.LeaderboardViewModel +import com.spongycode.songquest.ui.screen.gameplay.playing.PlayingViewModel +import com.spongycode.songquest.ui.screen.gameplay.profile.ProfileViewModel +import com.spongycode.songquest.ui.screen.starter.SplashViewModel +import com.spongycode.songquest.util.BasePreferenceManager +import io.ktor.client.HttpClient +import io.ktor.client.plugins.contentnegotiation.ContentNegotiation +import io.ktor.client.plugins.logging.LogLevel +import io.ktor.client.plugins.logging.Logger +import io.ktor.client.plugins.logging.Logging +import io.ktor.serialization.kotlinx.json.json +import kotlinx.serialization.json.Json + + +class AppPreferenceManager : BasePreferenceManager() + +object AppContainer { + val client: HttpClient by lazy { provideClient() } + + lateinit var settingsRepository: SettingsRepository + + val splashViewModel by lazy { SplashViewModel(authRepository, settingsRepository) } + val registerViewModel by lazy { RegisterViewModel(authRepository, settingsRepository) } + val loginViewModel by lazy { LoginViewModel(authRepository, settingsRepository) } + val forgotPasswordViewModel by lazy { ForgotPasswordViewModel(authRepository) } + val homeViewModel by lazy { HomeViewModel(settingsRepository) } + val playingViewModel by lazy { PlayingViewModel(gameplayRepository, settingsRepository) } + val gameOverViewModel by lazy { GameOverViewModel(settingsRepository, gameplayRepository) } + val profileViewModel by lazy { ProfileViewModel(authRepository, settingsRepository) } + val historyViewModel by lazy { HistoryViewModel(gameplayRepository, settingsRepository) } + val leaderboardViewModel by lazy { + LeaderboardViewModel( + settingsRepository, + gameplayRepository + ) + } + private val gameplayRepository by lazy { GameplayRepositoryImpl(client) } + private val authRepository by lazy { AuthRepositoryImpl(client) } + + fun init() { + settingsRepository = SettingsRepositoryImpl(AppPreferenceManager()) + } + + private fun provideClient(): HttpClient = HttpClient { + install(ContentNegotiation) { + json(Json { ignoreUnknownKeys = true; coerceInputValues = true }) + } + install(Logging) { + logger = object : Logger { + override fun log(message: String) { + println("http $message") + } + } + level = LogLevel.ALL + } + } +} diff --git a/app/src/main/java/com/spongycode/songquest/domain/repository/AuthRepository.kt b/composeApp/src/commonMain/kotlin/com/spongycode/songquest/repository/AuthRepository.kt similarity index 94% rename from app/src/main/java/com/spongycode/songquest/domain/repository/AuthRepository.kt rename to composeApp/src/commonMain/kotlin/com/spongycode/songquest/repository/AuthRepository.kt index 95322b1..980055f 100644 --- a/app/src/main/java/com/spongycode/songquest/domain/repository/AuthRepository.kt +++ b/composeApp/src/commonMain/kotlin/com/spongycode/songquest/repository/AuthRepository.kt @@ -1,4 +1,4 @@ -package com.spongycode.songquest.domain.repository +package com.spongycode.songquest.repository import com.spongycode.songquest.data.model.ApiResponse import com.spongycode.songquest.data.model.auth.AuthModel diff --git a/app/src/main/java/com/spongycode/songquest/data/repository/AuthRepositoryImpl.kt b/composeApp/src/commonMain/kotlin/com/spongycode/songquest/repository/AuthRepositoryImpl.kt similarity index 84% rename from app/src/main/java/com/spongycode/songquest/data/repository/AuthRepositoryImpl.kt rename to composeApp/src/commonMain/kotlin/com/spongycode/songquest/repository/AuthRepositoryImpl.kt index 3333a09..2606a05 100644 --- a/app/src/main/java/com/spongycode/songquest/data/repository/AuthRepositoryImpl.kt +++ b/composeApp/src/commonMain/kotlin/com/spongycode/songquest/repository/AuthRepositoryImpl.kt @@ -1,10 +1,9 @@ -package com.spongycode.songquest.data.repository +package com.spongycode.songquest.repository import com.spongycode.songquest.data.model.ApiResponse import com.spongycode.songquest.data.model.auth.AuthModel import com.spongycode.songquest.data.model.auth.UserModel -import com.spongycode.songquest.domain.repository.AuthRepository -import com.spongycode.songquest.util.Constants.BASE_URL +import com.spongycode.songquest.util.Constants import com.spongycode.songquest.util.Network.executeWithRetry import io.ktor.client.HttpClient import io.ktor.client.call.body @@ -14,9 +13,8 @@ import io.ktor.client.request.setBody import io.ktor.client.request.url import io.ktor.http.ContentType import io.ktor.http.contentType -import javax.inject.Inject -class AuthRepositoryImpl @Inject constructor( +class AuthRepositoryImpl( private val client: HttpClient ) : AuthRepository { override suspend fun register( @@ -26,7 +24,7 @@ class AuthRepositoryImpl @Inject constructor( ): ApiResponse? { return executeWithRetry { val res = client.post { - url("${BASE_URL}api/mobile/users/register") + url("${Constants.BASE_URL}api/mobile/users/register") contentType(ContentType.Application.Json) setBody( UserModel( @@ -46,7 +44,7 @@ class AuthRepositoryImpl @Inject constructor( ): ApiResponse? { return executeWithRetry { val res = client.post { - url("${BASE_URL}api/mobile/users/login") + url("${Constants.BASE_URL}api/mobile/users/login") contentType(ContentType.Application.Json) setBody( UserModel( @@ -65,7 +63,7 @@ class AuthRepositoryImpl @Inject constructor( ): ApiResponse? { return executeWithRetry { val res = client.post { - url("${BASE_URL}api/mobile/users/resetpassword") + url("${Constants.BASE_URL}api/mobile/users/resetpassword") contentType(ContentType.Application.Json) setBody( UserModel( @@ -80,7 +78,7 @@ class AuthRepositoryImpl @Inject constructor( override suspend fun changePassword(userModel: UserModel): ApiResponse? { return executeWithRetry { val res = client.post { - url("${BASE_URL}api/mobile/users/password") + url("${Constants.BASE_URL}api/mobile/users/password") contentType(ContentType.Application.Json) setBody(userModel) } @@ -93,7 +91,7 @@ class AuthRepositoryImpl @Inject constructor( ): ApiResponse? { return executeWithRetry { val res = client.post { - url("${BASE_URL}api/mobile/users/refreshtoken") + url("${Constants.BASE_URL}api/mobile/users/refreshtoken") contentType(ContentType.Application.Json) setBody( UserModel( @@ -108,7 +106,7 @@ class AuthRepositoryImpl @Inject constructor( override suspend fun updateProfile(userModel: UserModel): ApiResponse? { return executeWithRetry { val res = client.patch { - url("${BASE_URL}api/mobile/users/profile") + url("${Constants.BASE_URL}api/mobile/users/profile") contentType(ContentType.Application.Json) setBody(userModel) } diff --git a/app/src/main/java/com/spongycode/songquest/domain/repository/GameplayRepository.kt b/composeApp/src/commonMain/kotlin/com/spongycode/songquest/repository/GameplayRepository.kt similarity index 94% rename from app/src/main/java/com/spongycode/songquest/domain/repository/GameplayRepository.kt rename to composeApp/src/commonMain/kotlin/com/spongycode/songquest/repository/GameplayRepository.kt index e344465..de35a5a 100644 --- a/app/src/main/java/com/spongycode/songquest/domain/repository/GameplayRepository.kt +++ b/composeApp/src/commonMain/kotlin/com/spongycode/songquest/repository/GameplayRepository.kt @@ -1,4 +1,4 @@ -package com.spongycode.songquest.domain.repository +package com.spongycode.songquest.repository import com.spongycode.songquest.data.model.ApiResponse import com.spongycode.songquest.data.model.auth.AuthModel diff --git a/app/src/main/java/com/spongycode/songquest/data/repository/GameplayRepositoryImpl.kt b/composeApp/src/commonMain/kotlin/com/spongycode/songquest/repository/GameplayRepositoryImpl.kt similarity index 75% rename from app/src/main/java/com/spongycode/songquest/data/repository/GameplayRepositoryImpl.kt rename to composeApp/src/commonMain/kotlin/com/spongycode/songquest/repository/GameplayRepositoryImpl.kt index 3885549..9aa50b5 100644 --- a/app/src/main/java/com/spongycode/songquest/data/repository/GameplayRepositoryImpl.kt +++ b/composeApp/src/commonMain/kotlin/com/spongycode/songquest/repository/GameplayRepositoryImpl.kt @@ -1,4 +1,4 @@ -package com.spongycode.songquest.data.repository +package com.spongycode.songquest.repository import com.spongycode.songquest.data.model.ApiResponse import com.spongycode.songquest.data.model.auth.AuthModel @@ -7,9 +7,8 @@ import com.spongycode.songquest.data.model.gameplay.CreateGameModel import com.spongycode.songquest.data.model.gameplay.HistoryModel import com.spongycode.songquest.data.model.gameplay.LeaderboardModel import com.spongycode.songquest.data.model.gameplay.PlayingModel -import com.spongycode.songquest.domain.repository.GameplayRepository -import com.spongycode.songquest.util.Constants.BASE_URL -import com.spongycode.songquest.util.Network.executeWithRetry +import com.spongycode.songquest.util.Constants +import com.spongycode.songquest.util.Network import io.ktor.client.HttpClient import io.ktor.client.call.body import io.ktor.client.request.post @@ -17,15 +16,14 @@ import io.ktor.client.request.setBody import io.ktor.client.request.url import io.ktor.http.ContentType import io.ktor.http.contentType -import javax.inject.Inject -class GameplayRepositoryImpl @Inject constructor( +class GameplayRepositoryImpl( private val client: HttpClient ) : GameplayRepository { override suspend fun createGame(createGameModel: CreateGameModel): ApiResponse? { - return executeWithRetry { + return Network.executeWithRetry { val res = client.post { - url("${BASE_URL}api/mobile/gameplay/create") + url("${Constants.BASE_URL}api/mobile/gameplay/create") contentType(ContentType.Application.Json) setBody(createGameModel) } @@ -38,9 +36,9 @@ class GameplayRepositoryImpl @Inject constructor( } override suspend fun checkAnswer(checkAnswerModel: CheckAnswerModel): ApiResponse? { - return executeWithRetry { + return Network.executeWithRetry { val res = client.post { - url("${BASE_URL}api/mobile/gameplay/check") + url("${Constants.BASE_URL}api/mobile/gameplay/check") contentType(ContentType.Application.Json) setBody(checkAnswerModel) } @@ -49,9 +47,9 @@ class GameplayRepositoryImpl @Inject constructor( } override suspend fun saveGame(checkAnswerModel: CheckAnswerModel): ApiResponse? { - return executeWithRetry { + return Network.executeWithRetry { val res = client.post { - url("${BASE_URL}api/mobile/gameplay/save") + url("${Constants.BASE_URL}api/mobile/gameplay/save") contentType(ContentType.Application.Json) setBody(checkAnswerModel) } @@ -60,9 +58,9 @@ class GameplayRepositoryImpl @Inject constructor( } override suspend fun history(authModel: AuthModel): ApiResponse? { - return executeWithRetry { + return Network.executeWithRetry { val res = client.post { - url("${BASE_URL}api/mobile/gameplay/history") + url("${Constants.BASE_URL}api/mobile/gameplay/history") contentType(ContentType.Application.Json) setBody(authModel) } @@ -71,9 +69,9 @@ class GameplayRepositoryImpl @Inject constructor( } override suspend fun leaderboard(authModel: AuthModel): ApiResponse>? { - return executeWithRetry { + return Network.executeWithRetry { val res = client.post { - url("${BASE_URL}api/mobile/gameplay/highscore") + url("${Constants.BASE_URL}api/mobile/gameplay/highscore") contentType(ContentType.Application.Json) setBody(authModel) } diff --git a/composeApp/src/commonMain/kotlin/com/spongycode/songquest/repository/SettingsRepository.kt b/composeApp/src/commonMain/kotlin/com/spongycode/songquest/repository/SettingsRepository.kt new file mode 100644 index 0000000..3a5eeae --- /dev/null +++ b/composeApp/src/commonMain/kotlin/com/spongycode/songquest/repository/SettingsRepository.kt @@ -0,0 +1,7 @@ +package com.spongycode.songquest.repository + +interface SettingsRepository { + suspend fun getString(key: String): String? + suspend fun storeString(key: String, value: String) + suspend fun storeListString(list: List>) +} diff --git a/composeApp/src/commonMain/kotlin/com/spongycode/songquest/repository/SettingsRepositoryImpl.kt b/composeApp/src/commonMain/kotlin/com/spongycode/songquest/repository/SettingsRepositoryImpl.kt new file mode 100644 index 0000000..0c19e2c --- /dev/null +++ b/composeApp/src/commonMain/kotlin/com/spongycode/songquest/repository/SettingsRepositoryImpl.kt @@ -0,0 +1,30 @@ +package com.spongycode.songquest.repository + +import com.spongycode.songquest.util.BasePreferenceManager + +class SettingsRepositoryImpl( + private val prefs: BasePreferenceManager +) : SettingsRepository { + + override suspend fun getString(key: String): String? { + return prefs.getStringOrNull(key) + } + + override suspend fun storeString(key: String, value: String) { + prefs.putString(key, value) + } + + override suspend fun storeListString(list: List>) { + list.forEach { (key, value) -> + prefs.putString(key, value) + } + } + + companion object { + const val ACCESS_TOKEN_SESSION = "ACCESS_TOKEN_SESSION" + const val REFRESH_TOKEN_SESSION = "REFRESH_TOKEN_SESSION" + const val USERNAME_SESSION = "USERNAME_SESSION" + const val EMAIL_SESSION = "EMAIL_SESSION" + const val GAMES_PLAYED_SESSION = "GAMES_PLAYED_SESSION" + } +} diff --git a/composeApp/src/commonMain/kotlin/com/spongycode/songquest/ui/navigation/NavContainer.kt b/composeApp/src/commonMain/kotlin/com/spongycode/songquest/ui/navigation/NavContainer.kt new file mode 100644 index 0000000..496d017 --- /dev/null +++ b/composeApp/src/commonMain/kotlin/com/spongycode/songquest/ui/navigation/NavContainer.kt @@ -0,0 +1,70 @@ +package com.spongycode.songquest.ui.navigation + +import androidx.compose.runtime.Composable +import androidx.compose.runtime.CompositionLocalProvider +import androidx.compose.runtime.compositionLocalOf +import androidx.navigation.NavHostController +import androidx.navigation.compose.NavHost +import androidx.navigation.compose.composable +import androidx.navigation.compose.rememberNavController +import androidx.savedstate.read +import com.spongycode.songquest.di.AppContainer +import com.spongycode.songquest.ui.screen.auth.forgot_password.ForgotPasswordScreenRoot +import com.spongycode.songquest.ui.screen.auth.login.LoginScreenRoot +import com.spongycode.songquest.ui.screen.auth.register.RegisterScreenRoot +import com.spongycode.songquest.ui.screen.gameplay.gameover.GameOverScreenRoot +import com.spongycode.songquest.ui.screen.gameplay.history.HistoryScreenRoot +import com.spongycode.songquest.ui.screen.gameplay.home.HomeScreenRoot +import com.spongycode.songquest.ui.screen.gameplay.leaderboard.LeaderboardScreenRoot +import com.spongycode.songquest.ui.screen.gameplay.playing.PlayingScreenRoot +import com.spongycode.songquest.ui.screen.gameplay.profile.ProfileScreenRoot +import com.spongycode.songquest.ui.screen.starter.SplashScreenRoot +import com.spongycode.songquest.util.Constants.BOLLYWOOD_CODE +import com.spongycode.songquest.util.Constants.CATEGORY +import com.spongycode.songquest.util.Constants.FORGOT_PASSWORD_SCREEN +import com.spongycode.songquest.util.Constants.GAME_ID +import com.spongycode.songquest.util.Constants.GAME_OVER_SCREEN +import com.spongycode.songquest.util.Constants.HISTORY_SCREEN +import com.spongycode.songquest.util.Constants.HOME_SCREEN +import com.spongycode.songquest.util.Constants.LEADERBOARD_SCREEN +import com.spongycode.songquest.util.Constants.LOGIN_SCREEN +import com.spongycode.songquest.util.Constants.PLAYING_SCREEN +import com.spongycode.songquest.util.Constants.PROFILE_SCREEN +import com.spongycode.songquest.util.Constants.REGISTER_SCREEN +import com.spongycode.songquest.util.Constants.SPLASH_SCREEN +import io.ktor.websocket.FrameType.Companion.get + +val LocalNavController = compositionLocalOf { error("No NavController") } + +@Composable +fun NavContainer( + startDestination: String, + appContainer: AppContainer +) { + val navController = rememberNavController() + CompositionLocalProvider(LocalNavController provides navController) { + NavHost(navController, startDestination) { + composable(SPLASH_SCREEN) { SplashScreenRoot(appContainer.splashViewModel) } + composable(REGISTER_SCREEN) { RegisterScreenRoot(viewModel = appContainer.registerViewModel) } + composable(LOGIN_SCREEN) { LoginScreenRoot(viewModel = appContainer.loginViewModel) } + composable(FORGOT_PASSWORD_SCREEN) { ForgotPasswordScreenRoot(viewModel = appContainer.forgotPasswordViewModel) } + composable(HOME_SCREEN) { HomeScreenRoot(viewModel = appContainer.homeViewModel) } + composable("$PLAYING_SCREEN/{$CATEGORY}") { + val category = it.arguments?.read { getStringOrNull(CATEGORY) } + PlayingScreenRoot( + category = category ?: BOLLYWOOD_CODE, + viewModel = appContainer.playingViewModel + ) + } + composable("$GAME_OVER_SCREEN/{$GAME_ID}") { + GameOverScreenRoot( + gameId = it.arguments?.read { getStringOrNull(GAME_ID) }.toString(), + viewModel = appContainer.gameOverViewModel + ) + } + composable(PROFILE_SCREEN) { ProfileScreenRoot(viewModel = appContainer.profileViewModel) } + composable(HISTORY_SCREEN) { HistoryScreenRoot(viewModel = appContainer.historyViewModel) } + composable(LEADERBOARD_SCREEN) { LeaderboardScreenRoot(viewModel = appContainer.leaderboardViewModel) } + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/spongycode/songquest/ui/screen/auth/components/CustomAnnotatedString.kt b/composeApp/src/commonMain/kotlin/com/spongycode/songquest/ui/screen/auth/components/CustomAnnotatedString.kt similarity index 88% rename from app/src/main/java/com/spongycode/songquest/ui/screen/auth/components/CustomAnnotatedString.kt rename to composeApp/src/commonMain/kotlin/com/spongycode/songquest/ui/screen/auth/components/CustomAnnotatedString.kt index fd40058..0c3158d 100644 --- a/app/src/main/java/com/spongycode/songquest/ui/screen/auth/components/CustomAnnotatedString.kt +++ b/composeApp/src/commonMain/kotlin/com/spongycode/songquest/ui/screen/auth/components/CustomAnnotatedString.kt @@ -11,7 +11,7 @@ import androidx.compose.ui.text.buildAnnotatedString import androidx.compose.ui.text.font.FontWeight import androidx.compose.ui.text.style.TextDecoration import androidx.compose.ui.text.withStyle -import com.spongycode.songquest.util.Fonts +import com.spongycode.songquest.util.defaultFontFamily @Composable fun CustomAnnotatedString( @@ -25,7 +25,7 @@ fun CustomAnnotatedString( withStyle( style = SpanStyle( color = MaterialTheme.colorScheme.primary, - fontFamily = Fonts.poppinsFamily + fontFamily = defaultFontFamily ) ) { append(str1) @@ -37,7 +37,7 @@ fun CustomAnnotatedString( withStyle( style = SpanStyle( color = Color(0xFF267BC4), textDecoration = TextDecoration.Underline, - fontFamily = Fonts.poppinsFamily, fontWeight = FontWeight.W600 + fontFamily = defaultFontFamily, fontWeight = FontWeight.W600 ) ) { append(str2) diff --git a/app/src/main/java/com/spongycode/songquest/ui/screen/auth/components/CustomButton.kt b/composeApp/src/commonMain/kotlin/com/spongycode/songquest/ui/screen/auth/components/CustomButton.kt similarity index 93% rename from app/src/main/java/com/spongycode/songquest/ui/screen/auth/components/CustomButton.kt rename to composeApp/src/commonMain/kotlin/com/spongycode/songquest/ui/screen/auth/components/CustomButton.kt index 9d40adb..5712f47 100644 --- a/app/src/main/java/com/spongycode/songquest/ui/screen/auth/components/CustomButton.kt +++ b/composeApp/src/commonMain/kotlin/com/spongycode/songquest/ui/screen/auth/components/CustomButton.kt @@ -12,7 +12,7 @@ import androidx.compose.ui.graphics.Color import androidx.compose.ui.text.font.FontWeight import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.sp -import com.spongycode.songquest.util.Fonts +import com.spongycode.songquest.util.defaultFontFamily import com.spongycode.songquest.util.bounceClick @Composable @@ -39,7 +39,7 @@ fun CustomButton( color = Color.White, modifier = Modifier.padding(8.dp), text = displayText, - fontFamily = Fonts.poppinsFamily, + fontFamily = defaultFontFamily, fontWeight = FontWeight.W600, fontSize = 15.sp ) diff --git a/app/src/main/java/com/spongycode/songquest/ui/screen/auth/components/CustomTextField.kt b/composeApp/src/commonMain/kotlin/com/spongycode/songquest/ui/screen/auth/components/CustomTextField.kt similarity index 84% rename from app/src/main/java/com/spongycode/songquest/ui/screen/auth/components/CustomTextField.kt rename to composeApp/src/commonMain/kotlin/com/spongycode/songquest/ui/screen/auth/components/CustomTextField.kt index 24d3d2e..6445e5a 100644 --- a/app/src/main/java/com/spongycode/songquest/ui/screen/auth/components/CustomTextField.kt +++ b/composeApp/src/commonMain/kotlin/com/spongycode/songquest/ui/screen/auth/components/CustomTextField.kt @@ -17,7 +17,6 @@ import androidx.compose.ui.focus.FocusRequester import androidx.compose.ui.focus.focusRequester import androidx.compose.ui.graphics.Color import androidx.compose.ui.graphics.Shape -import androidx.compose.ui.res.painterResource import androidx.compose.ui.text.TextStyle import androidx.compose.ui.text.font.FontWeight import androidx.compose.ui.text.input.KeyboardType @@ -25,8 +24,11 @@ import androidx.compose.ui.text.input.PasswordVisualTransformation import androidx.compose.ui.text.input.VisualTransformation import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.sp -import com.spongycode.songquest.R -import com.spongycode.songquest.util.Fonts +import com.spongycode.songquest.util.defaultFontFamily +import org.jetbrains.compose.resources.painterResource +import song_quest.composeapp.generated.resources.Res +import song_quest.composeapp.generated.resources.baseline_visibility_24 +import song_quest.composeapp.generated.resources.baseline_visibility_off_24 @Composable fun CustomTextField( @@ -55,13 +57,13 @@ fun CustomTextField( onValueChange(it) }, label = { - Text(text = labelText, fontFamily = Fonts.poppinsFamily) + Text(text = labelText, fontFamily = defaultFontFamily) }, placeholder = { Text( color = MaterialTheme.colorScheme.inversePrimary, text = placeHolderText, - fontFamily = Fonts.poppinsFamily + fontFamily = defaultFontFamily ) }, keyboardOptions = KeyboardOptions( @@ -89,8 +91,8 @@ fun CustomTextField( trailingIcon = if (isPasswordToggleDisplayed) { val icon: @Composable () -> Unit = { Icon( - painter = if (isPasswordVisible) painterResource(id = R.drawable.baseline_visibility_24) - else painterResource(id = R.drawable.baseline_visibility_off_24), + painter = if (isPasswordVisible.not()) painterResource(resource = Res.drawable.baseline_visibility_24) + else painterResource(resource = Res.drawable.baseline_visibility_off_24), contentDescription = null, modifier = Modifier .size(30.dp) @@ -103,7 +105,7 @@ fun CustomTextField( textStyle = TextStyle( fontWeight = FontWeight.W500, fontSize = 18.sp, - fontFamily = Fonts.poppinsFamily + fontFamily = defaultFontFamily ) ) } diff --git a/app/src/main/java/com/spongycode/songquest/ui/screen/auth/components/TitleText.kt b/composeApp/src/commonMain/kotlin/com/spongycode/songquest/ui/screen/auth/components/TitleText.kt similarity index 82% rename from app/src/main/java/com/spongycode/songquest/ui/screen/auth/components/TitleText.kt rename to composeApp/src/commonMain/kotlin/com/spongycode/songquest/ui/screen/auth/components/TitleText.kt index e25a9fe..a28a570 100644 --- a/app/src/main/java/com/spongycode/songquest/ui/screen/auth/components/TitleText.kt +++ b/composeApp/src/commonMain/kotlin/com/spongycode/songquest/ui/screen/auth/components/TitleText.kt @@ -5,7 +5,7 @@ import androidx.compose.runtime.Composable import androidx.compose.ui.graphics.Color import androidx.compose.ui.text.font.FontWeight import androidx.compose.ui.unit.sp -import com.spongycode.songquest.util.Fonts +import com.spongycode.songquest.util.defaultFontFamily @Composable fun TitleText(title: String) { @@ -13,7 +13,7 @@ fun TitleText(title: String) { text = title, fontSize = 30.sp, fontWeight = FontWeight.W600, - fontFamily = Fonts.poppinsFamily, + fontFamily = defaultFontFamily, color = Color.Black ) } \ No newline at end of file diff --git a/app/src/main/java/com/spongycode/songquest/ui/screen/auth/forgot_password/ForgotPasswordScreen.kt b/composeApp/src/commonMain/kotlin/com/spongycode/songquest/ui/screen/auth/forgot_password/ForgotPasswordScreen.kt similarity index 95% rename from app/src/main/java/com/spongycode/songquest/ui/screen/auth/forgot_password/ForgotPasswordScreen.kt rename to composeApp/src/commonMain/kotlin/com/spongycode/songquest/ui/screen/auth/forgot_password/ForgotPasswordScreen.kt index 5543d45..fbab43c 100644 --- a/app/src/main/java/com/spongycode/songquest/ui/screen/auth/forgot_password/ForgotPasswordScreen.kt +++ b/composeApp/src/commonMain/kotlin/com/spongycode/songquest/ui/screen/auth/forgot_password/ForgotPasswordScreen.kt @@ -23,12 +23,8 @@ import androidx.compose.ui.Modifier import androidx.compose.ui.graphics.Color import androidx.compose.ui.platform.LocalFocusManager import androidx.compose.ui.platform.LocalSoftwareKeyboardController -import androidx.compose.ui.res.stringResource import androidx.compose.ui.text.input.KeyboardType -import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.unit.dp -import androidx.hilt.navigation.compose.hiltViewModel -import com.spongycode.songquest.R import com.spongycode.songquest.ui.navigation.LocalNavController import com.spongycode.songquest.ui.screen.auth.components.CustomButton import com.spongycode.songquest.ui.screen.auth.components.CustomTextField @@ -44,10 +40,14 @@ import com.spongycode.songquest.util.ComposeLocalWrapper import com.spongycode.songquest.util.Constants import com.spongycode.songquest.util.Constants.LOGIN_SCREEN import kotlinx.coroutines.flow.collectLatest +import org.jetbrains.compose.resources.stringResource +import org.jetbrains.compose.ui.tooling.preview.Preview +import song_quest.composeapp.generated.resources.Res +import song_quest.composeapp.generated.resources.registration_error @Composable fun ForgotPasswordScreenRoot( - viewModel: ForgotPasswordViewModel = hiltViewModel() + viewModel: ForgotPasswordViewModel ) { val navController = LocalNavController.current val snackBarHostState = remember { SnackbarHostState() } @@ -147,7 +147,7 @@ private fun ForgotPasswordScreen( displayText = when (uiState.forgotPasswordState) { Checking -> "Sending..." Idle -> "Send OTP" - Error -> stringResource(R.string.registration_error) + Error -> stringResource(Res.string.registration_error) Success -> "Check mail 🚀" } ) @@ -207,7 +207,7 @@ private fun ForgotPasswordScreen( displayText = when (uiState.changePasswordState) { Checking -> "Updating password.." Idle -> "Update Password" - Error -> stringResource(R.string.registration_error) + Error -> stringResource(Res.string.registration_error) Success -> "Success, Proceed to Login 🚀" } ) diff --git a/app/src/main/java/com/spongycode/songquest/ui/screen/auth/forgot_password/ForgotPasswordViewModel.kt b/composeApp/src/commonMain/kotlin/com/spongycode/songquest/ui/screen/auth/forgot_password/ForgotPasswordViewModel.kt similarity index 96% rename from app/src/main/java/com/spongycode/songquest/ui/screen/auth/forgot_password/ForgotPasswordViewModel.kt rename to composeApp/src/commonMain/kotlin/com/spongycode/songquest/ui/screen/auth/forgot_password/ForgotPasswordViewModel.kt index c16f5fc..1d325a2 100644 --- a/app/src/main/java/com/spongycode/songquest/ui/screen/auth/forgot_password/ForgotPasswordViewModel.kt +++ b/composeApp/src/commonMain/kotlin/com/spongycode/songquest/ui/screen/auth/forgot_password/ForgotPasswordViewModel.kt @@ -3,19 +3,16 @@ package com.spongycode.songquest.ui.screen.auth.forgot_password import androidx.lifecycle.ViewModel import androidx.lifecycle.viewModelScope import com.spongycode.songquest.data.model.auth.UserModel -import com.spongycode.songquest.domain.repository.AuthRepository +import com.spongycode.songquest.repository.AuthRepository import com.spongycode.songquest.util.ValidationHelper -import dagger.hilt.android.lifecycle.HiltViewModel import kotlinx.coroutines.flow.MutableSharedFlow import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.SharedFlow import kotlinx.coroutines.flow.asSharedFlow import kotlinx.coroutines.flow.asStateFlow import kotlinx.coroutines.launch -import javax.inject.Inject -@HiltViewModel -class ForgotPasswordViewModel @Inject constructor( +class ForgotPasswordViewModel( private val repository: AuthRepository ) : ViewModel() { diff --git a/app/src/main/java/com/spongycode/songquest/ui/screen/auth/login/LoginScreen.kt b/composeApp/src/commonMain/kotlin/com/spongycode/songquest/ui/screen/auth/login/LoginScreen.kt similarity index 92% rename from app/src/main/java/com/spongycode/songquest/ui/screen/auth/login/LoginScreen.kt rename to composeApp/src/commonMain/kotlin/com/spongycode/songquest/ui/screen/auth/login/LoginScreen.kt index c9c7b62..b5eb08e 100644 --- a/app/src/main/java/com/spongycode/songquest/ui/screen/auth/login/LoginScreen.kt +++ b/composeApp/src/commonMain/kotlin/com/spongycode/songquest/ui/screen/auth/login/LoginScreen.kt @@ -25,14 +25,10 @@ import androidx.compose.ui.Modifier import androidx.compose.ui.graphics.Color import androidx.compose.ui.platform.LocalFocusManager import androidx.compose.ui.platform.LocalSoftwareKeyboardController -import androidx.compose.ui.res.stringResource import androidx.compose.ui.text.font.FontWeight import androidx.compose.ui.text.input.KeyboardType import androidx.compose.ui.text.style.TextDecoration -import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.unit.dp -import androidx.hilt.navigation.compose.hiltViewModel -import com.spongycode.songquest.R import com.spongycode.songquest.ui.navigation.LocalNavController import com.spongycode.songquest.ui.screen.auth.components.CustomAnnotatedString import com.spongycode.songquest.ui.screen.auth.components.CustomButton @@ -46,12 +42,17 @@ import com.spongycode.songquest.util.Constants import com.spongycode.songquest.util.Constants.FORGOT_PASSWORD_SCREEN import com.spongycode.songquest.util.Constants.HOME_SCREEN import com.spongycode.songquest.util.Constants.REGISTER_SCREEN -import com.spongycode.songquest.util.Fonts +import com.spongycode.songquest.util.defaultFontFamily import kotlinx.coroutines.flow.collectLatest +import org.jetbrains.compose.resources.stringResource +import org.jetbrains.compose.ui.tooling.preview.Preview +import song_quest.composeapp.generated.resources.Res +import song_quest.composeapp.generated.resources.registration_error +import song_quest.composeapp.generated.resources.start_playing @Composable fun LoginScreenRoot( - viewModel: LoginViewModel = hiltViewModel() + viewModel: LoginViewModel ) { val navController = LocalNavController.current val snackBarHostState = remember { SnackbarHostState() } @@ -146,7 +147,7 @@ fun LoginScreen( text = "Forgot password?", color = Color(0xFF267BC4), textDecoration = TextDecoration.Underline, - fontFamily = Fonts.poppinsFamily, + fontFamily = defaultFontFamily, fontWeight = FontWeight.W600, modifier = Modifier .clickable { @@ -181,8 +182,8 @@ fun LoginScreen( displayText = when (uiState.loginState) { LoginState.Checking -> "Logging in..." LoginState.Idle -> "Login" - LoginState.Error -> stringResource(R.string.registration_error) - LoginState.Success -> stringResource(R.string.start_playing) + LoginState.Error -> stringResource(Res.string.registration_error) + LoginState.Success -> stringResource(Res.string.start_playing) } ) } diff --git a/app/src/main/java/com/spongycode/songquest/ui/screen/auth/login/LoginViewModel.kt b/composeApp/src/commonMain/kotlin/com/spongycode/songquest/ui/screen/auth/login/LoginViewModel.kt similarity index 81% rename from app/src/main/java/com/spongycode/songquest/ui/screen/auth/login/LoginViewModel.kt rename to composeApp/src/commonMain/kotlin/com/spongycode/songquest/ui/screen/auth/login/LoginViewModel.kt index d97e1d0..74c8a18 100644 --- a/app/src/main/java/com/spongycode/songquest/ui/screen/auth/login/LoginViewModel.kt +++ b/composeApp/src/commonMain/kotlin/com/spongycode/songquest/ui/screen/auth/login/LoginViewModel.kt @@ -2,27 +2,25 @@ package com.spongycode.songquest.ui.screen.auth.login import androidx.lifecycle.ViewModel import androidx.lifecycle.viewModelScope -import com.spongycode.songquest.data.repository.DatastoreRepositoryImpl.Companion.accessTokenSession -import com.spongycode.songquest.data.repository.DatastoreRepositoryImpl.Companion.emailSession -import com.spongycode.songquest.data.repository.DatastoreRepositoryImpl.Companion.gamesPlayedSession -import com.spongycode.songquest.data.repository.DatastoreRepositoryImpl.Companion.refreshTokenSession -import com.spongycode.songquest.data.repository.DatastoreRepositoryImpl.Companion.usernameSession -import com.spongycode.songquest.domain.repository.AuthRepository -import com.spongycode.songquest.domain.repository.DatastoreRepository +import com.spongycode.songquest.repository.AuthRepository +import com.spongycode.songquest.repository.SettingsRepository +import com.spongycode.songquest.repository.SettingsRepositoryImpl.Companion.ACCESS_TOKEN_SESSION +import com.spongycode.songquest.repository.SettingsRepositoryImpl.Companion.EMAIL_SESSION +import com.spongycode.songquest.repository.SettingsRepositoryImpl.Companion.GAMES_PLAYED_SESSION +import com.spongycode.songquest.repository.SettingsRepositoryImpl.Companion.REFRESH_TOKEN_SESSION +import com.spongycode.songquest.repository.SettingsRepositoryImpl.Companion.USERNAME_SESSION import com.spongycode.songquest.util.ValidationHelper -import dagger.hilt.android.lifecycle.HiltViewModel import kotlinx.coroutines.flow.MutableSharedFlow import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.SharedFlow import kotlinx.coroutines.flow.asSharedFlow import kotlinx.coroutines.flow.asStateFlow import kotlinx.coroutines.launch -import javax.inject.Inject +import kotlin.collections.listOf -@HiltViewModel -class LoginViewModel @Inject constructor( +class LoginViewModel( private val authRepository: AuthRepository, - private val datastoreRepository: DatastoreRepository + private val settingsRepository: SettingsRepository ) : ViewModel() { private val _uiState = MutableStateFlow(LoginUiState()) val uiState = _uiState.asStateFlow() @@ -82,26 +80,26 @@ class LoginViewModel @Inject constructor( _uiState.value.password ) if (res?.status == "success") { - datastoreRepository.storeListString( + settingsRepository.storeListString( listOf( Pair( - accessTokenSession, + ACCESS_TOKEN_SESSION, res.data?.accessToken.toString() ), Pair( - refreshTokenSession, + REFRESH_TOKEN_SESSION, res.data?.refreshToken.toString() ), Pair( - usernameSession, + USERNAME_SESSION, res.data?.user?.username.toString() ), Pair( - emailSession, + EMAIL_SESSION, res.data?.user?.email.toString() ), Pair( - gamesPlayedSession, + GAMES_PLAYED_SESSION, res.data?.user?.gamesPlayed.toString() ) ) diff --git a/app/src/main/java/com/spongycode/songquest/ui/screen/auth/register/RegisterScreen.kt b/composeApp/src/commonMain/kotlin/com/spongycode/songquest/ui/screen/auth/register/RegisterScreen.kt similarity index 91% rename from app/src/main/java/com/spongycode/songquest/ui/screen/auth/register/RegisterScreen.kt rename to composeApp/src/commonMain/kotlin/com/spongycode/songquest/ui/screen/auth/register/RegisterScreen.kt index 407dfe4..f882ae0 100644 --- a/app/src/main/java/com/spongycode/songquest/ui/screen/auth/register/RegisterScreen.kt +++ b/composeApp/src/commonMain/kotlin/com/spongycode/songquest/ui/screen/auth/register/RegisterScreen.kt @@ -23,12 +23,8 @@ import androidx.compose.ui.Modifier import androidx.compose.ui.graphics.Color import androidx.compose.ui.platform.LocalFocusManager import androidx.compose.ui.platform.LocalSoftwareKeyboardController -import androidx.compose.ui.res.stringResource import androidx.compose.ui.text.input.KeyboardType -import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.unit.dp -import androidx.hilt.navigation.compose.hiltViewModel -import com.spongycode.songquest.R import com.spongycode.songquest.ui.navigation.LocalNavController import com.spongycode.songquest.ui.screen.auth.components.CustomAnnotatedString import com.spongycode.songquest.ui.screen.auth.components.CustomButton @@ -51,10 +47,17 @@ import com.spongycode.songquest.util.Constants import com.spongycode.songquest.util.Constants.HOME_SCREEN import com.spongycode.songquest.util.Constants.LOGIN_SCREEN import kotlinx.coroutines.flow.collectLatest +import org.jetbrains.compose.resources.stringResource +import org.jetbrains.compose.ui.tooling.preview.Preview +import song_quest.composeapp.generated.resources.Res +import song_quest.composeapp.generated.resources.register +import song_quest.composeapp.generated.resources.registering +import song_quest.composeapp.generated.resources.registration_error +import song_quest.composeapp.generated.resources.start_playing @Composable fun RegisterScreenRoot( - viewModel: RegisterViewModel = hiltViewModel() + viewModel: RegisterViewModel ) { val snackBarHostState = remember { SnackbarHostState() } val navController = LocalNavController.current @@ -174,10 +177,10 @@ fun RegisterScreen( }, contentColor = Color.Black, displayText = when (uiState.registerState) { - Checking -> stringResource(R.string.registering) - Idle -> stringResource(R.string.register) - Error -> stringResource(R.string.registration_error) - Success -> stringResource(R.string.start_playing) + Checking -> stringResource(Res.string.registering) + Idle -> stringResource(Res.string.register) + Error -> stringResource(Res.string.registration_error) + Success -> stringResource(Res.string.start_playing) } ) diff --git a/app/src/main/java/com/spongycode/songquest/ui/screen/auth/register/RegisterViewModel.kt b/composeApp/src/commonMain/kotlin/com/spongycode/songquest/ui/screen/auth/register/RegisterViewModel.kt similarity index 83% rename from app/src/main/java/com/spongycode/songquest/ui/screen/auth/register/RegisterViewModel.kt rename to composeApp/src/commonMain/kotlin/com/spongycode/songquest/ui/screen/auth/register/RegisterViewModel.kt index 9409a47..52bbe68 100644 --- a/app/src/main/java/com/spongycode/songquest/ui/screen/auth/register/RegisterViewModel.kt +++ b/composeApp/src/commonMain/kotlin/com/spongycode/songquest/ui/screen/auth/register/RegisterViewModel.kt @@ -2,32 +2,29 @@ package com.spongycode.songquest.ui.screen.auth.register import androidx.lifecycle.ViewModel import androidx.lifecycle.viewModelScope -import com.spongycode.songquest.data.repository.DatastoreRepositoryImpl.Companion.accessTokenSession -import com.spongycode.songquest.data.repository.DatastoreRepositoryImpl.Companion.emailSession -import com.spongycode.songquest.data.repository.DatastoreRepositoryImpl.Companion.gamesPlayedSession -import com.spongycode.songquest.data.repository.DatastoreRepositoryImpl.Companion.refreshTokenSession -import com.spongycode.songquest.data.repository.DatastoreRepositoryImpl.Companion.usernameSession -import com.spongycode.songquest.domain.repository.AuthRepository -import com.spongycode.songquest.domain.repository.DatastoreRepository +import com.spongycode.songquest.repository.AuthRepository +import com.spongycode.songquest.repository.SettingsRepository +import com.spongycode.songquest.repository.SettingsRepositoryImpl.Companion.ACCESS_TOKEN_SESSION +import com.spongycode.songquest.repository.SettingsRepositoryImpl.Companion.EMAIL_SESSION +import com.spongycode.songquest.repository.SettingsRepositoryImpl.Companion.GAMES_PLAYED_SESSION +import com.spongycode.songquest.repository.SettingsRepositoryImpl.Companion.REFRESH_TOKEN_SESSION +import com.spongycode.songquest.repository.SettingsRepositoryImpl.Companion.USERNAME_SESSION import com.spongycode.songquest.ui.screen.auth.register.RegisterState.Checking import com.spongycode.songquest.ui.screen.auth.register.RegisterState.Error import com.spongycode.songquest.ui.screen.auth.register.RegisterState.Idle import com.spongycode.songquest.ui.screen.auth.register.RegisterState.Success import com.spongycode.songquest.ui.screen.auth.register.RegisterViewEffect.ShowSnackBar import com.spongycode.songquest.util.ValidationHelper -import dagger.hilt.android.lifecycle.HiltViewModel import kotlinx.coroutines.flow.MutableSharedFlow import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.SharedFlow import kotlinx.coroutines.flow.asSharedFlow import kotlinx.coroutines.flow.asStateFlow import kotlinx.coroutines.launch -import javax.inject.Inject -@HiltViewModel -class RegisterViewModel @Inject constructor( +class RegisterViewModel( private val authRepository: AuthRepository, - private val datastoreRepository: DatastoreRepository + private val settingsRepository: SettingsRepository ) : ViewModel() { private val _uiState = MutableStateFlow(RegisterUiState()) val uiState = _uiState.asStateFlow() @@ -104,26 +101,26 @@ class RegisterViewModel @Inject constructor( _uiState.value.password ) if (res?.status == "success") { - datastoreRepository.storeListString( + settingsRepository.storeListString( listOf( Pair( - accessTokenSession, + ACCESS_TOKEN_SESSION, res.data?.accessToken.toString() ), Pair( - refreshTokenSession, + REFRESH_TOKEN_SESSION, res.data?.refreshToken.toString() ), Pair( - usernameSession, + USERNAME_SESSION, res.data?.user?.username.toString() ), Pair( - emailSession, + EMAIL_SESSION, res.data?.user?.email.toString() ), Pair( - gamesPlayedSession, + GAMES_PLAYED_SESSION, 0.toString() ) ) diff --git a/app/src/main/java/com/spongycode/songquest/ui/screen/gameplay/components/PlaceholderMessageText.kt b/composeApp/src/commonMain/kotlin/com/spongycode/songquest/ui/screen/gameplay/components/PlaceholderMessageText.kt similarity index 91% rename from app/src/main/java/com/spongycode/songquest/ui/screen/gameplay/components/PlaceholderMessageText.kt rename to composeApp/src/commonMain/kotlin/com/spongycode/songquest/ui/screen/gameplay/components/PlaceholderMessageText.kt index 0c89406..21b3143 100644 --- a/app/src/main/java/com/spongycode/songquest/ui/screen/gameplay/components/PlaceholderMessageText.kt +++ b/composeApp/src/commonMain/kotlin/com/spongycode/songquest/ui/screen/gameplay/components/PlaceholderMessageText.kt @@ -11,7 +11,7 @@ import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.text.font.FontWeight import androidx.compose.ui.unit.sp -import com.spongycode.songquest.util.Fonts +import com.spongycode.songquest.util.defaultFontFamily @Composable fun PlaceholderMessageText(text: String) { @@ -26,7 +26,7 @@ fun PlaceholderMessageText(text: String) { text = text, fontSize = 20.sp, color = MaterialTheme.colorScheme.primary, fontWeight = FontWeight.W600, - fontFamily = Fonts.poppinsFamily + fontFamily = defaultFontFamily ) } } \ No newline at end of file diff --git a/app/src/main/java/com/spongycode/songquest/ui/screen/gameplay/gameover/GameOverScreen.kt b/composeApp/src/commonMain/kotlin/com/spongycode/songquest/ui/screen/gameplay/gameover/GameOverScreen.kt similarity index 87% rename from app/src/main/java/com/spongycode/songquest/ui/screen/gameplay/gameover/GameOverScreen.kt rename to composeApp/src/commonMain/kotlin/com/spongycode/songquest/ui/screen/gameplay/gameover/GameOverScreen.kt index e038c52..5bf4dce 100644 --- a/app/src/main/java/com/spongycode/songquest/ui/screen/gameplay/gameover/GameOverScreen.kt +++ b/composeApp/src/commonMain/kotlin/com/spongycode/songquest/ui/screen/gameplay/gameover/GameOverScreen.kt @@ -17,16 +17,14 @@ import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.draw.drawWithContent import androidx.compose.ui.graphics.Color -import androidx.compose.ui.graphics.asAndroidBitmap import androidx.compose.ui.graphics.layer.drawLayer import androidx.compose.ui.graphics.rememberGraphicsLayer -import androidx.compose.ui.platform.LocalContext import androidx.compose.ui.text.font.FontWeight -import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.sp -import androidx.hilt.navigation.compose.hiltViewModel +import com.spongycode.songquest.PlatformContext import com.spongycode.songquest.data.model.gameplay.GameModel +import com.spongycode.songquest.share import com.spongycode.songquest.ui.navigation.LocalNavController import com.spongycode.songquest.ui.screen.auth.components.CustomButton import com.spongycode.songquest.ui.screen.gameplay.components.PlaceholderMessageText @@ -34,18 +32,16 @@ import com.spongycode.songquest.ui.screen.gameplay.gameover.components.GameOverD import com.spongycode.songquest.ui.theme.OptionDarkBlue import com.spongycode.songquest.ui.theme.OptionDarkGreen import com.spongycode.songquest.util.Constants -import com.spongycode.songquest.util.Constants.BASE_URL import com.spongycode.songquest.util.Constants.PLAYING_SCREEN -import com.spongycode.songquest.util.Fonts -import com.spongycode.songquest.util.Image.saveBitmapAndGetUri -import com.spongycode.songquest.util.Image.shareImageUriWithText +import com.spongycode.songquest.util.defaultFontFamily import kotlinx.coroutines.flow.collectLatest import kotlinx.coroutines.launch +import org.jetbrains.compose.ui.tooling.preview.Preview @Composable fun GameOverScreenRoot( gameId: String, - viewModel: GameOverViewModel = hiltViewModel() + viewModel: GameOverViewModel ) { val navController = LocalNavController.current LaunchedEffect(null) { @@ -82,7 +78,6 @@ fun GameOverScreen( ) { val coroutineScope = rememberCoroutineScope() val graphicsLayer = rememberGraphicsLayer() - val context = LocalContext.current Column( modifier = modifier @@ -96,7 +91,7 @@ fun GameOverScreen( text = "Game Over", fontSize = 30.sp, fontWeight = FontWeight.W600, - fontFamily = Fonts.poppinsFamily, + fontFamily = defaultFontFamily, color = MaterialTheme.colorScheme.primary ) Column( @@ -126,11 +121,11 @@ fun GameOverScreen( CustomButton( onClick = { coroutineScope.launch { - val bitmap = graphicsLayer.toImageBitmap().asAndroidBitmap() - val uri = saveBitmapAndGetUri(context, bitmap) - val message = - "I scored ${uiState.game.score?.toInt()} in #${uiState.game.category} Quiz! Think you can beat me?\nDownload the app: $BASE_URL" - shareImageUriWithText(context, uri, message) + graphicsLayer.toImageBitmap().share( + PlatformContext, + uiState.game.score?.toInt(), + uiState.game.category + ) } }, containerColor = OptionDarkGreen, diff --git a/app/src/main/java/com/spongycode/songquest/ui/screen/gameplay/gameover/GameOverViewModel.kt b/composeApp/src/commonMain/kotlin/com/spongycode/songquest/ui/screen/gameplay/gameover/GameOverViewModel.kt similarity index 79% rename from app/src/main/java/com/spongycode/songquest/ui/screen/gameplay/gameover/GameOverViewModel.kt rename to composeApp/src/commonMain/kotlin/com/spongycode/songquest/ui/screen/gameplay/gameover/GameOverViewModel.kt index 73cf00f..22c00c8 100644 --- a/app/src/main/java/com/spongycode/songquest/ui/screen/gameplay/gameover/GameOverViewModel.kt +++ b/composeApp/src/commonMain/kotlin/com/spongycode/songquest/ui/screen/gameplay/gameover/GameOverViewModel.kt @@ -1,26 +1,21 @@ package com.spongycode.songquest.ui.screen.gameplay.gameover -import android.util.Log import androidx.lifecycle.ViewModel import androidx.lifecycle.viewModelScope import com.spongycode.songquest.data.model.gameplay.CheckAnswerModel import com.spongycode.songquest.data.model.gameplay.GameModel -import com.spongycode.songquest.data.repository.DatastoreRepositoryImpl -import com.spongycode.songquest.data.repository.DatastoreRepositoryImpl.Companion.gamesPlayedSession -import com.spongycode.songquest.domain.repository.DatastoreRepository -import com.spongycode.songquest.domain.repository.GameplayRepository -import dagger.hilt.android.lifecycle.HiltViewModel +import com.spongycode.songquest.repository.GameplayRepository +import com.spongycode.songquest.repository.SettingsRepository +import com.spongycode.songquest.repository.SettingsRepositoryImpl import kotlinx.coroutines.flow.MutableSharedFlow import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.SharedFlow import kotlinx.coroutines.flow.asSharedFlow import kotlinx.coroutines.flow.asStateFlow import kotlinx.coroutines.launch -import javax.inject.Inject -@HiltViewModel -class GameOverViewModel @Inject constructor( - private val datastoreRepository: DatastoreRepository, +class GameOverViewModel( + private val settingsRepository: SettingsRepository, private val gameplayRepository: GameplayRepository ) : ViewModel() { @@ -35,7 +30,7 @@ class GameOverViewModel @Inject constructor( GameOverEvent.GetData -> { viewModelScope.launch { _uiState.value = _uiState.value.copy( - username = datastoreRepository.getString(DatastoreRepositoryImpl.usernameSession) + username = settingsRepository.getString(SettingsRepositoryImpl.USERNAME_SESSION) .toString() ) } @@ -57,10 +52,9 @@ class GameOverViewModel @Inject constructor( } private fun saveGame(gameId: String) { - Log.d("saveGame", "saveGame: $gameId") viewModelScope.launch { val accessToken = - datastoreRepository.getString(DatastoreRepositoryImpl.accessTokenSession) + settingsRepository.getString(SettingsRepositoryImpl.ACCESS_TOKEN_SESSION) try { val res = gameplayRepository.saveGame( CheckAnswerModel( @@ -74,8 +68,8 @@ class GameOverViewModel @Inject constructor( gameOverState = GameOverState.Success ) val gamesPlayed = res.data.gamesPlayed?.toString() - datastoreRepository.storeString( - gamesPlayedSession, gamesPlayed.toString() + settingsRepository.storeString( + SettingsRepositoryImpl.GAMES_PLAYED_SESSION, gamesPlayed.toString() ) } else { diff --git a/app/src/main/java/com/spongycode/songquest/ui/screen/gameplay/gameover/components/GameOverDisplayCard.kt b/composeApp/src/commonMain/kotlin/com/spongycode/songquest/ui/screen/gameplay/gameover/components/GameOverDisplayCard.kt similarity index 83% rename from app/src/main/java/com/spongycode/songquest/ui/screen/gameplay/gameover/components/GameOverDisplayCard.kt rename to composeApp/src/commonMain/kotlin/com/spongycode/songquest/ui/screen/gameplay/gameover/components/GameOverDisplayCard.kt index 911d42c..d97b76c 100644 --- a/app/src/main/java/com/spongycode/songquest/ui/screen/gameplay/gameover/components/GameOverDisplayCard.kt +++ b/composeApp/src/commonMain/kotlin/com/spongycode/songquest/ui/screen/gameplay/gameover/components/GameOverDisplayCard.kt @@ -24,16 +24,21 @@ import androidx.compose.ui.draw.shadow import androidx.compose.ui.graphics.Brush import androidx.compose.ui.graphics.Color import androidx.compose.ui.layout.ContentScale -import androidx.compose.ui.platform.LocalConfiguration -import androidx.compose.ui.res.painterResource import androidx.compose.ui.text.font.FontWeight -import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.sp -import com.spongycode.songquest.R import com.spongycode.songquest.data.model.gameplay.GameModel +import com.spongycode.songquest.getScreenHeight +import com.spongycode.songquest.getScreenWidth import com.spongycode.songquest.util.Constants -import com.spongycode.songquest.util.Fonts +import com.spongycode.songquest.util.defaultFontFamily +import org.jetbrains.compose.resources.painterResource +import org.jetbrains.compose.ui.tooling.preview.Preview +import song_quest.composeapp.generated.resources.Res +import song_quest.composeapp.generated.resources.bollywood_banner +import song_quest.composeapp.generated.resources.desi_hip_hop_banner +import song_quest.composeapp.generated.resources.hip_hop_banner +import song_quest.composeapp.generated.resources.hollywood_banner @Composable fun GameOverDisplayCard( @@ -41,9 +46,8 @@ fun GameOverDisplayCard( game: GameModel, username: String ) { - val configuration = LocalConfiguration.current - val width = (configuration.screenWidthDp) * 3 / 4 - val height = configuration.screenHeightDp / 2 + val width = (getScreenWidth()) * 3 / 4 + val height = getScreenHeight() / 2 Box( contentAlignment = Alignment.BottomEnd, modifier = modifier @@ -74,21 +78,21 @@ fun GameOverDisplayCard( modifier = Modifier .background(Color.Red), painter = painterResource( - id = when (game.category) { + resource = when (game.category) { Constants.BOLLYWOOD_CODE -> { - R.drawable.bollywood_banner + Res.drawable.bollywood_banner } Constants.HOLLYWOOD_CODE -> { - R.drawable.hollywood_banner + Res.drawable.hollywood_banner } Constants.DESI_HIP_HOP_CODE -> { - R.drawable.desi_hip_hop_banner + Res.drawable.desi_hip_hop_banner } else -> { - R.drawable.hip_hop_banner + Res.drawable.hip_hop_banner } } ), @@ -123,7 +127,7 @@ fun GameOverDisplayCard( Text( text = "Score: ", fontSize = 22.sp, fontWeight = FontWeight.Medium, - fontFamily = Fonts.poppinsFamily, + fontFamily = defaultFontFamily, color = Color.White ) Text( @@ -131,7 +135,7 @@ fun GameOverDisplayCard( fontSize = 30.sp, color = Color.White, fontWeight = FontWeight.W600, - fontFamily = Fonts.poppinsFamily + fontFamily = defaultFontFamily ) } Text( @@ -139,7 +143,7 @@ fun GameOverDisplayCard( fontSize = 18.sp, color = Color.White, fontWeight = FontWeight.Medium, - fontFamily = Fonts.poppinsFamily + fontFamily = defaultFontFamily ) } Row( @@ -149,7 +153,7 @@ fun GameOverDisplayCard( Text( text = "# ", fontSize = 25.sp, fontWeight = FontWeight.W600, - fontFamily = Fonts.poppinsFamily, + fontFamily = defaultFontFamily, color = Color.White ) @@ -162,7 +166,7 @@ fun GameOverDisplayCard( }, fontSize = 22.sp, fontWeight = FontWeight.W600, - fontFamily = Fonts.poppinsFamily, + fontFamily = defaultFontFamily, color = Color.White ) } diff --git a/app/src/main/java/com/spongycode/songquest/ui/screen/gameplay/history/HistoryScreen.kt b/composeApp/src/commonMain/kotlin/com/spongycode/songquest/ui/screen/gameplay/history/HistoryScreen.kt similarity index 93% rename from app/src/main/java/com/spongycode/songquest/ui/screen/gameplay/history/HistoryScreen.kt rename to composeApp/src/commonMain/kotlin/com/spongycode/songquest/ui/screen/gameplay/history/HistoryScreen.kt index 73101be..5b054f7 100644 --- a/app/src/main/java/com/spongycode/songquest/ui/screen/gameplay/history/HistoryScreen.kt +++ b/composeApp/src/commonMain/kotlin/com/spongycode/songquest/ui/screen/gameplay/history/HistoryScreen.kt @@ -7,18 +7,17 @@ import androidx.compose.runtime.Composable import androidx.compose.runtime.LaunchedEffect import androidx.compose.runtime.collectAsState import androidx.compose.ui.Modifier -import androidx.compose.ui.tooling.preview.Preview -import androidx.hilt.navigation.compose.hiltViewModel import com.spongycode.songquest.data.model.gameplay.GameModel import com.spongycode.songquest.ui.navigation.LocalNavController import com.spongycode.songquest.ui.screen.gameplay.components.PlaceholderMessageText import com.spongycode.songquest.ui.screen.gameplay.history.components.HistoryList import com.spongycode.songquest.ui.screen.gameplay.profile.components.Topbar +import org.jetbrains.compose.ui.tooling.preview.Preview @OptIn(ExperimentalMaterial3Api::class) @Composable fun HistoryScreenRoot( - viewModel: HistoryViewModel = hiltViewModel() + viewModel: HistoryViewModel ) { val navController = LocalNavController.current Scaffold(topBar = { diff --git a/app/src/main/java/com/spongycode/songquest/ui/screen/gameplay/history/HistoryViewModel.kt b/composeApp/src/commonMain/kotlin/com/spongycode/songquest/ui/screen/gameplay/history/HistoryViewModel.kt similarity index 79% rename from app/src/main/java/com/spongycode/songquest/ui/screen/gameplay/history/HistoryViewModel.kt rename to composeApp/src/commonMain/kotlin/com/spongycode/songquest/ui/screen/gameplay/history/HistoryViewModel.kt index bfa6ddd..aef6c88 100644 --- a/app/src/main/java/com/spongycode/songquest/ui/screen/gameplay/history/HistoryViewModel.kt +++ b/composeApp/src/commonMain/kotlin/com/spongycode/songquest/ui/screen/gameplay/history/HistoryViewModel.kt @@ -4,19 +4,16 @@ import androidx.lifecycle.ViewModel import androidx.lifecycle.viewModelScope import com.spongycode.songquest.data.model.auth.AuthModel import com.spongycode.songquest.data.model.gameplay.GameModel -import com.spongycode.songquest.data.repository.DatastoreRepositoryImpl -import com.spongycode.songquest.domain.repository.DatastoreRepository -import com.spongycode.songquest.domain.repository.GameplayRepository -import dagger.hilt.android.lifecycle.HiltViewModel +import com.spongycode.songquest.repository.GameplayRepository +import com.spongycode.songquest.repository.SettingsRepository +import com.spongycode.songquest.repository.SettingsRepositoryImpl import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.asStateFlow import kotlinx.coroutines.launch -import javax.inject.Inject -@HiltViewModel -class HistoryViewModel @Inject constructor( +class HistoryViewModel( private val gameplayRepository: GameplayRepository, - private val datastoreRepository: DatastoreRepository + private val settingsRepository: SettingsRepository ) : ViewModel() { private val _uiState = MutableStateFlow(HistoryUiState()) @@ -31,7 +28,7 @@ class HistoryViewModel @Inject constructor( private fun fetchHistoryGames() { viewModelScope.launch { val accessToken = - datastoreRepository.getString(DatastoreRepositoryImpl.accessTokenSession) + settingsRepository.getString(SettingsRepositoryImpl.ACCESS_TOKEN_SESSION) try { val res = gameplayRepository.history( AuthModel(accessToken = accessToken) diff --git a/app/src/main/java/com/spongycode/songquest/ui/screen/gameplay/history/components/HistoryList.kt b/composeApp/src/commonMain/kotlin/com/spongycode/songquest/ui/screen/gameplay/history/components/HistoryList.kt similarity index 93% rename from app/src/main/java/com/spongycode/songquest/ui/screen/gameplay/history/components/HistoryList.kt rename to composeApp/src/commonMain/kotlin/com/spongycode/songquest/ui/screen/gameplay/history/components/HistoryList.kt index 9cec9e8..d22a05b 100644 --- a/app/src/main/java/com/spongycode/songquest/ui/screen/gameplay/history/components/HistoryList.kt +++ b/composeApp/src/commonMain/kotlin/com/spongycode/songquest/ui/screen/gameplay/history/components/HistoryList.kt @@ -22,18 +22,18 @@ import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.draw.clip import androidx.compose.ui.graphics.Color -import androidx.compose.ui.platform.LocalConfiguration import androidx.compose.ui.text.font.FontWeight import androidx.compose.ui.text.style.TextAlign -import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.sp import com.spongycode.songquest.data.model.gameplay.GameModel +import com.spongycode.songquest.getScreenWidth import com.spongycode.songquest.ui.theme.OptionLightYellow import com.spongycode.songquest.util.CategoryConvertor import com.spongycode.songquest.util.Constants -import com.spongycode.songquest.util.Fonts import com.spongycode.songquest.util.TimesAgo +import com.spongycode.songquest.util.defaultFontFamily +import org.jetbrains.compose.ui.tooling.preview.Preview const val column1Weight = .3f @@ -45,8 +45,7 @@ fun HistoryList( modifier: Modifier = Modifier, games: List = emptyList() ) { - val configuration = LocalConfiguration.current - val width = (configuration.screenWidthDp - 20) / 2 + val width = (getScreenWidth() - 20) / 2 Column( modifier .background(MaterialTheme.colorScheme.background) @@ -123,7 +122,7 @@ fun RowScope.NormalText( fontWeight = if (title) FontWeight.W600 else FontWeight.W500, textAlign = alignment, fontSize = 18.sp, - fontFamily = Fonts.poppinsFamily + fontFamily = defaultFontFamily ) } @@ -146,7 +145,7 @@ fun RowScope.CategoryDateText( fontWeight = FontWeight.W600, textAlign = alignment, fontSize = 16.sp, - fontFamily = Fonts.poppinsFamily + fontFamily = defaultFontFamily ) Text( text = time, @@ -154,7 +153,7 @@ fun RowScope.CategoryDateText( textAlign = alignment, fontSize = 12.sp, color = Color.Gray, - fontFamily = Fonts.poppinsFamily + fontFamily = defaultFontFamily ) } } diff --git a/app/src/main/java/com/spongycode/songquest/ui/screen/gameplay/home/HomeScreen.kt b/composeApp/src/commonMain/kotlin/com/spongycode/songquest/ui/screen/gameplay/home/HomeScreen.kt similarity index 85% rename from app/src/main/java/com/spongycode/songquest/ui/screen/gameplay/home/HomeScreen.kt rename to composeApp/src/commonMain/kotlin/com/spongycode/songquest/ui/screen/gameplay/home/HomeScreen.kt index 74f103b..f8c9eb6 100644 --- a/app/src/main/java/com/spongycode/songquest/ui/screen/gameplay/home/HomeScreen.kt +++ b/composeApp/src/commonMain/kotlin/com/spongycode/songquest/ui/screen/gameplay/home/HomeScreen.kt @@ -18,11 +18,8 @@ import androidx.compose.runtime.collectAsState import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.text.font.FontWeight -import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.sp -import androidx.hilt.navigation.compose.hiltViewModel -import com.spongycode.songquest.R import com.spongycode.songquest.ui.navigation.LocalNavController import com.spongycode.songquest.ui.screen.gameplay.home.components.CardInfo import com.spongycode.songquest.ui.screen.gameplay.home.components.CategorySelector @@ -35,12 +32,21 @@ import com.spongycode.songquest.util.Constants.LEADERBOARD_SCREEN import com.spongycode.songquest.util.Constants.PLAYING_SCREEN import com.spongycode.songquest.util.Constants.PROFILE_SCREEN import com.spongycode.songquest.util.Constants.SMALL_HEIGHT -import com.spongycode.songquest.util.Fonts +import com.spongycode.songquest.util.defaultFontFamily import kotlinx.coroutines.flow.collectLatest +import org.jetbrains.compose.resources.painterResource +import org.jetbrains.compose.ui.tooling.preview.Preview +import song_quest.composeapp.generated.resources.Res +import song_quest.composeapp.generated.resources.bollywood_banner +import song_quest.composeapp.generated.resources.desi_hip_hop_banner +import song_quest.composeapp.generated.resources.gameplay_count +import song_quest.composeapp.generated.resources.hip_hop_banner +import song_quest.composeapp.generated.resources.hollywood_banner +import song_quest.composeapp.generated.resources.leader_board_icon @Composable fun HomeScreenRoot( - viewModel: HomeViewModel = hiltViewModel(), + viewModel: HomeViewModel ) { val navController = LocalNavController.current LaunchedEffect(null) { @@ -86,7 +92,7 @@ private fun HomeScreen( CardInfo( "Games played: ${uiState.gamesPlayed}", - trailingIcon = R.drawable.gameplay_count, + trailingIcon = Res.drawable.gameplay_count, bgColor = OptionLightBlue, onClick = { onEvent(HomeEvent.Navigate(route = HISTORY_SCREEN, popBackStack = false)) } ) @@ -95,7 +101,7 @@ private fun HomeScreen( text = "Pick a category", fontSize = 20.sp, fontWeight = FontWeight.W600, - fontFamily = Fonts.poppinsFamily + fontFamily = defaultFontFamily ) Box { @@ -114,7 +120,7 @@ private fun HomeScreen( ) ) }, - R.drawable.bollywood_banner + Res.drawable.bollywood_banner ) CategorySelector( Constants.HOLLYWOOD_DISPLAY_TEXT, @@ -126,7 +132,7 @@ private fun HomeScreen( ) ) }, - R.drawable.hollywood_banner + Res.drawable.hollywood_banner ) } @@ -146,7 +152,7 @@ private fun HomeScreen( ) ) }, - R.drawable.desi_hip_hop_banner + Res.drawable.desi_hip_hop_banner ) CategorySelector( Constants.HIP_HOP_DISPLAY_TEXT, @@ -158,7 +164,7 @@ private fun HomeScreen( ) ) }, - R.drawable.hip_hop_banner + Res.drawable.hip_hop_banner ) } } @@ -166,7 +172,7 @@ private fun HomeScreen( CardInfo( "Leaderboard", - trailingIcon = R.drawable.leader_board_icon, + trailingIcon = Res.drawable.leader_board_icon, bgColor = OptionLightGreen, onClick = { onEvent( diff --git a/app/src/main/java/com/spongycode/songquest/ui/screen/gameplay/home/HomeViewModel.kt b/composeApp/src/commonMain/kotlin/com/spongycode/songquest/ui/screen/gameplay/home/HomeViewModel.kt similarity index 72% rename from app/src/main/java/com/spongycode/songquest/ui/screen/gameplay/home/HomeViewModel.kt rename to composeApp/src/commonMain/kotlin/com/spongycode/songquest/ui/screen/gameplay/home/HomeViewModel.kt index 10ea13a..c0e175f 100644 --- a/app/src/main/java/com/spongycode/songquest/ui/screen/gameplay/home/HomeViewModel.kt +++ b/composeApp/src/commonMain/kotlin/com/spongycode/songquest/ui/screen/gameplay/home/HomeViewModel.kt @@ -2,20 +2,17 @@ package com.spongycode.songquest.ui.screen.gameplay.home import androidx.lifecycle.ViewModel import androidx.lifecycle.viewModelScope -import com.spongycode.songquest.data.repository.DatastoreRepositoryImpl -import com.spongycode.songquest.domain.repository.DatastoreRepository -import dagger.hilt.android.lifecycle.HiltViewModel +import com.spongycode.songquest.repository.SettingsRepository +import com.spongycode.songquest.repository.SettingsRepositoryImpl import kotlinx.coroutines.flow.MutableSharedFlow import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.SharedFlow import kotlinx.coroutines.flow.asSharedFlow import kotlinx.coroutines.flow.asStateFlow import kotlinx.coroutines.launch -import javax.inject.Inject -@HiltViewModel -class HomeViewModel @Inject constructor( - private val datastoreRepository: DatastoreRepository +class HomeViewModel( + private val settingsRepository: SettingsRepository ) : ViewModel() { private val _uiState = MutableStateFlow(HomeUiState()) @@ -39,11 +36,11 @@ class HomeViewModel @Inject constructor( private fun getData() { viewModelScope.launch { _uiState.value = _uiState.value.copy( - username = datastoreRepository.getString(DatastoreRepositoryImpl.usernameSession) + username = settingsRepository.getString(SettingsRepositoryImpl.USERNAME_SESSION) .toString(), - email = datastoreRepository.getString(DatastoreRepositoryImpl.emailSession) + email = settingsRepository.getString(SettingsRepositoryImpl.EMAIL_SESSION) .toString(), - gamesPlayed = datastoreRepository.getString(DatastoreRepositoryImpl.gamesPlayedSession) + gamesPlayed = settingsRepository.getString(SettingsRepositoryImpl.GAMES_PLAYED_SESSION) .toString().toInt() ) } diff --git a/app/src/main/java/com/spongycode/songquest/ui/screen/gameplay/home/components/CardInfo.kt b/composeApp/src/commonMain/kotlin/com/spongycode/songquest/ui/screen/gameplay/home/components/CardInfo.kt similarity index 78% rename from app/src/main/java/com/spongycode/songquest/ui/screen/gameplay/home/components/CardInfo.kt rename to composeApp/src/commonMain/kotlin/com/spongycode/songquest/ui/screen/gameplay/home/components/CardInfo.kt index 839812e..a8c5c29 100644 --- a/app/src/main/java/com/spongycode/songquest/ui/screen/gameplay/home/components/CardInfo.kt +++ b/composeApp/src/commonMain/kotlin/com/spongycode/songquest/ui/screen/gameplay/home/components/CardInfo.kt @@ -19,16 +19,18 @@ import androidx.compose.ui.Modifier import androidx.compose.ui.draw.clip import androidx.compose.ui.graphics.Color import androidx.compose.ui.layout.ContentScale -import androidx.compose.ui.platform.LocalConfiguration -import androidx.compose.ui.res.painterResource import androidx.compose.ui.text.font.FontWeight -import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.unit.dp -import com.spongycode.songquest.R +import com.spongycode.songquest.getScreenWidth import com.spongycode.songquest.util.Constants import com.spongycode.songquest.util.Constants.MEDIUM_HEIGHT -import com.spongycode.songquest.util.Fonts +import com.spongycode.songquest.util.defaultFontFamily import com.spongycode.songquest.util.bounceClick +import org.jetbrains.compose.resources.DrawableResource +import org.jetbrains.compose.resources.painterResource +import org.jetbrains.compose.ui.tooling.preview.Preview +import song_quest.composeapp.generated.resources.Res +import song_quest.composeapp.generated.resources.gameplay_count @Preview @@ -36,11 +38,10 @@ import com.spongycode.songquest.util.bounceClick fun CardInfo( categoryDisplayText: String = "Leaderboard", onClick: () -> Unit = {}, - trailingIcon: Int = R.drawable.gameplay_count, + trailingIcon: DrawableResource = Res.drawable.gameplay_count, bgColor: Color = Color.Red ) { - val configuration = LocalConfiguration.current - val width = (configuration.screenWidthDp - 20) / 2 + val width = (getScreenWidth() - 20) / 2 Box( modifier = Modifier @@ -65,12 +66,12 @@ fun CardInfo( style = MaterialTheme.typography.titleMedium, fontWeight = FontWeight.Medium, color = Color.Black, - fontFamily = Fonts.poppinsFamily + fontFamily = defaultFontFamily ) Image( modifier = Modifier.size(MEDIUM_HEIGHT + 10.dp), contentScale = ContentScale.Crop, - painter = painterResource(id = trailingIcon), contentDescription = null + painter = painterResource(resource = trailingIcon), contentDescription = null ) } } diff --git a/app/src/main/java/com/spongycode/songquest/ui/screen/gameplay/home/components/CategorySelector.kt b/composeApp/src/commonMain/kotlin/com/spongycode/songquest/ui/screen/gameplay/home/components/CategorySelector.kt similarity index 86% rename from app/src/main/java/com/spongycode/songquest/ui/screen/gameplay/home/components/CategorySelector.kt rename to composeApp/src/commonMain/kotlin/com/spongycode/songquest/ui/screen/gameplay/home/components/CategorySelector.kt index aab54fd..7375ede 100644 --- a/app/src/main/java/com/spongycode/songquest/ui/screen/gameplay/home/components/CategorySelector.kt +++ b/composeApp/src/commonMain/kotlin/com/spongycode/songquest/ui/screen/gameplay/home/components/CategorySelector.kt @@ -19,23 +19,23 @@ import androidx.compose.ui.draw.clip import androidx.compose.ui.graphics.Brush import androidx.compose.ui.graphics.Color import androidx.compose.ui.layout.ContentScale -import androidx.compose.ui.platform.LocalConfiguration -import androidx.compose.ui.res.painterResource import androidx.compose.ui.text.font.FontWeight import androidx.compose.ui.unit.dp +import com.spongycode.songquest.getScreenWidth import com.spongycode.songquest.util.Constants -import com.spongycode.songquest.util.Fonts +import com.spongycode.songquest.util.defaultFontFamily import com.spongycode.songquest.util.bounceClick +import org.jetbrains.compose.resources.DrawableResource +import org.jetbrains.compose.resources.painterResource @Composable fun CategorySelector( categoryDisplayText: String, onClick: () -> Unit, - bannerId: Int + bannerId: DrawableResource ) { - val configuration = LocalConfiguration.current - val width = (configuration.screenWidthDp - 40) / 2 + val width = (getScreenWidth() - 40) / 2 Box( contentAlignment = Alignment.BottomEnd, modifier = Modifier @@ -53,7 +53,7 @@ fun CategorySelector( ) { Image( - painter = painterResource(id = bannerId), + painter = painterResource(resource = bannerId), contentDescription = null, contentScale = ContentScale.Crop, modifier = Modifier @@ -79,7 +79,7 @@ fun CategorySelector( style = MaterialTheme.typography.titleMedium, fontWeight = FontWeight.W600, color = Color.White, - fontFamily = Fonts.poppinsFamily + fontFamily = defaultFontFamily ) } } diff --git a/app/src/main/java/com/spongycode/songquest/ui/screen/gameplay/home/components/Header.kt b/composeApp/src/commonMain/kotlin/com/spongycode/songquest/ui/screen/gameplay/home/components/Header.kt similarity index 82% rename from app/src/main/java/com/spongycode/songquest/ui/screen/gameplay/home/components/Header.kt rename to composeApp/src/commonMain/kotlin/com/spongycode/songquest/ui/screen/gameplay/home/components/Header.kt index 250a3a7..21745a2 100644 --- a/app/src/main/java/com/spongycode/songquest/ui/screen/gameplay/home/components/Header.kt +++ b/composeApp/src/commonMain/kotlin/com/spongycode/songquest/ui/screen/gameplay/home/components/Header.kt @@ -15,13 +15,14 @@ import androidx.compose.runtime.Composable import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.draw.clip -import androidx.compose.ui.res.painterResource import androidx.compose.ui.text.font.FontWeight import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.sp -import com.spongycode.songquest.R import com.spongycode.songquest.util.Constants -import com.spongycode.songquest.util.Fonts +import com.spongycode.songquest.util.defaultFontFamily +import org.jetbrains.compose.resources.painterResource +import song_quest.composeapp.generated.resources.Res +import song_quest.composeapp.generated.resources.baseline_account_circle_24 @Composable fun Header( @@ -40,7 +41,7 @@ fun Header( text = "Hi, $username", fontSize = 22.sp, fontWeight = FontWeight.W600, - fontFamily = Fonts.poppinsFamily + fontFamily = defaultFontFamily ) Icon( @@ -50,7 +51,7 @@ fun Header( .clickable { onClick() }, - painter = painterResource(id = R.drawable.baseline_account_circle_24), + painter = painterResource(resource = Res.drawable.baseline_account_circle_24), tint = MaterialTheme.colorScheme.primary, contentDescription = "profile image" ) diff --git a/app/src/main/java/com/spongycode/songquest/ui/screen/gameplay/leaderboard/LeaderboardScreen.kt b/composeApp/src/commonMain/kotlin/com/spongycode/songquest/ui/screen/gameplay/leaderboard/LeaderboardScreen.kt similarity index 94% rename from app/src/main/java/com/spongycode/songquest/ui/screen/gameplay/leaderboard/LeaderboardScreen.kt rename to composeApp/src/commonMain/kotlin/com/spongycode/songquest/ui/screen/gameplay/leaderboard/LeaderboardScreen.kt index a7d3a97..dd320ad 100644 --- a/app/src/main/java/com/spongycode/songquest/ui/screen/gameplay/leaderboard/LeaderboardScreen.kt +++ b/composeApp/src/commonMain/kotlin/com/spongycode/songquest/ui/screen/gameplay/leaderboard/LeaderboardScreen.kt @@ -11,20 +11,19 @@ import androidx.compose.runtime.LaunchedEffect import androidx.compose.runtime.collectAsState import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier -import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.unit.dp -import androidx.hilt.navigation.compose.hiltViewModel import com.spongycode.songquest.ui.navigation.LocalNavController import com.spongycode.songquest.ui.screen.gameplay.components.PlaceholderMessageText import com.spongycode.songquest.ui.screen.gameplay.leaderboard.components.CustomDropDownMenu import com.spongycode.songquest.ui.screen.gameplay.leaderboard.components.CustomTableList import com.spongycode.songquest.ui.screen.gameplay.profile.components.Topbar import com.spongycode.songquest.util.ComposeLocalWrapper +import org.jetbrains.compose.ui.tooling.preview.Preview @OptIn(ExperimentalMaterial3Api::class) @Composable fun LeaderboardScreenRoot( - viewModel: LeaderboardViewModel = hiltViewModel() + viewModel: LeaderboardViewModel ) { val navController = LocalNavController.current Scaffold(topBar = { diff --git a/app/src/main/java/com/spongycode/songquest/ui/screen/gameplay/leaderboard/LeaderboardViewModel.kt b/composeApp/src/commonMain/kotlin/com/spongycode/songquest/ui/screen/gameplay/leaderboard/LeaderboardViewModel.kt similarity index 85% rename from app/src/main/java/com/spongycode/songquest/ui/screen/gameplay/leaderboard/LeaderboardViewModel.kt rename to composeApp/src/commonMain/kotlin/com/spongycode/songquest/ui/screen/gameplay/leaderboard/LeaderboardViewModel.kt index 2fc5276..a070da3 100644 --- a/app/src/main/java/com/spongycode/songquest/ui/screen/gameplay/leaderboard/LeaderboardViewModel.kt +++ b/composeApp/src/commonMain/kotlin/com/spongycode/songquest/ui/screen/gameplay/leaderboard/LeaderboardViewModel.kt @@ -4,19 +4,16 @@ import androidx.lifecycle.ViewModel import androidx.lifecycle.viewModelScope import com.spongycode.songquest.data.model.auth.AuthModel import com.spongycode.songquest.data.model.gameplay.LeaderboardUsersModel -import com.spongycode.songquest.data.repository.DatastoreRepositoryImpl -import com.spongycode.songquest.domain.repository.DatastoreRepository -import com.spongycode.songquest.domain.repository.GameplayRepository +import com.spongycode.songquest.repository.GameplayRepository +import com.spongycode.songquest.repository.SettingsRepository +import com.spongycode.songquest.repository.SettingsRepositoryImpl import com.spongycode.songquest.util.CategoryConvertor -import dagger.hilt.android.lifecycle.HiltViewModel import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.asStateFlow import kotlinx.coroutines.launch -import javax.inject.Inject -@HiltViewModel -class LeaderboardViewModel @Inject constructor( - private val datastoreRepository: DatastoreRepository, +class LeaderboardViewModel( + private val settingsRepository: SettingsRepository, private val gameplayRepository: GameplayRepository ) : ViewModel() { @@ -39,7 +36,7 @@ class LeaderboardViewModel @Inject constructor( private fun fetchLeaderboard() { viewModelScope.launch { val accessToken = - datastoreRepository.getString(DatastoreRepositoryImpl.accessTokenSession) + settingsRepository.getString(SettingsRepositoryImpl.ACCESS_TOKEN_SESSION) try { val res = gameplayRepository.leaderboard( AuthModel( diff --git a/app/src/main/java/com/spongycode/songquest/ui/screen/gameplay/leaderboard/components/CustomDropDownMenu.kt b/composeApp/src/commonMain/kotlin/com/spongycode/songquest/ui/screen/gameplay/leaderboard/components/CustomDropDownMenu.kt similarity index 90% rename from app/src/main/java/com/spongycode/songquest/ui/screen/gameplay/leaderboard/components/CustomDropDownMenu.kt rename to composeApp/src/commonMain/kotlin/com/spongycode/songquest/ui/screen/gameplay/leaderboard/components/CustomDropDownMenu.kt index fd7b69a..5ad79a1 100644 --- a/app/src/main/java/com/spongycode/songquest/ui/screen/gameplay/leaderboard/components/CustomDropDownMenu.kt +++ b/composeApp/src/commonMain/kotlin/com/spongycode/songquest/ui/screen/gameplay/leaderboard/components/CustomDropDownMenu.kt @@ -21,14 +21,14 @@ import androidx.compose.runtime.remember import androidx.compose.runtime.setValue import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier -import androidx.compose.ui.platform.LocalConfiguration import androidx.compose.ui.text.TextStyle import androidx.compose.ui.text.font.FontWeight -import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.sp +import com.spongycode.songquest.getScreenWidth import com.spongycode.songquest.util.CategoryConvertor -import com.spongycode.songquest.util.Fonts +import com.spongycode.songquest.util.defaultFontFamily +import org.jetbrains.compose.ui.tooling.preview.Preview @OptIn(ExperimentalMaterial3Api::class) @Composable @@ -39,8 +39,7 @@ fun CustomDropDownMenu( var expanded by remember { mutableStateOf(false) } val categories = CategoryConvertor.giveAllCategories() - val configuration = LocalConfiguration.current - val width = (configuration.screenWidthDp - 70) + val width = (getScreenWidth() - 70) Box( modifier = Modifier @@ -61,7 +60,7 @@ fun CustomDropDownMenu( trailingIcon = { ExposedDropdownMenuDefaults.TrailingIcon(expanded = expanded) }, textStyle = TextStyle( fontWeight = FontWeight.Bold, - fontFamily = Fonts.poppinsFamily, + fontFamily = defaultFontFamily, fontSize = 18.sp ), modifier = Modifier @@ -82,7 +81,7 @@ fun CustomDropDownMenu( text = { Text( text = displayText, - fontFamily = Fonts.poppinsFamily, + fontFamily = defaultFontFamily, fontSize = 15.sp ) }, diff --git a/app/src/main/java/com/spongycode/songquest/ui/screen/gameplay/leaderboard/components/CustomTableList.kt b/composeApp/src/commonMain/kotlin/com/spongycode/songquest/ui/screen/gameplay/leaderboard/components/CustomTableList.kt similarity index 93% rename from app/src/main/java/com/spongycode/songquest/ui/screen/gameplay/leaderboard/components/CustomTableList.kt rename to composeApp/src/commonMain/kotlin/com/spongycode/songquest/ui/screen/gameplay/leaderboard/components/CustomTableList.kt index 4ce1fc2..0401d91 100644 --- a/app/src/main/java/com/spongycode/songquest/ui/screen/gameplay/leaderboard/components/CustomTableList.kt +++ b/composeApp/src/commonMain/kotlin/com/spongycode/songquest/ui/screen/gameplay/leaderboard/components/CustomTableList.kt @@ -21,17 +21,17 @@ import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.draw.clip import androidx.compose.ui.graphics.Color -import androidx.compose.ui.platform.LocalConfiguration import androidx.compose.ui.text.font.FontWeight import androidx.compose.ui.text.style.TextAlign import androidx.compose.ui.unit.Dp import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.sp import com.spongycode.songquest.data.model.gameplay.LeaderboardUsersModel +import com.spongycode.songquest.getScreenWidth import com.spongycode.songquest.ui.theme.OptionLightYellow import com.spongycode.songquest.util.Constants -import com.spongycode.songquest.util.Fonts import com.spongycode.songquest.util.TimesAgo +import com.spongycode.songquest.util.defaultFontFamily const val column1Weight = .3f const val column2Weight = .3f @@ -42,8 +42,7 @@ fun CustomTableList( listItems: List, topPadding: Dp ) { - val configuration = LocalConfiguration.current - val width = (configuration.screenWidthDp - 20) / 2 + val width = (getScreenWidth()) / 2 Column(Modifier.padding(start = 10.dp, end = 10.dp, top = topPadding)) { Row( Modifier.fillMaxWidth(), @@ -111,7 +110,7 @@ fun RowScope.NormalText( fontWeight = if (title) FontWeight.W600 else FontWeight.W500, textAlign = alignment, fontSize = 18.sp, - fontFamily = Fonts.poppinsFamily + fontFamily = defaultFontFamily ) } @@ -135,7 +134,7 @@ fun RowScope.CategoryDateText( fontWeight = FontWeight.W600, textAlign = alignment, fontSize = 16.sp, - fontFamily = Fonts.poppinsFamily + fontFamily = defaultFontFamily ) Text( text = time, @@ -143,7 +142,7 @@ fun RowScope.CategoryDateText( textAlign = alignment, fontSize = 12.sp, color = Color.Gray, - fontFamily = Fonts.poppinsFamily + fontFamily = defaultFontFamily ) } } \ No newline at end of file diff --git a/app/src/main/java/com/spongycode/songquest/ui/screen/gameplay/playing/CreateGameState.kt b/composeApp/src/commonMain/kotlin/com/spongycode/songquest/ui/screen/gameplay/playing/CreateGameState.kt similarity index 100% rename from app/src/main/java/com/spongycode/songquest/ui/screen/gameplay/playing/CreateGameState.kt rename to composeApp/src/commonMain/kotlin/com/spongycode/songquest/ui/screen/gameplay/playing/CreateGameState.kt diff --git a/app/src/main/java/com/spongycode/songquest/ui/screen/gameplay/playing/OptionTapState.kt b/composeApp/src/commonMain/kotlin/com/spongycode/songquest/ui/screen/gameplay/playing/OptionTapState.kt similarity index 100% rename from app/src/main/java/com/spongycode/songquest/ui/screen/gameplay/playing/OptionTapState.kt rename to composeApp/src/commonMain/kotlin/com/spongycode/songquest/ui/screen/gameplay/playing/OptionTapState.kt diff --git a/app/src/main/java/com/spongycode/songquest/ui/screen/gameplay/playing/PlayingScreen.kt b/composeApp/src/commonMain/kotlin/com/spongycode/songquest/ui/screen/gameplay/playing/PlayingScreen.kt similarity index 87% rename from app/src/main/java/com/spongycode/songquest/ui/screen/gameplay/playing/PlayingScreen.kt rename to composeApp/src/commonMain/kotlin/com/spongycode/songquest/ui/screen/gameplay/playing/PlayingScreen.kt index 3d0540d..ca6d236 100644 --- a/app/src/main/java/com/spongycode/songquest/ui/screen/gameplay/playing/PlayingScreen.kt +++ b/composeApp/src/commonMain/kotlin/com/spongycode/songquest/ui/screen/gameplay/playing/PlayingScreen.kt @@ -10,21 +10,22 @@ import androidx.compose.runtime.LaunchedEffect import androidx.compose.runtime.collectAsState import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier -import androidx.compose.ui.res.stringResource -import androidx.compose.ui.tooling.preview.Preview -import androidx.hilt.navigation.compose.hiltViewModel -import com.spongycode.songquest.R import com.spongycode.songquest.ui.navigation.LocalNavController import com.spongycode.songquest.ui.screen.gameplay.playing.components.PlayingScreenPlaceholder import com.spongycode.songquest.ui.screen.gameplay.playing.components.PlayingScreenSuccess import com.spongycode.songquest.util.ComposeLocalWrapper import com.spongycode.songquest.util.Constants.CATEGORY import kotlinx.coroutines.flow.collectLatest +import org.jetbrains.compose.resources.stringResource +import org.jetbrains.compose.ui.tooling.preview.Preview +import song_quest.composeapp.generated.resources.Res +import song_quest.composeapp.generated.resources.error_fetching_question +import song_quest.composeapp.generated.resources.loading_questions @Composable fun PlayingScreenRoot( category: String, - viewModel: PlayingViewModel = hiltViewModel() + viewModel: PlayingViewModel ) { val navController = LocalNavController.current LaunchedEffect(null) { @@ -65,12 +66,12 @@ fun PlayingScreen( ) { when (uiState.createGameState) { CreateGameState.Error -> PlayingScreenPlaceholder( - stringResource(R.string.error_fetching_question), + stringResource(Res.string.error_fetching_question), category ) CreateGameState.Fetching -> PlayingScreenPlaceholder( - stringResource(R.string.loading_questions), + stringResource(Res.string.loading_questions), category ) diff --git a/app/src/main/java/com/spongycode/songquest/ui/screen/gameplay/playing/PlayingViewModel.kt b/composeApp/src/commonMain/kotlin/com/spongycode/songquest/ui/screen/gameplay/playing/PlayingViewModel.kt similarity index 88% rename from app/src/main/java/com/spongycode/songquest/ui/screen/gameplay/playing/PlayingViewModel.kt rename to composeApp/src/commonMain/kotlin/com/spongycode/songquest/ui/screen/gameplay/playing/PlayingViewModel.kt index fefc4d2..3eb139f 100644 --- a/app/src/main/java/com/spongycode/songquest/ui/screen/gameplay/playing/PlayingViewModel.kt +++ b/composeApp/src/commonMain/kotlin/com/spongycode/songquest/ui/screen/gameplay/playing/PlayingViewModel.kt @@ -1,15 +1,15 @@ package com.spongycode.songquest.ui.screen.gameplay.playing -import android.media.MediaPlayer import androidx.lifecycle.ViewModel import androidx.lifecycle.viewModelScope +import com.spongycode.songquest.AudioPlayer import com.spongycode.songquest.data.model.gameplay.CheckAnswerModel import com.spongycode.songquest.data.model.gameplay.CreateGameModel import com.spongycode.songquest.data.model.gameplay.GameModel import com.spongycode.songquest.data.model.gameplay.QuestionModel -import com.spongycode.songquest.data.repository.DatastoreRepositoryImpl.Companion.accessTokenSession -import com.spongycode.songquest.domain.repository.DatastoreRepository -import com.spongycode.songquest.domain.repository.GameplayRepository +import com.spongycode.songquest.repository.GameplayRepository +import com.spongycode.songquest.repository.SettingsRepository +import com.spongycode.songquest.repository.SettingsRepositoryImpl import com.spongycode.songquest.ui.screen.gameplay.playing.OptionTapState.Checking import com.spongycode.songquest.ui.screen.gameplay.playing.OptionTapState.CorrectAnswer import com.spongycode.songquest.ui.screen.gameplay.playing.OptionTapState.Idle @@ -17,7 +17,6 @@ import com.spongycode.songquest.ui.screen.gameplay.playing.OptionTapState.WrongA import com.spongycode.songquest.util.Constants.GAME_OVER_SCREEN import com.spongycode.songquest.util.Constants.TIME_PER_QUESTION import com.spongycode.songquest.util.Constants.TOTAL_CHANCE -import dagger.hilt.android.lifecycle.HiltViewModel import kotlinx.coroutines.Job import kotlinx.coroutines.delay import kotlinx.coroutines.flow.MutableSharedFlow @@ -26,12 +25,10 @@ import kotlinx.coroutines.flow.SharedFlow import kotlinx.coroutines.flow.asSharedFlow import kotlinx.coroutines.flow.asStateFlow import kotlinx.coroutines.launch -import javax.inject.Inject -@HiltViewModel -class PlayingViewModel @Inject constructor( +class PlayingViewModel( private val gameplayRepository: GameplayRepository, - private val datastoreRepository: DatastoreRepository + private val settingsRepository: SettingsRepository ) : ViewModel() { private val _uiState = MutableStateFlow(PlayingUiState()) val uiState = _uiState.asStateFlow() @@ -39,7 +36,8 @@ class PlayingViewModel @Inject constructor( private val _viewEffect = MutableSharedFlow() val viewEffect: SharedFlow = _viewEffect.asSharedFlow() - private var mediaPlayer: MediaPlayer? = MediaPlayer() + + private var audioPlayer = AudioPlayer() private var timerJob: Job? = null @@ -68,7 +66,7 @@ class PlayingViewModel @Inject constructor( currentScore = 0f ) viewModelScope.launch { - val accessToken = datastoreRepository.getString(accessTokenSession) + val accessToken = settingsRepository.getString(SettingsRepositoryImpl.ACCESS_TOKEN_SESSION) val res = gameplayRepository.createGame( CreateGameModel( accessToken = accessToken!!, @@ -98,7 +96,7 @@ class PlayingViewModel @Inject constructor( private fun checkAnswer(optionId: Int) { if (optionId == -1) { if (_uiState.value.totalLife == 1) { - mediaPlayer?.release() + audioPlayer.release() _uiState.value = _uiState.value.copy( isGameOver = true ) @@ -136,7 +134,7 @@ class PlayingViewModel @Inject constructor( optionTapState = WrongAnswer ) if (_uiState.value.totalLife == 1) { - mediaPlayer?.release() + audioPlayer.release() _uiState.value = _uiState.value.copy( isGameOver = true ) @@ -204,15 +202,11 @@ class PlayingViewModel @Inject constructor( private fun playCurrentSong() { val index = _uiState.value.currentSongIndex if (index < _uiState.value.questions.size) { - mediaPlayer?.release() - mediaPlayer = MediaPlayer() - mediaPlayer?.setDataSource(_uiState.value.questions[index].songUrl) - mediaPlayer?.prepareAsync() - mediaPlayer?.setOnPreparedListener { - mediaPlayer?.start() - startTimer() - mediaPlayer?.isLooping = true - } + audioPlayer.release() + val songUrl = _uiState.value.questions[index].songUrl + audioPlayer.setSource(songUrl.toString()) + audioPlayer.prepareAndPlay(looping = true) + startTimer() } } @@ -223,7 +217,7 @@ class PlayingViewModel @Inject constructor( } override fun onCleared() { - mediaPlayer?.release() + audioPlayer.release() super.onCleared() } } diff --git a/app/src/main/java/com/spongycode/songquest/ui/screen/gameplay/playing/components/CircularTimer.kt b/composeApp/src/commonMain/kotlin/com/spongycode/songquest/ui/screen/gameplay/playing/components/CircularTimer.kt similarity index 93% rename from app/src/main/java/com/spongycode/songquest/ui/screen/gameplay/playing/components/CircularTimer.kt rename to composeApp/src/commonMain/kotlin/com/spongycode/songquest/ui/screen/gameplay/playing/components/CircularTimer.kt index b91bb4a..742fb40 100644 --- a/app/src/main/java/com/spongycode/songquest/ui/screen/gameplay/playing/components/CircularTimer.kt +++ b/composeApp/src/commonMain/kotlin/com/spongycode/songquest/ui/screen/gameplay/playing/components/CircularTimer.kt @@ -11,13 +11,14 @@ import androidx.compose.ui.graphics.Color import androidx.compose.ui.graphics.StrokeCap import androidx.compose.ui.graphics.drawscope.Stroke import androidx.compose.ui.graphics.drawscope.inset +import androidx.compose.ui.text.TextStyle import androidx.compose.ui.text.drawText import androidx.compose.ui.text.font.FontWeight import androidx.compose.ui.text.rememberTextMeasurer import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.sp import com.spongycode.songquest.util.Constants.CIRCULAR_TIMER_RADIUS -import com.spongycode.songquest.util.Fonts +import com.spongycode.songquest.util.defaultFontFamily @Composable fun CircularTimer( @@ -29,12 +30,12 @@ fun CircularTimer( val textToDraw = time.toString() - val style = androidx.compose.ui.text.TextStyle( + val style = TextStyle( fontSize = 20.sp, color = Color.Black, background = Color.Transparent, fontWeight = FontWeight.W800, - fontFamily = Fonts.poppinsFamily + fontFamily = defaultFontFamily ) val textLayoutResult = remember(textToDraw) { diff --git a/app/src/main/java/com/spongycode/songquest/ui/screen/gameplay/playing/components/CircularTransitionData.kt b/composeApp/src/commonMain/kotlin/com/spongycode/songquest/ui/screen/gameplay/playing/components/CircularTransitionData.kt similarity index 95% rename from app/src/main/java/com/spongycode/songquest/ui/screen/gameplay/playing/components/CircularTransitionData.kt rename to composeApp/src/commonMain/kotlin/com/spongycode/songquest/ui/screen/gameplay/playing/components/CircularTransitionData.kt index 29a76e8..8d05c6c 100644 --- a/app/src/main/java/com/spongycode/songquest/ui/screen/gameplay/playing/components/CircularTransitionData.kt +++ b/composeApp/src/commonMain/kotlin/com/spongycode/songquest/ui/screen/gameplay/playing/components/CircularTransitionData.kt @@ -1,6 +1,5 @@ package com.spongycode.songquest.ui.screen.gameplay.playing.components -import android.annotation.SuppressLint import androidx.compose.animation.animateColor import androidx.compose.animation.core.LinearEasing import androidx.compose.animation.core.animateFloat @@ -24,7 +23,6 @@ class CircularTransitionData( val color by color } -@SuppressLint("UnusedTransitionTargetStateParameter") @Composable fun updateCircularTransitionData( remainingTime: Long, diff --git a/app/src/main/java/com/spongycode/songquest/ui/screen/gameplay/playing/components/HealthMeter.kt b/composeApp/src/commonMain/kotlin/com/spongycode/songquest/ui/screen/gameplay/playing/components/HealthMeter.kt similarity index 81% rename from app/src/main/java/com/spongycode/songquest/ui/screen/gameplay/playing/components/HealthMeter.kt rename to composeApp/src/commonMain/kotlin/com/spongycode/songquest/ui/screen/gameplay/playing/components/HealthMeter.kt index 0660321..9744243 100644 --- a/app/src/main/java/com/spongycode/songquest/ui/screen/gameplay/playing/components/HealthMeter.kt +++ b/composeApp/src/commonMain/kotlin/com/spongycode/songquest/ui/screen/gameplay/playing/components/HealthMeter.kt @@ -7,12 +7,13 @@ import androidx.compose.material3.Icon import androidx.compose.runtime.Composable import androidx.compose.ui.Modifier import androidx.compose.ui.graphics.Color -import androidx.compose.ui.res.painterResource import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.times -import com.spongycode.songquest.R import com.spongycode.songquest.ui.theme.OptionDarkRed import com.spongycode.songquest.util.Constants +import org.jetbrains.compose.resources.painterResource +import song_quest.composeapp.generated.resources.Res +import song_quest.composeapp.generated.resources.heart import kotlin.math.min @Composable @@ -24,7 +25,7 @@ fun HealthMeter(totalLife: Int = Constants.TOTAL_CHANCE) { modifier = Modifier .size(2 * Constants.SMALL_HEIGHT) .padding(2.dp), - painter = painterResource(id = R.drawable.heart), + painter = painterResource(resource = Res.drawable.heart), contentDescription = "fill", tint = OptionDarkRed ) @@ -36,7 +37,7 @@ fun HealthMeter(totalLife: Int = Constants.TOTAL_CHANCE) { modifier = Modifier .size(2 * Constants.SMALL_HEIGHT) .padding(2.dp), - painter = painterResource(id = R.drawable.heart), + painter = painterResource(resource = Res.drawable.heart), contentDescription = "empty", tint = Color.LightGray ) diff --git a/app/src/main/java/com/spongycode/songquest/ui/screen/gameplay/playing/components/OptionField.kt b/composeApp/src/commonMain/kotlin/com/spongycode/songquest/ui/screen/gameplay/playing/components/OptionField.kt similarity index 86% rename from app/src/main/java/com/spongycode/songquest/ui/screen/gameplay/playing/components/OptionField.kt rename to composeApp/src/commonMain/kotlin/com/spongycode/songquest/ui/screen/gameplay/playing/components/OptionField.kt index 8eda4c6..9e96e97 100644 --- a/app/src/main/java/com/spongycode/songquest/ui/screen/gameplay/playing/components/OptionField.kt +++ b/composeApp/src/commonMain/kotlin/com/spongycode/songquest/ui/screen/gameplay/playing/components/OptionField.kt @@ -18,14 +18,15 @@ import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.graphics.Color import androidx.compose.ui.graphics.compositeOver -import androidx.compose.ui.res.painterResource import androidx.compose.ui.text.font.FontWeight -import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.sp import com.spongycode.songquest.util.Constants.LARGE_HEIGHT -import com.spongycode.songquest.util.Fonts import com.spongycode.songquest.util.bounceClick +import com.spongycode.songquest.util.defaultFontFamily +import org.jetbrains.compose.resources.DrawableResource +import org.jetbrains.compose.resources.painterResource +import org.jetbrains.compose.ui.tooling.preview.Preview @Preview @Composable @@ -35,7 +36,7 @@ fun OptionField( onClick: () -> Unit = {}, fillColor: Color = Color.White, tint: Color = Color.Black, - iconId: Int? = null + iconId: DrawableResource? = null ) { Surface( color = Color.Transparent, @@ -65,9 +66,9 @@ fun OptionField( color = Color.Black, fontSize = 20.sp, fontWeight = FontWeight.Medium, - fontFamily = Fonts.poppinsFamily + fontFamily = defaultFontFamily ) - iconId?.let { painterResource(id = it) }?.let { + iconId?.let { painterResource(resource = it) }?.let { Icon( painter = it, contentDescription = null, diff --git a/app/src/main/java/com/spongycode/songquest/ui/screen/gameplay/playing/components/OptionsArea.kt b/composeApp/src/commonMain/kotlin/com/spongycode/songquest/ui/screen/gameplay/playing/components/OptionsArea.kt similarity index 87% rename from app/src/main/java/com/spongycode/songquest/ui/screen/gameplay/playing/components/OptionsArea.kt rename to composeApp/src/commonMain/kotlin/com/spongycode/songquest/ui/screen/gameplay/playing/components/OptionsArea.kt index 1eb5e7c..97685af 100644 --- a/app/src/main/java/com/spongycode/songquest/ui/screen/gameplay/playing/components/OptionsArea.kt +++ b/composeApp/src/commonMain/kotlin/com/spongycode/songquest/ui/screen/gameplay/playing/components/OptionsArea.kt @@ -10,7 +10,6 @@ import androidx.compose.runtime.Composable import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.graphics.Color -import com.spongycode.songquest.R import com.spongycode.songquest.data.model.gameplay.QuestionModel import com.spongycode.songquest.ui.screen.gameplay.playing.OptionTapState import com.spongycode.songquest.ui.theme.OptionDarkGreen @@ -20,6 +19,9 @@ import com.spongycode.songquest.ui.theme.OptionLightGreen import com.spongycode.songquest.ui.theme.OptionLightRed import com.spongycode.songquest.ui.theme.OptionLightYellow import com.spongycode.songquest.util.Constants +import song_quest.composeapp.generated.resources.Res +import song_quest.composeapp.generated.resources.baseline_cancel_24 +import song_quest.composeapp.generated.resources.baseline_check_circle_24 @Composable fun OptionsArea( @@ -40,7 +42,7 @@ fun OptionsArea( text = option.value!!, onClick = { if ((optionTapState == OptionTapState.Idle)) { - onTapButton(option.optionid!!) + onTapButton(option.optionid) onCheckAnswer(option.optionid) } }, @@ -63,9 +65,9 @@ fun OptionsArea( iconId = if (option.optionid != tappedButtonId) null else { when (optionTapState) { OptionTapState.Checking -> null - OptionTapState.CorrectAnswer -> R.drawable.baseline_check_circle_24 + OptionTapState.CorrectAnswer -> Res.drawable.baseline_check_circle_24 OptionTapState.Idle -> null - OptionTapState.WrongAnswer -> R.drawable.baseline_cancel_24 + OptionTapState.WrongAnswer -> Res.drawable.baseline_cancel_24 } } ) diff --git a/app/src/main/java/com/spongycode/songquest/ui/screen/gameplay/playing/components/PlayingScreenPlaceholder.kt b/composeApp/src/commonMain/kotlin/com/spongycode/songquest/ui/screen/gameplay/playing/components/PlayingScreenPlaceholder.kt similarity index 73% rename from app/src/main/java/com/spongycode/songquest/ui/screen/gameplay/playing/components/PlayingScreenPlaceholder.kt rename to composeApp/src/commonMain/kotlin/com/spongycode/songquest/ui/screen/gameplay/playing/components/PlayingScreenPlaceholder.kt index 4ab6750..a5e620d 100644 --- a/app/src/main/java/com/spongycode/songquest/ui/screen/gameplay/playing/components/PlayingScreenPlaceholder.kt +++ b/composeApp/src/commonMain/kotlin/com/spongycode/songquest/ui/screen/gameplay/playing/components/PlayingScreenPlaceholder.kt @@ -14,13 +14,17 @@ import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.graphics.Color import androidx.compose.ui.layout.ContentScale -import androidx.compose.ui.res.painterResource +import org.jetbrains.compose.resources.painterResource import androidx.compose.ui.text.font.FontWeight import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.sp -import com.spongycode.songquest.R import com.spongycode.songquest.util.Constants -import com.spongycode.songquest.util.Fonts +import com.spongycode.songquest.util.defaultFontFamily +import song_quest.composeapp.generated.resources.Res +import song_quest.composeapp.generated.resources.bollywood_banner +import song_quest.composeapp.generated.resources.desi_hip_hop_banner +import song_quest.composeapp.generated.resources.hip_hop_banner +import song_quest.composeapp.generated.resources.hollywood_banner @Composable fun PlayingScreenPlaceholder( @@ -40,28 +44,28 @@ fun PlayingScreenPlaceholder( fontSize = 25.sp, color = MaterialTheme.colorScheme.background, fontWeight = FontWeight.W600, - fontFamily = Fonts.poppinsFamily + fontFamily = defaultFontFamily ) Image( modifier = Modifier .fillMaxWidth() .background(Color.Red), painter = painterResource( - id = when (category) { + resource = when (category) { Constants.BOLLYWOOD_CODE -> { - R.drawable.bollywood_banner + Res.drawable.bollywood_banner } Constants.HOLLYWOOD_CODE -> { - R.drawable.hollywood_banner + Res.drawable.hollywood_banner } Constants.DESI_HIP_HOP_CODE -> { - R.drawable.desi_hip_hop_banner + Res.drawable.desi_hip_hop_banner } else -> { - R.drawable.hip_hop_banner + Res.drawable.hip_hop_banner } } ), contentDescription = null, diff --git a/app/src/main/java/com/spongycode/songquest/ui/screen/gameplay/playing/components/PlayingScreenSuccess.kt b/composeApp/src/commonMain/kotlin/com/spongycode/songquest/ui/screen/gameplay/playing/components/PlayingScreenSuccess.kt similarity index 100% rename from app/src/main/java/com/spongycode/songquest/ui/screen/gameplay/playing/components/PlayingScreenSuccess.kt rename to composeApp/src/commonMain/kotlin/com/spongycode/songquest/ui/screen/gameplay/playing/components/PlayingScreenSuccess.kt diff --git a/app/src/main/java/com/spongycode/songquest/ui/screen/gameplay/playing/components/QuestionTitle.kt b/composeApp/src/commonMain/kotlin/com/spongycode/songquest/ui/screen/gameplay/playing/components/QuestionTitle.kt similarity index 91% rename from app/src/main/java/com/spongycode/songquest/ui/screen/gameplay/playing/components/QuestionTitle.kt rename to composeApp/src/commonMain/kotlin/com/spongycode/songquest/ui/screen/gameplay/playing/components/QuestionTitle.kt index 5268217..4515a2c 100644 --- a/app/src/main/java/com/spongycode/songquest/ui/screen/gameplay/playing/components/QuestionTitle.kt +++ b/composeApp/src/commonMain/kotlin/com/spongycode/songquest/ui/screen/gameplay/playing/components/QuestionTitle.kt @@ -13,12 +13,12 @@ import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.draw.clip import androidx.compose.ui.text.font.FontWeight -import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.sp import com.spongycode.songquest.ui.theme.OptionLightBlue import com.spongycode.songquest.util.Constants -import com.spongycode.songquest.util.Fonts +import com.spongycode.songquest.util.defaultFontFamily +import org.jetbrains.compose.ui.tooling.preview.Preview @Preview @Composable @@ -45,7 +45,7 @@ fun QuestionTitle(title: String = "") { text = title, fontSize = 20.sp, fontWeight = FontWeight.W600, - fontFamily = Fonts.poppinsFamily + fontFamily = defaultFontFamily ) } } diff --git a/app/src/main/java/com/spongycode/songquest/ui/screen/gameplay/playing/components/ScoreBoard.kt b/composeApp/src/commonMain/kotlin/com/spongycode/songquest/ui/screen/gameplay/playing/components/ScoreBoard.kt similarity index 85% rename from app/src/main/java/com/spongycode/songquest/ui/screen/gameplay/playing/components/ScoreBoard.kt rename to composeApp/src/commonMain/kotlin/com/spongycode/songquest/ui/screen/gameplay/playing/components/ScoreBoard.kt index fb9b971..d9479e9 100644 --- a/app/src/main/java/com/spongycode/songquest/ui/screen/gameplay/playing/components/ScoreBoard.kt +++ b/composeApp/src/commonMain/kotlin/com/spongycode/songquest/ui/screen/gameplay/playing/components/ScoreBoard.kt @@ -7,7 +7,7 @@ import androidx.compose.runtime.Composable import androidx.compose.ui.Alignment import androidx.compose.ui.text.font.FontWeight import androidx.compose.ui.unit.sp -import com.spongycode.songquest.util.Fonts +import com.spongycode.songquest.util.defaultFontFamily @Composable fun ScoreBoard(score: Float) { @@ -17,14 +17,14 @@ fun ScoreBoard(score: Float) { fontWeight = FontWeight.Medium, fontSize = 20.sp, color = MaterialTheme.colorScheme.primary, - fontFamily = Fonts.poppinsFamily + fontFamily = defaultFontFamily ) Text( text = "${score.toInt()}", fontWeight = FontWeight.W800, fontSize = 25.sp, color = MaterialTheme.colorScheme.primary, - fontFamily = Fonts.poppinsFamily + fontFamily = defaultFontFamily ) } } diff --git a/app/src/main/java/com/spongycode/songquest/ui/screen/gameplay/profile/ProfileScreen.kt b/composeApp/src/commonMain/kotlin/com/spongycode/songquest/ui/screen/gameplay/profile/ProfileScreen.kt similarity index 94% rename from app/src/main/java/com/spongycode/songquest/ui/screen/gameplay/profile/ProfileScreen.kt rename to composeApp/src/commonMain/kotlin/com/spongycode/songquest/ui/screen/gameplay/profile/ProfileScreen.kt index c2d68d3..171d02d 100644 --- a/app/src/main/java/com/spongycode/songquest/ui/screen/gameplay/profile/ProfileScreen.kt +++ b/composeApp/src/commonMain/kotlin/com/spongycode/songquest/ui/screen/gameplay/profile/ProfileScreen.kt @@ -23,11 +23,7 @@ import androidx.compose.ui.Modifier import androidx.compose.ui.graphics.Color import androidx.compose.ui.platform.LocalFocusManager import androidx.compose.ui.platform.LocalSoftwareKeyboardController -import androidx.compose.ui.res.stringResource -import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.unit.dp -import androidx.hilt.navigation.compose.hiltViewModel -import com.spongycode.songquest.R import com.spongycode.songquest.ui.navigation.LocalNavController import com.spongycode.songquest.ui.screen.auth.components.CustomButton import com.spongycode.songquest.ui.screen.auth.components.CustomTextField @@ -39,11 +35,15 @@ import com.spongycode.songquest.ui.theme.OptionDarkRed import com.spongycode.songquest.util.Constants import com.spongycode.songquest.util.Constants.REGISTER_SCREEN import kotlinx.coroutines.flow.collectLatest +import org.jetbrains.compose.resources.stringResource +import org.jetbrains.compose.ui.tooling.preview.Preview +import song_quest.composeapp.generated.resources.Res +import song_quest.composeapp.generated.resources.registration_error @OptIn(ExperimentalMaterial3Api::class) @Composable fun ProfileScreenRoot( - viewModel: ProfileViewModel = hiltViewModel() + viewModel: ProfileViewModel ) { val navController = LocalNavController.current val snackBarHostState = remember { SnackbarHostState() } @@ -149,7 +149,7 @@ fun ProfileScreen( displayText = when (uiState.profileState) { ProfileState.Checking -> "Updating profile.." ProfileState.Idle -> "Update Profile" - ProfileState.Error -> stringResource(R.string.registration_error) + ProfileState.Error -> stringResource(Res.string.registration_error) ProfileState.Success -> "Success, Proceed to Home" } ) diff --git a/app/src/main/java/com/spongycode/songquest/ui/screen/gameplay/profile/ProfileViewModel.kt b/composeApp/src/commonMain/kotlin/com/spongycode/songquest/ui/screen/gameplay/profile/ProfileViewModel.kt similarity index 82% rename from app/src/main/java/com/spongycode/songquest/ui/screen/gameplay/profile/ProfileViewModel.kt rename to composeApp/src/commonMain/kotlin/com/spongycode/songquest/ui/screen/gameplay/profile/ProfileViewModel.kt index 8a6e87e..58d48d8 100644 --- a/app/src/main/java/com/spongycode/songquest/ui/screen/gameplay/profile/ProfileViewModel.kt +++ b/composeApp/src/commonMain/kotlin/com/spongycode/songquest/ui/screen/gameplay/profile/ProfileViewModel.kt @@ -3,23 +3,20 @@ package com.spongycode.songquest.ui.screen.gameplay.profile import androidx.lifecycle.ViewModel import androidx.lifecycle.viewModelScope import com.spongycode.songquest.data.model.auth.UserModel -import com.spongycode.songquest.data.repository.DatastoreRepositoryImpl -import com.spongycode.songquest.domain.repository.AuthRepository -import com.spongycode.songquest.domain.repository.DatastoreRepository +import com.spongycode.songquest.repository.AuthRepository +import com.spongycode.songquest.repository.SettingsRepository +import com.spongycode.songquest.repository.SettingsRepositoryImpl import com.spongycode.songquest.util.ValidationHelper -import dagger.hilt.android.lifecycle.HiltViewModel import kotlinx.coroutines.flow.MutableSharedFlow import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.SharedFlow import kotlinx.coroutines.flow.asSharedFlow import kotlinx.coroutines.flow.asStateFlow import kotlinx.coroutines.launch -import javax.inject.Inject -@HiltViewModel -class ProfileViewModel @Inject constructor( +class ProfileViewModel( private val authRepository: AuthRepository, - private val datastoreRepository: DatastoreRepository + private val settingsRepository: SettingsRepository ) : ViewModel() { private val _uiState = MutableStateFlow(ProfileUiState()) val uiState = _uiState.asStateFlow() @@ -58,8 +55,8 @@ class ProfileViewModel @Inject constructor( private fun logout() { viewModelScope.launch { - datastoreRepository.storeString(DatastoreRepositoryImpl.accessTokenSession, "") - datastoreRepository.storeString(DatastoreRepositoryImpl.refreshTokenSession, "") + settingsRepository.storeString(SettingsRepositoryImpl.ACCESS_TOKEN_SESSION, "") + settingsRepository.storeString(SettingsRepositoryImpl.REFRESH_TOKEN_SESSION, "") } } @@ -76,14 +73,14 @@ class ProfileViewModel @Inject constructor( ) try { val accessToken = - datastoreRepository.getString(DatastoreRepositoryImpl.accessTokenSession) + settingsRepository.getString(SettingsRepositoryImpl.ACCESS_TOKEN_SESSION) val res = authRepository.updateProfile( UserModel(accessToken = accessToken, username = _uiState.value.username) ) if (res?.status == "success") { - datastoreRepository.storeString( - key = DatastoreRepositoryImpl.usernameSession, + settingsRepository.storeString( + key = SettingsRepositoryImpl.USERNAME_SESSION, value = res.data?.user?.username.toString() ) _uiState.value = _uiState.value.copy( @@ -106,9 +103,9 @@ class ProfileViewModel @Inject constructor( private fun getPersonalDetails() { viewModelScope.launch { _uiState.value = _uiState.value.copy( - username = datastoreRepository.getString(DatastoreRepositoryImpl.usernameSession) + username = settingsRepository.getString(SettingsRepositoryImpl.USERNAME_SESSION) .toString(), - email = datastoreRepository.getString(DatastoreRepositoryImpl.emailSession) + email = settingsRepository.getString(SettingsRepositoryImpl.EMAIL_SESSION) .toString() ) } diff --git a/app/src/main/java/com/spongycode/songquest/ui/screen/gameplay/profile/components/Topbar.kt b/composeApp/src/commonMain/kotlin/com/spongycode/songquest/ui/screen/gameplay/profile/components/Topbar.kt similarity index 87% rename from app/src/main/java/com/spongycode/songquest/ui/screen/gameplay/profile/components/Topbar.kt rename to composeApp/src/commonMain/kotlin/com/spongycode/songquest/ui/screen/gameplay/profile/components/Topbar.kt index 8d103f8..d335142 100644 --- a/app/src/main/java/com/spongycode/songquest/ui/screen/gameplay/profile/components/Topbar.kt +++ b/composeApp/src/commonMain/kotlin/com/spongycode/songquest/ui/screen/gameplay/profile/components/Topbar.kt @@ -2,6 +2,7 @@ package com.spongycode.songquest.ui.screen.gameplay.profile.components import androidx.compose.foundation.layout.size import androidx.compose.material.icons.Icons +import androidx.compose.material.icons.automirrored.filled.ArrowBack import androidx.compose.material.icons.filled.ArrowBack import androidx.compose.material3.CenterAlignedTopAppBar import androidx.compose.material3.ExperimentalMaterial3Api @@ -15,7 +16,7 @@ import androidx.compose.ui.Modifier import androidx.compose.ui.text.font.FontWeight import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.sp -import com.spongycode.songquest.util.Fonts +import com.spongycode.songquest.util.defaultFontFamily @ExperimentalMaterial3Api @Composable @@ -27,7 +28,7 @@ fun Topbar(onBackPressed: () -> Unit, title: String) { text = title, fontSize = 20.sp, fontWeight = FontWeight.Medium, - fontFamily = Fonts.poppinsFamily + fontFamily = defaultFontFamily ) }, navigationIcon = { @@ -35,7 +36,7 @@ fun Topbar(onBackPressed: () -> Unit, title: String) { onClick = onBackPressed ) { Icon( - Icons.Default.ArrowBack, + Icons.AutoMirrored.Filled.ArrowBack, contentDescription = "Back", modifier = Modifier.size(26.dp), tint = MaterialTheme.colorScheme.primary diff --git a/app/src/main/java/com/spongycode/songquest/ui/screen/starter/SplashScreen.kt b/composeApp/src/commonMain/kotlin/com/spongycode/songquest/ui/screen/starter/SplashScreen.kt similarity index 85% rename from app/src/main/java/com/spongycode/songquest/ui/screen/starter/SplashScreen.kt rename to composeApp/src/commonMain/kotlin/com/spongycode/songquest/ui/screen/starter/SplashScreen.kt index 3ccd28e..adffa0c 100644 --- a/app/src/main/java/com/spongycode/songquest/ui/screen/starter/SplashScreen.kt +++ b/composeApp/src/commonMain/kotlin/com/spongycode/songquest/ui/screen/starter/SplashScreen.kt @@ -20,23 +20,24 @@ import androidx.compose.ui.Modifier import androidx.compose.ui.draw.drawBehind import androidx.compose.ui.graphics.Color import androidx.compose.ui.graphics.drawscope.Stroke -import androidx.compose.ui.res.painterResource import androidx.compose.ui.text.font.FontWeight -import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.sp -import androidx.hilt.navigation.compose.hiltViewModel -import com.spongycode.songquest.R import com.spongycode.songquest.ui.navigation.LocalNavController -import com.spongycode.songquest.util.Fonts +import com.spongycode.songquest.util.defaultFontFamily import kotlinx.coroutines.flow.collectLatest +import org.jetbrains.compose.resources.painterResource +import org.jetbrains.compose.ui.tooling.preview.Preview +import song_quest.composeapp.generated.resources.Res +import song_quest.composeapp.generated.resources.compose_multiplatform +import song_quest.composeapp.generated.resources.logo_text @Composable fun SplashScreenRoot( - viewModel: SplashViewModel = hiltViewModel() + viewModel: SplashViewModel ) { val navController = LocalNavController.current - LaunchedEffect(null) { + LaunchedEffect(Unit) { viewModel.viewEffect.collectLatest { when (it) { is SplashViewEffect.Navigate -> { @@ -48,7 +49,6 @@ fun SplashScreenRoot( } } } - SplashScreen(onEvent = viewModel::onEvent) } @@ -75,7 +75,7 @@ fun SplashScreen( modifier = Modifier .height(200.dp) .width(210.dp), - painter = painterResource(id = R.drawable.logo_text), contentDescription = null + painter = painterResource(resource = Res.drawable.logo_text), contentDescription = null ) } Row( @@ -87,7 +87,7 @@ fun SplashScreen( text = "Authenticating ", fontSize = 25.sp, fontWeight = FontWeight.Medium, - fontFamily = Fonts.poppinsFamily, + fontFamily = defaultFontFamily, color = Color.White ) val strokeWidth = 3.dp diff --git a/app/src/main/java/com/spongycode/songquest/ui/screen/starter/SplashViewModel.kt b/composeApp/src/commonMain/kotlin/com/spongycode/songquest/ui/screen/starter/SplashViewModel.kt similarity index 67% rename from app/src/main/java/com/spongycode/songquest/ui/screen/starter/SplashViewModel.kt rename to composeApp/src/commonMain/kotlin/com/spongycode/songquest/ui/screen/starter/SplashViewModel.kt index 8d1315e..89879c1 100644 --- a/app/src/main/java/com/spongycode/songquest/ui/screen/starter/SplashViewModel.kt +++ b/composeApp/src/commonMain/kotlin/com/spongycode/songquest/ui/screen/starter/SplashViewModel.kt @@ -2,29 +2,27 @@ package com.spongycode.songquest.ui.screen.starter import androidx.lifecycle.ViewModel import androidx.lifecycle.viewModelScope -import com.spongycode.songquest.data.repository.DatastoreRepositoryImpl.Companion.accessTokenSession -import com.spongycode.songquest.data.repository.DatastoreRepositoryImpl.Companion.emailSession -import com.spongycode.songquest.data.repository.DatastoreRepositoryImpl.Companion.gamesPlayedSession -import com.spongycode.songquest.data.repository.DatastoreRepositoryImpl.Companion.refreshTokenSession -import com.spongycode.songquest.data.repository.DatastoreRepositoryImpl.Companion.usernameSession -import com.spongycode.songquest.domain.repository.AuthRepository -import com.spongycode.songquest.domain.repository.DatastoreRepository +import com.spongycode.songquest.repository.AuthRepository +import com.spongycode.songquest.repository.SettingsRepository +import com.spongycode.songquest.repository.SettingsRepositoryImpl.Companion.ACCESS_TOKEN_SESSION +import com.spongycode.songquest.repository.SettingsRepositoryImpl.Companion.EMAIL_SESSION +import com.spongycode.songquest.repository.SettingsRepositoryImpl.Companion.GAMES_PLAYED_SESSION +import com.spongycode.songquest.repository.SettingsRepositoryImpl.Companion.REFRESH_TOKEN_SESSION +import com.spongycode.songquest.repository.SettingsRepositoryImpl.Companion.USERNAME_SESSION import com.spongycode.songquest.util.Constants.HOME_SCREEN import com.spongycode.songquest.util.Constants.REGISTER_SCREEN -import dagger.hilt.android.lifecycle.HiltViewModel +import kotlinx.coroutines.delay import kotlinx.coroutines.flow.MutableSharedFlow import kotlinx.coroutines.flow.SharedFlow import kotlinx.coroutines.flow.asSharedFlow import kotlinx.coroutines.launch -import javax.inject.Inject -@HiltViewModel -class SplashViewModel @Inject constructor( +class SplashViewModel( private val authRepository: AuthRepository, - private val datastoreRepository: DatastoreRepository + private val settingsRepository: SettingsRepository ) : ViewModel() { - private val _viewEffect = MutableSharedFlow() + private val _viewEffect = MutableSharedFlow(replay = 1) val viewEffect: SharedFlow = _viewEffect.asSharedFlow() fun onEvent(event: SplashEvent) { @@ -38,32 +36,32 @@ class SplashViewModel @Inject constructor( private fun refreshToken() { viewModelScope.launch { try { - val refreshToken = datastoreRepository.getString(refreshTokenSession) + val refreshToken = settingsRepository.getString(REFRESH_TOKEN_SESSION) if (refreshToken.isNullOrBlank()) { _viewEffect.emit(SplashViewEffect.Navigate(route = REGISTER_SCREEN)) } else { val res = authRepository.refreshToken(refreshToken) if (res?.status == "success") { - datastoreRepository.storeListString( + settingsRepository.storeListString( listOf( Pair( - accessTokenSession, + ACCESS_TOKEN_SESSION, res.data?.accessToken.toString() ), Pair( - refreshTokenSession, + REFRESH_TOKEN_SESSION, res.data?.refreshToken.toString() ), Pair( - usernameSession, + USERNAME_SESSION, res.data?.user?.username.toString() ), Pair( - emailSession, + EMAIL_SESSION, res.data?.user?.email.toString() ), Pair( - gamesPlayedSession, + GAMES_PLAYED_SESSION, res.data?.user?.gamesPlayed.toString() ) ) diff --git a/app/src/main/java/com/spongycode/songquest/ui/theme/Color.kt b/composeApp/src/commonMain/kotlin/com/spongycode/songquest/ui/theme/Color.kt similarity index 100% rename from app/src/main/java/com/spongycode/songquest/ui/theme/Color.kt rename to composeApp/src/commonMain/kotlin/com/spongycode/songquest/ui/theme/Color.kt diff --git a/composeApp/src/commonMain/kotlin/com/spongycode/songquest/ui/theme/Theme.kt b/composeApp/src/commonMain/kotlin/com/spongycode/songquest/ui/theme/Theme.kt new file mode 100644 index 0000000..4e65b61 --- /dev/null +++ b/composeApp/src/commonMain/kotlin/com/spongycode/songquest/ui/theme/Theme.kt @@ -0,0 +1,29 @@ +package com.spongycode.songquest.ui.theme + +import androidx.compose.material3.MaterialTheme +import androidx.compose.material3.lightColorScheme +import androidx.compose.runtime.Composable +import androidx.compose.ui.graphics.Color + +private val LightColorScheme = lightColorScheme( + primary = Color.Black, + primaryContainer = Color(0xFFF1ECEC), + secondaryContainer = Color(0xFFE2D8D8), + inversePrimary = Color(0xFF777373), + secondary = PurpleGrey40, + tertiary = Pink40, + background = Color.White, +) + +@Composable +fun SongQuestTheme( + content: @Composable () -> Unit +) { + val colorScheme = LightColorScheme + + MaterialTheme( + colorScheme = colorScheme, + typography = Typography, + content = content + ) +} \ No newline at end of file diff --git a/composeApp/src/commonMain/kotlin/com/spongycode/songquest/ui/theme/Type.kt b/composeApp/src/commonMain/kotlin/com/spongycode/songquest/ui/theme/Type.kt new file mode 100644 index 0000000..b4aac5a --- /dev/null +++ b/composeApp/src/commonMain/kotlin/com/spongycode/songquest/ui/theme/Type.kt @@ -0,0 +1,17 @@ +package com.spongycode.songquest.ui.theme + +import androidx.compose.material3.Typography +import androidx.compose.ui.text.TextStyle +import androidx.compose.ui.text.font.FontFamily +import androidx.compose.ui.text.font.FontWeight +import androidx.compose.ui.unit.sp + +val Typography = Typography( + bodyLarge = TextStyle( + fontFamily = FontFamily.Default, + fontWeight = FontWeight.Normal, + fontSize = 16.sp, + lineHeight = 24.sp, + letterSpacing = 0.5.sp + ) +) \ No newline at end of file diff --git a/app/src/main/java/com/spongycode/songquest/ui/screen/ui_events/SnackBarEvent.kt b/composeApp/src/commonMain/kotlin/com/spongycode/songquest/ui/ui_events/SnackBarEvent.kt similarity index 60% rename from app/src/main/java/com/spongycode/songquest/ui/screen/ui_events/SnackBarEvent.kt rename to composeApp/src/commonMain/kotlin/com/spongycode/songquest/ui/ui_events/SnackBarEvent.kt index 1e2e35e..42f26c2 100644 --- a/app/src/main/java/com/spongycode/songquest/ui/screen/ui_events/SnackBarEvent.kt +++ b/composeApp/src/commonMain/kotlin/com/spongycode/songquest/ui/ui_events/SnackBarEvent.kt @@ -1,4 +1,4 @@ -package com.spongycode.songquest.ui.screen.ui_events +package com.spongycode.songquest.ui.ui_events data class SnackBarEvent( val show: Boolean = false, diff --git a/app/src/main/java/com/spongycode/songquest/util/CategoryConvertor.kt b/composeApp/src/commonMain/kotlin/com/spongycode/songquest/util/CategoryConvertor.kt similarity index 100% rename from app/src/main/java/com/spongycode/songquest/util/CategoryConvertor.kt rename to composeApp/src/commonMain/kotlin/com/spongycode/songquest/util/CategoryConvertor.kt diff --git a/app/src/main/java/com/spongycode/songquest/util/ComposeWrapper.kt b/composeApp/src/commonMain/kotlin/com/spongycode/songquest/util/ComposeWrapper.kt similarity index 100% rename from app/src/main/java/com/spongycode/songquest/util/ComposeWrapper.kt rename to composeApp/src/commonMain/kotlin/com/spongycode/songquest/util/ComposeWrapper.kt diff --git a/app/src/main/java/com/spongycode/songquest/util/Constants.kt b/composeApp/src/commonMain/kotlin/com/spongycode/songquest/util/Constants.kt similarity index 100% rename from app/src/main/java/com/spongycode/songquest/util/Constants.kt rename to composeApp/src/commonMain/kotlin/com/spongycode/songquest/util/Constants.kt diff --git a/composeApp/src/commonMain/kotlin/com/spongycode/songquest/util/Fonts.kt b/composeApp/src/commonMain/kotlin/com/spongycode/songquest/util/Fonts.kt new file mode 100644 index 0000000..ba54008 --- /dev/null +++ b/composeApp/src/commonMain/kotlin/com/spongycode/songquest/util/Fonts.kt @@ -0,0 +1,22 @@ +package com.spongycode.songquest.util + +import androidx.compose.runtime.Composable +import androidx.compose.ui.text.font.FontFamily +import androidx.compose.ui.text.font.FontWeight +import org.jetbrains.compose.resources.Font +import song_quest.composeapp.generated.resources.Res +import song_quest.composeapp.generated.resources.poppins_bold +import song_quest.composeapp.generated.resources.poppins_extra_bold +import song_quest.composeapp.generated.resources.poppins_light +import song_quest.composeapp.generated.resources.poppins_medium +import song_quest.composeapp.generated.resources.poppins_regular + +val defaultFontFamily: FontFamily + @Composable get() = FontFamily.Default +// @Composable get() = FontFamily( +// Font(weight = FontWeight.Bold, resource = Res.font.poppins_bold), +// Font(weight = FontWeight.Medium, resource = Res.font.poppins_medium), +// Font(weight = FontWeight.Normal, resource = Res.font.poppins_regular), +// Font(weight = FontWeight.SemiBold, resource = Res.font.poppins_light), +// Font(weight = FontWeight.ExtraBold, resource = Res.font.poppins_extra_bold) +// ) \ No newline at end of file diff --git a/app/src/main/java/com/spongycode/songquest/util/ModifierExt.kt b/composeApp/src/commonMain/kotlin/com/spongycode/songquest/util/ModifierExt.kt similarity index 100% rename from app/src/main/java/com/spongycode/songquest/util/ModifierExt.kt rename to composeApp/src/commonMain/kotlin/com/spongycode/songquest/util/ModifierExt.kt diff --git a/app/src/main/java/com/spongycode/songquest/util/Network.kt b/composeApp/src/commonMain/kotlin/com/spongycode/songquest/util/Network.kt similarity index 68% rename from app/src/main/java/com/spongycode/songquest/util/Network.kt rename to composeApp/src/commonMain/kotlin/com/spongycode/songquest/util/Network.kt index 9da1bc5..5790d7c 100644 --- a/app/src/main/java/com/spongycode/songquest/util/Network.kt +++ b/composeApp/src/commonMain/kotlin/com/spongycode/songquest/util/Network.kt @@ -1,8 +1,7 @@ package com.spongycode.songquest.util -import android.util.Log import kotlinx.coroutines.delay -import java.io.IOException +import kotlinx.io.IOException import kotlin.math.pow object Network { @@ -19,15 +18,15 @@ object Network { } catch (err: IOException) { lastException = err attempt++ - Log.d("http", "Retry attempt $attempt after IOException: ${err.message}") + println("http Retry attempt $attempt after IOException: ${err.message}") delay((500L * 2.0.pow(attempt)).toLong()) } catch (err: Exception) { - Log.e("http", "Non-IOException error: ${err.message}") + println("http Non-IOException error: ${err.message}") break } } - Log.e("http", "Request failed after $maxRetries attempts: ${lastException?.message}") + println("http Request failed after $maxRetries attempts: ${lastException?.message}") return null } } \ No newline at end of file diff --git a/composeApp/src/commonMain/kotlin/com/spongycode/songquest/util/PreferenceManager.kt b/composeApp/src/commonMain/kotlin/com/spongycode/songquest/util/PreferenceManager.kt new file mode 100644 index 0000000..8b8511e --- /dev/null +++ b/composeApp/src/commonMain/kotlin/com/spongycode/songquest/util/PreferenceManager.kt @@ -0,0 +1,102 @@ +package com.spongycode.songquest.util + +import com.russhwolf.settings.Settings +import kotlinx.serialization.json.Json + +abstract class BasePreferenceManager { + + val settings = Settings() + + open fun clear() { + settings.clear() + } + + fun getStringOrNull(key: String): String? { + return settings.getStringOrNull(key) + } + + fun putBoolean(key: String, value: Boolean) { + settings.putBoolean(key, value) + } + + fun getBoolean(key: String) = settings.getBoolean(key, false) + + fun putString(key: String, value: String?) { + value?.run { + settings.putString(key, value) + } ?: settings.remove(key) + } + + fun getLongOrNull(key: String): Long? { + return settings.getLongOrNull(key) + } + + fun putLong(key: String, value: Long?) { + value?.run { + settings.putLong(key, value) + } ?: settings.remove(key) + } + + fun getIntOrNull(key: String): Int? { + return settings.getIntOrNull(key) + } + + fun putInt(key: String, value: Int?) { + value?.run { + settings.putInt(key, value) + } ?: settings.remove(key) + } + + fun getBooleanOrNull(key: String): Boolean? { + return settings.getBooleanOrNull(key) + } + + fun putBoolean(key: String, value: Boolean?) { + value?.run { + settings.putBoolean(key, value) + } ?: settings.remove(key) + } + + fun getFloatOrNull(key: String): Float? { + return settings.getFloatOrNull(key) + } + + fun putFloat(key: String, value: Float?) { + value?.run { + settings.putFloat(key, value) + } ?: settings.remove(key) + } + + fun getDoubleOrNull(key: String): Double? { + return settings.getDoubleOrNull(key) + } + + fun putDouble(key: String, value: Double?) { + value?.run { + settings.putDouble(key, value) + } ?: settings.remove(key) + } + + inline fun putObject(key: String, classObject: T?): Boolean { + return try { + val objectString = Json.encodeToString(classObject) + settings.putString(key, objectString) + true + } catch (_: Exception) { + false + } + } + + inline fun getObject(key: String): T? { + return try { + val objectClassInstance = Json.decodeFromString(settings.getString(key, "")) + objectClassInstance + } catch (e: Exception) { + null + } + } + + fun removeObject(key: String) { + settings.remove(key) + } +} \ No newline at end of file diff --git a/composeApp/src/commonMain/kotlin/com/spongycode/songquest/util/TimesAgo.kt b/composeApp/src/commonMain/kotlin/com/spongycode/songquest/util/TimesAgo.kt new file mode 100644 index 0000000..949e2ec --- /dev/null +++ b/composeApp/src/commonMain/kotlin/com/spongycode/songquest/util/TimesAgo.kt @@ -0,0 +1,40 @@ +package com.spongycode.songquest.util + +import kotlinx.datetime.TimeZone +import kotlinx.datetime.toLocalDateTime +import kotlin.time.Clock +import kotlin.time.ExperimentalTime +import kotlin.time.Instant + +object TimesAgo { + @OptIn(ExperimentalTime::class) + fun getTimeAgo(time: String): String { + return try { + val serverInstant = Instant.parse(time) + val nowInstant = Clock.System.now() + val diff = nowInstant.epochSeconds - serverInstant.epochSeconds + val seconds = diff + val minutes = seconds / 60 + val hours = minutes / 60 + val days = hours / 24 + + when { + days > 2 -> { + val localDateTime = + serverInstant.toLocalDateTime(TimeZone.currentSystemDefault()) + val hour = localDateTime.hour.toString().padStart(2, '0') + val minute = localDateTime.minute.toString().padStart(2, '0') + "${localDateTime.month.name.lowercase().replaceFirstChar { it.uppercase() }} " + + "${localDateTime.day} at $hour:$minute" + } + + days >= 1 -> if (days > 1) "$days days ago" else "yesterday" + hours >= 1 -> "$hours hour${if (hours > 1) "s" else ""} ago" + minutes >= 1 -> "$minutes min${if (minutes > 1) "s" else ""} ago" + else -> "$seconds sec${if (seconds > 1) "s" else ""} ago" + } + } catch (e: Exception) { + "just now" + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/spongycode/songquest/util/ValidationHelper.kt b/composeApp/src/commonMain/kotlin/com/spongycode/songquest/util/ValidationHelper.kt similarity index 93% rename from app/src/main/java/com/spongycode/songquest/util/ValidationHelper.kt rename to composeApp/src/commonMain/kotlin/com/spongycode/songquest/util/ValidationHelper.kt index 0c43b4d..7acf04c 100644 --- a/app/src/main/java/com/spongycode/songquest/util/ValidationHelper.kt +++ b/composeApp/src/commonMain/kotlin/com/spongycode/songquest/util/ValidationHelper.kt @@ -1,7 +1,5 @@ package com.spongycode.songquest.util -import android.util.Patterns - object ValidationHelper { fun validateUsername(username: String): String? { val trimmedUsername = username.trim() @@ -19,13 +17,16 @@ object ValidationHelper { return null } + private val EMAIL_REGEX = + "^[A-Za-z0-9+_.-]+@[A-Za-z0-9.-]+$".toRegex() + fun validateEmail(email: String): String? { val trimmedEmail = email.trim() if (trimmedEmail.isBlank()) { return "Email is required" } - if (!Patterns.EMAIL_ADDRESS.matcher(trimmedEmail).matches()) { + if (!EMAIL_REGEX.matches(trimmedEmail)) { return "Email not valid" } return null diff --git a/composeApp/src/iosMain/kotlin/com/spongycode/songquest/AudioPlayer.ios.kt b/composeApp/src/iosMain/kotlin/com/spongycode/songquest/AudioPlayer.ios.kt new file mode 100644 index 0000000..465b2a4 --- /dev/null +++ b/composeApp/src/iosMain/kotlin/com/spongycode/songquest/AudioPlayer.ios.kt @@ -0,0 +1,51 @@ +package com.spongycode.songquest + +import kotlinx.cinterop.ExperimentalForeignApi +import kotlinx.cinterop.cValue +import platform.AVFoundation.AVPlayer +import platform.AVFoundation.AVPlayerItemDidPlayToEndTimeNotification +import platform.AVFoundation.currentItem +import platform.AVFoundation.pause +import platform.AVFoundation.play +import platform.AVFoundation.seekToTime +import platform.CoreMedia.CMTimeMake +import platform.CoreMedia.kCMTimeZero +import platform.Foundation.NSURL + +actual class AudioPlayer actual constructor() { + private var player: AVPlayer? = null + private var sourceUrl: String? = null + + actual fun setSource(url: String) { + sourceUrl = url + } + + @OptIn(ExperimentalForeignApi::class) + actual fun prepareAndPlay(looping: Boolean) { + val nsUrl = NSURL(string = sourceUrl ?: return) + player = AVPlayer.playerWithURL(nsUrl) + player?.play() + + if (looping) { + // Add observer to loop playback + platform.Foundation.NSNotificationCenter.defaultCenter.addObserverForName( + name = AVPlayerItemDidPlayToEndTimeNotification, + `object` = player?.currentItem, + queue = null + ) { _ -> + player?.seekToTime(cValue { value = 0L }) + player?.play() + } + } + } + + actual fun stop() { + player?.pause() + } + + actual fun release() { + player?.pause() + player = null + } +} + diff --git a/composeApp/src/iosMain/kotlin/com/spongycode/songquest/BitmapShare.ios.kt b/composeApp/src/iosMain/kotlin/com/spongycode/songquest/BitmapShare.ios.kt new file mode 100644 index 0000000..13f7a5d --- /dev/null +++ b/composeApp/src/iosMain/kotlin/com/spongycode/songquest/BitmapShare.ios.kt @@ -0,0 +1,10 @@ +package com.spongycode.songquest + +import androidx.compose.ui.graphics.ImageBitmap + +actual fun ImageBitmap.share( + context: PlatformContext, + score: Int?, + category: String? +) { +} \ No newline at end of file diff --git a/composeApp/src/iosMain/kotlin/com/spongycode/songquest/MainViewController.kt b/composeApp/src/iosMain/kotlin/com/spongycode/songquest/MainViewController.kt new file mode 100644 index 0000000..a1031ca --- /dev/null +++ b/composeApp/src/iosMain/kotlin/com/spongycode/songquest/MainViewController.kt @@ -0,0 +1,8 @@ +package com.spongycode.songquest + +import androidx.compose.ui.window.ComposeUIViewController + + +fun MainViewController() = ComposeUIViewController { + App() +} \ No newline at end of file diff --git a/composeApp/src/iosMain/kotlin/com/spongycode/songquest/Platform.ios.kt b/composeApp/src/iosMain/kotlin/com/spongycode/songquest/Platform.ios.kt new file mode 100644 index 0000000..1ca4500 --- /dev/null +++ b/composeApp/src/iosMain/kotlin/com/spongycode/songquest/Platform.ios.kt @@ -0,0 +1,31 @@ +package com.spongycode.songquest + +import kotlinx.cinterop.ExperimentalForeignApi +import platform.CoreGraphics.CGRectGetHeight +import platform.CoreGraphics.CGRectGetWidth +import platform.UIKit.UIScreen + +actual fun platform(): String = "iOS" +@OptIn(ExperimentalForeignApi::class) +actual fun getScreenWidth(): Float { + val bounds = UIScreen.mainScreen.bounds + return CGRectGetWidth(bounds).toFloat() +} + +@OptIn(ExperimentalForeignApi::class) +actual fun getScreenHeight(): Float { + val bounds = UIScreen.mainScreen.bounds + return CGRectGetHeight(bounds).toFloat() +} + +actual object PlatformContext { + private var appContext: Any? = null + + actual fun setContext(context: Any) { + appContext = context + } + + actual fun getContext(): Any? { + return appContext + } +} \ No newline at end of file diff --git a/composeApp/src/wasmJsMain/kotlin/com/spongycode/songquest/AudioPlayer.wasmJs.kt b/composeApp/src/wasmJsMain/kotlin/com/spongycode/songquest/AudioPlayer.wasmJs.kt new file mode 100644 index 0000000..4d12a73 --- /dev/null +++ b/composeApp/src/wasmJsMain/kotlin/com/spongycode/songquest/AudioPlayer.wasmJs.kt @@ -0,0 +1,30 @@ +package com.spongycode.songquest + +import kotlinx.browser.document +import org.w3c.dom.HTMLAudioElement + +actual class AudioPlayer actual constructor() { + private var audio: HTMLAudioElement? = null + private var sourceUrl: String? = null + + actual fun setSource(url: String) { + sourceUrl = url + } + + @OptIn(ExperimentalWasmJsInterop::class) + actual fun prepareAndPlay(looping: Boolean) { + audio = document.createElement("audio") as HTMLAudioElement + audio?.src = sourceUrl ?: return + audio?.loop = looping + audio?.play() + } + + actual fun stop() { + audio?.pause() + } + + actual fun release() { + audio?.pause() + audio = null + } +} \ No newline at end of file diff --git a/composeApp/src/wasmJsMain/kotlin/com/spongycode/songquest/BitmapShare.wasmJs.kt b/composeApp/src/wasmJsMain/kotlin/com/spongycode/songquest/BitmapShare.wasmJs.kt new file mode 100644 index 0000000..13f7a5d --- /dev/null +++ b/composeApp/src/wasmJsMain/kotlin/com/spongycode/songquest/BitmapShare.wasmJs.kt @@ -0,0 +1,10 @@ +package com.spongycode.songquest + +import androidx.compose.ui.graphics.ImageBitmap + +actual fun ImageBitmap.share( + context: PlatformContext, + score: Int?, + category: String? +) { +} \ No newline at end of file diff --git a/composeApp/src/wasmJsMain/kotlin/com/spongycode/songquest/Platform.wasmJs.kt b/composeApp/src/wasmJsMain/kotlin/com/spongycode/songquest/Platform.wasmJs.kt new file mode 100644 index 0000000..750771b --- /dev/null +++ b/composeApp/src/wasmJsMain/kotlin/com/spongycode/songquest/Platform.wasmJs.kt @@ -0,0 +1,24 @@ +package com.spongycode.songquest + +import kotlinx.browser.window + +actual fun platform(): String = "Web" +actual fun getScreenHeight(): Float { + return window.innerHeight.toFloat() +} + +actual fun getScreenWidth(): Float { + return window.innerWidth.toFloat() +} + +actual object PlatformContext { + private var appContext: Any? = null + + actual fun setContext(context: Any) { + appContext = context + } + + actual fun getContext(): Any? { + return appContext + } +} \ No newline at end of file diff --git a/composeApp/src/wasmJsMain/kotlin/com/spongycode/songquest/main.kt b/composeApp/src/wasmJsMain/kotlin/com/spongycode/songquest/main.kt new file mode 100644 index 0000000..a56eb12 --- /dev/null +++ b/composeApp/src/wasmJsMain/kotlin/com/spongycode/songquest/main.kt @@ -0,0 +1,12 @@ +package com.spongycode.songquest + +import androidx.compose.ui.ExperimentalComposeUiApi +import androidx.compose.ui.window.ComposeViewport +import kotlinx.browser.document + +@OptIn(ExperimentalComposeUiApi::class) +fun main() { + ComposeViewport(document.body!!) { + App() + } +} \ No newline at end of file diff --git a/composeApp/src/wasmJsMain/resources/index.html b/composeApp/src/wasmJsMain/resources/index.html new file mode 100644 index 0000000..5b3c63b --- /dev/null +++ b/composeApp/src/wasmJsMain/resources/index.html @@ -0,0 +1,12 @@ + + + + + + Song quest + + + + + + \ No newline at end of file diff --git a/composeApp/src/wasmJsMain/resources/styles.css b/composeApp/src/wasmJsMain/resources/styles.css new file mode 100644 index 0000000..0549b10 --- /dev/null +++ b/composeApp/src/wasmJsMain/resources/styles.css @@ -0,0 +1,7 @@ +html, body { + width: 100%; + height: 100%; + margin: 0; + padding: 0; + overflow: hidden; +} \ No newline at end of file diff --git a/gradle.properties b/gradle.properties index 3c5031e..2d73063 100644 --- a/gradle.properties +++ b/gradle.properties @@ -1,23 +1,5 @@ -# Project-wide Gradle settings. -# IDE (e.g. Android Studio) users: -# Gradle settings configured through the IDE *will override* -# any settings specified in this file. -# For more details on how to configure your build environment visit -# http://www.gradle.org/docs/current/userguide/build_environment.html -# Specifies the JVM arguments used for the daemon process. -# The setting is particularly useful for tweaking memory settings. org.gradle.jvmargs=-Xmx2048m -Dfile.encoding=UTF-8 -# When configured, Gradle will run in incubating parallel mode. -# This option should only be used with decoupled projects. More details, visit -# http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects -# org.gradle.parallel=true -# AndroidX package structure to make it clearer which packages are bundled with the -# Android operating system, and which are packaged with your app's APK -# https://developer.android.com/topic/libraries/support-library/androidx-rn android.useAndroidX=true -# Kotlin code style for this project: "official" or "obsolete": kotlin.code.style=official -# Enables namespacing of each library's R class so that its R class includes only the -# resources declared in the library itself and none from the library's dependencies, -# thereby reducing the size of the R class for that library -android.nonTransitiveRClass=true \ No newline at end of file +android.nonTransitiveRClass=true +kotlin.daemon.jvmargs=-Xmx6g \ No newline at end of file diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml new file mode 100644 index 0000000..2304f9c --- /dev/null +++ b/gradle/libs.versions.toml @@ -0,0 +1,77 @@ +[versions] +agp = "8.13.0" +activityCompose = "1.11.0" +androidx-lifecycle = "2.9.4" +composeBom = "2025.09.00" +composeMultiplatform = "1.9.0" +coreKtx = "1.17.0" +datastorePreferences = "1.1.7" +junit = "4.13.2" +composeHotReload = "1.0.0-beta08" +kotlin = "2.2.20" +kotlinStdlib = "2.2.20" +kotlinxDatetime = "0.7.1" +kotlinxSerializationJson = "1.9.0" +ktor = "3.3.0" +ktorClientContentNegotiation = "3.3.0" +lifecycleRuntimeKtx = "2.9.4" +materialIconsCore = "1.7.3" +navigationCompose = "2.9.0" +runtimeLivedata = "1.9.1" +multiplatformSettings = "1.3.0" + +[libraries] +kotlinx-datetime = { module = "org.jetbrains.kotlinx:kotlinx-datetime", version.ref = "kotlinxDatetime" } +material-icons-core = { module = "org.jetbrains.compose.material:material-icons-core", version.ref = "materialIconsCore" } +multiplatform-settings-no-arg = { group = "com.russhwolf", name = "multiplatform-settings-no-arg", version.ref = "multiplatformSettings" } +multiplatform-settings = { group = "com.russhwolf", name = "multiplatform-settings", version.ref = "multiplatformSettings" } +androidx-activity-compose = { module = "androidx.activity:activity-compose", version.ref = "activityCompose" } +androidx-compose-bom = { module = "androidx.compose:compose-bom", version.ref = "composeBom" } +androidx-compose-material3 = { module = "androidx.compose.material3:material3" } +androidx-compose-material3-window-size-class1 = { module = "androidx.compose.material3:material3-window-size-class" } +androidx-compose-runtime-livedata = { module = "androidx.compose.runtime:runtime-livedata", version.ref = "runtimeLivedata" } +androidx-core-ktx = { module = "androidx.core:core-ktx", version.ref = "coreKtx" } +androidx-datastore-preferences = { module = "androidx.datastore:datastore-preferences", version.ref = "datastorePreferences" } +androidx-lifecycle-runtime-ktx = { module = "androidx.lifecycle:lifecycle-runtime-ktx", version.ref = "lifecycleRuntimeKtx" } +androidx-material3 = { module = "androidx.compose.material3:material3" } +androidx-material3-window-size-class1 = { module = "androidx.compose.material3:material3-window-size-class" } +navigation-compose = { module = "org.jetbrains.androidx.navigation:navigation-compose", version.ref = "navigationCompose" } +androidx-ui = { module = "androidx.compose.ui:ui" } +androidx-ui-graphics = { module = "androidx.compose.ui:ui-graphics" } +androidx-ui-tooling-preview = { module = "androidx.compose.ui:ui-tooling-preview" } +kotlin-stdlib = { module = "org.jetbrains.kotlin:kotlin-stdlib", version.ref = "kotlinStdlib" } +kotlin-test = { module = "org.jetbrains.kotlin:kotlin-test", version.ref = "kotlin" } +kotlin-testJunit = { module = "org.jetbrains.kotlin:kotlin-test-junit", version.ref = "kotlin" } +junit = { module = "junit:junit", version.ref = "junit" } +androidx-lifecycle-viewmodelCompose = { module = "org.jetbrains.androidx.lifecycle:lifecycle-viewmodel-compose", version.ref = "androidx-lifecycle" } +androidx-lifecycle-viewmodel = { module = "org.jetbrains.androidx.lifecycle:lifecycle-viewmodel", version.ref = "androidx-lifecycle" } +androidx-lifecycle-runtimeCompose = { module = "org.jetbrains.androidx.lifecycle:lifecycle-runtime-compose", version.ref = "androidx-lifecycle" } +kotlinx-serialization-json = { module = "org.jetbrains.kotlinx:kotlinx-serialization-json", version.ref = "kotlinxSerializationJson" } +ktor-client-cio = { module = "io.ktor:ktor-client-cio", version.ref = "ktorClientContentNegotiation" } +ktor-bom = { group = "io.ktor", name = "ktor-bom", version.ref = "ktor" } +ktor-client-core = { group = "io.ktor", name = "ktor-client-core"} +ktor-client-json = { group = "io.ktor", name = "ktor-client-json" } +ktor-serialization-kotlinx-json = { group = "io.ktor", name = "ktor-serialization-kotlinx-json" } +ktor-client-logging = { group = "io.ktor", name = "ktor-client-logging" } +ktor-client-serialization = { group = "io.ktor", name = "ktor-client-serialization" } +ktor-client-content-negotiation = { group = "io.ktor", name = "ktor-client-content-negotiation" } +ktor-client-auth = { group = "io.ktor", name = "ktor-client-auth"} +ktor-client-encoding = { group = "io.ktor", name = "ktor-client-encoding"} +ktor-client-darwin = { group = "io.ktor", name = "ktor-client-darwin" } +ktor-client-js = { group = "io.ktor", name = "ktor-client-js" } +ktor-client-java = { group = "io.ktor", name = "ktor-client-java" } +ktor-client-okhttp = { group = "io.ktor", name = "ktor-client-okhttp"} + +[bundles] +ktor-common = ["ktor-client-core", "ktor-client-json", "ktor-client-logging", + "ktor-client-serialization", "ktor-client-content-negotiation", + "ktor-serialization-kotlinx-json", "ktor-client-auth", "ktor-client-encoding"] + + +[plugins] +androidLibrary = {id = "com.android.library", version.ref = "agp" } +androidApplication = {id = "com.android.application", version.ref = "agp" } +composeMultiplatform = { id = "org.jetbrains.compose", version.ref = "composeMultiplatform" } +composeCompiler = { id = "org.jetbrains.kotlin.plugin.compose", version.ref = "kotlin" } +composeHotReload = { id = "org.jetbrains.compose.hot-reload", version.ref = "composeHotReload" } +kotlinMultiplatform = { id = "org.jetbrains.kotlin.multiplatform", version.ref = "kotlin" } diff --git a/gradlew b/gradlew old mode 100644 new mode 100755 diff --git a/iosApp/Configuration/Config.xcconfig b/iosApp/Configuration/Config.xcconfig new file mode 100644 index 0000000..7fd30c7 --- /dev/null +++ b/iosApp/Configuration/Config.xcconfig @@ -0,0 +1,7 @@ +TEAM_ID= + +PRODUCT_NAME=songquest +PRODUCT_BUNDLE_IDENTIFIER=com.spongycode.songquest.songquest$(TEAM_ID) + +CURRENT_PROJECT_VERSION=1 +MARKETING_VERSION=1.0 \ No newline at end of file diff --git a/iosApp/iosApp.xcodeproj/project.pbxproj b/iosApp/iosApp.xcodeproj/project.pbxproj new file mode 100644 index 0000000..a541b5f --- /dev/null +++ b/iosApp/iosApp.xcodeproj/project.pbxproj @@ -0,0 +1,379 @@ +// !$*UTF8*$! +{ + archiveVersion = 1; + classes = { + }; + objectVersion = 77; + objects = { + +/* Begin PBXFileReference section */ + B9DA97B12DC1472C00A4DA20 /* songquest.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = flight.app; sourceTree = BUILT_PRODUCTS_DIR; }; +/* End PBXFileReference section */ + +/* Begin PBXFileSystemSynchronizedBuildFileExceptionSet section */ + B99700CA2DC9B8D800C7335B /* Exceptions for "iosApp" folder in "iosApp" target */ = { + isa = PBXFileSystemSynchronizedBuildFileExceptionSet; + membershipExceptions = ( + Info.plist, + ); + target = B9DA97B02DC1472C00A4DA20 /* iosApp */; + }; +/* End PBXFileSystemSynchronizedBuildFileExceptionSet section */ + +/* Begin PBXFileSystemSynchronizedRootGroup section */ + B9DA97B32DC1472C00A4DA20 /* iosApp */ = { + isa = PBXFileSystemSynchronizedRootGroup; + exceptions = ( + B99700CA2DC9B8D800C7335B /* Exceptions for "iosApp" folder in "iosApp" target */, + ); + path = iosApp; + sourceTree = ""; + }; + B9DA98002DC14AA900A4DA20 /* Configuration */ = { + isa = PBXFileSystemSynchronizedRootGroup; + path = Configuration; + sourceTree = ""; + }; +/* End PBXFileSystemSynchronizedRootGroup section */ + +/* Begin PBXFrameworksBuildPhase section */ + B9DA97AE2DC1472C00A4DA20 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXFrameworksBuildPhase section */ + +/* Begin PBXGroup section */ + B9DA97A82DC1472C00A4DA20 = { + isa = PBXGroup; + children = ( + B9DA98002DC14AA900A4DA20 /* Configuration */, + B9DA97B32DC1472C00A4DA20 /* iosApp */, + B9DA97B22DC1472C00A4DA20 /* Products */, + ); + sourceTree = ""; + }; + B9DA97B22DC1472C00A4DA20 /* Products */ = { + isa = PBXGroup; + children = ( + B9DA97B12DC1472C00A4DA20 /* songquest.app */, + ); + name = Products; + sourceTree = ""; + }; +/* End PBXGroup section */ + +/* Begin PBXNativeTarget section */ + B9DA97B02DC1472C00A4DA20 /* iosApp */ = { + isa = PBXNativeTarget; + buildConfigurationList = B9DA97BF2DC1472D00A4DA20 /* Build configuration list for PBXNativeTarget "iosApp" */; + buildPhases = ( + B9DA97F42DC1497100A4DA20 /* Compile Kotlin Framework */, + B9DA97AD2DC1472C00A4DA20 /* Sources */, + B9DA97AE2DC1472C00A4DA20 /* Frameworks */, + B9DA97AF2DC1472C00A4DA20 /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + ); + fileSystemSynchronizedGroups = ( + B9DA97B32DC1472C00A4DA20 /* iosApp */, + ); + name = iosApp; + packageProductDependencies = ( + ); + productName = iosApp; + productReference = B9DA97B12DC1472C00A4DA20 /* songquest.app */; + productType = "com.apple.product-type.application"; + }; +/* End PBXNativeTarget section */ + +/* Begin PBXProject section */ + B9DA97A92DC1472C00A4DA20 /* Project object */ = { + isa = PBXProject; + attributes = { + BuildIndependentTargetsInParallel = 1; + LastSwiftUpdateCheck = 1620; + LastUpgradeCheck = 1620; + TargetAttributes = { + B9DA97B02DC1472C00A4DA20 = { + CreatedOnToolsVersion = 16.2; + }; + }; + }; + buildConfigurationList = B9DA97AC2DC1472C00A4DA20 /* Build configuration list for PBXProject "iosApp" */; + developmentRegion = en; + hasScannedForEncodings = 0; + knownRegions = ( + en, + Base, + ); + mainGroup = B9DA97A82DC1472C00A4DA20; + minimizedProjectReferenceProxies = 1; + preferredProjectObjectVersion = 77; + productRefGroup = B9DA97B22DC1472C00A4DA20 /* Products */; + projectDirPath = ""; + projectRoot = ""; + targets = ( + B9DA97B02DC1472C00A4DA20 /* iosApp */, + ); + }; +/* End PBXProject section */ + +/* Begin PBXResourcesBuildPhase section */ + B9DA97AF2DC1472C00A4DA20 /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXResourcesBuildPhase section */ + +/* Begin PBXShellScriptBuildPhase section */ + B9DA97F42DC1497100A4DA20 /* Compile Kotlin Framework */ = { + isa = PBXShellScriptBuildPhase; + alwaysOutOfDate = 1; + buildActionMask = 2147483647; + files = ( + ); + inputFileListPaths = ( + ); + inputPaths = ( + ); + name = "Compile Kotlin Framework"; + outputFileListPaths = ( + ); + outputPaths = ( + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "if [ \"YES\" = \"$OVERRIDE_KOTLIN_BUILD_IDE_SUPPORTED\" ]; then\n echo \"Skipping Gradle build task invocation due to OVERRIDE_KOTLIN_BUILD_IDE_SUPPORTED environment variable set to \\\"YES\\\"\"\n exit 0\nfi\ncd \"$SRCROOT/..\"\n./gradlew :composeApp:embedAndSignAppleFrameworkForXcode\n"; + }; +/* End PBXShellScriptBuildPhase section */ + +/* Begin PBXSourcesBuildPhase section */ + B9DA97AD2DC1472C00A4DA20 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXSourcesBuildPhase section */ + +/* Begin XCBuildConfiguration section */ + B9DA97BD2DC1472D00A4DA20 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = YES; + CLANG_ANALYZER_NONNULL = YES; + CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++20"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_ENABLE_OBJC_WEAK = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_DOCUMENTATION_COMMENTS = YES; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = dwarf; + ENABLE_STRICT_OBJC_MSGSEND = YES; + ENABLE_TESTABILITY = YES; + ENABLE_USER_SCRIPT_SANDBOXING = NO; + GCC_C_LANGUAGE_STANDARD = gnu17; + GCC_DYNAMIC_NO_PIC = NO; + GCC_NO_COMMON_BLOCKS = YES; + GCC_OPTIMIZATION_LEVEL = 0; + GCC_PREPROCESSOR_DEFINITIONS = ( + "DEBUG=1", + "$(inherited)", + ); + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + IPHONEOS_DEPLOYMENT_TARGET = 18.2; + LOCALIZATION_PREFERS_STRING_CATALOGS = YES; + MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE; + MTL_FAST_MATH = YES; + ONLY_ACTIVE_ARCH = YES; + SDKROOT = iphoneos; + SWIFT_ACTIVE_COMPILATION_CONDITIONS = "DEBUG $(inherited)"; + SWIFT_OPTIMIZATION_LEVEL = "-Onone"; + }; + name = Debug; + }; + B9DA97BE2DC1472D00A4DA20 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = YES; + CLANG_ANALYZER_NONNULL = YES; + CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++20"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_ENABLE_OBJC_WEAK = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_DOCUMENTATION_COMMENTS = YES; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + ENABLE_NS_ASSERTIONS = NO; + ENABLE_STRICT_OBJC_MSGSEND = YES; + ENABLE_USER_SCRIPT_SANDBOXING = NO; + GCC_C_LANGUAGE_STANDARD = gnu17; + GCC_NO_COMMON_BLOCKS = YES; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + IPHONEOS_DEPLOYMENT_TARGET = 18.2; + LOCALIZATION_PREFERS_STRING_CATALOGS = YES; + MTL_ENABLE_DEBUG_INFO = NO; + MTL_FAST_MATH = YES; + SDKROOT = iphoneos; + SWIFT_COMPILATION_MODE = wholemodule; + VALIDATE_PRODUCT = YES; + }; + name = Release; + }; + B9DA97C02DC1472D00A4DA20 /* Debug */ = { + isa = XCBuildConfiguration; + baseConfigurationReferenceAnchor = B9DA98002DC14AA900A4DA20 /* Configuration */; + baseConfigurationReferenceRelativePath = Config.xcconfig; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor; + CODE_SIGN_IDENTITY = "Apple Development"; + CODE_SIGN_STYLE = Automatic; + DEVELOPMENT_ASSET_PATHS = "\"iosApp/Preview Content\""; + DEVELOPMENT_TEAM = "${TEAM_ID}"; + ENABLE_PREVIEWS = YES; + FRAMEWORK_SEARCH_PATHS = ( + "$(inherited)", + "$(SRCROOT)/../shared/build/xcode-frameworks/$(CONFIGURATION)/$(SDK_NAME)\n$(SRCROOT)/../composeApp/build/xcode-frameworks/$(CONFIGURATION)/$(SDK_NAME)", + ); + GENERATE_INFOPLIST_FILE = YES; + INFOPLIST_FILE = iosApp/Info.plist; + INFOPLIST_KEY_UIApplicationSceneManifest_Generation = YES; + INFOPLIST_KEY_UIApplicationSupportsIndirectInputEvents = YES; + INFOPLIST_KEY_UILaunchScreen_Generation = YES; + INFOPLIST_KEY_UISupportedInterfaceOrientations_iPad = "UIInterfaceOrientationPortrait UIInterfaceOrientationPortraitUpsideDown UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight"; + INFOPLIST_KEY_UISupportedInterfaceOrientations_iPhone = "UIInterfaceOrientationPortrait UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight"; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + ); + SWIFT_EMIT_LOC_STRINGS = YES; + SWIFT_VERSION = 5.0; + TARGETED_DEVICE_FAMILY = "1,2"; + }; + name = Debug; + }; + B9DA97C12DC1472D00A4DA20 /* Release */ = { + isa = XCBuildConfiguration; + baseConfigurationReferenceAnchor = B9DA98002DC14AA900A4DA20 /* Configuration */; + baseConfigurationReferenceRelativePath = Config.xcconfig; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor; + CODE_SIGN_IDENTITY = "Apple Development"; + CODE_SIGN_STYLE = Automatic; + DEVELOPMENT_ASSET_PATHS = "\"iosApp/Preview Content\""; + DEVELOPMENT_TEAM = "${TEAM_ID}"; + ENABLE_PREVIEWS = YES; + FRAMEWORK_SEARCH_PATHS = ( + "$(inherited)", + "$(SRCROOT)/../shared/build/xcode-frameworks/$(CONFIGURATION)/$(SDK_NAME)\n$(SRCROOT)/../composeApp/build/xcode-frameworks/$(CONFIGURATION)/$(SDK_NAME)", + ); + GENERATE_INFOPLIST_FILE = YES; + INFOPLIST_FILE = iosApp/Info.plist; + INFOPLIST_KEY_UIApplicationSceneManifest_Generation = YES; + INFOPLIST_KEY_UIApplicationSupportsIndirectInputEvents = YES; + INFOPLIST_KEY_UILaunchScreen_Generation = YES; + INFOPLIST_KEY_UISupportedInterfaceOrientations_iPad = "UIInterfaceOrientationPortrait UIInterfaceOrientationPortraitUpsideDown UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight"; + INFOPLIST_KEY_UISupportedInterfaceOrientations_iPhone = "UIInterfaceOrientationPortrait UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight"; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + ); + SWIFT_EMIT_LOC_STRINGS = YES; + SWIFT_VERSION = 5.0; + TARGETED_DEVICE_FAMILY = "1,2"; + }; + name = Release; + }; +/* End XCBuildConfiguration section */ + +/* Begin XCConfigurationList section */ + B9DA97AC2DC1472C00A4DA20 /* Build configuration list for PBXProject "iosApp" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + B9DA97BD2DC1472D00A4DA20 /* Debug */, + B9DA97BE2DC1472D00A4DA20 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + B9DA97BF2DC1472D00A4DA20 /* Build configuration list for PBXNativeTarget "iosApp" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + B9DA97C02DC1472D00A4DA20 /* Debug */, + B9DA97C12DC1472D00A4DA20 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; +/* End XCConfigurationList section */ + }; + rootObject = B9DA97A92DC1472C00A4DA20 /* Project object */; +} \ No newline at end of file diff --git a/iosApp/iosApp/Assets.xcassets/AccentColor.colorset/Contents.json b/iosApp/iosApp/Assets.xcassets/AccentColor.colorset/Contents.json new file mode 100644 index 0000000..eb87897 --- /dev/null +++ b/iosApp/iosApp/Assets.xcassets/AccentColor.colorset/Contents.json @@ -0,0 +1,11 @@ +{ + "colors" : [ + { + "idiom" : "universal" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/iosApp/iosApp/Assets.xcassets/AppIcon.appiconset/Contents.json b/iosApp/iosApp/Assets.xcassets/AppIcon.appiconset/Contents.json new file mode 100644 index 0000000..4e8d485 --- /dev/null +++ b/iosApp/iosApp/Assets.xcassets/AppIcon.appiconset/Contents.json @@ -0,0 +1,36 @@ +{ + "images" : [ + { + "filename" : "app-icon-1024.png", + "idiom" : "universal", + "platform" : "ios", + "size" : "1024x1024" + }, + { + "appearances" : [ + { + "appearance" : "luminosity", + "value" : "dark" + } + ], + "idiom" : "universal", + "platform" : "ios", + "size" : "1024x1024" + }, + { + "appearances" : [ + { + "appearance" : "luminosity", + "value" : "tinted" + } + ], + "idiom" : "universal", + "platform" : "ios", + "size" : "1024x1024" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/iosApp/iosApp/Assets.xcassets/AppIcon.appiconset/app-icon-1024.png b/iosApp/iosApp/Assets.xcassets/AppIcon.appiconset/app-icon-1024.png new file mode 100644 index 0000000..53fc536 Binary files /dev/null and b/iosApp/iosApp/Assets.xcassets/AppIcon.appiconset/app-icon-1024.png differ diff --git a/iosApp/iosApp/Assets.xcassets/Contents.json b/iosApp/iosApp/Assets.xcassets/Contents.json new file mode 100644 index 0000000..73c0059 --- /dev/null +++ b/iosApp/iosApp/Assets.xcassets/Contents.json @@ -0,0 +1,6 @@ +{ + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/iosApp/iosApp/ContentView.swift b/iosApp/iosApp/ContentView.swift new file mode 100644 index 0000000..cb095b3 --- /dev/null +++ b/iosApp/iosApp/ContentView.swift @@ -0,0 +1,21 @@ +import UIKit +import SwiftUI +import composeApp + +struct ComposeView: UIViewControllerRepresentable { + func makeUIViewController(context: Context) -> UIViewController { + MainViewControllerKt.MainViewController() + } + + func updateUIViewController(_ uiViewController: UIViewController, context: Context) {} +} + +struct ContentView: View { + var body: some View { + ComposeView() + .ignoresSafeArea(.keyboard) // Compose has own keyboard handler + } +} + + + diff --git a/iosApp/iosApp/Info.plist b/iosApp/iosApp/Info.plist new file mode 100644 index 0000000..d350fdc --- /dev/null +++ b/iosApp/iosApp/Info.plist @@ -0,0 +1,10 @@ + + + + + CADisableMinimumFrameDurationOnPhone + + NSAllowsArbitraryLoads + + + diff --git a/iosApp/iosApp/Preview Content/Preview Assets.xcassets/Contents.json b/iosApp/iosApp/Preview Content/Preview Assets.xcassets/Contents.json new file mode 100644 index 0000000..73c0059 --- /dev/null +++ b/iosApp/iosApp/Preview Content/Preview Assets.xcassets/Contents.json @@ -0,0 +1,6 @@ +{ + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/iosApp/iosApp/iOSApp.swift b/iosApp/iosApp/iOSApp.swift new file mode 100644 index 0000000..d83dca6 --- /dev/null +++ b/iosApp/iosApp/iOSApp.swift @@ -0,0 +1,10 @@ +import SwiftUI + +@main +struct iOSApp: App { + var body: some Scene { + WindowGroup { + ContentView() + } + } +} \ No newline at end of file diff --git a/settings.gradle.kts b/settings.gradle.kts index 5b3224c..2a9aa44 100644 --- a/settings.gradle.kts +++ b/settings.gradle.kts @@ -1,17 +1,30 @@ +rootProject.name = "song-quest" + pluginManagement { repositories { - google() + google { + mavenContent { + includeGroupAndSubgroups("androidx") + includeGroupAndSubgroups("com.android") + includeGroupAndSubgroups("com.google") + } + } mavenCentral() gradlePluginPortal() } } + dependencyResolutionManagement { - repositoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_REPOS) repositories { - google() + google { + mavenContent { + includeGroupAndSubgroups("androidx") + includeGroupAndSubgroups("com.android") + includeGroupAndSubgroups("com.google") + } + } mavenCentral() } } -rootProject.name = "Song Quest" -include(":app") +include(":composeApp")