mirror of
https://github.com/ruffle-rs/ruffle-android.git
synced 2024-11-23 05:39:38 +00:00
Add ktlint
This commit is contained in:
parent
e395c087b4
commit
bf88d5c8e6
7
.editorconfig
Normal file
7
.editorconfig
Normal 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
|
@ -69,7 +69,6 @@ android {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
splits {
|
splits {
|
||||||
// Configures multiple APKs based on ABI.
|
// Configures multiple APKs based on ABI.
|
||||||
abi {
|
abi {
|
||||||
@ -121,4 +120,4 @@ if (System.getenv("GITHUB_ACTIONS") == null) {
|
|||||||
apiLevel = 26
|
apiLevel = 26
|
||||||
buildType = "release"
|
buildType = "release"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,13 +1,11 @@
|
|||||||
package rs.ruffle
|
package rs.ruffle
|
||||||
|
|
||||||
import androidx.test.platform.app.InstrumentationRegistry
|
|
||||||
import androidx.test.ext.junit.runners.AndroidJUnit4
|
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.Test
|
||||||
import org.junit.runner.RunWith
|
import org.junit.runner.RunWith
|
||||||
|
|
||||||
import org.junit.Assert.*
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Instrumented test, which will execute on an Android device.
|
* Instrumented test, which will execute on an Android device.
|
||||||
*
|
*
|
||||||
@ -21,4 +19,4 @@ class ExampleInstrumentedTest {
|
|||||||
val appContext = InstrumentationRegistry.getInstrumentation().targetContext
|
val appContext = InstrumentationRegistry.getInstrumentation().targetContext
|
||||||
assertEquals("rs.ruffle", appContext.packageName)
|
assertEquals("rs.ruffle", appContext.packageName)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -6,8 +6,8 @@ import android.os.Bundle
|
|||||||
import androidx.activity.ComponentActivity
|
import androidx.activity.ComponentActivity
|
||||||
import androidx.activity.compose.setContent
|
import androidx.activity.compose.setContent
|
||||||
import androidx.activity.enableEdgeToEdge
|
import androidx.activity.enableEdgeToEdge
|
||||||
import rs.ruffle.ui.theme.RuffleTheme
|
|
||||||
import java.io.IOException
|
import java.io.IOException
|
||||||
|
import rs.ruffle.ui.theme.RuffleTheme
|
||||||
|
|
||||||
class MainActivity : ComponentActivity() {
|
class MainActivity : ComponentActivity() {
|
||||||
override fun onCreate(savedInstanceState: Bundle?) {
|
override fun onCreate(savedInstanceState: Bundle?) {
|
||||||
|
@ -1,29 +1,29 @@
|
|||||||
package rs.ruffle
|
package rs.ruffle
|
||||||
|
|
||||||
import android.net.Uri
|
import android.net.Uri
|
||||||
import androidx.compose.runtime.Composable
|
import androidx.compose.runtime.Composable
|
||||||
import androidx.navigation.NavHostController
|
import androidx.navigation.NavHostController
|
||||||
import androidx.navigation.compose.NavHost
|
import androidx.navigation.compose.NavHost
|
||||||
import androidx.navigation.compose.composable
|
import androidx.navigation.compose.composable
|
||||||
import androidx.navigation.compose.rememberNavController
|
import androidx.navigation.compose.rememberNavController
|
||||||
|
|
||||||
object Destinations {
|
object Destinations {
|
||||||
const val SELECT_SWF_ROUTE = "select"
|
const val SELECT_SWF_ROUTE = "select"
|
||||||
}
|
}
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
fun RuffleNavHost(
|
fun RuffleNavHost(
|
||||||
navController: NavHostController = rememberNavController(),
|
navController: NavHostController = rememberNavController(),
|
||||||
openSwf: (uri: Uri) -> Unit
|
openSwf: (uri: Uri) -> Unit
|
||||||
) {
|
) {
|
||||||
NavHost(
|
NavHost(
|
||||||
navController = navController,
|
navController = navController,
|
||||||
startDestination = Destinations.SELECT_SWF_ROUTE,
|
startDestination = Destinations.SELECT_SWF_ROUTE
|
||||||
) {
|
) {
|
||||||
composable(Destinations.SELECT_SWF_ROUTE) {
|
composable(Destinations.SELECT_SWF_ROUTE) {
|
||||||
SelectSwfRoute(
|
SelectSwfRoute(
|
||||||
openSwf = openSwf
|
openSwf = openSwf
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,200 +1,198 @@
|
|||||||
package rs.ruffle
|
package rs.ruffle
|
||||||
|
|
||||||
import android.content.res.Configuration
|
import android.content.res.Configuration
|
||||||
import android.net.Uri
|
import android.net.Uri
|
||||||
import androidx.activity.compose.rememberLauncherForActivityResult
|
import androidx.activity.compose.rememberLauncherForActivityResult
|
||||||
import androidx.activity.result.contract.ActivityResultContracts
|
import androidx.activity.result.contract.ActivityResultContracts
|
||||||
import androidx.compose.foundation.Image
|
import androidx.compose.foundation.Image
|
||||||
import androidx.compose.foundation.layout.Column
|
import androidx.compose.foundation.layout.Column
|
||||||
import androidx.compose.foundation.layout.Row
|
import androidx.compose.foundation.layout.Row
|
||||||
import androidx.compose.foundation.layout.Spacer
|
import androidx.compose.foundation.layout.Spacer
|
||||||
import androidx.compose.foundation.layout.fillMaxWidth
|
import androidx.compose.foundation.layout.fillMaxWidth
|
||||||
import androidx.compose.foundation.layout.padding
|
import androidx.compose.foundation.layout.padding
|
||||||
import androidx.compose.foundation.layout.paddingFromBaseline
|
import androidx.compose.foundation.layout.paddingFromBaseline
|
||||||
import androidx.compose.foundation.layout.width
|
import androidx.compose.foundation.layout.width
|
||||||
import androidx.compose.foundation.layout.wrapContentHeight
|
import androidx.compose.foundation.layout.wrapContentHeight
|
||||||
import androidx.compose.foundation.text.KeyboardActions
|
import androidx.compose.foundation.text.KeyboardActions
|
||||||
import androidx.compose.foundation.text.KeyboardOptions
|
import androidx.compose.foundation.text.KeyboardOptions
|
||||||
import androidx.compose.material3.Button
|
import androidx.compose.material3.Button
|
||||||
import androidx.compose.material3.MaterialTheme
|
import androidx.compose.material3.MaterialTheme
|
||||||
import androidx.compose.material3.OutlinedButton
|
import androidx.compose.material3.OutlinedButton
|
||||||
import androidx.compose.material3.OutlinedTextField
|
import androidx.compose.material3.OutlinedTextField
|
||||||
import androidx.compose.material3.Scaffold
|
import androidx.compose.material3.Scaffold
|
||||||
import androidx.compose.material3.Surface
|
import androidx.compose.material3.Surface
|
||||||
import androidx.compose.material3.Text
|
import androidx.compose.material3.Text
|
||||||
import androidx.compose.runtime.Composable
|
import androidx.compose.runtime.Composable
|
||||||
import androidx.compose.runtime.getValue
|
import androidx.compose.runtime.getValue
|
||||||
import androidx.compose.runtime.mutableStateOf
|
import androidx.compose.runtime.mutableStateOf
|
||||||
import androidx.compose.runtime.saveable.rememberSaveable
|
import androidx.compose.runtime.saveable.rememberSaveable
|
||||||
import androidx.compose.ui.Alignment
|
import androidx.compose.ui.Alignment
|
||||||
import androidx.compose.ui.Modifier
|
import androidx.compose.ui.Modifier
|
||||||
import androidx.compose.ui.focus.onFocusChanged
|
import androidx.compose.ui.focus.onFocusChanged
|
||||||
import androidx.compose.ui.res.painterResource
|
import androidx.compose.ui.res.painterResource
|
||||||
import androidx.compose.ui.res.stringResource
|
import androidx.compose.ui.res.stringResource
|
||||||
import androidx.compose.ui.text.input.ImeAction
|
import androidx.compose.ui.text.input.ImeAction
|
||||||
import androidx.compose.ui.text.input.KeyboardType
|
import androidx.compose.ui.text.input.KeyboardType
|
||||||
import androidx.compose.ui.tooling.preview.Preview
|
import androidx.compose.ui.tooling.preview.Preview
|
||||||
import androidx.compose.ui.unit.dp
|
import androidx.compose.ui.unit.dp
|
||||||
import rs.ruffle.ui.theme.RuffleTheme
|
import rs.ruffle.ui.theme.RuffleTheme
|
||||||
import rs.ruffle.ui.theme.slightlyDeemphasizedAlpha
|
import rs.ruffle.ui.theme.SLIGHTLY_DEEMPHASIZED_ALPHA
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
fun BrandBar() {
|
fun BrandBar() {
|
||||||
Image(
|
Image(
|
||||||
painter = painterResource(id = R.drawable.ic_logo_dark),
|
painter = painterResource(id = R.drawable.ic_logo_dark),
|
||||||
contentDescription = stringResource(id = R.string.logo_description),
|
contentDescription = stringResource(id = R.string.logo_description),
|
||||||
modifier = Modifier
|
modifier = Modifier
|
||||||
.padding(horizontal = 76.dp)
|
.padding(horizontal = 76.dp)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
fun SelectSwfRoute(
|
fun SelectSwfRoute(openSwf: (uri: Uri) -> Unit) {
|
||||||
openSwf: (uri: Uri) -> Unit
|
SelectSwfScreen(
|
||||||
) {
|
openSwf = openSwf
|
||||||
SelectSwfScreen(
|
)
|
||||||
openSwf = openSwf
|
}
|
||||||
)
|
|
||||||
}
|
@Composable
|
||||||
|
fun SelectSwfScreen(openSwf: (uri: Uri) -> Unit) {
|
||||||
@Composable
|
Scaffold { innerPadding ->
|
||||||
fun SelectSwfScreen(openSwf: (uri: Uri) -> Unit) {
|
Column(
|
||||||
Scaffold { innerPadding ->
|
modifier = Modifier.padding(innerPadding)
|
||||||
Column(
|
) {
|
||||||
modifier = Modifier.padding(innerPadding)
|
Column(
|
||||||
) {
|
modifier = Modifier.wrapContentHeight(align = Alignment.CenterVertically)
|
||||||
Column(
|
) {
|
||||||
modifier = Modifier.wrapContentHeight(align = Alignment.CenterVertically)
|
BrandBar()
|
||||||
) {
|
}
|
||||||
BrandBar()
|
Text(
|
||||||
}
|
modifier = Modifier.padding(horizontal = 8.dp, vertical = 75.dp),
|
||||||
Text(
|
text = stringResource(id = R.string.work_in_progress_warning)
|
||||||
modifier = Modifier.padding(horizontal = 8.dp, vertical = 75.dp),
|
)
|
||||||
text = stringResource(id = R.string.work_in_progress_warning)
|
SelectSwfUrlOrFile(openSwf)
|
||||||
)
|
}
|
||||||
SelectSwfUrlOrFile(openSwf)
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
@Composable
|
||||||
|
private fun SelectSwfUrlOrFile(openSwf: (uri: Uri) -> Unit) {
|
||||||
@Composable
|
val urlState by rememberSaveable(stateSaver = UrlStateSaver) {
|
||||||
private fun SelectSwfUrlOrFile(
|
mutableStateOf(UrlState())
|
||||||
openSwf: (uri: Uri) -> Unit
|
}
|
||||||
) {
|
Column(
|
||||||
val urlState by rememberSaveable(stateSaver = UrlStateSaver) {
|
modifier = Modifier
|
||||||
mutableStateOf(UrlState())
|
.padding(horizontal = 20.dp)
|
||||||
}
|
) {
|
||||||
Column(
|
val submitUrl = {
|
||||||
modifier = Modifier
|
if (urlState.isValid) {
|
||||||
.padding(horizontal = 20.dp)
|
openSwf(Uri.parse(urlState.text))
|
||||||
) {
|
} else {
|
||||||
val submitUrl = {
|
urlState.enableShowErrors()
|
||||||
if (urlState.isValid) {
|
}
|
||||||
openSwf(Uri.parse(urlState.text))
|
}
|
||||||
} else {
|
OutlinedTextField(
|
||||||
urlState.enableShowErrors()
|
value = urlState.text,
|
||||||
}
|
onValueChange = { urlState.text = it },
|
||||||
}
|
modifier = Modifier
|
||||||
OutlinedTextField(
|
.fillMaxWidth()
|
||||||
value = urlState.text,
|
.onFocusChanged { focusState ->
|
||||||
onValueChange = { urlState.text = it },
|
urlState.onFocusChange(focusState.isFocused)
|
||||||
modifier = Modifier
|
if (!focusState.isFocused) {
|
||||||
.fillMaxWidth()
|
urlState.enableShowErrors()
|
||||||
.onFocusChanged { focusState ->
|
}
|
||||||
urlState.onFocusChange(focusState.isFocused)
|
},
|
||||||
if (!focusState.isFocused) {
|
label = {
|
||||||
urlState.enableShowErrors()
|
Text(
|
||||||
}
|
text = stringResource(id = R.string.url),
|
||||||
},
|
style = MaterialTheme.typography.bodyMedium
|
||||||
label = {
|
)
|
||||||
Text(
|
},
|
||||||
text = stringResource(id = R.string.url),
|
textStyle = MaterialTheme.typography.bodyMedium,
|
||||||
style = MaterialTheme.typography.bodyMedium,
|
isError = urlState.showErrors(),
|
||||||
)
|
keyboardOptions = KeyboardOptions.Default.copy(
|
||||||
},
|
imeAction = ImeAction.Go,
|
||||||
textStyle = MaterialTheme.typography.bodyMedium,
|
keyboardType = KeyboardType.Uri
|
||||||
isError = urlState.showErrors(),
|
),
|
||||||
keyboardOptions = KeyboardOptions.Default.copy(
|
keyboardActions = KeyboardActions(
|
||||||
imeAction = ImeAction.Go,
|
onDone = { submitUrl() }
|
||||||
keyboardType = KeyboardType.Uri
|
),
|
||||||
),
|
singleLine = true
|
||||||
keyboardActions = KeyboardActions(
|
)
|
||||||
onDone = { submitUrl() }
|
urlState.getError()?.let { error -> TextFieldError(textError = error) }
|
||||||
),
|
|
||||||
singleLine = true
|
Button(
|
||||||
)
|
onClick = submitUrl,
|
||||||
urlState.getError()?.let { error -> TextFieldError(textError = error) }
|
modifier = Modifier
|
||||||
|
.fillMaxWidth()
|
||||||
Button(
|
.padding(top = 28.dp, bottom = 3.dp)
|
||||||
onClick = submitUrl,
|
) {
|
||||||
modifier = Modifier
|
Text(
|
||||||
.fillMaxWidth()
|
text = stringResource(id = R.string.open_url),
|
||||||
.padding(top = 28.dp, bottom = 3.dp)
|
style = MaterialTheme.typography.titleSmall
|
||||||
) {
|
)
|
||||||
Text(
|
}
|
||||||
text = stringResource(id = R.string.open_url),
|
|
||||||
style = MaterialTheme.typography.titleSmall
|
Column(
|
||||||
)
|
horizontalAlignment = Alignment.CenterHorizontally
|
||||||
}
|
) {
|
||||||
|
Text(
|
||||||
Column(
|
text = stringResource(id = R.string.or),
|
||||||
horizontalAlignment = Alignment.CenterHorizontally
|
style = MaterialTheme.typography.titleSmall,
|
||||||
) {
|
color = MaterialTheme.colorScheme.onSurface.copy(
|
||||||
Text(
|
alpha = SLIGHTLY_DEEMPHASIZED_ALPHA
|
||||||
text = stringResource(id = R.string.or),
|
),
|
||||||
style = MaterialTheme.typography.titleSmall,
|
modifier = Modifier.paddingFromBaseline(top = 25.dp)
|
||||||
color = MaterialTheme.colorScheme.onSurface.copy(alpha = slightlyDeemphasizedAlpha),
|
)
|
||||||
modifier = Modifier.paddingFromBaseline(top = 25.dp)
|
PickSwfButton(openSwf)
|
||||||
)
|
}
|
||||||
PickSwfButton(openSwf)
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
@Composable
|
||||||
|
fun PickSwfButton(onSelect: (uri: Uri) -> Unit) {
|
||||||
@Composable
|
val launcher = rememberLauncherForActivityResult(ActivityResultContracts.GetContent()) {
|
||||||
fun PickSwfButton(onSelect: (uri: Uri) -> Unit) {
|
if (it != null) {
|
||||||
val launcher = rememberLauncherForActivityResult(ActivityResultContracts.GetContent()) {
|
onSelect(it)
|
||||||
if (it != null) {
|
}
|
||||||
onSelect(it)
|
}
|
||||||
}
|
|
||||||
}
|
OutlinedButton(
|
||||||
|
onClick = {
|
||||||
OutlinedButton(
|
launcher.launch(
|
||||||
onClick = {
|
"application/x-shockwave-flash"
|
||||||
launcher.launch(
|
)
|
||||||
"application/x-shockwave-flash"
|
},
|
||||||
)
|
modifier = Modifier
|
||||||
},
|
.fillMaxWidth()
|
||||||
modifier = Modifier
|
.padding(top = 20.dp, bottom = 24.dp)
|
||||||
.fillMaxWidth()
|
|
||||||
.padding(top = 20.dp, bottom = 24.dp),
|
) {
|
||||||
|
Text(text = stringResource(id = R.string.select_a_swf))
|
||||||
) {
|
}
|
||||||
Text(text = stringResource(id = R.string.select_a_swf))
|
}
|
||||||
}
|
|
||||||
}
|
@Composable
|
||||||
|
fun TextFieldError(textError: String) {
|
||||||
@Composable
|
Row(modifier = Modifier.fillMaxWidth()) {
|
||||||
fun TextFieldError(textError: String) {
|
Spacer(modifier = Modifier.width(16.dp))
|
||||||
Row(modifier = Modifier.fillMaxWidth()) {
|
Text(
|
||||||
Spacer(modifier = Modifier.width(16.dp))
|
text = textError,
|
||||||
Text(
|
modifier = Modifier.fillMaxWidth(),
|
||||||
text = textError,
|
color = MaterialTheme.colorScheme.error
|
||||||
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)
|
||||||
@Preview(name = "Select SWF - Light", uiMode = Configuration.UI_MODE_NIGHT_NO)
|
@Composable
|
||||||
@Preview(name = "Select SWF - Dark", uiMode = Configuration.UI_MODE_NIGHT_YES)
|
fun SelectSwfScreenPreview() {
|
||||||
@Composable
|
RuffleTheme {
|
||||||
fun SelectSwfScreenPreview() {
|
Surface {
|
||||||
RuffleTheme {
|
SelectSwfScreen(
|
||||||
Surface {
|
openSwf = {}
|
||||||
SelectSwfScreen(
|
)
|
||||||
openSwf = {}
|
}
|
||||||
)
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
|
||||||
|
@ -1,53 +1,53 @@
|
|||||||
package rs.ruffle
|
package rs.ruffle
|
||||||
|
|
||||||
import androidx.compose.runtime.getValue
|
import androidx.compose.runtime.getValue
|
||||||
import androidx.compose.runtime.mutableStateOf
|
import androidx.compose.runtime.mutableStateOf
|
||||||
import androidx.compose.runtime.saveable.listSaver
|
import androidx.compose.runtime.saveable.listSaver
|
||||||
import androidx.compose.runtime.setValue
|
import androidx.compose.runtime.setValue
|
||||||
|
|
||||||
open class TextFieldState(
|
open class TextFieldState(
|
||||||
private val validator: (String) -> Boolean = { true },
|
private val validator: (String) -> Boolean = { true },
|
||||||
private val errorFor: (String) -> String = { "" }
|
private val errorFor: (String) -> String = { "" }
|
||||||
) {
|
) {
|
||||||
var text: String by mutableStateOf("")
|
var text: String by mutableStateOf("")
|
||||||
|
|
||||||
// was the TextField ever focused
|
// was the TextField ever focused
|
||||||
var isFocusedDirty: Boolean by mutableStateOf(false)
|
var isFocusedDirty: Boolean by mutableStateOf(false)
|
||||||
var isFocused: Boolean by mutableStateOf(false)
|
var isFocused: Boolean by mutableStateOf(false)
|
||||||
private var displayErrors: Boolean by mutableStateOf(false)
|
private var displayErrors: Boolean by mutableStateOf(false)
|
||||||
|
|
||||||
open val isValid: Boolean
|
open val isValid: Boolean
|
||||||
get() = validator(text)
|
get() = validator(text)
|
||||||
|
|
||||||
fun onFocusChange(focused: Boolean) {
|
fun onFocusChange(focused: Boolean) {
|
||||||
isFocused = focused
|
isFocused = focused
|
||||||
if (focused) isFocusedDirty = true
|
if (focused) isFocusedDirty = true
|
||||||
}
|
}
|
||||||
|
|
||||||
fun enableShowErrors() {
|
fun enableShowErrors() {
|
||||||
// only show errors if the text was at least once focused
|
// only show errors if the text was at least once focused
|
||||||
if (isFocusedDirty) {
|
if (isFocusedDirty) {
|
||||||
displayErrors = true
|
displayErrors = true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun showErrors() = !isValid && displayErrors
|
fun showErrors() = !isValid && displayErrors
|
||||||
|
|
||||||
open fun getError(): String? {
|
open fun getError(): String? {
|
||||||
return if (showErrors()) {
|
return if (showErrors()) {
|
||||||
errorFor(text)
|
errorFor(text)
|
||||||
} else {
|
} else {
|
||||||
null
|
null
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun textFieldStateSaver(state: TextFieldState) = listSaver<TextFieldState, Any>(
|
fun textFieldStateSaver(state: TextFieldState) = listSaver<TextFieldState, Any>(
|
||||||
save = { listOf(it.text, it.isFocusedDirty) },
|
save = { listOf(it.text, it.isFocusedDirty) },
|
||||||
restore = {
|
restore = {
|
||||||
state.apply {
|
state.apply {
|
||||||
text = it[0] as String
|
text = it[0] as String
|
||||||
isFocusedDirty = it[1] as Boolean
|
isFocusedDirty = it[1] as Boolean
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
@ -1,22 +1,22 @@
|
|||||||
package rs.ruffle
|
package rs.ruffle
|
||||||
|
|
||||||
import android.util.Patterns
|
import android.util.Patterns
|
||||||
|
|
||||||
class UrlState(val url: String? = null) :
|
class UrlState(val url: String? = null) :
|
||||||
TextFieldState(validator = ::isUrlValid, errorFor = ::urlValidationError) {
|
TextFieldState(validator = ::isUrlValid, errorFor = ::urlValidationError) {
|
||||||
init {
|
init {
|
||||||
url?.let {
|
url?.let {
|
||||||
text = it
|
text = it
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun urlValidationError(url: String): String {
|
private fun urlValidationError(url: String): String {
|
||||||
return "Invalid url: $url"
|
return "Invalid url: $url"
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun isUrlValid(url: String): Boolean {
|
private fun isUrlValid(url: String): Boolean {
|
||||||
return Patterns.WEB_URL.matcher(url).matches()
|
return Patterns.WEB_URL.matcher(url).matches()
|
||||||
}
|
}
|
||||||
|
|
||||||
val UrlStateSaver = textFieldStateSaver(UrlState())
|
val UrlStateSaver = textFieldStateSaver(UrlState())
|
||||||
|
@ -219,10 +219,3 @@ val surfaceContainerLowDarkHighContrast = Color(0xFF211A12)
|
|||||||
val surfaceContainerDarkHighContrast = Color(0xFF261E16)
|
val surfaceContainerDarkHighContrast = Color(0xFF261E16)
|
||||||
val surfaceContainerHighDarkHighContrast = Color(0xFF302920)
|
val surfaceContainerHighDarkHighContrast = Color(0xFF302920)
|
||||||
val surfaceContainerHighestDarkHighContrast = Color(0xFF3C332A)
|
val surfaceContainerHighestDarkHighContrast = Color(0xFF3C332A)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@ -12,8 +12,8 @@ import androidx.compose.runtime.Immutable
|
|||||||
import androidx.compose.ui.graphics.Color
|
import androidx.compose.ui.graphics.Color
|
||||||
import androidx.compose.ui.platform.LocalContext
|
import androidx.compose.ui.platform.LocalContext
|
||||||
|
|
||||||
const val stronglyDeemphasizedAlpha = 0.6f
|
const val STRONGLY_DEEMPHASIZED_ALPHA = 0.6f
|
||||||
const val slightlyDeemphasizedAlpha = 0.87f
|
const val SLIGHTLY_DEEMPHASIZED_ALPHA = 0.87f
|
||||||
|
|
||||||
private val lightScheme = lightColorScheme(
|
private val lightScheme = lightColorScheme(
|
||||||
primary = primaryLight,
|
primary = primaryLight,
|
||||||
@ -50,7 +50,7 @@ private val lightScheme = lightColorScheme(
|
|||||||
surfaceContainerLow = surfaceContainerLowLight,
|
surfaceContainerLow = surfaceContainerLowLight,
|
||||||
surfaceContainer = surfaceContainerLight,
|
surfaceContainer = surfaceContainerLight,
|
||||||
surfaceContainerHigh = surfaceContainerHighLight,
|
surfaceContainerHigh = surfaceContainerHighLight,
|
||||||
surfaceContainerHighest = surfaceContainerHighestLight,
|
surfaceContainerHighest = surfaceContainerHighestLight
|
||||||
)
|
)
|
||||||
|
|
||||||
private val darkScheme = darkColorScheme(
|
private val darkScheme = darkColorScheme(
|
||||||
@ -88,7 +88,7 @@ private val darkScheme = darkColorScheme(
|
|||||||
surfaceContainerLow = surfaceContainerLowDark,
|
surfaceContainerLow = surfaceContainerLowDark,
|
||||||
surfaceContainer = surfaceContainerDark,
|
surfaceContainer = surfaceContainerDark,
|
||||||
surfaceContainerHigh = surfaceContainerHighDark,
|
surfaceContainerHigh = surfaceContainerHighDark,
|
||||||
surfaceContainerHighest = surfaceContainerHighestDark,
|
surfaceContainerHighest = surfaceContainerHighestDark
|
||||||
)
|
)
|
||||||
|
|
||||||
private val mediumContrastLightColorScheme = lightColorScheme(
|
private val mediumContrastLightColorScheme = lightColorScheme(
|
||||||
@ -126,7 +126,7 @@ private val mediumContrastLightColorScheme = lightColorScheme(
|
|||||||
surfaceContainerLow = surfaceContainerLowLightMediumContrast,
|
surfaceContainerLow = surfaceContainerLowLightMediumContrast,
|
||||||
surfaceContainer = surfaceContainerLightMediumContrast,
|
surfaceContainer = surfaceContainerLightMediumContrast,
|
||||||
surfaceContainerHigh = surfaceContainerHighLightMediumContrast,
|
surfaceContainerHigh = surfaceContainerHighLightMediumContrast,
|
||||||
surfaceContainerHighest = surfaceContainerHighestLightMediumContrast,
|
surfaceContainerHighest = surfaceContainerHighestLightMediumContrast
|
||||||
)
|
)
|
||||||
|
|
||||||
private val highContrastLightColorScheme = lightColorScheme(
|
private val highContrastLightColorScheme = lightColorScheme(
|
||||||
@ -164,7 +164,7 @@ private val highContrastLightColorScheme = lightColorScheme(
|
|||||||
surfaceContainerLow = surfaceContainerLowLightHighContrast,
|
surfaceContainerLow = surfaceContainerLowLightHighContrast,
|
||||||
surfaceContainer = surfaceContainerLightHighContrast,
|
surfaceContainer = surfaceContainerLightHighContrast,
|
||||||
surfaceContainerHigh = surfaceContainerHighLightHighContrast,
|
surfaceContainerHigh = surfaceContainerHighLightHighContrast,
|
||||||
surfaceContainerHighest = surfaceContainerHighestLightHighContrast,
|
surfaceContainerHighest = surfaceContainerHighestLightHighContrast
|
||||||
)
|
)
|
||||||
|
|
||||||
private val mediumContrastDarkColorScheme = darkColorScheme(
|
private val mediumContrastDarkColorScheme = darkColorScheme(
|
||||||
@ -202,7 +202,7 @@ private val mediumContrastDarkColorScheme = darkColorScheme(
|
|||||||
surfaceContainerLow = surfaceContainerLowDarkMediumContrast,
|
surfaceContainerLow = surfaceContainerLowDarkMediumContrast,
|
||||||
surfaceContainer = surfaceContainerDarkMediumContrast,
|
surfaceContainer = surfaceContainerDarkMediumContrast,
|
||||||
surfaceContainerHigh = surfaceContainerHighDarkMediumContrast,
|
surfaceContainerHigh = surfaceContainerHighDarkMediumContrast,
|
||||||
surfaceContainerHighest = surfaceContainerHighestDarkMediumContrast,
|
surfaceContainerHighest = surfaceContainerHighestDarkMediumContrast
|
||||||
)
|
)
|
||||||
|
|
||||||
private val highContrastDarkColorScheme = darkColorScheme(
|
private val highContrastDarkColorScheme = darkColorScheme(
|
||||||
@ -240,7 +240,7 @@ private val highContrastDarkColorScheme = darkColorScheme(
|
|||||||
surfaceContainerLow = surfaceContainerLowDarkHighContrast,
|
surfaceContainerLow = surfaceContainerLowDarkHighContrast,
|
||||||
surfaceContainer = surfaceContainerDarkHighContrast,
|
surfaceContainer = surfaceContainerDarkHighContrast,
|
||||||
surfaceContainerHigh = surfaceContainerHighDarkHighContrast,
|
surfaceContainerHigh = surfaceContainerHighDarkHighContrast,
|
||||||
surfaceContainerHighest = surfaceContainerHighestDarkHighContrast,
|
surfaceContainerHighest = surfaceContainerHighestDarkHighContrast
|
||||||
)
|
)
|
||||||
|
|
||||||
@Immutable
|
@Immutable
|
||||||
@ -252,7 +252,10 @@ data class ColorFamily(
|
|||||||
)
|
)
|
||||||
|
|
||||||
val unspecified_scheme = ColorFamily(
|
val unspecified_scheme = ColorFamily(
|
||||||
Color.Unspecified, Color.Unspecified, Color.Unspecified, Color.Unspecified
|
Color.Unspecified,
|
||||||
|
Color.Unspecified,
|
||||||
|
Color.Unspecified,
|
||||||
|
Color.Unspecified
|
||||||
)
|
)
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
@ -260,7 +263,9 @@ fun RuffleTheme(
|
|||||||
darkTheme: Boolean = isSystemInDarkTheme(),
|
darkTheme: Boolean = isSystemInDarkTheme(),
|
||||||
// Dynamic color is available on Android 12+
|
// Dynamic color is available on Android 12+
|
||||||
dynamicColor: Boolean = false,
|
dynamicColor: Boolean = false,
|
||||||
content: @Composable() () -> Unit
|
content:
|
||||||
|
@Composable()
|
||||||
|
() -> Unit
|
||||||
) {
|
) {
|
||||||
val colorScheme = when {
|
val colorScheme = when {
|
||||||
dynamicColor && Build.VERSION.SDK_INT >= Build.VERSION_CODES.S -> {
|
dynamicColor && Build.VERSION.SDK_INT >= Build.VERSION_CODES.S -> {
|
||||||
@ -278,4 +283,3 @@ fun RuffleTheme(
|
|||||||
content = content
|
content = content
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -8,13 +8,13 @@ import androidx.compose.ui.unit.sp
|
|||||||
|
|
||||||
// Set of Material typography styles to start with
|
// Set of Material typography styles to start with
|
||||||
val Typography = Typography(
|
val Typography = Typography(
|
||||||
bodyLarge = TextStyle(
|
bodyLarge = TextStyle(
|
||||||
fontFamily = FontFamily.Default,
|
fontFamily = FontFamily.Default,
|
||||||
fontWeight = FontWeight.Normal,
|
fontWeight = FontWeight.Normal,
|
||||||
fontSize = 16.sp,
|
fontSize = 16.sp,
|
||||||
lineHeight = 24.sp,
|
lineHeight = 24.sp,
|
||||||
letterSpacing = 0.5.sp
|
letterSpacing = 0.5.sp
|
||||||
)
|
)
|
||||||
/* Other default text styles to override
|
/* Other default text styles to override
|
||||||
titleLarge = TextStyle(
|
titleLarge = TextStyle(
|
||||||
fontFamily = FontFamily.Default,
|
fontFamily = FontFamily.Default,
|
||||||
@ -30,5 +30,5 @@ val Typography = Typography(
|
|||||||
lineHeight = 16.sp,
|
lineHeight = 16.sp,
|
||||||
letterSpacing = 0.5.sp
|
letterSpacing = 0.5.sp
|
||||||
)
|
)
|
||||||
*/
|
*/
|
||||||
)
|
)
|
||||||
|
@ -1,9 +1,8 @@
|
|||||||
package rs.ruffle
|
package rs.ruffle
|
||||||
|
|
||||||
|
import org.junit.Assert.assertEquals
|
||||||
import org.junit.Test
|
import org.junit.Test
|
||||||
|
|
||||||
import org.junit.Assert.*
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Example local unit test, which will execute on the development machine (host).
|
* Example local unit test, which will execute on the development machine (host).
|
||||||
*
|
*
|
||||||
@ -14,4 +13,4 @@ class ExampleUnitTest {
|
|||||||
fun addition_isCorrect() {
|
fun addition_isCorrect() {
|
||||||
assertEquals(4, 2 + 2)
|
assertEquals(4, 2 + 2)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,6 +1,15 @@
|
|||||||
// Top-level build file where you can add configuration options common to all sub-projects/modules.
|
// Top-level build file where you can add configuration options common to all sub-projects/modules.
|
||||||
plugins {
|
plugins {
|
||||||
|
alias(libs.plugins.ktlint)
|
||||||
alias(libs.plugins.androidApplication) apply false
|
alias(libs.plugins.androidApplication) apply false
|
||||||
alias(libs.plugins.jetbrainsKotlinAndroid) apply false
|
alias(libs.plugins.jetbrainsKotlinAndroid) apply false
|
||||||
alias(libs.plugins.cargoNdkAndroid) apply false
|
alias(libs.plugins.cargoNdkAndroid) apply false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
allprojects {
|
||||||
|
apply(plugin = rootProject.libs.plugins.ktlint.get().pluginId)
|
||||||
|
}
|
||||||
|
|
||||||
|
ktlint {
|
||||||
|
android.set(true)
|
||||||
|
}
|
||||||
|
@ -14,6 +14,7 @@ navigationCompose = "2.7.7"
|
|||||||
gamesActivity = "2.0.2" # Needs to be in sync with android-activity crate
|
gamesActivity = "2.0.2" # Needs to be in sync with android-activity crate
|
||||||
constraintlayout = "2.1.4"
|
constraintlayout = "2.1.4"
|
||||||
appcompat = "1.6.1"
|
appcompat = "1.6.1"
|
||||||
|
ktlint = "12.1.0"
|
||||||
|
|
||||||
[libraries]
|
[libraries]
|
||||||
androidx-core-ktx = { group = "androidx.core", name = "core-ktx", version.ref = "coreKtx" }
|
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]
|
[plugins]
|
||||||
androidApplication = { id = "com.android.application", version.ref = "agp" }
|
androidApplication = { id = "com.android.application", version.ref = "agp" }
|
||||||
jetbrainsKotlinAndroid = { id = "org.jetbrains.kotlin.android", version.ref = "kotlin" }
|
jetbrainsKotlinAndroid = { id = "org.jetbrains.kotlin.android", version.ref = "kotlin" }
|
||||||
|
|
||||||
cargoNdkAndroid = { id = "com.github.willir.rust.cargo-ndk-android", version = "0.3.4" }
|
cargoNdkAndroid = { id = "com.github.willir.rust.cargo-ndk-android", version = "0.3.4" }
|
||||||
|
ktlint = { id = "org.jlleitschuh.gradle.ktlint", version.ref = "ktlint" }
|
||||||
|
|
||||||
|
@ -21,4 +21,3 @@ dependencyResolutionManagement {
|
|||||||
|
|
||||||
rootProject.name = "Ruffle"
|
rootProject.name = "Ruffle"
|
||||||
include(":app")
|
include(":app")
|
||||||
|
|
Loading…
Reference in New Issue
Block a user