Added light theme support, monochrome laucher icon

This commit is contained in:
Pr0pHesyer authored and Arty Bishop committed 2025-12-27 15:01:46 +00:00
1 parent 34ec942e7b
commit f1c978d167
27 files changed
+530 -218

No files matched your search

@@ -25,7 +25,7 @@ import androidx.activity.ComponentActivity
import androidx.activity.compose.setContent
import androidx.core.splashscreen.SplashScreen.Companion.installSplashScreen
import com.rtbishop.look4sat.presentation.MainScreen
import com.rtbishop.look4sat.presentation.MainTheme
import com.rtbishop.look4sat.presentation.theme.MainTheme
class MainActivity : ComponentActivity() {
@@ -1,114 +0,0 @@
package com.rtbishop.look4sat.presentation
import androidx.compose.foundation.ExperimentalFoundationApi
import androidx.compose.foundation.LocalOverscrollConfiguration
import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Shapes
import androidx.compose.material3.Typography
import androidx.compose.material3.lightColorScheme
import androidx.compose.runtime.Composable
import androidx.compose.runtime.CompositionLocalProvider
import androidx.compose.ui.graphics.Color
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.dp
import androidx.compose.ui.unit.sp
@OptIn(ExperimentalFoundationApi::class)
@Composable
fun MainTheme(
// darkTheme: Boolean = isSystemInDarkTheme(),
// dynamicColor: Boolean = false,
content: @Composable () -> Unit
) {
// val colorScheme = when {
// dynamicColor && Build.VERSION.SDK_INT >= Build.VERSION_CODES.S -> {
// val context = LocalContext.current
// if (darkTheme) dynamicDarkColorScheme(context) else dynamicLightColorScheme(context)
// }
// darkTheme -> DarkColorScheme
// else -> LightColorScheme
// }
val colors = themeColors
// val view = LocalView.current
// if (!view.isInEditMode) {
// SideEffect {
// (view.context as Activity).window.statusBarColor = colorScheme.primary.toArgb()
// ViewCompat.getWindowInsetsController(view)?.isAppearanceLightStatusBars = darkTheme
// }
// }
MaterialTheme(colorScheme = colors, typography = typography, shapes = shapes) {
CompositionLocalProvider(LocalOverscrollConfiguration.provides(null), content = content)
}
}
private val accentYellow = Color(0xFFFFE082)
private val textWhite = Color(0xCCFFFFFF)
private val textGrey = Color(0x66FFFFFF)
private val textBlack = Color(0xFF000000)
private val surfaceInverse = Color(0x40FFFFFF)
private val surfaceBtn = Color(0xFF303030)
private val surfaceCard = Color(0xFF1C1C1C)
private val surfaceBg = Color(0xFF121212)
private val transparent = Color(0x00000000)
private val themeColors = lightColorScheme(
primary = accentYellow,
onPrimary = textBlack,
// primaryContainer = primaryContainer,
// onPrimaryContainer = onPrimaryContainer,
// inversePrimary = inversePrimary,
secondary = accentYellow,
onSecondary = textBlack,
secondaryContainer = accentYellow, // navBar indicator
onSecondaryContainer = textBlack, // navBar active icon
tertiary = surfaceBtn,
onTertiary = textWhite,
// tertiaryContainer = tertiaryContainer,
// onTertiaryContainer = onTertiaryContainer,
background = surfaceBg,
onBackground = textWhite,
surface = surfaceCard,
onSurface = textWhite,
surfaceVariant = surfaceCard,
onSurfaceVariant = textGrey, // navBar inactive icon
surfaceTint = transparent,
inverseSurface = surfaceInverse,
// inverseOnSurface = inverseOnSurface,
// error = error,
// onError = onError,
// errorContainer = errorContainer,
// onErrorContainer = onErrorContainer,
// outline = outline,
// outlineVariant = outlineVariant,
// scrim = scrim,
)
private val typography = Typography(
bodyLarge = TextStyle(
fontFamily = FontFamily.Default,
fontWeight = FontWeight.Normal,
fontSize = 16.sp,
lineHeight = 24.sp,
letterSpacing = 0.5.sp
), 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
)
)
private val shapes = Shapes(
extraSmall = RoundedCornerShape(4.dp), small = RoundedCornerShape(6.dp), // buttons corners
medium = RoundedCornerShape(8.dp), // cards corners
large = RoundedCornerShape(12.dp), extraLarge = RoundedCornerShape(16.dp)
)
@@ -41,7 +41,7 @@ import com.rtbishop.look4sat.R
import com.rtbishop.look4sat.domain.predict.NearEarthObject
import com.rtbishop.look4sat.domain.predict.OrbitalData
import com.rtbishop.look4sat.domain.predict.OrbitalPass
import com.rtbishop.look4sat.presentation.MainTheme
import com.rtbishop.look4sat.presentation.theme.MainTheme
import java.text.SimpleDateFormat
import java.util.Date
import java.util.Locale
@@ -23,7 +23,7 @@ import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.text.style.TextOverflow
import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.dp
import com.rtbishop.look4sat.presentation.MainTheme
import com.rtbishop.look4sat.presentation.theme.MainTheme
@Preview(showBackground = true)
@Composable
@@ -39,7 +39,7 @@ import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp
import com.rtbishop.look4sat.R
import com.rtbishop.look4sat.domain.model.SatItem
import com.rtbishop.look4sat.presentation.MainTheme
import com.rtbishop.look4sat.presentation.theme.MainTheme
import com.rtbishop.look4sat.presentation.components.CardIcon
import com.rtbishop.look4sat.presentation.components.CardLoadingIndicator
@@ -22,7 +22,7 @@ import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp
import com.rtbishop.look4sat.R
import com.rtbishop.look4sat.presentation.MainTheme
import com.rtbishop.look4sat.presentation.theme.MainTheme
import com.rtbishop.look4sat.presentation.components.CardButton
import com.rtbishop.look4sat.presentation.components.gotoUrl
@@ -9,6 +9,7 @@ import android.graphics.Paint
import android.graphics.Rect
import android.graphics.drawable.BitmapDrawable
import android.graphics.drawable.Drawable
import androidx.compose.foundation.isSystemInDarkTheme
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.fillMaxSize
@@ -237,13 +238,18 @@ private fun rememberMapViewLifecycleObserver(mapView: MapView) = remember(mapVie
}
}
@Composable
private fun getColorFilter(): ColorMatrixColorFilter {
val viewModel = viewModel(MapViewModel::class.java, factory = MapViewModel.Factory)
val grayScaleMatrix = ColorMatrix().apply { setSaturation(0f) }
val negativeMatrix = ColorMatrix(
floatArrayOf(-1f, 0f, 0f, 0f, 260f, 0f, -1f, 0f, 0f, 260f, 0f, 0f, -1f, 0f, 260f, 0f, 0f, 0f, 1f, 0f)
)
negativeMatrix.preConcat(grayScaleMatrix)
return ColorMatrixColorFilter(negativeMatrix)
return when {
isSystemInDarkTheme() || viewModel.stateOfOldScheme -> ColorMatrixColorFilter(negativeMatrix)
else -> ColorMatrixColorFilter(grayScaleMatrix)
}
}
private fun getMinZoom(screenHeight: Int): Double {
@@ -53,6 +53,8 @@ class MapViewModel(private val satelliteRepo: ISatelliteRepo, settingsRepo: ISet
private var dataUpdateRate = 1000L
private var selectedOrbitalObject: OrbitalObject? = null
val stateOfOldScheme = settingsRepo.otherSettings.value.stateOfOldScheme
val stationPosition = flow {
val osmLat = clipLat(stationPos.latitude)
val osmLon = clipLon(stationPos.longitude)
@@ -56,7 +56,7 @@ import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp
import com.rtbishop.look4sat.R
import com.rtbishop.look4sat.presentation.MainTheme
import com.rtbishop.look4sat.presentation.theme.MainTheme
import com.rtbishop.look4sat.presentation.components.CardButton
private val allModes = listOf(
@@ -35,7 +35,7 @@ import com.rtbishop.look4sat.domain.predict.DeepSpaceObject
import com.rtbishop.look4sat.domain.predict.NearEarthObject
import com.rtbishop.look4sat.domain.predict.OrbitalData
import com.rtbishop.look4sat.domain.predict.OrbitalPass
import com.rtbishop.look4sat.presentation.MainTheme
import com.rtbishop.look4sat.presentation.theme.MainTheme
import com.rtbishop.look4sat.presentation.components.CardIcon
import com.rtbishop.look4sat.presentation.components.NextPassRow
import com.rtbishop.look4sat.presentation.components.PullRefreshIndicator
@@ -214,7 +214,8 @@ private fun PassItem(pass: OrbitalPass, navToRadar: (Int, Long) -> Unit, modifie
modifier = modifier
.fillMaxWidth(0.75f)
.padding(top = 2.dp),
trackColor = MaterialTheme.colorScheme.inverseSurface
color = MaterialTheme.colorScheme.primary,
trackColor = MaterialTheme.colorScheme.secondaryContainer
)
Text(
text = if (pass.isDeepSpace) defaultTime else sdfTime.format(Date(pass.losTime)),
@@ -1,18 +1,14 @@
package com.rtbishop.look4sat.presentation.radar
import android.media.AudioAttributes
import android.media.SoundPool
import androidx.compose.animation.core.animateFloat
import androidx.compose.animation.core.infiniteRepeatable
import androidx.compose.animation.core.rememberInfiniteTransition
import androidx.compose.animation.core.tween
import androidx.compose.foundation.Canvas
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.material3.MaterialTheme
import androidx.compose.runtime.Composable
import androidx.compose.runtime.DisposableEffect
import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.mutableFloatStateOf
import androidx.compose.runtime.mutableIntStateOf
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.ui.Modifier
@@ -29,107 +25,33 @@ import androidx.compose.ui.graphics.drawscope.Fill
import androidx.compose.ui.graphics.drawscope.Stroke
import androidx.compose.ui.graphics.drawscope.rotate
import androidx.compose.ui.graphics.drawscope.translate
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.platform.LocalView
import androidx.compose.ui.text.TextMeasurer
import androidx.compose.ui.text.TextStyle
import androidx.compose.ui.text.drawText
import androidx.compose.ui.text.rememberTextMeasurer
import androidx.compose.ui.unit.sp
import androidx.core.view.HapticFeedbackConstantsCompat
import com.rtbishop.look4sat.R
import androidx.lifecycle.viewmodel.compose.viewModel
import com.rtbishop.look4sat.domain.predict.OrbitalPos
import com.rtbishop.look4sat.domain.predict.PI_2
import com.rtbishop.look4sat.domain.utility.toRadians
import kotlin.math.abs
import kotlin.math.cos
import kotlin.math.min
import kotlin.math.pow
import kotlin.math.sin
import kotlin.math.sqrt
@Composable
fun RadarViewCompose(item: OrbitalPos, items: List<OrbitalPos>, azimElev: Pair<Float, Float>) {
val context = LocalContext.current
val view = LocalView.current
val radarColor = Color(0xFFDCDCDC)
val primaryColor = Color(0xFFFFE082)
val secondaryColor = Color(0xFFDC0000)
val viewModel = viewModel(RadarViewModel::class.java, factory = RadarViewModel.Factory)
val radarColor: Color = if (viewModel.stateOfOldScheme) Color(0xFFDCDCDC) else MaterialTheme.colorScheme.tertiary
val primaryColor: Color = if (viewModel.stateOfOldScheme) Color(0xFFFFE082) else MaterialTheme.colorScheme.primary
val secondaryColor: Color = if (viewModel.stateOfOldScheme) Color(0xFFDC0000) else MaterialTheme.colorScheme.onSurface
val strokeWidth = 4f
val animTransition = rememberInfiniteTransition(label = "animScale")
val animSpec = infiniteRepeatable<Float>(tween(1000))
val animScale = animTransition.animateFloat(16f, 64f, animSpec, label = "animScale")
val aimThreshold = 0.05f
val measurer = rememberTextMeasurer()
val sweepDegrees = remember { mutableFloatStateOf(0f) }
val trackCreated = remember { mutableStateOf(false) }
val trackPath = remember { mutableStateOf(Path()) }
val trackEffect = remember { mutableStateOf(PathEffect.cornerPathEffect(0f)) }
val soundPool = remember { mutableStateOf<SoundPool?>(null) }
val beepSoundId = remember { mutableIntStateOf(0) }
val aimTargetDifference = remember { mutableFloatStateOf(0f) }
LaunchedEffect(item.azimuth, item.elevation, azimElev.first, azimElev.second) {
val aimAzimuthRadians = azimElev.first.toDouble().toRadians()
val aimElevationRadians = abs(min(azimElev.second, 0f)).toDouble().toRadians()
// radius of 0.5 makes the aimTargetDifference range 0.0 to 1.0
val radius = 0.5
val aimX = sph2CartX(aimAzimuthRadians, aimElevationRadians, radius)
val aimY = sph2CartY(aimAzimuthRadians, aimElevationRadians, radius)
val satX = sph2CartX(item.azimuth, item.elevation, radius)
val satY = sph2CartY(item.azimuth, item.elevation, radius)
aimTargetDifference.floatValue = sqrt((satX - aimX).pow(2) + (satY - aimY).pow(2))
val minPlaybackRate = 0.5f
val maxPlaybackRate = 2.0f
val playbackRate =
maxPlaybackRate - (aimTargetDifference.floatValue / (maxPlaybackRate - minPlaybackRate))
soundPool.value?.setRate(beepSoundId.intValue, playbackRate)
}
LaunchedEffect(aimTargetDifference.floatValue < aimThreshold) {
if (aimTargetDifference.floatValue < aimThreshold) {
view.performHapticFeedback(HapticFeedbackConstantsCompat.VIRTUAL_KEY)
soundPool.value?.pause(beepSoundId.intValue)
} else {
soundPool.value?.resume(beepSoundId.intValue)
}
}
LaunchedEffect(item.elevation > 0) {
if(item.elevation > 0) {
soundPool.value?.resume(beepSoundId.intValue)
} else {
soundPool.value?.pause(beepSoundId.intValue)
}
}
DisposableEffect(Unit) {
val audioAttributes = AudioAttributes.Builder()
.setUsage(AudioAttributes.USAGE_ASSISTANCE_SONIFICATION)
.setContentType(AudioAttributes.CONTENT_TYPE_SONIFICATION)
.build()
soundPool.value = SoundPool.Builder()
.setMaxStreams(1)
.setAudioAttributes(audioAttributes)
.build()
beepSoundId.intValue = soundPool.value?.load(context, R.raw.beep, 1) ?: 0
soundPool.value?.setOnLoadCompleteListener { soundPool, _, status ->
if (status == 0) {
soundPool.play(beepSoundId.intValue, 0.5f, 0.5f, 0, -1, 1f)
}
}
onDispose {
soundPool.value?.release()
}
}
Canvas(modifier = Modifier.fillMaxSize()) {
val radius = (size.minDimension / 2f) * 0.95f
if (!trackCreated.value) {
@@ -56,6 +56,7 @@ class RadarViewModel(
private val stationPos = settingsRepo.stationPosition.value
private val magDeclination = getMagDeclination(stationPos)
val stateOfOldScheme = settingsRepo.otherSettings.value.stateOfOldScheme
val transmitters = mutableStateOf<List<SatRadio>>(emptyList())
val radarData = mutableStateOf<RadarData?>(null)
val orientation = mutableStateOf(sensorsRepo.orientation.value)
@@ -19,7 +19,7 @@ import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.dp
import androidx.compose.ui.window.Dialog
import com.rtbishop.look4sat.R
import com.rtbishop.look4sat.presentation.MainTheme
import com.rtbishop.look4sat.presentation.theme.MainTheme
import com.rtbishop.look4sat.presentation.components.CardButton
@Preview(showBackground = true)
@@ -36,7 +36,7 @@ import androidx.lifecycle.viewmodel.compose.viewModel
import com.rtbishop.look4sat.R
import com.rtbishop.look4sat.domain.model.OtherSettings
import com.rtbishop.look4sat.domain.predict.GeoPos
import com.rtbishop.look4sat.presentation.MainTheme
import com.rtbishop.look4sat.presentation.theme.MainTheme
import com.rtbishop.look4sat.presentation.components.CardButton
import com.rtbishop.look4sat.presentation.components.gotoUrl
import com.rtbishop.look4sat.presentation.components.showToast
@@ -110,6 +110,7 @@ fun SettingsScreen() {
val toggleUpdate = { value: Boolean -> viewModel.toggleUpdate(value) }
val toggleSweep = { value: Boolean -> viewModel.toggleSweep(value) }
val toggleSensor = { value: Boolean -> viewModel.toggleSensor(value) }
val toggleOldScheme = { value: Boolean -> viewModel.toggleOldScheme(value)}
// Screen setup
val versionName = context.packageManager.getPackageInfo(context.packageName, 0).versionName ?: "4.0.0"
@@ -117,7 +118,7 @@ fun SettingsScreen() {
item { CardAbout(versionName) }
item { LocationCard(positionSettings, setGpsPos, showPosDialog, showLocDialog, dismissPos) }
item { DataCard(dataSettings, updateFromWeb, updateFromFile, clearAllData) }
item { OtherCard(otherSettings, toggleUtc, toggleUpdate, toggleSweep, toggleSensor) }
item { OtherCard(otherSettings, toggleUtc, toggleUpdate, toggleSweep, toggleSensor,toggleOldScheme) }
}
}
@@ -368,8 +369,13 @@ private fun DataCard(
@Preview(showBackground = true)
@Composable
private fun OtherCardPreview() = MainTheme {
val values = OtherSettings(stateOfAutoUpdate = true, stateOfSensors = true, stateOfSweep = true, stateOfUtc = false)
OtherCard(settings = values, {}, {}, {}, {})
val values = OtherSettings(
stateOfAutoUpdate = true,
stateOfSensors = true,
stateOfSweep = true,
stateOfUtc = false,
stateOfOldScheme = false)
OtherCard(settings = values, {}, {}, {}, {},{})
}
@Composable
@@ -378,7 +384,8 @@ private fun OtherCard(
toggleUtc: (Boolean) -> Unit,
toggleUpdate: (Boolean) -> Unit,
toggleSweep: (Boolean) -> Unit,
toggleSensor: (Boolean) -> Unit
toggleSensor: (Boolean) -> Unit,
toggleOldScheme: (Boolean) -> Unit
) {
ElevatedCard(modifier = Modifier.fillMaxWidth()) {
Column(modifier = Modifier.padding(horizontal = 8.dp, vertical = 2.dp)) {
@@ -414,6 +421,14 @@ private fun OtherCard(
Text(text = stringResource(id = R.string.other_switch_sensors))
Switch(checked = settings.stateOfSensors, onCheckedChange = { toggleSensor(it) })
}
Row(
horizontalArrangement = Arrangement.SpaceBetween,
verticalAlignment = Alignment.CenterVertically,
modifier = Modifier.fillMaxWidth()
) {
Text(text = stringResource(id = R.string.other_switch_old_scheme))
Switch(checked = settings.stateOfOldScheme, onCheckedChange = { toggleOldScheme(it) })
}
}
}
}
@@ -433,12 +448,14 @@ private fun setUpdateTime(updateTime: Long): String {
private fun UpdateIndicator(isUpdating: Boolean, modifier: Modifier = Modifier) = if (isUpdating) {
LinearProgressIndicator(
modifier = modifier.padding(start = 6.dp),
trackColor = MaterialTheme.colorScheme.inverseSurface
color = MaterialTheme.colorScheme.primary,
trackColor = MaterialTheme.colorScheme.secondaryContainer
)
} else {
LinearProgressIndicator(
progress = { 0f },
modifier = modifier.padding(start = 6.dp),
trackColor = MaterialTheme.colorScheme.inverseSurface,
color = MaterialTheme.colorScheme.primary,
trackColor = MaterialTheme.colorScheme.secondaryContainer
)
}
@@ -129,7 +129,7 @@ class SettingsViewModel(
fun toggleUpdate(value: Boolean) = settingsRepo.setStateOfAutoUpdate(value)
fun toggleSweep(value: Boolean) = settingsRepo.setStateOfSweep(value)
fun toggleSensor(value: Boolean) = settingsRepo.setStateOfSensors(value)
fun toggleOldScheme(value: Boolean) = settingsRepo.setStateOfOldScheme(value)
// fun getRotatorEnabled(): Boolean = settings.getRotatorEnabled()
// fun setRotatorEnabled(value: Boolean) = settings.setRotatorEnabled(value)
// fun getRotatorServer(): String = settings.getRotatorServer()
@@ -0,0 +1,225 @@
package com.rtbishop.look4sat.presentation.theme
import androidx.compose.ui.graphics.Color
val primaryLight = Color(0xFF715C0C)
val onPrimaryLight = Color(0xFFFFFFFF)
val primaryContainerLight = Color(0xFFFEE086)
val onPrimaryContainerLight = Color(0xFF231B00)
val secondaryLight = Color(0xFF685E40)
val onSecondaryLight = Color(0xFFFFFFFF)
val secondaryContainerLight = Color(0xFFF1E1BB)
val onSecondaryContainerLight = Color(0xFF221B04)
val tertiaryLight = Color(0xFF46664B)
val onTertiaryLight = Color(0xFFFFFFFF)
val tertiaryContainerLight = Color(0xFFC7ECCA)
val onTertiaryContainerLight = Color(0xFF02210C)
val errorLight = Color(0xFFBA1A1A)
val onErrorLight = Color(0xFFFFFFFF)
val errorContainerLight = Color(0xFFFFDAD6)
val onErrorContainerLight = Color(0xFF410002)
val backgroundLight = Color(0xFFFFF8F0)
val onBackgroundLight = Color(0xFF1E1B13)
val surfaceLight = Color(0xFFFFF8F0)
val onSurfaceLight = Color(0xFF1E1B13)
val surfaceVariantLight = Color(0xFFEBE2CF)
val onSurfaceVariantLight = Color(0xFF4C4639)
val outlineLight = Color(0xFF7D7667)
val outlineVariantLight = Color(0xFFCEC6B4)
val scrimLight = Color(0xFF000000)
val inverseSurfaceLight = Color(0xFF343027)
val inverseOnSurfaceLight = Color(0xFFF8F0E2)
val inversePrimaryLight = Color(0xFFE1C46D)
val surfaceDimLight = Color(0xFFE1D9CC)
val surfaceBrightLight = Color(0xFFFFF8F0)
val surfaceContainerLowestLight = Color(0xFFFFFFFF)
val surfaceContainerLowLight = Color(0xFFFBF3E5)
val surfaceContainerLight = Color(0xFFF5EDDF)
val surfaceContainerHighLight = Color(0xFFEFE7DA)
val surfaceContainerHighestLight = Color(0xFFE9E2D4)
val primaryLightMediumContrast = Color(0xFF524100)
val onPrimaryLightMediumContrast = Color(0xFFFFFFFF)
val primaryContainerLightMediumContrast = Color(0xFF897224)
val onPrimaryContainerLightMediumContrast = Color(0xFFFFFFFF)
val secondaryLightMediumContrast = Color(0xFF4B4226)
val onSecondaryLightMediumContrast = Color(0xFFFFFFFF)
val secondaryContainerLightMediumContrast = Color(0xFF7F7454)
val onSecondaryContainerLightMediumContrast = Color(0xFFFFFFFF)
val tertiaryLightMediumContrast = Color(0xFF2B4A31)
val onTertiaryLightMediumContrast = Color(0xFFFFFFFF)
val tertiaryContainerLightMediumContrast = Color(0xFF5C7C60)
val onTertiaryContainerLightMediumContrast = Color(0xFFFFFFFF)
val errorLightMediumContrast = Color(0xFF8C0009)
val onErrorLightMediumContrast = Color(0xFFFFFFFF)
val errorContainerLightMediumContrast = Color(0xFFDA342E)
val onErrorContainerLightMediumContrast = Color(0xFFFFFFFF)
val backgroundLightMediumContrast = Color(0xFFFFF8F0)
val onBackgroundLightMediumContrast = Color(0xFF1E1B13)
val surfaceLightMediumContrast = Color(0xFFFFF8F0)
val onSurfaceLightMediumContrast = Color(0xFF1E1B13)
val surfaceVariantLightMediumContrast = Color(0xFFEBE2CF)
val onSurfaceVariantLightMediumContrast = Color(0xFF484235)
val outlineLightMediumContrast = Color(0xFF655F50)
val outlineVariantLightMediumContrast = Color(0xFF817A6B)
val scrimLightMediumContrast = Color(0xFF000000)
val inverseSurfaceLightMediumContrast = Color(0xFF343027)
val inverseOnSurfaceLightMediumContrast = Color(0xFFF8F0E2)
val inversePrimaryLightMediumContrast = Color(0xFFE1C46D)
val surfaceDimLightMediumContrast = Color(0xFFE1D9CC)
val surfaceBrightLightMediumContrast = Color(0xFFFFF8F0)
val surfaceContainerLowestLightMediumContrast = Color(0xFFFFFFFF)
val surfaceContainerLowLightMediumContrast = Color(0xFFFBF3E5)
val surfaceContainerLightMediumContrast = Color(0xFFF5EDDF)
val surfaceContainerHighLightMediumContrast = Color(0xFFEFE7DA)
val surfaceContainerHighestLightMediumContrast = Color(0xFFE9E2D4)
val primaryLightHighContrast = Color(0xFF2B2100)
val onPrimaryLightHighContrast = Color(0xFFFFFFFF)
val primaryContainerLightHighContrast = Color(0xFF524100)
val onPrimaryContainerLightHighContrast = Color(0xFFFFFFFF)
val secondaryLightHighContrast = Color(0xFF292209)
val onSecondaryLightHighContrast = Color(0xFFFFFFFF)
val secondaryContainerLightHighContrast = Color(0xFF4B4226)
val onSecondaryContainerLightHighContrast = Color(0xFFFFFFFF)
val tertiaryLightHighContrast = Color(0xFF082813)
val onTertiaryLightHighContrast = Color(0xFFFFFFFF)
val tertiaryContainerLightHighContrast = Color(0xFF2B4A31)
val onTertiaryContainerLightHighContrast = Color(0xFFFFFFFF)
val errorLightHighContrast = Color(0xFF4E0002)
val onErrorLightHighContrast = Color(0xFFFFFFFF)
val errorContainerLightHighContrast = Color(0xFF8C0009)
val onErrorContainerLightHighContrast = Color(0xFFFFFFFF)
val backgroundLightHighContrast = Color(0xFFFFF8F0)
val onBackgroundLightHighContrast = Color(0xFF1E1B13)
val surfaceLightHighContrast = Color(0xFFFFF8F0)
val onSurfaceLightHighContrast = Color(0xFF000000)
val surfaceVariantLightHighContrast = Color(0xFFEBE2CF)
val onSurfaceVariantLightHighContrast = Color(0xFF282418)
val outlineLightHighContrast = Color(0xFF484235)
val outlineVariantLightHighContrast = Color(0xFF484235)
val scrimLightHighContrast = Color(0xFF000000)
val inverseSurfaceLightHighContrast = Color(0xFF343027)
val inverseOnSurfaceLightHighContrast = Color(0xFFFFFFFF)
val inversePrimaryLightHighContrast = Color(0xFFFFEBB4)
val surfaceDimLightHighContrast = Color(0xFFE1D9CC)
val surfaceBrightLightHighContrast = Color(0xFFFFF8F0)
val surfaceContainerLowestLightHighContrast = Color(0xFFFFFFFF)
val surfaceContainerLowLightHighContrast = Color(0xFFFBF3E5)
val surfaceContainerLightHighContrast = Color(0xFFF5EDDF)
val surfaceContainerHighLightHighContrast = Color(0xFFEFE7DA)
val surfaceContainerHighestLightHighContrast = Color(0xFFE9E2D4)
val primaryDark = Color(0xFFE1C46D)
val onPrimaryDark = Color(0xFF3C2F00)
val primaryContainerDark = Color(0xFF564500)
val onPrimaryContainerDark = Color(0xFFFEE086)
val secondaryDark = Color(0xFFD4C5A1)
val onSecondaryDark = Color(0xFF383016)
val secondaryContainerDark = Color(0xFF50462A)
val onSecondaryContainerDark = Color(0xFFF1E1BB)
val tertiaryDark = Color(0xFFACCFAF)
val onTertiaryDark = Color(0xFF183720)
val tertiaryContainerDark = Color(0xFF2E4E35)
val onTertiaryContainerDark = Color(0xFFC7ECCA)
val errorDark = Color(0xFFFFB4AB)
val onErrorDark = Color(0xFF690005)
val errorContainerDark = Color(0xFF93000A)
val onErrorContainerDark = Color(0xFFFFDAD6)
val backgroundDark = Color(0xFF16130B)
val onBackgroundDark = Color(0xFFE9E2D4)
val surfaceDark = Color(0xFF16130B)
val onSurfaceDark = Color(0xFFE9E2D4)
val surfaceVariantDark = Color(0xFF4C4639)
val onSurfaceVariantDark = Color(0xFFCEC6B4)
val outlineDark = Color(0xFF979080)
val outlineVariantDark = Color(0xFF4C4639)
val scrimDark = Color(0xFF000000)
val inverseSurfaceDark = Color(0xFFE9E2D4)
val inverseOnSurfaceDark = Color(0xFF343027)
val inversePrimaryDark = Color(0xFF715C0C)
val surfaceDimDark = Color(0xFF16130B)
val surfaceBrightDark = Color(0xFF3D392F)
val surfaceContainerLowestDark = Color(0xFF110E07)
val surfaceContainerLowDark = Color(0xFF1E1B13)
val surfaceContainerDark = Color(0xFF231F17)
val surfaceContainerHighDark = Color(0xFF2D2A21)
val surfaceContainerHighestDark = Color(0xFF38342B)
val primaryDarkMediumContrast = Color(0xFFE5C971)
val onPrimaryDarkMediumContrast = Color(0xFF1D1500)
val primaryContainerDarkMediumContrast = Color(0xFFA88F3D)
val onPrimaryContainerDarkMediumContrast = Color(0xFF000000)
val secondaryDarkMediumContrast = Color(0xFFD8CAA5)
val onSecondaryDarkMediumContrast = Color(0xFF1C1601)
val secondaryContainerDarkMediumContrast = Color(0xFF9C906E)
val onSecondaryContainerDarkMediumContrast = Color(0xFF000000)
val tertiaryDarkMediumContrast = Color(0xFFB0D4B3)
val onTertiaryDarkMediumContrast = Color(0xFF001B08)
val tertiaryContainerDarkMediumContrast = Color(0xFF77997B)
val onTertiaryContainerDarkMediumContrast = Color(0xFF000000)
val errorDarkMediumContrast = Color(0xFFFFBAB1)
val onErrorDarkMediumContrast = Color(0xFF370001)
val errorContainerDarkMediumContrast = Color(0xFFFF5449)
val onErrorContainerDarkMediumContrast = Color(0xFF000000)
val backgroundDarkMediumContrast = Color(0xFF16130B)
val onBackgroundDarkMediumContrast = Color(0xFFE9E2D4)
val surfaceDarkMediumContrast = Color(0xFF16130B)
val onSurfaceDarkMediumContrast = Color(0xFFFFFAF6)
val surfaceVariantDarkMediumContrast = Color(0xFF4C4639)
val onSurfaceVariantDarkMediumContrast = Color(0xFFD3CAB8)
val outlineDarkMediumContrast = Color(0xFFAAA291)
val outlineVariantDarkMediumContrast = Color(0xFF898273)
val scrimDarkMediumContrast = Color(0xFF000000)
val inverseSurfaceDarkMediumContrast = Color(0xFFE9E2D4)
val inverseOnSurfaceDarkMediumContrast = Color(0xFF2D2A21)
val inversePrimaryDarkMediumContrast = Color(0xFF584600)
val surfaceDimDarkMediumContrast = Color(0xFF16130B)
val surfaceBrightDarkMediumContrast = Color(0xFF3D392F)
val surfaceContainerLowestDarkMediumContrast = Color(0xFF110E07)
val surfaceContainerLowDarkMediumContrast = Color(0xFF1E1B13)
val surfaceContainerDarkMediumContrast = Color(0xFF231F17)
val surfaceContainerHighDarkMediumContrast = Color(0xFF2D2A21)
val surfaceContainerHighestDarkMediumContrast = Color(0xFF38342B)
val primaryDarkHighContrast = Color(0xFFFFFAF6)
val onPrimaryDarkHighContrast = Color(0xFF000000)
val primaryContainerDarkHighContrast = Color(0xFFE5C971)
val onPrimaryContainerDarkHighContrast = Color(0xFF000000)
val secondaryDarkHighContrast = Color(0xFFFFFAF6)
val onSecondaryDarkHighContrast = Color(0xFF000000)
val secondaryContainerDarkHighContrast = Color(0xFFD8CAA5)
val onSecondaryContainerDarkHighContrast = Color(0xFF000000)
val tertiaryDarkHighContrast = Color(0xFFF0FFEE)
val onTertiaryDarkHighContrast = Color(0xFF000000)
val tertiaryContainerDarkHighContrast = Color(0xFFB0D4B3)
val onTertiaryContainerDarkHighContrast = Color(0xFF000000)
val errorDarkHighContrast = Color(0xFFFFF9F9)
val onErrorDarkHighContrast = Color(0xFF000000)
val errorContainerDarkHighContrast = Color(0xFFFFBAB1)
val onErrorContainerDarkHighContrast = Color(0xFF000000)
val backgroundDarkHighContrast = Color(0xFF16130B)
val onBackgroundDarkHighContrast = Color(0xFFE9E2D4)
val surfaceDarkHighContrast = Color(0xFF16130B)
val onSurfaceDarkHighContrast = Color(0xFFFFFFFF)
val surfaceVariantDarkHighContrast = Color(0xFF4C4639)
val onSurfaceVariantDarkHighContrast = Color(0xFFFFFAF6)
val outlineDarkHighContrast = Color(0xFFD3CAB8)
val outlineVariantDarkHighContrast = Color(0xFFD3CAB8)
val scrimDarkHighContrast = Color(0xFF000000)
val inverseSurfaceDarkHighContrast = Color(0xFFE9E2D4)
val inverseOnSurfaceDarkHighContrast = Color(0xFF000000)
val inversePrimaryDarkHighContrast = Color(0xFF342900)
val surfaceDimDarkHighContrast = Color(0xFF16130B)
val surfaceBrightDarkHighContrast = Color(0xFF3D392F)
val surfaceContainerLowestDarkHighContrast = Color(0xFF110E07)
val surfaceContainerLowDarkHighContrast = Color(0xFF1E1B13)
val surfaceContainerDarkHighContrast = Color(0xFF231F17)
val surfaceContainerHighDarkHighContrast = Color(0xFF2D2A21)
val surfaceContainerHighestDarkHighContrast = Color(0xFF38342B)
@@ -0,0 +1,217 @@
package com.rtbishop.look4sat.presentation.theme
import android.app.Activity
import android.os.Build
import androidx.compose.foundation.ExperimentalFoundationApi
import androidx.compose.foundation.LocalOverscrollConfiguration
import androidx.compose.foundation.isSystemInDarkTheme
import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Shapes
import androidx.compose.material3.lightColorScheme
import androidx.compose.material3.darkColorScheme
import androidx.compose.material3.dynamicDarkColorScheme
import androidx.compose.material3.dynamicLightColorScheme
import androidx.compose.material3.Typography
import androidx.compose.runtime.Composable
import androidx.compose.runtime.CompositionLocalProvider
import androidx.compose.runtime.SideEffect
import androidx.compose.runtime.collectAsState
import androidx.compose.runtime.getValue
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.graphics.toArgb
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.platform.LocalView
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.dp
import androidx.compose.ui.unit.sp
import androidx.core.view.WindowCompat
import com.rtbishop.look4sat.MainApplication
@OptIn(ExperimentalFoundationApi::class)
@Composable
fun MainTheme(
darkTheme: Boolean = isSystemInDarkTheme(),
dynamicColor: Boolean = true,
content: @Composable () -> Unit
) {
val view = LocalView.current
if (view.isInEditMode) MaterialTheme(
colorScheme = lightScheme,
typography = typography,
shapes = shapes
) {
CompositionLocalProvider(LocalOverscrollConfiguration.provides(null), content = content)
}
else {
val otherSettings by (LocalContext.current.applicationContext as MainApplication).container.settingsRepo.otherSettings.collectAsState()
val isOldScheme = otherSettings.stateOfOldScheme
val colorScheme = when {
isOldScheme -> oldScheme
dynamicColor && Build.VERSION.SDK_INT >= Build.VERSION_CODES.S -> {
val context = LocalContext.current
if (darkTheme) dynamicDarkColorScheme(context) else dynamicLightColorScheme(context)
}
darkTheme -> darkScheme
else -> lightScheme
}
SideEffect {
val window = (view.context as Activity).window
window.statusBarColor = colorScheme.background.toArgb()
WindowCompat.getInsetsController(window, view).isAppearanceLightStatusBars =
if (isOldScheme) false else !darkTheme
}
MaterialTheme(colorScheme = colorScheme, typography = typography, shapes = shapes) {
CompositionLocalProvider(LocalOverscrollConfiguration.provides(null), content = content)
}
}
}
private val typography = Typography(
bodyLarge = TextStyle(
fontFamily = FontFamily.Default,
fontWeight = FontWeight.Normal,
fontSize = 16.sp,
lineHeight = 24.sp,
letterSpacing = 0.5.sp
), 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
)
)
private val shapes = Shapes(
extraSmall = RoundedCornerShape(4.dp), small = RoundedCornerShape(6.dp), // buttons corners
medium = RoundedCornerShape(8.dp), // cards corners
large = RoundedCornerShape(12.dp), extraLarge = RoundedCornerShape(16.dp)
)
private val accentYellow = Color(0xFFFFE082)
private val textWhite = Color(0xCCFFFFFF)
private val textGrey = Color(0x66FFFFFF)
private val textBlack = Color(0xFF000000)
private val surfaceInverse = Color(0x40FFFFFF)
private val surfaceBtn = Color(0xFF303030)
private val surfaceCard = Color(0xFF1C1C1C)
private val surfaceBg = Color(0xFF121212)
private val transparent = Color(0x00000000)
private val oldScheme = lightColorScheme(
primary = accentYellow,
onPrimary = textBlack,
// primaryContainer = primaryContainer,
// onPrimaryContainer = onPrimaryContainer,
// inversePrimary = inversePrimary,
secondary = accentYellow,
onSecondary = textBlack,
secondaryContainer = surfaceInverse, // navBar indicator
onSecondaryContainer = textBlack, // navBar active icon
tertiary = surfaceBtn,
onTertiary = textWhite,
// tertiaryContainer = tertiaryContainer,
// onTertiaryContainer = onTertiaryContainer,
background = surfaceBg,
onBackground = textWhite,
surface = surfaceCard,
onSurface = textWhite,
surfaceVariant = surfaceCard,
onSurfaceVariant = textGrey, // navBar inactive icon
surfaceTint = transparent,
inverseSurface = surfaceInverse,
// inverseOnSurface = inverseOnSurface,
// error = error,
// onError = onError,
// errorContainer = errorContainer,
// onErrorContainer = onErrorContainer,
// outline = outline,
// outlineVariant = outlineVariant,
// scrim = scrim,
)
private val lightScheme = lightColorScheme(
primary = primaryLight,
onPrimary = onPrimaryLight,
primaryContainer = primaryContainerLight,
onPrimaryContainer = onPrimaryContainerLight,
secondary = secondaryLight,
onSecondary = onSecondaryLight,
secondaryContainer = secondaryContainerLight,
onSecondaryContainer = onSecondaryContainerLight,
tertiary = tertiaryLight,
onTertiary = onTertiaryLight,
tertiaryContainer = tertiaryContainerLight,
onTertiaryContainer = onTertiaryContainerLight,
error = errorLight,
onError = onErrorLight,
errorContainer = errorContainerLight,
onErrorContainer = onErrorContainerLight,
background = backgroundLight,
onBackground = onBackgroundLight,
surface = surfaceLight,
onSurface = onSurfaceLight,
surfaceVariant = surfaceVariantLight,
onSurfaceVariant = onSurfaceVariantLight,
outline = outlineLight,
outlineVariant = outlineVariantLight,
scrim = scrimLight,
inverseSurface = inverseSurfaceLight,
inverseOnSurface = inverseOnSurfaceLight,
inversePrimary = inversePrimaryLight,
surfaceDim = surfaceDimLight,
surfaceBright = surfaceBrightLight,
surfaceContainerLowest = surfaceContainerLowestLight,
surfaceContainerLow = surfaceContainerLowLight,
surfaceContainer = surfaceContainerLight,
surfaceContainerHigh = surfaceContainerHighLight,
surfaceContainerHighest = surfaceContainerHighestLight,
)
private val darkScheme = darkColorScheme(
primary = primaryDark,
onPrimary = onPrimaryDark,
primaryContainer = primaryContainerDark,
onPrimaryContainer = onPrimaryContainerDark,
secondary = secondaryDark,
onSecondary = onSecondaryDark,
secondaryContainer = secondaryContainerDark,
onSecondaryContainer = onSecondaryContainerDark,
tertiary = tertiaryDark,
onTertiary = onTertiaryDark,
tertiaryContainer = tertiaryContainerDark,
onTertiaryContainer = onTertiaryContainerDark,
error = errorDark,
onError = onErrorDark,
errorContainer = errorContainerDark,
onErrorContainer = onErrorContainerDark,
background = backgroundDark,
onBackground = onBackgroundDark,
surface = surfaceDark,
onSurface = onSurfaceDark,
surfaceVariant = surfaceVariantDark,
onSurfaceVariant = onSurfaceVariantDark,
outline = outlineDark,
outlineVariant = outlineVariantDark,
scrim = scrimDark,
inverseSurface = inverseSurfaceDark,
inverseOnSurface = inverseOnSurfaceDark,
inversePrimary = inversePrimaryDark,
surfaceDim = surfaceDimDark,
surfaceBright = surfaceBrightDark,
surfaceContainerLowest = surfaceContainerLowestDark,
surfaceContainerLow = surfaceContainerLowDark,
surfaceContainer = surfaceContainerDark,
surfaceContainerHigh = surfaceContainerHighDark,
surfaceContainerHighest = surfaceContainerHighestDark,
)
+20
View File
@@ -0,0 +1,20 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="108dp"
android:height="108dp"
android:viewportWidth="271.24"
android:viewportHeight="271.24">
<group
android:translateX="1.3562195"
android:translateY="1.3562195">
<group
android:translateX="70.26573"
android:translateY="70.26573">
<path
android:fillColor="@color/accent"
android:pathData="m96.64,31.5c7.91,8 17.14,13.58 25.36,15.58l1.75,-4C123.78,43.05 123.79,43.01 123.8,42.97 125.83,38.99 127,34.49 127,29.72 127,13.88 114.38,1 98.87,1c-5.13,0 -9.92,1.43 -14.06,3.88l-3.4,1.6c0.08,0.31 0.13,0.6 0.22,0.91 2.32,8.1 7.65,16.67 15.02,24.11z" />
<path
android:fillColor="@color/accent"
android:pathData="M93.88,34.3C86.05,26.39 80.37,17.23 77.87,8.49 77.84,8.39 77.82,8.28 77.79,8.18L2.63,43.51c-1.4,0.66 -2.02,2.36 -1.37,3.79 0.47,1.05 1.49,1.66 2.55,1.66 0.39,0 0.79,-0.08 1.17,-0.26L74.04,16.24c-1.87,3.58 -3,7.61 -3.23,11.89L35.57,51.73c-1.29,0.87 -1.65,2.64 -0.81,3.96 0.54,0.84 1.43,1.29 2.34,1.29 0.53,0 1.06,-0.15 1.53,-0.47L71.19,34.71c1.4,8.11 6.14,15.04 12.72,19.28l-54.94,68.34c-0.98,1.22 -0.81,3.02 0.39,4.02 0.52,0.44 1.15,0.65 1.77,0.65 0.81,0 1.61,-0.36 2.17,-1.04L89.06,56.6c3.06,1.17 6.36,1.84 9.81,1.84 4.93,0 9.57,-1.31 13.6,-3.6L84.6,118.32c-0.63,1.44 0,3.13 1.41,3.78 0.37,0.17 0.76,0.25 1.14,0.25 1.07,0 2.09,-0.63 2.56,-1.69L120.4,50.74C111.64,48.42 102.04,42.56 93.88,34.3Z" />
</group>
</group>
</vector>
+1
View File
@@ -2,4 +2,5 @@
<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
<background android:drawable="@drawable/launcher_bg" />
<foreground android:drawable="@drawable/launcher_fg" />
<monochrome android:drawable="@drawable/launcher_mc" />
</adaptive-icon>
@@ -2,4 +2,5 @@
<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
<background android:drawable="@drawable/launcher_bg" />
<foreground android:drawable="@drawable/launcher_fg" />
<monochrome android:drawable="@drawable/launcher_mc" />
</adaptive-icon>
+1
View File
@@ -178,4 +178,5 @@
за интерес к приложению и публикацию интервью на сайте.
</string>
<string name="outro_license">Это ПО поставляется без гарантий.</string>
<string name="other_switch_old_scheme">• Используйте старую цветовую схему.</string>
</resources>
+1
View File
@@ -175,4 +175,5 @@
<a href="https://db.satnogs.org/">SatNOGS</a>Web අඩවියට API හා DB විශාල දත්ත ප්‍රමාණයක් ලබාදීම සඳහා.
\n• <a href="https://appoftheday.downloadastro.com/app/look4sat-satellite-tracker/">DownloadAstro</a> කණ්ඩායමට යෙදුම පිළිබඳ ඔවුන්ගේ උනන්දුව සහ කැපවීම ලැබිම සම්බන්ධයෙන්.</string>
<string name="outro_license">මෘදුකාංගය වගකීමක් සමග නොලැබේ</string>
<string name="other_switch_old_scheme">• පැරණි වර්ණ පටිපාටිය භාවිතා කරන්න</string>
</resources>
@@ -179,4 +179,5 @@
team for their interest to the app and the interview published.
</string>
<string name="outro_license">该应用程序不提供任何保修.</string>
<string name="other_switch_old_scheme">• 使用旧版配色方案</string>
</resources>
+1
View File
@@ -180,4 +180,5 @@
team for their interest to the app and the interview published.
</string>
<string name="outro_license">The app comes with no warranty.</string>
<string name="other_switch_old_scheme">• Use the old color scheme</string>
</resources>