Add ktlint

This commit is contained in:
Nathan Adams 2024-03-16 23:55:01 +01:00 committed by TÖRÖK Attila
parent e395c087b4
commit bf88d5c8e6
15 changed files with 352 additions and 345 deletions

7
.editorconfig Normal file
View File

@ -0,0 +1,7 @@
root = true
[*.{kt,kts}]
ktlint_code_style = android_studio
ij_kotlin_name_count_to_use_star_import = 9999
ij_kotlin_name_count_to_use_star_import_for_members = 9999
ktlint_function_naming_ignore_when_annotated_with=Composable

View File

@ -69,7 +69,6 @@ android {
}
}
splits {
// Configures multiple APKs based on ABI.
abi {
@ -121,4 +120,4 @@ if (System.getenv("GITHUB_ACTIONS") == null) {
apiLevel = 26
buildType = "release"
}
}
}

View File

@ -1,13 +1,11 @@
package rs.ruffle
import androidx.test.platform.app.InstrumentationRegistry
import androidx.test.ext.junit.runners.AndroidJUnit4
import androidx.test.platform.app.InstrumentationRegistry
import org.junit.Assert.assertEquals
import org.junit.Test
import org.junit.runner.RunWith
import org.junit.Assert.*
/**
* Instrumented test, which will execute on an Android device.
*
@ -21,4 +19,4 @@ class ExampleInstrumentedTest {
val appContext = InstrumentationRegistry.getInstrumentation().targetContext
assertEquals("rs.ruffle", appContext.packageName)
}
}
}

View File

@ -6,8 +6,8 @@ import android.os.Bundle
import androidx.activity.ComponentActivity
import androidx.activity.compose.setContent
import androidx.activity.enableEdgeToEdge
import rs.ruffle.ui.theme.RuffleTheme
import java.io.IOException
import rs.ruffle.ui.theme.RuffleTheme
class MainActivity : ComponentActivity() {
override fun onCreate(savedInstanceState: Bundle?) {

View File

@ -1,29 +1,29 @@
package rs.ruffle
import android.net.Uri
import androidx.compose.runtime.Composable
import androidx.navigation.NavHostController
import androidx.navigation.compose.NavHost
import androidx.navigation.compose.composable
import androidx.navigation.compose.rememberNavController
object Destinations {
const val SELECT_SWF_ROUTE = "select"
}
@Composable
fun RuffleNavHost(
navController: NavHostController = rememberNavController(),
openSwf: (uri: Uri) -> Unit
) {
NavHost(
navController = navController,
startDestination = Destinations.SELECT_SWF_ROUTE,
) {
composable(Destinations.SELECT_SWF_ROUTE) {
SelectSwfRoute(
openSwf = openSwf
)
}
}
}
package rs.ruffle
import android.net.Uri
import androidx.compose.runtime.Composable
import androidx.navigation.NavHostController
import androidx.navigation.compose.NavHost
import androidx.navigation.compose.composable
import androidx.navigation.compose.rememberNavController
object Destinations {
const val SELECT_SWF_ROUTE = "select"
}
@Composable
fun RuffleNavHost(
navController: NavHostController = rememberNavController(),
openSwf: (uri: Uri) -> Unit
) {
NavHost(
navController = navController,
startDestination = Destinations.SELECT_SWF_ROUTE
) {
composable(Destinations.SELECT_SWF_ROUTE) {
SelectSwfRoute(
openSwf = openSwf
)
}
}
}

View File

@ -1,200 +1,198 @@
package rs.ruffle
import android.content.res.Configuration
import android.net.Uri
import androidx.activity.compose.rememberLauncherForActivityResult
import androidx.activity.result.contract.ActivityResultContracts
import androidx.compose.foundation.Image
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.paddingFromBaseline
import androidx.compose.foundation.layout.width
import androidx.compose.foundation.layout.wrapContentHeight
import androidx.compose.foundation.text.KeyboardActions
import androidx.compose.foundation.text.KeyboardOptions
import androidx.compose.material3.Button
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.OutlinedButton
import androidx.compose.material3.OutlinedTextField
import androidx.compose.material3.Scaffold
import androidx.compose.material3.Surface
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.saveable.rememberSaveable
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.focus.onFocusChanged
import androidx.compose.ui.res.painterResource
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.text.input.ImeAction
import androidx.compose.ui.text.input.KeyboardType
import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.dp
import rs.ruffle.ui.theme.RuffleTheme
import rs.ruffle.ui.theme.slightlyDeemphasizedAlpha
@Composable
fun BrandBar() {
Image(
painter = painterResource(id = R.drawable.ic_logo_dark),
contentDescription = stringResource(id = R.string.logo_description),
modifier = Modifier
.padding(horizontal = 76.dp)
)
}
@Composable
fun SelectSwfRoute(
openSwf: (uri: Uri) -> Unit
) {
SelectSwfScreen(
openSwf = openSwf
)
}
@Composable
fun SelectSwfScreen(openSwf: (uri: Uri) -> Unit) {
Scaffold { innerPadding ->
Column(
modifier = Modifier.padding(innerPadding)
) {
Column(
modifier = Modifier.wrapContentHeight(align = Alignment.CenterVertically)
) {
BrandBar()
}
Text(
modifier = Modifier.padding(horizontal = 8.dp, vertical = 75.dp),
text = stringResource(id = R.string.work_in_progress_warning)
)
SelectSwfUrlOrFile(openSwf)
}
}
}
@Composable
private fun SelectSwfUrlOrFile(
openSwf: (uri: Uri) -> Unit
) {
val urlState by rememberSaveable(stateSaver = UrlStateSaver) {
mutableStateOf(UrlState())
}
Column(
modifier = Modifier
.padding(horizontal = 20.dp)
) {
val submitUrl = {
if (urlState.isValid) {
openSwf(Uri.parse(urlState.text))
} else {
urlState.enableShowErrors()
}
}
OutlinedTextField(
value = urlState.text,
onValueChange = { urlState.text = it },
modifier = Modifier
.fillMaxWidth()
.onFocusChanged { focusState ->
urlState.onFocusChange(focusState.isFocused)
if (!focusState.isFocused) {
urlState.enableShowErrors()
}
},
label = {
Text(
text = stringResource(id = R.string.url),
style = MaterialTheme.typography.bodyMedium,
)
},
textStyle = MaterialTheme.typography.bodyMedium,
isError = urlState.showErrors(),
keyboardOptions = KeyboardOptions.Default.copy(
imeAction = ImeAction.Go,
keyboardType = KeyboardType.Uri
),
keyboardActions = KeyboardActions(
onDone = { submitUrl() }
),
singleLine = true
)
urlState.getError()?.let { error -> TextFieldError(textError = error) }
Button(
onClick = submitUrl,
modifier = Modifier
.fillMaxWidth()
.padding(top = 28.dp, bottom = 3.dp)
) {
Text(
text = stringResource(id = R.string.open_url),
style = MaterialTheme.typography.titleSmall
)
}
Column(
horizontalAlignment = Alignment.CenterHorizontally
) {
Text(
text = stringResource(id = R.string.or),
style = MaterialTheme.typography.titleSmall,
color = MaterialTheme.colorScheme.onSurface.copy(alpha = slightlyDeemphasizedAlpha),
modifier = Modifier.paddingFromBaseline(top = 25.dp)
)
PickSwfButton(openSwf)
}
}
}
@Composable
fun PickSwfButton(onSelect: (uri: Uri) -> Unit) {
val launcher = rememberLauncherForActivityResult(ActivityResultContracts.GetContent()) {
if (it != null) {
onSelect(it)
}
}
OutlinedButton(
onClick = {
launcher.launch(
"application/x-shockwave-flash"
)
},
modifier = Modifier
.fillMaxWidth()
.padding(top = 20.dp, bottom = 24.dp),
) {
Text(text = stringResource(id = R.string.select_a_swf))
}
}
@Composable
fun TextFieldError(textError: String) {
Row(modifier = Modifier.fillMaxWidth()) {
Spacer(modifier = Modifier.width(16.dp))
Text(
text = textError,
modifier = Modifier.fillMaxWidth(),
color = MaterialTheme.colorScheme.error
)
}
}
@Preview(name = "Select SWF - Light", uiMode = Configuration.UI_MODE_NIGHT_NO)
@Preview(name = "Select SWF - Dark", uiMode = Configuration.UI_MODE_NIGHT_YES)
@Composable
fun SelectSwfScreenPreview() {
RuffleTheme {
Surface {
SelectSwfScreen(
openSwf = {}
)
}
}
}
package rs.ruffle
import android.content.res.Configuration
import android.net.Uri
import androidx.activity.compose.rememberLauncherForActivityResult
import androidx.activity.result.contract.ActivityResultContracts
import androidx.compose.foundation.Image
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.paddingFromBaseline
import androidx.compose.foundation.layout.width
import androidx.compose.foundation.layout.wrapContentHeight
import androidx.compose.foundation.text.KeyboardActions
import androidx.compose.foundation.text.KeyboardOptions
import androidx.compose.material3.Button
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.OutlinedButton
import androidx.compose.material3.OutlinedTextField
import androidx.compose.material3.Scaffold
import androidx.compose.material3.Surface
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.saveable.rememberSaveable
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.focus.onFocusChanged
import androidx.compose.ui.res.painterResource
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.text.input.ImeAction
import androidx.compose.ui.text.input.KeyboardType
import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.dp
import rs.ruffle.ui.theme.RuffleTheme
import rs.ruffle.ui.theme.SLIGHTLY_DEEMPHASIZED_ALPHA
@Composable
fun BrandBar() {
Image(
painter = painterResource(id = R.drawable.ic_logo_dark),
contentDescription = stringResource(id = R.string.logo_description),
modifier = Modifier
.padding(horizontal = 76.dp)
)
}
@Composable
fun SelectSwfRoute(openSwf: (uri: Uri) -> Unit) {
SelectSwfScreen(
openSwf = openSwf
)
}
@Composable
fun SelectSwfScreen(openSwf: (uri: Uri) -> Unit) {
Scaffold { innerPadding ->
Column(
modifier = Modifier.padding(innerPadding)
) {
Column(
modifier = Modifier.wrapContentHeight(align = Alignment.CenterVertically)
) {
BrandBar()
}
Text(
modifier = Modifier.padding(horizontal = 8.dp, vertical = 75.dp),
text = stringResource(id = R.string.work_in_progress_warning)
)
SelectSwfUrlOrFile(openSwf)
}
}
}
@Composable
private fun SelectSwfUrlOrFile(openSwf: (uri: Uri) -> Unit) {
val urlState by rememberSaveable(stateSaver = UrlStateSaver) {
mutableStateOf(UrlState())
}
Column(
modifier = Modifier
.padding(horizontal = 20.dp)
) {
val submitUrl = {
if (urlState.isValid) {
openSwf(Uri.parse(urlState.text))
} else {
urlState.enableShowErrors()
}
}
OutlinedTextField(
value = urlState.text,
onValueChange = { urlState.text = it },
modifier = Modifier
.fillMaxWidth()
.onFocusChanged { focusState ->
urlState.onFocusChange(focusState.isFocused)
if (!focusState.isFocused) {
urlState.enableShowErrors()
}
},
label = {
Text(
text = stringResource(id = R.string.url),
style = MaterialTheme.typography.bodyMedium
)
},
textStyle = MaterialTheme.typography.bodyMedium,
isError = urlState.showErrors(),
keyboardOptions = KeyboardOptions.Default.copy(
imeAction = ImeAction.Go,
keyboardType = KeyboardType.Uri
),
keyboardActions = KeyboardActions(
onDone = { submitUrl() }
),
singleLine = true
)
urlState.getError()?.let { error -> TextFieldError(textError = error) }
Button(
onClick = submitUrl,
modifier = Modifier
.fillMaxWidth()
.padding(top = 28.dp, bottom = 3.dp)
) {
Text(
text = stringResource(id = R.string.open_url),
style = MaterialTheme.typography.titleSmall
)
}
Column(
horizontalAlignment = Alignment.CenterHorizontally
) {
Text(
text = stringResource(id = R.string.or),
style = MaterialTheme.typography.titleSmall,
color = MaterialTheme.colorScheme.onSurface.copy(
alpha = SLIGHTLY_DEEMPHASIZED_ALPHA
),
modifier = Modifier.paddingFromBaseline(top = 25.dp)
)
PickSwfButton(openSwf)
}
}
}
@Composable
fun PickSwfButton(onSelect: (uri: Uri) -> Unit) {
val launcher = rememberLauncherForActivityResult(ActivityResultContracts.GetContent()) {
if (it != null) {
onSelect(it)
}
}
OutlinedButton(
onClick = {
launcher.launch(
"application/x-shockwave-flash"
)
},
modifier = Modifier
.fillMaxWidth()
.padding(top = 20.dp, bottom = 24.dp)
) {
Text(text = stringResource(id = R.string.select_a_swf))
}
}
@Composable
fun TextFieldError(textError: String) {
Row(modifier = Modifier.fillMaxWidth()) {
Spacer(modifier = Modifier.width(16.dp))
Text(
text = textError,
modifier = Modifier.fillMaxWidth(),
color = MaterialTheme.colorScheme.error
)
}
}
@Preview(name = "Select SWF - Light", uiMode = Configuration.UI_MODE_NIGHT_NO)
@Preview(name = "Select SWF - Dark", uiMode = Configuration.UI_MODE_NIGHT_YES)
@Composable
fun SelectSwfScreenPreview() {
RuffleTheme {
Surface {
SelectSwfScreen(
openSwf = {}
)
}
}
}

View File

@ -1,53 +1,53 @@
package rs.ruffle
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.saveable.listSaver
import androidx.compose.runtime.setValue
open class TextFieldState(
private val validator: (String) -> Boolean = { true },
private val errorFor: (String) -> String = { "" }
) {
var text: String by mutableStateOf("")
// was the TextField ever focused
var isFocusedDirty: Boolean by mutableStateOf(false)
var isFocused: Boolean by mutableStateOf(false)
private var displayErrors: Boolean by mutableStateOf(false)
open val isValid: Boolean
get() = validator(text)
fun onFocusChange(focused: Boolean) {
isFocused = focused
if (focused) isFocusedDirty = true
}
fun enableShowErrors() {
// only show errors if the text was at least once focused
if (isFocusedDirty) {
displayErrors = true
}
}
fun showErrors() = !isValid && displayErrors
open fun getError(): String? {
return if (showErrors()) {
errorFor(text)
} else {
null
}
}
}
fun textFieldStateSaver(state: TextFieldState) = listSaver<TextFieldState, Any>(
save = { listOf(it.text, it.isFocusedDirty) },
restore = {
state.apply {
text = it[0] as String
isFocusedDirty = it[1] as Boolean
}
}
)
package rs.ruffle
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.saveable.listSaver
import androidx.compose.runtime.setValue
open class TextFieldState(
private val validator: (String) -> Boolean = { true },
private val errorFor: (String) -> String = { "" }
) {
var text: String by mutableStateOf("")
// was the TextField ever focused
var isFocusedDirty: Boolean by mutableStateOf(false)
var isFocused: Boolean by mutableStateOf(false)
private var displayErrors: Boolean by mutableStateOf(false)
open val isValid: Boolean
get() = validator(text)
fun onFocusChange(focused: Boolean) {
isFocused = focused
if (focused) isFocusedDirty = true
}
fun enableShowErrors() {
// only show errors if the text was at least once focused
if (isFocusedDirty) {
displayErrors = true
}
}
fun showErrors() = !isValid && displayErrors
open fun getError(): String? {
return if (showErrors()) {
errorFor(text)
} else {
null
}
}
}
fun textFieldStateSaver(state: TextFieldState) = listSaver<TextFieldState, Any>(
save = { listOf(it.text, it.isFocusedDirty) },
restore = {
state.apply {
text = it[0] as String
isFocusedDirty = it[1] as Boolean
}
}
)

View File

@ -1,22 +1,22 @@
package rs.ruffle
import android.util.Patterns
class UrlState(val url: String? = null) :
TextFieldState(validator = ::isUrlValid, errorFor = ::urlValidationError) {
init {
url?.let {
text = it
}
}
}
private fun urlValidationError(url: String): String {
return "Invalid url: $url"
}
private fun isUrlValid(url: String): Boolean {
return Patterns.WEB_URL.matcher(url).matches()
}
val UrlStateSaver = textFieldStateSaver(UrlState())
package rs.ruffle
import android.util.Patterns
class UrlState(val url: String? = null) :
TextFieldState(validator = ::isUrlValid, errorFor = ::urlValidationError) {
init {
url?.let {
text = it
}
}
}
private fun urlValidationError(url: String): String {
return "Invalid url: $url"
}
private fun isUrlValid(url: String): Boolean {
return Patterns.WEB_URL.matcher(url).matches()
}
val UrlStateSaver = textFieldStateSaver(UrlState())

View File

@ -219,10 +219,3 @@ val surfaceContainerLowDarkHighContrast = Color(0xFF211A12)
val surfaceContainerDarkHighContrast = Color(0xFF261E16)
val surfaceContainerHighDarkHighContrast = Color(0xFF302920)
val surfaceContainerHighestDarkHighContrast = Color(0xFF3C332A)

View File

@ -12,8 +12,8 @@ import androidx.compose.runtime.Immutable
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.platform.LocalContext
const val stronglyDeemphasizedAlpha = 0.6f
const val slightlyDeemphasizedAlpha = 0.87f
const val STRONGLY_DEEMPHASIZED_ALPHA = 0.6f
const val SLIGHTLY_DEEMPHASIZED_ALPHA = 0.87f
private val lightScheme = lightColorScheme(
primary = primaryLight,
@ -50,7 +50,7 @@ private val lightScheme = lightColorScheme(
surfaceContainerLow = surfaceContainerLowLight,
surfaceContainer = surfaceContainerLight,
surfaceContainerHigh = surfaceContainerHighLight,
surfaceContainerHighest = surfaceContainerHighestLight,
surfaceContainerHighest = surfaceContainerHighestLight
)
private val darkScheme = darkColorScheme(
@ -88,7 +88,7 @@ private val darkScheme = darkColorScheme(
surfaceContainerLow = surfaceContainerLowDark,
surfaceContainer = surfaceContainerDark,
surfaceContainerHigh = surfaceContainerHighDark,
surfaceContainerHighest = surfaceContainerHighestDark,
surfaceContainerHighest = surfaceContainerHighestDark
)
private val mediumContrastLightColorScheme = lightColorScheme(
@ -126,7 +126,7 @@ private val mediumContrastLightColorScheme = lightColorScheme(
surfaceContainerLow = surfaceContainerLowLightMediumContrast,
surfaceContainer = surfaceContainerLightMediumContrast,
surfaceContainerHigh = surfaceContainerHighLightMediumContrast,
surfaceContainerHighest = surfaceContainerHighestLightMediumContrast,
surfaceContainerHighest = surfaceContainerHighestLightMediumContrast
)
private val highContrastLightColorScheme = lightColorScheme(
@ -164,7 +164,7 @@ private val highContrastLightColorScheme = lightColorScheme(
surfaceContainerLow = surfaceContainerLowLightHighContrast,
surfaceContainer = surfaceContainerLightHighContrast,
surfaceContainerHigh = surfaceContainerHighLightHighContrast,
surfaceContainerHighest = surfaceContainerHighestLightHighContrast,
surfaceContainerHighest = surfaceContainerHighestLightHighContrast
)
private val mediumContrastDarkColorScheme = darkColorScheme(
@ -202,7 +202,7 @@ private val mediumContrastDarkColorScheme = darkColorScheme(
surfaceContainerLow = surfaceContainerLowDarkMediumContrast,
surfaceContainer = surfaceContainerDarkMediumContrast,
surfaceContainerHigh = surfaceContainerHighDarkMediumContrast,
surfaceContainerHighest = surfaceContainerHighestDarkMediumContrast,
surfaceContainerHighest = surfaceContainerHighestDarkMediumContrast
)
private val highContrastDarkColorScheme = darkColorScheme(
@ -240,7 +240,7 @@ private val highContrastDarkColorScheme = darkColorScheme(
surfaceContainerLow = surfaceContainerLowDarkHighContrast,
surfaceContainer = surfaceContainerDarkHighContrast,
surfaceContainerHigh = surfaceContainerHighDarkHighContrast,
surfaceContainerHighest = surfaceContainerHighestDarkHighContrast,
surfaceContainerHighest = surfaceContainerHighestDarkHighContrast
)
@Immutable
@ -252,7 +252,10 @@ data class ColorFamily(
)
val unspecified_scheme = ColorFamily(
Color.Unspecified, Color.Unspecified, Color.Unspecified, Color.Unspecified
Color.Unspecified,
Color.Unspecified,
Color.Unspecified,
Color.Unspecified
)
@Composable
@ -260,7 +263,9 @@ fun RuffleTheme(
darkTheme: Boolean = isSystemInDarkTheme(),
// Dynamic color is available on Android 12+
dynamicColor: Boolean = false,
content: @Composable() () -> Unit
content:
@Composable()
() -> Unit
) {
val colorScheme = when {
dynamicColor && Build.VERSION.SDK_INT >= Build.VERSION_CODES.S -> {
@ -278,4 +283,3 @@ fun RuffleTheme(
content = content
)
}

View File

@ -8,13 +8,13 @@ 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
)
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,
@ -30,5 +30,5 @@ val Typography = Typography(
lineHeight = 16.sp,
letterSpacing = 0.5.sp
)
*/
)
*/
)

