M0: Floret skeleton — Material 3 Expressive scaffold over OpenTasks (planned)
All checks were successful
CI / ci (push) Successful in 6m39s
All checks were successful
CI / ci (push) Successful in 6m39s
Sibling to Calendula. Pure front-end posture; TaskContract data layer, task screens and reminder engine to follow (see docs/PLAN.md). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
11
app/src/main/java/de/jeanlucmakiola/floret/FloretApp.kt
Normal file
11
app/src/main/java/de/jeanlucmakiola/floret/FloretApp.kt
Normal file
@@ -0,0 +1,11 @@
|
||||
package de.jeanlucmakiola.floret
|
||||
|
||||
import android.app.Application
|
||||
import dagger.hilt.android.HiltAndroidApp
|
||||
|
||||
/**
|
||||
* Application entry point. Registered as android:name=".FloretApp"
|
||||
* in AndroidManifest.xml. Hilt initializes its component graph here.
|
||||
*/
|
||||
@HiltAndroidApp
|
||||
class FloretApp : Application()
|
||||
30
app/src/main/java/de/jeanlucmakiola/floret/MainActivity.kt
Normal file
30
app/src/main/java/de/jeanlucmakiola/floret/MainActivity.kt
Normal file
@@ -0,0 +1,30 @@
|
||||
package de.jeanlucmakiola.floret
|
||||
|
||||
import android.os.Bundle
|
||||
import androidx.activity.ComponentActivity
|
||||
import androidx.activity.compose.setContent
|
||||
import androidx.activity.enableEdgeToEdge
|
||||
import androidx.compose.foundation.layout.fillMaxSize
|
||||
import androidx.compose.ui.Modifier
|
||||
import dagger.hilt.android.AndroidEntryPoint
|
||||
import de.jeanlucmakiola.floret.ui.RootScreen
|
||||
import de.jeanlucmakiola.floret.ui.theme.FloretTheme
|
||||
|
||||
/**
|
||||
* Single activity. M0 hosts only a themed placeholder scaffold; the task
|
||||
* screens, theme-mode wiring (SettingsViewModel) and notification/widget
|
||||
* intent routing land in later milestones — mirroring Calendula's MainActivity.
|
||||
*/
|
||||
@AndroidEntryPoint
|
||||
class MainActivity : ComponentActivity() {
|
||||
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
enableEdgeToEdge()
|
||||
setContent {
|
||||
FloretTheme {
|
||||
RootScreen(modifier = Modifier.fillMaxSize())
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
48
app/src/main/java/de/jeanlucmakiola/floret/ui/RootScreen.kt
Normal file
48
app/src/main/java/de/jeanlucmakiola/floret/ui/RootScreen.kt
Normal file
@@ -0,0 +1,48 @@
|
||||
package de.jeanlucmakiola.floret.ui
|
||||
|
||||
import androidx.compose.foundation.layout.Arrangement
|
||||
import androidx.compose.foundation.layout.Column
|
||||
import androidx.compose.foundation.layout.fillMaxSize
|
||||
import androidx.compose.foundation.layout.padding
|
||||
import androidx.compose.material3.MaterialTheme
|
||||
import androidx.compose.material3.Scaffold
|
||||
import androidx.compose.material3.Text
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.res.stringResource
|
||||
import androidx.compose.ui.text.style.TextAlign
|
||||
import androidx.compose.ui.unit.dp
|
||||
import de.jeanlucmakiola.floret.R
|
||||
|
||||
/**
|
||||
* M0 placeholder root. Proves the theme, Hilt entry point and edge-to-edge
|
||||
* scaffold render. Replaced in M1 by the lists overview + nav host
|
||||
* (FloretHost), the analog of Calendula's CalendarHost.
|
||||
*/
|
||||
@Composable
|
||||
fun RootScreen(modifier: Modifier = Modifier) {
|
||||
Scaffold(modifier = modifier) { inner ->
|
||||
Column(
|
||||
modifier = Modifier
|
||||
.fillMaxSize()
|
||||
.padding(inner)
|
||||
.padding(24.dp),
|
||||
horizontalAlignment = Alignment.CenterHorizontally,
|
||||
verticalArrangement = Arrangement.Center,
|
||||
) {
|
||||
Text(
|
||||
text = stringResource(R.string.app_name),
|
||||
style = MaterialTheme.typography.displaySmall,
|
||||
color = MaterialTheme.colorScheme.primary,
|
||||
)
|
||||
Text(
|
||||
text = stringResource(R.string.app_tagline),
|
||||
style = MaterialTheme.typography.bodyLarge,
|
||||
color = MaterialTheme.colorScheme.onSurfaceVariant,
|
||||
textAlign = TextAlign.Center,
|
||||
modifier = Modifier.padding(top = 8.dp),
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
46
app/src/main/java/de/jeanlucmakiola/floret/ui/theme/Color.kt
Normal file
46
app/src/main/java/de/jeanlucmakiola/floret/ui/theme/Color.kt
Normal file
@@ -0,0 +1,46 @@
|
||||
package de.jeanlucmakiola.floret.ui.theme
|
||||
|
||||
import androidx.compose.material3.darkColorScheme
|
||||
import androidx.compose.material3.lightColorScheme
|
||||
import androidx.compose.ui.graphics.Color
|
||||
|
||||
/**
|
||||
* Seed color anchoring the entire palette. A warm mauve — sibling to
|
||||
* Calendula's cool slate ([0xFF5C6B7A]) and deliberately distinct from
|
||||
* HouseHoldKeaper's sage. Evokes the marigold florets a Calendula head is
|
||||
* made of, kept muted to match the family's restrained aesthetic.
|
||||
*
|
||||
* Placeholder until branding lands; refine alongside the launcher icon.
|
||||
*/
|
||||
val FloretSeed: Color = Color(0xFF7A5C6B)
|
||||
|
||||
/**
|
||||
* Fallback light scheme for devices without dynamic color (API < 31) or when
|
||||
* the user disables it. Dynamic color (API 31+) is the real path; these are a
|
||||
* hand-picked approximation of the tonal palette generated from [FloretSeed].
|
||||
*/
|
||||
val FloretLightFallback = lightColorScheme(
|
||||
primary = Color(0xFF6A4E5B),
|
||||
onPrimary = Color(0xFFFFFFFF),
|
||||
primaryContainer = Color(0xFFF6D9E5),
|
||||
onPrimaryContainer = Color(0xFF2A101C),
|
||||
secondary = Color(0xFF705560),
|
||||
onSecondary = Color(0xFFFFFFFF),
|
||||
background = Color(0xFFFEFBFC),
|
||||
onBackground = Color(0xFF1F1A1C),
|
||||
surface = Color(0xFFFEFBFC),
|
||||
onSurface = Color(0xFF1F1A1C),
|
||||
)
|
||||
|
||||
val FloretDarkFallback = darkColorScheme(
|
||||
primary = Color(0xFFE2BAC9),
|
||||
onPrimary = Color(0xFF402533),
|
||||
primaryContainer = Color(0xFF583B49),
|
||||
onPrimaryContainer = Color(0xFFF6D9E5),
|
||||
secondary = Color(0xFFD8BCC6),
|
||||
onSecondary = Color(0xFF3A2831),
|
||||
background = Color(0xFF161113),
|
||||
onBackground = Color(0xFFE9E0E3),
|
||||
surface = Color(0xFF161113),
|
||||
onSurface = Color(0xFFE9E0E3),
|
||||
)
|
||||
48
app/src/main/java/de/jeanlucmakiola/floret/ui/theme/Theme.kt
Normal file
48
app/src/main/java/de/jeanlucmakiola/floret/ui/theme/Theme.kt
Normal file
@@ -0,0 +1,48 @@
|
||||
package de.jeanlucmakiola.floret.ui.theme
|
||||
|
||||
import android.os.Build
|
||||
import androidx.compose.foundation.isSystemInDarkTheme
|
||||
import androidx.compose.material3.ExperimentalMaterial3ExpressiveApi
|
||||
import androidx.compose.material3.MaterialExpressiveTheme
|
||||
import androidx.compose.material3.MotionScheme
|
||||
import androidx.compose.material3.dynamicDarkColorScheme
|
||||
import androidx.compose.material3.dynamicLightColorScheme
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.ui.platform.LocalContext
|
||||
|
||||
/**
|
||||
* App theme. Honors:
|
||||
* - System light/dark.
|
||||
* - Dynamic Color on API 31+, else falls back to the hand-tuned scheme
|
||||
* derived from [FloretSeed].
|
||||
*
|
||||
* Mirrors Calendula's theme: MaterialExpressiveTheme routes all component +
|
||||
* custom motion through MaterialTheme.motionScheme. STANDARD over expressive()
|
||||
* is the same deliberate choice — spring choreography without the overshoot.
|
||||
*
|
||||
* A Settings screen can later override dynamicColor and theme mode; the M0
|
||||
* foundation just follows the system.
|
||||
*/
|
||||
@OptIn(ExperimentalMaterial3ExpressiveApi::class)
|
||||
@Composable
|
||||
fun FloretTheme(
|
||||
darkTheme: Boolean = isSystemInDarkTheme(),
|
||||
dynamicColor: Boolean = true,
|
||||
content: @Composable () -> Unit,
|
||||
) {
|
||||
val colorScheme = when {
|
||||
dynamicColor && Build.VERSION.SDK_INT >= Build.VERSION_CODES.S -> {
|
||||
val ctx = LocalContext.current
|
||||
if (darkTheme) dynamicDarkColorScheme(ctx) else dynamicLightColorScheme(ctx)
|
||||
}
|
||||
darkTheme -> FloretDarkFallback
|
||||
else -> FloretLightFallback
|
||||
}
|
||||
|
||||
MaterialExpressiveTheme(
|
||||
colorScheme = colorScheme,
|
||||
typography = FloretTypography,
|
||||
motionScheme = MotionScheme.standard(),
|
||||
content = content,
|
||||
)
|
||||
}
|
||||
10
app/src/main/java/de/jeanlucmakiola/floret/ui/theme/Type.kt
Normal file
10
app/src/main/java/de/jeanlucmakiola/floret/ui/theme/Type.kt
Normal file
@@ -0,0 +1,10 @@
|
||||
package de.jeanlucmakiola.floret.ui.theme
|
||||
|
||||
import androidx.compose.material3.Typography
|
||||
|
||||
/**
|
||||
* Default Material 3 Expressive typography. A custom font + tuned scale will
|
||||
* land in a later UI-design iteration; the defaults keep the M0 foundation lean
|
||||
* (same posture as Calendula's scaffolding).
|
||||
*/
|
||||
val FloretTypography = Typography()
|
||||
Reference in New Issue
Block a user