diff --git a/.github/funding.yml b/.github/funding.yml new file mode 100644 index 0000000..332a2ab --- /dev/null +++ b/.github/funding.yml @@ -0,0 +1 @@ +buy_me_a_coffee: ricky9667 diff --git a/app/build.gradle.kts b/app/build.gradle.kts index bc1f3c4..2ea416f 100644 --- a/app/build.gradle.kts +++ b/app/build.gradle.kts @@ -92,6 +92,7 @@ dependencies { implementation(libs.androidx.compose.ui.graphics) implementation(libs.androidx.compose.ui.tooling.preview) implementation(libs.androidx.compose.material3) + implementation("androidx.compose.material:material-icons-extended") debugImplementation(libs.androidx.compose.ui.tooling) debugImplementation(libs.androidx.compose.ui.test.manifest) @@ -107,6 +108,8 @@ dependencies { implementation(libs.androidx.datastore) implementation(libs.kotlinx.serialization.json) + implementation(libs.tnoodle) + // Testing testImplementation(libs.junit) testImplementation(libs.robolectric) diff --git a/app/src/main/java/com/rickyhu/hushkeyboard/home/HomeScreen.kt b/app/src/main/java/com/rickyhu/hushkeyboard/home/HomeScreen.kt index a6ca2c8..01f3147 100644 --- a/app/src/main/java/com/rickyhu/hushkeyboard/home/HomeScreen.kt +++ b/app/src/main/java/com/rickyhu/hushkeyboard/home/HomeScreen.kt @@ -37,6 +37,8 @@ import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.unit.dp import com.rickyhu.hushkeyboard.R import com.rickyhu.hushkeyboard.theme.HushKeyboardTheme +import com.rickyhu.hushkeyboard.utils.ScrambleProvider +import org.worldcubeassociation.tnoodle.scrambles.PuzzleRegistry @Composable fun HomeScreen( @@ -44,6 +46,7 @@ fun HomeScreen( navigateToSettings: () -> Unit = {}, ) { var text by remember { mutableStateOf("") } + var scramble by remember { mutableStateOf("") } Scaffold( content = { paddingValues -> @@ -93,6 +96,25 @@ fun HomeScreen( ) { Text(text = stringResource(R.string.home_settings_button)) } + + Button( + onClick = { + scramble = ScrambleProvider.getScramble(PuzzleRegistry.THREE) + }, + modifier = + Modifier + .fillMaxWidth() + .padding(horizontal = 16.dp), + ) { + Text("Generate New Scramble") + } + + Text( + scramble, + style = MaterialTheme.typography.displaySmall, + modifier = Modifier.padding(16.dp), + ) + OutlinedTextField( value = text, onValueChange = { text = it }, diff --git a/app/src/main/java/com/rickyhu/hushkeyboard/settings/ui/ThemeOptionDropdownItem.kt b/app/src/main/java/com/rickyhu/hushkeyboard/settings/ui/ThemeOptionDropdownItem.kt index 379c37f..a56631a 100644 --- a/app/src/main/java/com/rickyhu/hushkeyboard/settings/ui/ThemeOptionDropdownItem.kt +++ b/app/src/main/java/com/rickyhu/hushkeyboard/settings/ui/ThemeOptionDropdownItem.kt @@ -43,7 +43,7 @@ fun ThemeOptionDropdownItem( expanded = expanded, onDismissRequest = { expanded = false }, ) { - for (option in ThemeOption.values()) { + for (option in ThemeOption.entries) { DropdownMenuItem( modifier = Modifier.testTag("ThemeOptionDropdownMenuItem"), text = { Text(option.name) }, diff --git a/app/src/main/java/com/rickyhu/hushkeyboard/theme/Type.kt b/app/src/main/java/com/rickyhu/hushkeyboard/theme/Type.kt index b24f5c8..f12c8d5 100644 --- a/app/src/main/java/com/rickyhu/hushkeyboard/theme/Type.kt +++ b/app/src/main/java/com/rickyhu/hushkeyboard/theme/Type.kt @@ -2,35 +2,97 @@ package com.rickyhu.hushkeyboard.theme import androidx.compose.material3.Typography import androidx.compose.ui.text.TextStyle +import androidx.compose.ui.text.font.Font import androidx.compose.ui.text.font.FontFamily +import androidx.compose.ui.text.font.FontStyle import androidx.compose.ui.text.font.FontWeight import androidx.compose.ui.unit.sp +import com.rickyhu.hushkeyboard.R + +val FontRubik = + FontFamily( + Font( + R.font.rubik_regular, + style = FontStyle.Normal, + ), + Font( + R.font.rubik_italic, + style = FontStyle.Italic, + ), + ) + +val FontMontserrat = + FontFamily( + Font( + R.font.montserrat_regular, + style = FontStyle.Normal, + ), + Font( + R.font.montserrat_italic, + style = FontStyle.Italic, + ), + ) -// Set of Material typography styles to start with val Typography = Typography( - bodyLarge = + displayLarge = + TextStyle( + fontFamily = FontRubik, + fontWeight = FontWeight.Bold, + fontSize = 60.sp, + ), + displayMedium = + TextStyle( + fontFamily = FontRubik, + fontWeight = FontWeight.Bold, + fontSize = 48.sp, + ), + displaySmall = + TextStyle( + fontFamily = FontRubik, + fontWeight = FontWeight.Bold, + fontSize = 24.sp, + ), + titleLarge = + TextStyle( + fontFamily = FontMontserrat, + fontWeight = FontWeight.Bold, + fontSize = 32.sp, + lineHeight = 36.sp, + ), + titleMedium = TextStyle( - fontFamily = FontFamily.Default, - fontWeight = FontWeight.Normal, + fontFamily = FontMontserrat, + fontWeight = FontWeight.Bold, + fontSize = 24.sp, + lineHeight = 28.sp, + ), + titleSmall = + TextStyle( + fontFamily = FontMontserrat, + fontWeight = FontWeight.Bold, 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 - ) - */ + ), + bodyLarge = + TextStyle( + fontFamily = FontMontserrat, + fontWeight = FontWeight.SemiBold, + fontSize = 18.sp, + lineHeight = 24.sp, + ), + bodyMedium = + TextStyle( + fontFamily = FontMontserrat, + fontWeight = FontWeight.SemiBold, + fontSize = 15.sp, + lineHeight = 20.sp, + ), + bodySmall = + TextStyle( + fontFamily = FontMontserrat, + fontWeight = FontWeight.SemiBold, + fontSize = 12.sp, + lineHeight = 20.sp, + ), ) diff --git a/app/src/main/java/com/rickyhu/hushkeyboard/utils/ScrambleProvider.kt b/app/src/main/java/com/rickyhu/hushkeyboard/utils/ScrambleProvider.kt new file mode 100644 index 0000000..8d9f00b --- /dev/null +++ b/app/src/main/java/com/rickyhu/hushkeyboard/utils/ScrambleProvider.kt @@ -0,0 +1,16 @@ +package com.rickyhu.hushkeyboard.utils + +import org.worldcubeassociation.tnoodle.scrambles.PuzzleRegistry +import java.security.NoSuchProviderException +import java.security.SecureRandom + +object ScrambleProvider { + val random: SecureRandom = + try { + SecureRandom.getInstance("SHA1PRNG", "AndroidOpenSSL") + } catch (e: NoSuchProviderException) { + SecureRandom() // Fallback to default + } + + fun getScramble(puzzleType: PuzzleRegistry): String = puzzleType.scrambler.generateWcaScramble(random) +} diff --git a/app/src/main/res/font/montserrat_italic.ttf b/app/src/main/res/font/montserrat_italic.ttf new file mode 100644 index 0000000..76e3f9d Binary files /dev/null and b/app/src/main/res/font/montserrat_italic.ttf differ diff --git a/app/src/main/res/font/montserrat_regular.ttf b/app/src/main/res/font/montserrat_regular.ttf new file mode 100644 index 0000000..451e692 Binary files /dev/null and b/app/src/main/res/font/montserrat_regular.ttf differ diff --git a/app/src/main/res/font/rubik_italic.ttf b/app/src/main/res/font/rubik_italic.ttf new file mode 100644 index 0000000..847a80f Binary files /dev/null and b/app/src/main/res/font/rubik_italic.ttf differ diff --git a/app/src/main/res/font/rubik_regular.ttf b/app/src/main/res/font/rubik_regular.ttf new file mode 100644 index 0000000..a5d54e9 Binary files /dev/null and b/app/src/main/res/font/rubik_regular.ttf differ diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index f4ae57b..2d46baf 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -1,5 +1,5 @@ - Hush Keyboard + HUSH Keyboard com.rickyhu.hushkeyboard diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 6b393b4..9f45b79 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -1,22 +1,23 @@ [versions] -activity-compose = "1.10.1" +activity-compose = "1.11.0" android-gradle-plugin = "8.11.1" -android-lifecycle = "2.9.2" -compose-bom = "2025.07.00" -core-ktx = "1.16.0" +android-lifecycle = "2.9.4" +compose-bom = "2025.09.01" +core-ktx = "1.17.0" datastore = "1.1.7" -hilt = "2.57" -hilt-navigation-compose = "1.2.0" +hilt = "2.57.1" +hilt-navigation-compose = "1.3.0" junit = "4.13.2" -junit-ext = "1.2.1" -kotlin = "2.2.0" -kotlin-serialization = "2.2.0" +junit-ext = "1.3.0" +kotlin = "2.2.20" +kotlin-serialization = "2.2.20" kotlinx-serialization-json = "1.9.0" -kover = "0.9.1" -ktlint = "13.0.0" -navigation-compose = "2.9.2" -robolectric = "4.15.1" +kover = "0.9.2" +ktlint = "13.1.0" +navigation-compose = "2.9.5" +robolectric = "4.16" splitties-systemservices = "3.0.0" +tnoodle = "0.19.2" [libraries] androidx-core-ktx = { group = "androidx.core", name = "core-ktx", version.ref = "core-ktx" } @@ -42,6 +43,7 @@ kotlin-serialization = { group = "org.jetbrains.kotlin", name = "kotlin-serializ kotlinx-serialization-json = { group = "org.jetbrains.kotlinx", name = "kotlinx-serialization-json", version.ref = "kotlinx-serialization-json" } robolectric = { group = "org.robolectric", name = "robolectric", version.ref = "robolectric" } splitties-systemservices = { group = "com.louiscad.splitties", name = "splitties-systemservices", version.ref = "splitties-systemservices" } +tnoodle = { module = "org.worldcubeassociation.tnoodle:lib-scrambles", version.ref = "tnoodle" } [plugins] android-application = { id = "com.android.application", version.ref = "android-gradle-plugin" }