View File

@ -1,9 +1,8 @@
package rs.ruffle
import org.junit.Assert.assertEquals
import org.junit.Test
import org.junit.Assert.*
/**
* Example local unit test, which will execute on the development machine (host).
*
@ -14,4 +13,4 @@ class ExampleUnitTest {
fun addition_isCorrect() {
assertEquals(4, 2 + 2)
}
}
}

View File

@ -1,6 +1,15 @@
// Top-level build file where you can add configuration options common to all sub-projects/modules.
plugins {
alias(libs.plugins.ktlint)
alias(libs.plugins.androidApplication) apply false
alias(libs.plugins.jetbrainsKotlinAndroid) apply false
alias(libs.plugins.cargoNdkAndroid) apply false
}
}
allprojects {
apply(plugin = rootProject.libs.plugins.ktlint.get().pluginId)
}
ktlint {
android.set(true)
}

View File

@ -14,6 +14,7 @@ navigationCompose = "2.7.7"
gamesActivity = "2.0.2" # Needs to be in sync with android-activity crate
constraintlayout = "2.1.4"
appcompat = "1.6.1"
ktlint = "12.1.0"
[libraries]
androidx-core-ktx = { group = "androidx.core", name = "core-ktx", version.ref = "coreKtx" }
@ -40,6 +41,6 @@ androidx-appcompat = { group = "androidx.appcompat", name = "appcompat", version
[plugins]
androidApplication = { id = "com.android.application", version.ref = "agp" }
jetbrainsKotlinAndroid = { id = "org.jetbrains.kotlin.android", version.ref = "kotlin" }
cargoNdkAndroid = { id = "com.github.willir.rust.cargo-ndk-android", version = "0.3.4" }
ktlint = { id = "org.jlleitschuh.gradle.ktlint", version.ref = "ktlint" }

View File

@ -21,4 +21,3 @@ dependencyResolutionManagement {
rootProject.name = "Ruffle"
include(":app")