diff --git a/android/ShieldAI/app/build.gradle.kts b/android/ShieldAI/app/build.gradle.kts
index 3e9ba6b..bad07e0 100644
--- a/android/ShieldAI/app/build.gradle.kts
+++ b/android/ShieldAI/app/build.gradle.kts
@@ -4,7 +4,7 @@ plugins {
}
android {
- namespace = "com.mikefreno.shieldai"
+ namespace = "com.shieldai.android"
compileSdk {
version = release(36) {
minorApiLevel = 1
@@ -12,7 +12,7 @@ android {
}
defaultConfig {
- applicationId = "com.mikefreno.shieldai"
+ applicationId = "com.shieldai.android"
minSdk = 26
targetSdk = 36
versionCode = 1
@@ -43,6 +43,7 @@ dependencies {
implementation(libs.androidx.core.ktx)
implementation(libs.androidx.lifecycle.runtime.ktx)
implementation(libs.androidx.activity.compose)
+ implementation(libs.androidx.navigation.compose)
implementation(platform(libs.androidx.compose.bom))
implementation(libs.androidx.compose.ui)
implementation(libs.androidx.compose.ui.graphics)
@@ -56,4 +57,4 @@ dependencies {
androidTestImplementation(libs.androidx.compose.ui.test.junit4)
debugImplementation(libs.androidx.compose.ui.tooling)
debugImplementation(libs.androidx.compose.ui.test.manifest)
-}
\ No newline at end of file
+}
diff --git a/android/ShieldAI/app/src/androidTest/java/com/mikefreno/shieldai/ExampleInstrumentedTest.kt b/android/ShieldAI/app/src/androidTest/java/com/shieldai/android/ExampleInstrumentedTest.kt
similarity index 53%
rename from android/ShieldAI/app/src/androidTest/java/com/mikefreno/shieldai/ExampleInstrumentedTest.kt
rename to android/ShieldAI/app/src/androidTest/java/com/shieldai/android/ExampleInstrumentedTest.kt
index 8e2b10f..8392f02 100644
--- a/android/ShieldAI/app/src/androidTest/java/com/mikefreno/shieldai/ExampleInstrumentedTest.kt
+++ b/android/ShieldAI/app/src/androidTest/java/com/shieldai/android/ExampleInstrumentedTest.kt
@@ -1,24 +1,16 @@
-package com.mikefreno.shieldai
+package com.shieldai.android
-import androidx.test.platform.app.InstrumentationRegistry
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.runner.RunWith
-import org.junit.Assert.*
-
-/**
- * Instrumented test, which will execute on an Android device.
- *
- * See [testing documentation](http://d.android.com/tools/testing).
- */
@RunWith(AndroidJUnit4::class)
class ExampleInstrumentedTest {
@Test
fun useAppContext() {
- // Context of the app under test.
val appContext = InstrumentationRegistry.getInstrumentation().targetContext
- assertEquals("com.mikefreno.shieldai", appContext.packageName)
+ assertEquals("com.shieldai.android", appContext.packageName)
}
-}
\ No newline at end of file
+}
diff --git a/android/ShieldAI/app/src/main/AndroidManifest.xml b/android/ShieldAI/app/src/main/AndroidManifest.xml
index 0cea239..9b03a97 100644
--- a/android/ShieldAI/app/src/main/AndroidManifest.xml
+++ b/android/ShieldAI/app/src/main/AndroidManifest.xml
@@ -3,6 +3,7 @@
xmlns:tools="http://schemas.android.com/tools">
-
-
\ No newline at end of file
+
diff --git a/android/ShieldAI/app/src/main/java/com/mikefreno/shieldai/MainActivity.kt b/android/ShieldAI/app/src/main/java/com/mikefreno/shieldai/MainActivity.kt
deleted file mode 100644
index df13126..0000000
--- a/android/ShieldAI/app/src/main/java/com/mikefreno/shieldai/MainActivity.kt
+++ /dev/null
@@ -1,91 +0,0 @@
-package com.mikefreno.shieldai
-
-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.foundation.layout.padding
-import androidx.compose.material3.Icon
-import androidx.compose.material3.Scaffold
-import androidx.compose.material3.Text
-import androidx.compose.material3.adaptive.navigationsuite.NavigationSuiteScaffold
-import androidx.compose.runtime.Composable
-import androidx.compose.runtime.getValue
-import androidx.compose.runtime.mutableStateOf
-import androidx.compose.runtime.saveable.rememberSaveable
-import androidx.compose.runtime.setValue
-import androidx.compose.ui.Modifier
-import androidx.compose.ui.res.painterResource
-import androidx.compose.ui.graphics.vector.ImageVector
-import androidx.compose.ui.tooling.preview.Preview
-import androidx.compose.ui.tooling.preview.PreviewScreenSizes
-import com.mikefreno.shieldai.ui.theme.ShieldAITheme
-
-class MainActivity : ComponentActivity() {
- override fun onCreate(savedInstanceState: Bundle?) {
- super.onCreate(savedInstanceState)
- enableEdgeToEdge()
- setContent {
- ShieldAITheme {
- ShieldAIApp()
- }
- }
- }
-}
-
-@PreviewScreenSizes
-@Composable
-fun ShieldAIApp() {
- var currentDestination by rememberSaveable { mutableStateOf(AppDestinations.HOME) }
-
- NavigationSuiteScaffold(
- navigationSuiteItems = {
- AppDestinations.entries.forEach {
- item(
- icon = {
- Icon(
- painterResource(it.icon),
- contentDescription = it.label
- )
- },
- label = { Text(it.label) },
- selected = it == currentDestination,
- onClick = { currentDestination = it }
- )
- }
- }
- ) {
- Scaffold(modifier = Modifier.fillMaxSize()) { innerPadding ->
- Greeting(
- name = "Android",
- modifier = Modifier.padding(innerPadding)
- )
- }
- }
-}
-
-enum class AppDestinations(
- val label: String,
- val icon: Int,
-) {
- HOME("Home", R.drawable.ic_home),
- FAVORITES("Favorites", R.drawable.ic_favorite),
- PROFILE("Profile", R.drawable.ic_account_box),
-}
-
-@Composable
-fun Greeting(name: String, modifier: Modifier = Modifier) {
- Text(
- text = "Hello $name!",
- modifier = modifier
- )
-}
-
-@Preview(showBackground = true)
-@Composable
-fun GreetingPreview() {
- ShieldAITheme {
- Greeting("Android")
- }
-}
\ No newline at end of file
diff --git a/android/ShieldAI/app/src/main/java/com/mikefreno/shieldai/ui/theme/Color.kt b/android/ShieldAI/app/src/main/java/com/mikefreno/shieldai/ui/theme/Color.kt
deleted file mode 100644
index 3b0f6f1..0000000
--- a/android/ShieldAI/app/src/main/java/com/mikefreno/shieldai/ui/theme/Color.kt
+++ /dev/null
@@ -1,11 +0,0 @@
-package com.mikefreno.shieldai.ui.theme
-
-import androidx.compose.ui.graphics.Color
-
-val Purple80 = Color(0xFFD0BCFF)
-val PurpleGrey80 = Color(0xFFCCC2DC)
-val Pink80 = Color(0xFFEFB8C8)
-
-val Purple40 = Color(0xFF6650a4)
-val PurpleGrey40 = Color(0xFF625b71)
-val Pink40 = Color(0xFF7D5260)
\ No newline at end of file
diff --git a/android/ShieldAI/app/src/main/java/com/mikefreno/shieldai/ui/theme/Theme.kt b/android/ShieldAI/app/src/main/java/com/mikefreno/shieldai/ui/theme/Theme.kt
deleted file mode 100644
index 1685537..0000000
--- a/android/ShieldAI/app/src/main/java/com/mikefreno/shieldai/ui/theme/Theme.kt
+++ /dev/null
@@ -1,58 +0,0 @@
-package com.mikefreno.shieldai.ui.theme
-
-import android.app.Activity
-import android.os.Build
-import androidx.compose.foundation.isSystemInDarkTheme
-import androidx.compose.material3.MaterialTheme
-import androidx.compose.material3.darkColorScheme
-import androidx.compose.material3.dynamicDarkColorScheme
-import androidx.compose.material3.dynamicLightColorScheme
-import androidx.compose.material3.lightColorScheme
-import androidx.compose.runtime.Composable
-import androidx.compose.ui.platform.LocalContext
-
-private val DarkColorScheme = darkColorScheme(
- primary = Purple80,
- secondary = PurpleGrey80,
- tertiary = Pink80
-)
-
-private val LightColorScheme = lightColorScheme(
- primary = Purple40,
- secondary = PurpleGrey40,
- tertiary = Pink40
-
- /* Other default colors to override
- background = Color(0xFFFFFBFE),
- surface = Color(0xFFFFFBFE),
- onPrimary = Color.White,
- onSecondary = Color.White,
- onTertiary = Color.White,
- onBackground = Color(0xFF1C1B1F),
- onSurface = Color(0xFF1C1B1F),
- */
-)
-
-@Composable
-fun ShieldAITheme(
- darkTheme: Boolean = isSystemInDarkTheme(),
- // Dynamic color is available on Android 12+
- dynamicColor: Boolean = true,
- 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
- }
-
- MaterialTheme(
- colorScheme = colorScheme,
- typography = Typography,
- content = content
- )
-}
\ No newline at end of file
diff --git a/android/ShieldAI/app/src/main/java/com/mikefreno/shieldai/ui/theme/Type.kt b/android/ShieldAI/app/src/main/java/com/mikefreno/shieldai/ui/theme/Type.kt
deleted file mode 100644
index c85542f..0000000
--- a/android/ShieldAI/app/src/main/java/com/mikefreno/shieldai/ui/theme/Type.kt
+++ /dev/null
@@ -1,34 +0,0 @@
-package com.mikefreno.shieldai.ui.theme
-
-import androidx.compose.material3.Typography
-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.sp
-
-// Set of Material typography styles to start with
-val Typography = Typography(
- bodyLarge = TextStyle(
- fontFamily = FontFamily.Default,
- fontWeight = FontWeight.Normal,
- fontSize = 16.sp,
- lineHeight = 24.sp,
- letterSpacing = 0.5.sp
- )
- /* Other default text styles to override
- 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
- )
- */
-)
\ No newline at end of file
diff --git a/android/ShieldAI/app/src/main/java/com/shieldai/android/MainActivity.kt b/android/ShieldAI/app/src/main/java/com/shieldai/android/MainActivity.kt
new file mode 100644
index 0000000..0d7fc5e
--- /dev/null
+++ b/android/ShieldAI/app/src/main/java/com/shieldai/android/MainActivity.kt
@@ -0,0 +1,20 @@
+package com.shieldai.android
+
+import android.os.Bundle
+import androidx.activity.ComponentActivity
+import androidx.activity.compose.setContent
+import androidx.activity.enableEdgeToEdge
+import com.shieldai.android.navigation.AppNavigation
+import com.shieldai.android.ui.theme.ShieldAITheme
+
+class MainActivity : ComponentActivity() {
+ override fun onCreate(savedInstanceState: Bundle?) {
+ super.onCreate(savedInstanceState)
+ enableEdgeToEdge()
+ setContent {
+ ShieldAITheme {
+ AppNavigation()
+ }
+ }
+ }
+}
diff --git a/android/ShieldAI/app/src/main/java/com/shieldai/android/ShieldAIApp.kt b/android/ShieldAI/app/src/main/java/com/shieldai/android/ShieldAIApp.kt
new file mode 100644
index 0000000..d262e1b
--- /dev/null
+++ b/android/ShieldAI/app/src/main/java/com/shieldai/android/ShieldAIApp.kt
@@ -0,0 +1,9 @@
+package com.shieldai.android
+
+import android.app.Application
+
+class ShieldAIApp : Application() {
+ override fun onCreate() {
+ super.onCreate()
+ }
+}
diff --git a/android/ShieldAI/app/src/main/java/com/shieldai/android/navigation/AppNavigation.kt b/android/ShieldAI/app/src/main/java/com/shieldai/android/navigation/AppNavigation.kt
new file mode 100644
index 0000000..2fbb44c
--- /dev/null
+++ b/android/ShieldAI/app/src/main/java/com/shieldai/android/navigation/AppNavigation.kt
@@ -0,0 +1,47 @@
+package com.shieldai.android.navigation
+
+import androidx.compose.foundation.layout.padding
+import androidx.compose.material3.Scaffold
+import androidx.compose.runtime.Composable
+import androidx.compose.runtime.getValue
+import androidx.compose.ui.Modifier
+import androidx.navigation.compose.currentBackStackEntryAsState
+import androidx.navigation.compose.rememberNavController
+
+@Composable
+fun AppNavigation() {
+ val navController = rememberNavController()
+ val navBackStackEntry by navController.currentBackStackEntryAsState()
+ val currentRoute = navBackStackEntry?.destination?.route
+
+ val bottomNavScreens = setOf(
+ Screen.Dashboard.route,
+ Screen.Services.route,
+ Screen.Alerts.route,
+ Screen.Settings.route,
+ Screen.Account.route
+ )
+ val showBottomBar = currentRoute in bottomNavScreens
+
+ Scaffold(
+ bottomBar = {
+ if (showBottomBar) {
+ BottomNavBar(
+ currentRoute = currentRoute,
+ onNavigate = { screen ->
+ navController.navigate(screen.route) {
+ popUpTo(navController.graph.startDestinationId)
+ launchSingleTop = true
+ restoreState = true
+ }
+ }
+ )
+ }
+ }
+ ) { innerPadding ->
+ NavGraph(
+ navController = navController,
+ modifier = Modifier.padding(innerPadding)
+ )
+ }
+}
diff --git a/android/ShieldAI/app/src/main/java/com/shieldai/android/navigation/BottomNavBar.kt b/android/ShieldAI/app/src/main/java/com/shieldai/android/navigation/BottomNavBar.kt
new file mode 100644
index 0000000..e43ef71
--- /dev/null
+++ b/android/ShieldAI/app/src/main/java/com/shieldai/android/navigation/BottomNavBar.kt
@@ -0,0 +1,41 @@
+package com.shieldai.android.navigation
+
+import androidx.compose.material3.Icon
+import androidx.compose.material3.NavigationBar
+import androidx.compose.material3.NavigationBarItem
+import androidx.compose.material3.Text
+import androidx.compose.runtime.Composable
+import androidx.compose.ui.graphics.vector.ImageVector
+import androidx.compose.ui.res.vectorResource
+import com.shieldai.android.R
+
+data class BottomNavItem(
+ val screen: Screen,
+ val label: String,
+ val icon: ImageVector
+)
+
+@Composable
+fun BottomNavBar(
+ currentRoute: String?,
+ onNavigate: (Screen) -> Unit
+) {
+ val items = listOf(
+ BottomNavItem(Screen.Dashboard, "Dashboard", ImageVector.vectorResource(R.drawable.ic_dashboard)),
+ BottomNavItem(Screen.Services, "Services", ImageVector.vectorResource(R.drawable.ic_services)),
+ BottomNavItem(Screen.Alerts, "Alerts", ImageVector.vectorResource(R.drawable.ic_alerts)),
+ BottomNavItem(Screen.Settings, "Settings", ImageVector.vectorResource(R.drawable.ic_settings)),
+ BottomNavItem(Screen.Account, "Account", ImageVector.vectorResource(R.drawable.ic_account_box))
+ )
+
+ NavigationBar {
+ items.forEach { item ->
+ NavigationBarItem(
+ icon = { Icon(item.icon, contentDescription = item.label) },
+ label = { Text(item.label) },
+ selected = currentRoute == item.screen.route,
+ onClick = { onNavigate(item.screen) }
+ )
+ }
+ }
+}
diff --git a/android/ShieldAI/app/src/main/java/com/shieldai/android/navigation/NavGraph.kt b/android/ShieldAI/app/src/main/java/com/shieldai/android/navigation/NavGraph.kt
new file mode 100644
index 0000000..9c91dc7
--- /dev/null
+++ b/android/ShieldAI/app/src/main/java/com/shieldai/android/navigation/NavGraph.kt
@@ -0,0 +1,74 @@
+package com.shieldai.android.navigation
+
+import androidx.compose.foundation.layout.Box
+import androidx.compose.foundation.layout.fillMaxSize
+import androidx.compose.material3.MaterialTheme
+import androidx.compose.material3.Text
+import androidx.compose.runtime.Composable
+import androidx.compose.ui.Alignment
+import androidx.compose.ui.Modifier
+import androidx.compose.ui.text.style.TextAlign
+import androidx.navigation.NavHostController
+import androidx.navigation.NavType
+import androidx.navigation.compose.NavHost
+import androidx.navigation.compose.composable
+import androidx.navigation.navArgument
+
+@Composable
+fun NavGraph(
+ navController: NavHostController,
+ modifier: Modifier = Modifier
+) {
+ NavHost(
+ navController = navController,
+ startDestination = Screen.Dashboard.route,
+ modifier = modifier
+ ) {
+ composable(Screen.Dashboard.route) {
+ PlaceholderScreen(title = "Dashboard")
+ }
+ composable(Screen.Services.route) {
+ PlaceholderScreen(title = "Services")
+ }
+ composable(Screen.Alerts.route) {
+ PlaceholderScreen(title = "Alerts")
+ }
+ composable(Screen.Settings.route) {
+ PlaceholderScreen(title = "Settings")
+ }
+ composable(Screen.Account.route) {
+ PlaceholderScreen(title = "Account")
+ }
+ composable(Screen.Login.route) {
+ PlaceholderScreen(title = "Login")
+ }
+ composable(Screen.Signup.route) {
+ PlaceholderScreen(title = "Signup")
+ }
+ composable(Screen.Onboarding.route) {
+ PlaceholderScreen(title = "Onboarding")
+ }
+ composable(
+ route = Screen.ServiceDetail.ROUTE,
+ arguments = listOf(navArgument("serviceId") { type = NavType.StringType })
+ ) { backStackEntry ->
+ val serviceId = backStackEntry.arguments?.getString("serviceId") ?: ""
+ PlaceholderScreen(title = "Service: $serviceId")
+ }
+ }
+}
+
+@Composable
+private fun PlaceholderScreen(title: String) {
+ Box(
+ modifier = Modifier.fillMaxSize(),
+ contentAlignment = Alignment.Center
+ ) {
+ Text(
+ text = title,
+ style = MaterialTheme.typography.headlineMedium,
+ textAlign = TextAlign.Center,
+ color = MaterialTheme.colorScheme.onBackground
+ )
+ }
+}
diff --git a/android/ShieldAI/app/src/main/java/com/shieldai/android/navigation/Screen.kt b/android/ShieldAI/app/src/main/java/com/shieldai/android/navigation/Screen.kt
new file mode 100644
index 0000000..685c27d
--- /dev/null
+++ b/android/ShieldAI/app/src/main/java/com/shieldai/android/navigation/Screen.kt
@@ -0,0 +1,18 @@
+package com.shieldai.android.navigation
+
+sealed class Screen(val route: String) {
+ data object Dashboard : Screen("dashboard")
+ data object Services : Screen("services")
+ data object Alerts : Screen("alerts")
+ data object Settings : Screen("settings")
+ data object Account : Screen("account")
+ data object Login : Screen("login")
+ data object Signup : Screen("signup")
+ data object Onboarding : Screen("onboarding")
+ data class ServiceDetail(val serviceId: String) : Screen("service_detail/{serviceId}") {
+ companion object {
+ const val ROUTE = "service_detail/{serviceId}"
+ fun createRoute(serviceId: String) = "service_detail/$serviceId"
+ }
+ }
+}
diff --git a/android/ShieldAI/app/src/main/java/com/shieldai/android/ui/theme/Color.kt b/android/ShieldAI/app/src/main/java/com/shieldai/android/ui/theme/Color.kt
new file mode 100644
index 0000000..0657a80
--- /dev/null
+++ b/android/ShieldAI/app/src/main/java/com/shieldai/android/ui/theme/Color.kt
@@ -0,0 +1,37 @@
+package com.shieldai.android.ui.theme
+
+import androidx.compose.ui.graphics.Color
+
+val BrandPrimary = Color(0xFF4F46E5)
+val BrandPrimaryLight = Color(0xFF818CF8)
+val BrandPrimaryDark = Color(0xFF3730A3)
+
+val BrandAccent = Color(0xFF06B6D4)
+val BrandAccentLight = Color(0xFF67E8F9)
+val BrandAccentDark = Color(0xFF0891B2)
+
+val BgPrimaryLight = Color(0xFFFFFFFF)
+val BgSecondaryLight = Color(0xFFF8FAFC)
+val BgTertiaryLight = Color(0xFFF1F5F9)
+
+val BgPrimaryDark = Color(0xFF0F172A)
+val BgSecondaryDark = Color(0xFF1E293B)
+val BgTertiaryDark = Color(0xFF334155)
+
+val TextPrimaryLight = Color(0xFF0F172A)
+val TextSecondaryLight = Color(0xFF475569)
+val TextTertiaryLight = Color(0xFF94A3B8)
+
+val TextPrimaryDark = Color(0xFFF1F5F9)
+val TextSecondaryDark = Color(0xFF94A3B8)
+val TextTertiaryDark = Color(0xFF64748B)
+
+val Success = Color(0xFF22C55E)
+val Warning = Color(0xFFF59E0B)
+val Error = Color(0xFFEF4444)
+val Info = Color(0xFF3B82F6)
+
+val SurfaceLight = Color(0xFFFFFFFF)
+val SurfaceDark = Color(0xFF1E293B)
+val OutlineLight = Color(0xFFE2E8F0)
+val OutlineDark = Color(0xFF475569)
diff --git a/android/ShieldAI/app/src/main/java/com/shieldai/android/ui/theme/Shape.kt b/android/ShieldAI/app/src/main/java/com/shieldai/android/ui/theme/Shape.kt
new file mode 100644
index 0000000..4bb24cf
--- /dev/null
+++ b/android/ShieldAI/app/src/main/java/com/shieldai/android/ui/theme/Shape.kt
@@ -0,0 +1,11 @@
+package com.shieldai.android.ui.theme
+
+import androidx.compose.foundation.shape.RoundedCornerShape
+import androidx.compose.material3.Shapes
+import androidx.compose.ui.unit.dp
+
+val Shapes = Shapes(
+ small = RoundedCornerShape(8.dp),
+ medium = RoundedCornerShape(12.dp),
+ large = RoundedCornerShape(16.dp)
+)
diff --git a/android/ShieldAI/app/src/main/java/com/shieldai/android/ui/theme/Theme.kt b/android/ShieldAI/app/src/main/java/com/shieldai/android/ui/theme/Theme.kt
new file mode 100644
index 0000000..827fb99
--- /dev/null
+++ b/android/ShieldAI/app/src/main/java/com/shieldai/android/ui/theme/Theme.kt
@@ -0,0 +1,80 @@
+package com.shieldai.android.ui.theme
+
+import android.os.Build
+import androidx.compose.foundation.isSystemInDarkTheme
+import androidx.compose.material3.MaterialTheme
+import androidx.compose.material3.darkColorScheme
+import androidx.compose.material3.dynamicDarkColorScheme
+import androidx.compose.material3.dynamicLightColorScheme
+import androidx.compose.material3.lightColorScheme
+import androidx.compose.runtime.Composable
+import androidx.compose.ui.platform.LocalContext
+
+private val LightColorScheme = lightColorScheme(
+ primary = BrandPrimary,
+ onPrimary = BgPrimaryLight,
+ primaryContainer = BrandPrimaryLight,
+ onPrimaryContainer = BgPrimaryLight,
+ secondary = BrandAccent,
+ onSecondary = BgPrimaryLight,
+ secondaryContainer = BrandAccentLight,
+ onSecondaryContainer = BgPrimaryDark,
+ tertiary = BrandPrimaryDark,
+ onTertiary = BgPrimaryLight,
+ background = BgPrimaryLight,
+ onBackground = TextPrimaryLight,
+ surface = SurfaceLight,
+ onSurface = TextPrimaryLight,
+ surfaceVariant = BgSecondaryLight,
+ onSurfaceVariant = TextSecondaryLight,
+ outline = OutlineLight,
+ outlineVariant = BgTertiaryLight,
+ error = Error,
+ onError = BgPrimaryLight
+)
+
+private val DarkColorScheme = darkColorScheme(
+ primary = BrandPrimaryLight,
+ onPrimary = BgPrimaryDark,
+ primaryContainer = BrandPrimary,
+ onPrimaryContainer = TextPrimaryDark,
+ secondary = BrandAccentLight,
+ onSecondary = BgPrimaryDark,
+ secondaryContainer = BrandAccent,
+ onSecondaryContainer = TextPrimaryDark,
+ tertiary = BrandPrimaryDark,
+ onTertiary = TextPrimaryDark,
+ background = BgPrimaryDark,
+ onBackground = TextPrimaryDark,
+ surface = SurfaceDark,
+ onSurface = TextPrimaryDark,
+ surfaceVariant = BgSecondaryDark,
+ onSurfaceVariant = TextSecondaryDark,
+ outline = OutlineDark,
+ outlineVariant = BgTertiaryDark,
+ error = Error,
+ onError = BgPrimaryDark
+)
+
+@Composable
+fun ShieldAITheme(
+ 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
+ }
+
+ MaterialTheme(
+ colorScheme = colorScheme,
+ typography = Typography,
+ shapes = Shapes,
+ content = content
+ )
+}
diff --git a/android/ShieldAI/app/src/main/java/com/shieldai/android/ui/theme/Type.kt b/android/ShieldAI/app/src/main/java/com/shieldai/android/ui/theme/Type.kt
new file mode 100644
index 0000000..c2fb516
--- /dev/null
+++ b/android/ShieldAI/app/src/main/java/com/shieldai/android/ui/theme/Type.kt
@@ -0,0 +1,109 @@
+package com.shieldai.android.ui.theme
+
+import androidx.compose.material3.Typography
+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.sp
+
+val Typography = Typography(
+ displayLarge = TextStyle(
+ fontFamily = FontFamily.Default,
+ fontWeight = FontWeight.Bold,
+ fontSize = 57.sp,
+ lineHeight = 64.sp,
+ letterSpacing = (-0.25).sp
+ ),
+ displayMedium = TextStyle(
+ fontFamily = FontFamily.Default,
+ fontWeight = FontWeight.Bold,
+ fontSize = 45.sp,
+ lineHeight = 52.sp
+ ),
+ displaySmall = TextStyle(
+ fontFamily = FontFamily.Default,
+ fontWeight = FontWeight.Bold,
+ fontSize = 36.sp,
+ lineHeight = 44.sp
+ ),
+ headlineLarge = TextStyle(
+ fontFamily = FontFamily.Default,
+ fontWeight = FontWeight.SemiBold,
+ fontSize = 32.sp,
+ lineHeight = 40.sp
+ ),
+ headlineMedium = TextStyle(
+ fontFamily = FontFamily.Default,
+ fontWeight = FontWeight.SemiBold,
+ fontSize = 28.sp,
+ lineHeight = 36.sp
+ ),
+ headlineSmall = TextStyle(
+ fontFamily = FontFamily.Default,
+ fontWeight = FontWeight.SemiBold,
+ fontSize = 24.sp,
+ lineHeight = 32.sp
+ ),
+ titleLarge = TextStyle(
+ fontFamily = FontFamily.Default,
+ fontWeight = FontWeight.SemiBold,
+ fontSize = 22.sp,
+ lineHeight = 28.sp
+ ),
+ titleMedium = TextStyle(
+ fontFamily = FontFamily.Default,
+ fontWeight = FontWeight.Medium,
+ fontSize = 16.sp,
+ lineHeight = 24.sp,
+ letterSpacing = 0.15.sp
+ ),
+ titleSmall = TextStyle(
+ fontFamily = FontFamily.Default,
+ fontWeight = FontWeight.Medium,
+ fontSize = 14.sp,
+ lineHeight = 20.sp,
+ letterSpacing = 0.1.sp
+ ),
+ bodyLarge = TextStyle(
+ fontFamily = FontFamily.Default,
+ fontWeight = FontWeight.Normal,
+ fontSize = 16.sp,
+ lineHeight = 24.sp,
+ letterSpacing = 0.5.sp
+ ),
+ bodyMedium = TextStyle(
+ fontFamily = FontFamily.Default,
+ fontWeight = FontWeight.Normal,
+ fontSize = 14.sp,
+ lineHeight = 20.sp,
+ letterSpacing = 0.25.sp
+ ),
+ bodySmall = TextStyle(
+ fontFamily = FontFamily.Default,
+ fontWeight = FontWeight.Normal,
+ fontSize = 12.sp,
+ lineHeight = 16.sp,
+ letterSpacing = 0.4.sp
+ ),
+ labelLarge = TextStyle(
+ fontFamily = FontFamily.Default,
+ fontWeight = FontWeight.Medium,
+ fontSize = 14.sp,
+ lineHeight = 20.sp,
+ letterSpacing = 0.1.sp
+ ),
+ labelMedium = TextStyle(
+ fontFamily = FontFamily.Default,
+ fontWeight = FontWeight.Medium,
+ fontSize = 12.sp,
+ lineHeight = 16.sp,
+ letterSpacing = 0.5.sp
+ ),
+ labelSmall = TextStyle(
+ fontFamily = FontFamily.Default,
+ fontWeight = FontWeight.Medium,
+ fontSize = 11.sp,
+ lineHeight = 16.sp,
+ letterSpacing = 0.5.sp
+ )
+)
diff --git a/android/ShieldAI/app/src/main/res/drawable/ic_alerts.xml b/android/ShieldAI/app/src/main/res/drawable/ic_alerts.xml
new file mode 100644
index 0000000..1e31ffa
--- /dev/null
+++ b/android/ShieldAI/app/src/main/res/drawable/ic_alerts.xml
@@ -0,0 +1,9 @@
+
+
+
diff --git a/android/ShieldAI/app/src/main/res/drawable/ic_dashboard.xml b/android/ShieldAI/app/src/main/res/drawable/ic_dashboard.xml
new file mode 100644
index 0000000..3a07383
--- /dev/null
+++ b/android/ShieldAI/app/src/main/res/drawable/ic_dashboard.xml
@@ -0,0 +1,9 @@
+
+
+
diff --git a/android/ShieldAI/app/src/main/res/drawable/ic_favorite.xml b/android/ShieldAI/app/src/main/res/drawable/ic_favorite.xml
deleted file mode 100644
index bdd6245..0000000
--- a/android/ShieldAI/app/src/main/res/drawable/ic_favorite.xml
+++ /dev/null
@@ -1,9 +0,0 @@
-
-
-
\ No newline at end of file
diff --git a/android/ShieldAI/app/src/main/res/drawable/ic_services.xml b/android/ShieldAI/app/src/main/res/drawable/ic_services.xml
new file mode 100644
index 0000000..82ee5ba
--- /dev/null
+++ b/android/ShieldAI/app/src/main/res/drawable/ic_services.xml
@@ -0,0 +1,9 @@
+
+
+
diff --git a/android/ShieldAI/app/src/main/res/drawable/ic_settings.xml b/android/ShieldAI/app/src/main/res/drawable/ic_settings.xml
new file mode 100644
index 0000000..018f673
--- /dev/null
+++ b/android/ShieldAI/app/src/main/res/drawable/ic_settings.xml
@@ -0,0 +1,9 @@
+
+
+
diff --git a/android/ShieldAI/app/src/main/res/values/colors.xml b/android/ShieldAI/app/src/main/res/values/colors.xml
index f8c6127..c32b548 100644
--- a/android/ShieldAI/app/src/main/res/values/colors.xml
+++ b/android/ShieldAI/app/src/main/res/values/colors.xml
@@ -1,10 +1,14 @@
- #FFBB86FC
- #FF6200EE
- #FF3700B3
- #FF03DAC5
- #FF018786
- #FF000000
- #FFFFFFFF
-
\ No newline at end of file
+ #FF4F46E5
+ #FF818CF8
+ #FF06B6D4
+ #FFFFFFFF
+ #FF0F172A
+ #FF0F172A
+ #FFF1F5F9
+ #FF22C55E
+ #FFF59E0B
+ #FFEF4444
+ #FF3B82F6
+
diff --git a/android/ShieldAI/app/src/main/res/values/strings.xml b/android/ShieldAI/app/src/main/res/values/strings.xml
index 2994f3d..27135d5 100644
--- a/android/ShieldAI/app/src/main/res/values/strings.xml
+++ b/android/ShieldAI/app/src/main/res/values/strings.xml
@@ -1,3 +1,3 @@
ShieldAI
-
\ No newline at end of file
+
diff --git a/android/ShieldAI/app/src/main/res/values/themes.xml b/android/ShieldAI/app/src/main/res/values/themes.xml
index 2549da6..cfa19dc 100644
--- a/android/ShieldAI/app/src/main/res/values/themes.xml
+++ b/android/ShieldAI/app/src/main/res/values/themes.xml
@@ -1,5 +1,4 @@
-
-
\ No newline at end of file
+
diff --git a/android/ShieldAI/app/src/test/java/com/mikefreno/shieldai/ExampleUnitTest.kt b/android/ShieldAI/app/src/test/java/com/mikefreno/shieldai/ExampleUnitTest.kt
deleted file mode 100644
index 6235b32..0000000
--- a/android/ShieldAI/app/src/test/java/com/mikefreno/shieldai/ExampleUnitTest.kt
+++ /dev/null
@@ -1,17 +0,0 @@
-package com.mikefreno.shieldai
-
-import org.junit.Test
-
-import org.junit.Assert.*
-
-/**
- * Example local unit test, which will execute on the development machine (host).
- *
- * See [testing documentation](http://d.android.com/tools/testing).
- */
-class ExampleUnitTest {
- @Test
- fun addition_isCorrect() {
- assertEquals(4, 2 + 2)
- }
-}
\ No newline at end of file
diff --git a/android/ShieldAI/app/src/test/java/com/shieldai/android/ExampleUnitTest.kt b/android/ShieldAI/app/src/test/java/com/shieldai/android/ExampleUnitTest.kt
new file mode 100644
index 0000000..e291412
--- /dev/null
+++ b/android/ShieldAI/app/src/test/java/com/shieldai/android/ExampleUnitTest.kt
@@ -0,0 +1,11 @@
+package com.shieldai.android
+
+import org.junit.Assert.assertEquals
+import org.junit.Test
+
+class ExampleUnitTest {
+ @Test
+ fun addition_isCorrect() {
+ assertEquals(4, 2 + 2)
+ }
+}
diff --git a/android/ShieldAI/gradle/libs.versions.toml b/android/ShieldAI/gradle/libs.versions.toml
index 94e9fb0..44af5c8 100644
--- a/android/ShieldAI/gradle/libs.versions.toml
+++ b/android/ShieldAI/gradle/libs.versions.toml
@@ -6,6 +6,7 @@ junitVersion = "1.1.5"
espressoCore = "3.5.1"
lifecycleRuntimeKtx = "2.6.1"
activityCompose = "1.8.0"
+navigationCompose = "2.7.7"
kotlin = "2.2.10"
composeBom = "2025.12.00"
@@ -16,6 +17,7 @@ androidx-junit = { group = "androidx.test.ext", name = "junit", version.ref = "j
androidx-espresso-core = { group = "androidx.test.espresso", name = "espresso-core", version.ref = "espressoCore" }
androidx-lifecycle-runtime-ktx = { group = "androidx.lifecycle", name = "lifecycle-runtime-ktx", version.ref = "lifecycleRuntimeKtx" }
androidx-activity-compose = { group = "androidx.activity", name = "activity-compose", version.ref = "activityCompose" }
+androidx-navigation-compose = { group = "androidx.navigation", name = "navigation-compose", version.ref = "navigationCompose" }
androidx-compose-bom = { group = "androidx.compose", name = "compose-bom", version.ref = "composeBom" }
androidx-compose-ui = { group = "androidx.compose.ui", name = "ui" }
androidx-compose-ui-graphics = { group = "androidx.compose.ui", name = "ui-graphics" }