Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Main #92

Merged
merged 17 commits into from
Jan 24, 2025
Merged

Main #92

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
6 changes: 6 additions & 0 deletions .idea/git_toolbox_blame.xml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions .idea/gradle.xml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 3 additions & 0 deletions .idea/inspectionProfiles/Project_Default.xml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

17 changes: 17 additions & 0 deletions .idea/runConfigurations.xml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 0 additions & 2 deletions README.MD
Original file line number Diff line number Diff line change
Expand Up @@ -45,8 +45,6 @@ note on changes:
- Switch build files to KTS, also build some custom plugins.
- Use lifecycle events from Google (we use our own now)
- Use preview light dark from google (we use our own now)
- Optionally: Setup proper Typography in AppTheme, using custom (non-material) Typography keys,
because that is what we have in 90%+ of our projects.
- Optionally: Add compose events from VM to
View (https://github.com/leonard-palm/compose-state-events) and showcase with snackbar or toast.
- Optionally: Switch from retrofit to ktor (because Ktor is multiplatform)
Expand Down
7 changes: 4 additions & 3 deletions app/src/main/kotlin/nl/q42/template/MainActivity.kt
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,12 @@ import androidx.activity.ComponentActivity
import androidx.activity.compose.setContent
import androidx.compose.animation.ExperimentalAnimationApi
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Surface
import androidx.compose.ui.Modifier
import androidx.navigation.compose.rememberNavController
import dagger.hilt.android.AndroidEntryPoint
import nl.q42.template.navigation.AppNavigation
import nl.q42.template.navigation.NavGraphs
import nl.q42.template.ui.compose.composables.widgets.AppSurface
import nl.q42.template.ui.theme.AppTheme

@AndroidEntryPoint
Expand All @@ -26,7 +25,9 @@ class MainActivity : ComponentActivity() {

val navController = rememberNavController()

Surface(modifier = Modifier.fillMaxSize(), color = MaterialTheme.colorScheme.background) {
AppSurface (
modifier = Modifier.fillMaxSize(),
) {
AppNavigation(navController = navController, navGraph = NavGraphs.root)
}
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
package nl.q42.template.ui.compose.composables.text

import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.ui.graphics.Color
import nl.q42.template.ui.theme.AppTheme
import nl.q42.template.ui.theme.PreviewLightDark

@Composable
fun BodyText(text: String, color: Color = AppTheme.colors.textPrimary) {
Text(
text = text,
color = color,
style = AppTheme.typography.body
)
}

@Composable
@PreviewLightDark
private fun BodyTextPreview() {
AppTheme {
BodyText("Body text")
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
package nl.q42.template.ui.compose.composables.text

import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.ui.graphics.Color
import nl.q42.template.ui.theme.AppTheme
import nl.q42.template.ui.theme.PreviewLightDark

@Composable
fun H1Text(text: String, color: Color = AppTheme.colors.textPrimary) {
Text(
text = text,
color = color,
style = AppTheme.typography.h1
)
}

@Composable
@PreviewLightDark
private fun H1TextPreview() {
AppTheme {
H1Text("H1 text")
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
package nl.q42.template.ui.compose.composables.widgets

import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.material3.Surface
import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
import nl.q42.template.ui.theme.AppTheme
import nl.q42.template.ui.theme.PreviewLightDark

@Composable
fun AppSurface(modifier: Modifier = Modifier, content: @Composable () -> Unit) {
Surface(
modifier = modifier,
color = AppTheme.colors.surface,
contentColor = AppTheme.colors.textPrimary,
content = content
)
}

@Composable
@PreviewLightDark
private fun AppSurfacePreview() {
AppTheme {
AppSurface(Modifier.fillMaxSize()) {}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
package nl.q42.template.ui.compose.composables.widgets

import androidx.compose.material3.Button
import androidx.compose.material3.ButtonDefaults
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import nl.q42.template.ui.theme.AppTheme
import nl.q42.template.ui.theme.PreviewLightDark

@Composable
fun TemplateButton(text: String, enabled: Boolean = true, onClick: () -> Unit) {
Button(
onClick = onClick,
enabled = enabled,
colors = ButtonDefaults.buttonColors(
containerColor = AppTheme.colors.accent,
contentColor = AppTheme.colors.buttonText,
disabledContentColor = AppTheme.colors.buttonText.copy(alpha = 0.5f),
disabledContainerColor = AppTheme.colors.accent.copy(alpha = 0.5f)
)
) {
Text(
text = text,
style = AppTheme.typography.body,
color = AppTheme.colors.buttonText
)
}
}

@Composable
@PreviewLightDark
private fun TemplateButtonPreview() {
AppTheme {
TemplateButton("Button",) {}
}
}
12 changes: 12 additions & 0 deletions core/ui/src/main/kotlin/nl/q42/template/ui/theme/AppColorScheme.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
package nl.q42.template.ui.theme

import androidx.compose.ui.graphics.Color

interface AppColorScheme {
val buttonText: Color
val accent: Color
val textPrimary: Color
val surface: Color
val surfaceSelected: Color
val error: Color
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
package nl.q42.template.ui.theme

import androidx.compose.ui.graphics.Color

object AppColorSchemeDark: AppColorScheme {
override val buttonText: Color = White
override val accent: Color = PurpleGrey80
override val textPrimary = White
override val surface = Black
override val surfaceSelected = White
override val error = Pink80
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
package nl.q42.template.ui.theme

import androidx.compose.ui.graphics.Color

object AppColorSchemeLight : AppColorScheme {
override val buttonText: Color = White
override val accent: Color = Purple40
override val textPrimary = Black
override val surface = White
override val surfaceSelected = Gray10
override val error: Color = Red80
}
31 changes: 31 additions & 0 deletions core/ui/src/main/kotlin/nl/q42/template/ui/theme/AppRipples.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
package nl.q42.template.ui.theme

import androidx.compose.foundation.Indication
import androidx.compose.material.ripple.RippleAlpha
import androidx.compose.material3.RippleConfiguration
import androidx.compose.material3.ripple
import androidx.compose.runtime.Composable
import androidx.compose.runtime.ReadOnlyComposable
import androidx.compose.ui.graphics.Color

val AppRippleConfiguration: RippleConfiguration
@Composable
@ReadOnlyComposable
get() = RippleConfiguration(
color = AppTheme.colors.surfaceSelected
)

val NoRippleConfiguration: RippleConfiguration
@Composable
@ReadOnlyComposable
get() = RippleConfiguration(
color = Color.Transparent,
rippleAlpha = RippleAlpha(0.0f, 0.0f, 0.0f, 0.0f)
)

val AppRipple: Indication
@Composable
@ReadOnlyComposable
get() = ripple(
color = AppTheme.colors.surfaceSelected
)
13 changes: 13 additions & 0 deletions core/ui/src/main/kotlin/nl/q42/template/ui/theme/AppShapes.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
package nl.q42.template.ui.theme

import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.runtime.Immutable
import androidx.compose.ui.graphics.Shape
import androidx.compose.ui.unit.dp

@Immutable
data class AppShapes(
val small: Shape = RoundedCornerShape(8.dp),
val medium: Shape = RoundedCornerShape(16.dp),
val large: Shape = RoundedCornerShape(20.dp)
)
94 changes: 94 additions & 0 deletions core/ui/src/main/kotlin/nl/q42/template/ui/theme/AppTheme.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
package nl.q42.template.ui.theme

import android.annotation.SuppressLint
import android.app.Activity
import androidx.compose.foundation.LocalIndication
import androidx.compose.foundation.clickable
import androidx.compose.foundation.isSystemInDarkTheme
import androidx.compose.material3.LocalContentColor
import androidx.compose.material3.LocalRippleConfiguration
import androidx.compose.material3.LocalTextStyle
import androidx.compose.material3.ProvideTextStyle
import androidx.compose.material3.Scaffold
import androidx.compose.runtime.Composable
import androidx.compose.runtime.CompositionLocalProvider
import androidx.compose.runtime.ReadOnlyComposable
import androidx.compose.runtime.SideEffect
import androidx.compose.runtime.staticCompositionLocalOf
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.toArgb
import androidx.compose.ui.platform.LocalView
import androidx.core.view.WindowCompat
import nl.q42.template.ui.compose.composables.widgets.AppSurface

/**
* Generate this using: https://m2.material.io/material-theme-builder/. For more info and resources: see the
* README file of our project.
*/

private val LocalAppTypography = staticCompositionLocalOf { AppTypography() }
private val LocalAppColorScheme = staticCompositionLocalOf<AppColorScheme> {
// Dummy default, will be replaced for the actual tokens by the Provider
AppColorSchemeLight
}
private val LocalAppShapes = staticCompositionLocalOf { AppShapes() }

@Composable
fun AppTheme(
darkTheme: Boolean = isSystemInDarkTheme(),
typography: AppTypography = AppTheme.typography,
colors: AppColorScheme = AppTheme.colors,
shapes: AppShapes = AppTheme.shapes,
content: @Composable () -> Unit
) {
// status bar color
val view = LocalView.current
if (!view.isInEditMode) {
SideEffect {
val window = (view.context as Activity).window
window.statusBarColor = colors.accent.toArgb()
WindowCompat.getInsetsController(window, view).isAppearanceLightStatusBars = darkTheme
}
}

CompositionLocalProvider(
LocalAppTypography provides typography,
LocalAppColorScheme provides if (darkTheme) AppColorSchemeDark else AppColorSchemeLight,
LocalAppShapes provides shapes,
/** configures the ripple for material components */
LocalRippleConfiguration provides AppRippleConfiguration,
/** needed for non-material components to have a material ripple. eg [Modifier.clickable] */
LocalIndication provides AppRipple,
/** merges the platform style with our type, @see [ProvideTextStyle] for more context */
LocalTextStyle provides LocalTextStyle.current.merge(typography.body),
LocalContentColor provides colors.textPrimary,
content = content
)
}

object AppTheme {
val typography: AppTypography
@Composable
@ReadOnlyComposable
get() = LocalAppTypography.current
val colors: AppColorScheme
@Composable
@ReadOnlyComposable
get() = LocalAppColorScheme.current
val shapes: AppShapes
@Composable
@ReadOnlyComposable
get() = LocalAppShapes.current
}

@SuppressLint("UnusedMaterial3ScaffoldPaddingParameter")
@Composable
fun PreviewAppTheme(content: @Composable () -> Unit) {
AppTheme {
Scaffold {
AppSurface {
content()
}
}
}
}
Loading