Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions Jetsnack/app/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,7 @@ android {
kotlin {
compilerOptions {
jvmTarget = JvmTarget.fromTarget("17")
freeCompilerArgs.add("-opt-in=androidx.compose.foundation.style.ExperimentalFoundationStyleApi")
}
}
compileOptions {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
package androidx.compose.material3

import androidx.compose.runtime.ProvidableCompositionLocal
import java.lang.reflect.Method

// This file is only because we don't have this yet implemented in Material 3 theming.

// This will not be how it's done when its released :)

val LocalShapes: ProvidableCompositionLocal<Shapes>
get() = getInternalLocal(
className = "androidx.compose.material3.ShapesKt",
methodName = "getLocalShapes",
readableName = "LocalShapes"
)

val LocalColorScheme: ProvidableCompositionLocal<ColorScheme>
get() = getInternalLocal(
className = "androidx.compose.material3.ColorSchemeKt",
methodName = "getLocalColorScheme",
readableName = "LocalColorScheme"
)

val LocalTypography: ProvidableCompositionLocal<Typography>
get() = getInternalLocal(
className = "androidx.compose.material3.TypographyKt",
methodName = "getLocalTypography",
readableName = "LocalTypography"
)

private fun <T> getInternalLocal(className: String, methodName: String, readableName: String): ProvidableCompositionLocal<T> {
try {
val clazz = Class.forName(className)
val method: Method = clazz.getDeclaredMethod(methodName)
method.isAccessible = true
@Suppress("UNCHECKED_CAST")
return method.invoke(null) as ProvidableCompositionLocal<T>
} catch (e: Exception) {
throw RuntimeException("Failed to access internal $readableName via reflection", e)
}
}
Comment on lines +31 to +41
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

high

Using reflection to access internal library APIs is highly discouraged as it's brittle and can break without warning on any library update, even minor ones. This makes the app fragile.

Also, catching a generic Exception is too broad. It would be safer to catch specific reflection-related exceptions like ClassNotFoundException, NoSuchMethodException, etc., to have a better understanding of what went wrong.

Original file line number Diff line number Diff line change
Expand Up @@ -14,66 +14,52 @@
* limitations under the License.
*/

@file:OptIn(ExperimentalFoundationStyleApi::class)

package com.example.jetsnack.ui.components

import android.content.res.Configuration.UI_MODE_NIGHT_YES
import androidx.compose.foundation.BorderStroke
import androidx.compose.foundation.background
import androidx.compose.foundation.clickable
import androidx.compose.foundation.indication
import androidx.compose.foundation.interaction.MutableInteractionSource
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.PaddingValues
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.RowScope
import androidx.compose.foundation.layout.defaultMinSize
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.foundation.style.ExperimentalFoundationStyleApi
import androidx.compose.foundation.style.Style
import androidx.compose.foundation.style.rememberUpdatedStyleState
import androidx.compose.foundation.style.then
import androidx.compose.material3.ButtonDefaults
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.ProvideTextStyle
import androidx.compose.material3.Text
import androidx.compose.material3.ripple
import androidx.compose.runtime.Composable
import androidx.compose.runtime.remember
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.clip
import androidx.compose.ui.graphics.Brush
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.graphics.RectangleShape
import androidx.compose.ui.graphics.Shape
import androidx.compose.ui.semantics.Role
import androidx.compose.ui.tooling.preview.Preview
import com.example.jetsnack.ui.theme.JetsnackTheme

//todo think about the text style here
@Composable
fun JetsnackButton(
onClick: () -> Unit,
modifier: Modifier = Modifier,
style: Style = Style,
enabled: Boolean = true,
interactionSource: MutableInteractionSource = remember { MutableInteractionSource() },
shape: Shape = ButtonShape,
border: BorderStroke? = null,
backgroundGradient: List<Color> = JetsnackTheme.colors.interactivePrimary,
disabledBackgroundGradient: List<Color> = JetsnackTheme.colors.interactiveSecondary,
contentColor: Color = JetsnackTheme.colors.textInteractive,
disabledContentColor: Color = JetsnackTheme.colors.textHelp,
contentPadding: PaddingValues = ButtonDefaults.ContentPadding,
content: @Composable RowScope.() -> Unit,
) {
val styleState = rememberUpdatedStyleState(interactionSource, {
it.isEnabled = enabled
})
JetsnackSurface(
shape = shape,
color = Color.Transparent,
contentColor = if (enabled) contentColor else disabledContentColor,
border = border,
style = JetsnackTheme.appStyles.buttonStyle then style,
styleState = styleState,
modifier = modifier
.clip(shape)
.background(
Brush.horizontalGradient(
colors = if (enabled) backgroundGradient else disabledBackgroundGradient,
),
)
.clickable(
onClick = onClick,
enabled = enabled,
Expand All @@ -91,8 +77,7 @@ fun JetsnackButton(
minWidth = ButtonDefaults.MinWidth,
minHeight = ButtonDefaults.MinHeight,
)
.indication(interactionSource, ripple())
.padding(contentPadding),
.indication(interactionSource, ripple()),
horizontalArrangement = Arrangement.Center,
verticalAlignment = Alignment.CenterVertically,
content = content,
Expand All @@ -101,16 +86,14 @@ fun JetsnackButton(
}
}

private val ButtonShape = RoundedCornerShape(percent = 50)

@Preview("default", "round")
@Preview("dark theme", "round", uiMode = UI_MODE_NIGHT_YES)
@Preview("large font", "round", fontScale = 2f)
@Composable
private fun ButtonPreview() {
JetsnackTheme {
JetsnackButton(onClick = {}) {
Text(text = "Demo")
JetsnackText(text = "Demo")
}
}
}
Expand All @@ -122,9 +105,11 @@ private fun ButtonPreview() {
private fun RectangleButtonPreview() {
JetsnackTheme {
JetsnackButton(
onClick = {}, shape = RectangleShape,
onClick = {}, style = {
shape(RectangleShape)
},
) {
Text(text = "Demo")
JetsnackText(text = "Demo")
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -14,39 +14,30 @@
* limitations under the License.
*/

@file:OptIn(ExperimentalFoundationStyleApi::class)

package com.example.jetsnack.ui.components

import android.content.res.Configuration
import androidx.compose.foundation.BorderStroke
import androidx.compose.foundation.layout.padding
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Text
import androidx.compose.foundation.style.ExperimentalFoundationStyleApi
import androidx.compose.foundation.style.Style
import androidx.compose.foundation.style.then
import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.graphics.Shape
import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.Dp
import androidx.compose.ui.unit.dp
import com.example.jetsnack.ui.theme.JetsnackTheme

@Composable
fun JetsnackCard(
modifier: Modifier = Modifier,
shape: Shape = MaterialTheme.shapes.medium,
color: Color = JetsnackTheme.colors.uiBackground,
contentColor: Color = JetsnackTheme.colors.textPrimary,
border: BorderStroke? = null,
elevation: Dp = 4.dp,
style: Style = Style,
content: @Composable () -> Unit,
) {
JetsnackSurface(
modifier = modifier,
shape = shape,
color = color,
contentColor = contentColor,
elevation = elevation,
border = border,
style = JetsnackTheme.appStyles.cardStyle then style,
content = content,
)
}
Expand All @@ -58,7 +49,7 @@ fun JetsnackCard(
private fun CardPreview() {
JetsnackTheme {
JetsnackCard {
Text(text = "Demo", modifier = Modifier.padding(16.dp))
JetsnackText(text = "Demo", modifier = Modifier.padding(16.dp))
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -14,35 +14,33 @@
* limitations under the License.
*/

@file:OptIn(ExperimentalFoundationStyleApi::class)

package com.example.jetsnack.ui.components

import android.content.res.Configuration
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.size
import androidx.compose.foundation.style.ExperimentalFoundationStyleApi
import androidx.compose.foundation.style.Style
import androidx.compose.foundation.style.styleable
import androidx.compose.material3.HorizontalDivider
import androidx.compose.runtime.Composable
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.Dp
import androidx.compose.ui.unit.dp
import com.example.jetsnack.ui.theme.JetsnackTheme
import com.example.jetsnack.ui.theme.LocalAppStyles

@Composable
fun JetsnackDivider(
modifier: Modifier = Modifier,
color: Color = JetsnackTheme.colors.uiBorder.copy(alpha = DividerAlpha),
thickness: Dp = 1.dp,
style: Style = Style
) {
HorizontalDivider(
modifier = modifier,
color = color,
thickness = thickness,
)
Box(modifier = modifier.styleable(null, LocalAppStyles.current.dividerStyle, style))
}

private const val DividerAlpha = 0.12f

@Preview("default", showBackground = true)
@Preview("dark theme", uiMode = Configuration.UI_MODE_NIGHT_YES, showBackground = true)
Expand Down
Loading
Loading