feat/#24 WebOS Completion (#25)

#24 WebOS Completion

Co-authored-by: Sayan Datta <sayan@Sayans-MacBook-Air.local>
Reviewed-on: sagnik/Project_Velocity#25
This commit is contained in:
2026-04-18 18:59:04 +05:30
parent 857e0b88e6
commit 84e439712c
459 changed files with 11713 additions and 3853 deletions

View File

@@ -0,0 +1,60 @@
plugins {
id("com.android.application")
id("org.jetbrains.kotlin.android")
id("org.jetbrains.kotlin.plugin.compose")
}
android {
namespace = "com.desineuron.velocity.edgephone"
compileSdk = 35
defaultConfig {
applicationId = "com.desineuron.velocity.edgephone"
minSdk = 28
targetSdk = 35
versionCode = 1
versionName = "1.0.0"
testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"
}
buildTypes {
release {
isMinifyEnabled = false
proguardFiles(
getDefaultProguardFile("proguard-android-optimize.txt"),
"proguard-rules.pro",
)
}
}
compileOptions {
sourceCompatibility = JavaVersion.VERSION_17
targetCompatibility = JavaVersion.VERSION_17
}
kotlinOptions {
jvmTarget = "17"
}
buildFeatures {
compose = true
}
}
dependencies {
val composeBom = platform("androidx.compose:compose-bom:2025.02.00")
implementation(composeBom)
androidTestImplementation(composeBom)
implementation("androidx.core:core-ktx:1.15.0")
implementation("androidx.activity:activity-compose:1.10.1")
implementation("androidx.lifecycle:lifecycle-runtime-ktx:2.8.7")
implementation("androidx.navigation:navigation-compose:2.8.5")
implementation("androidx.compose.material3:material3")
implementation("androidx.compose.ui:ui")
implementation("androidx.compose.ui:ui-tooling-preview")
debugImplementation("androidx.compose.ui:ui-tooling")
}

View File

@@ -0,0 +1 @@
# MVP scaffold: no custom rules yet.

View File

@@ -0,0 +1,17 @@
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
<application
android:allowBackup="true"
android:label="Velocity Edge"
android:supportsRtl="true"
android:theme="@android:style/Theme.DeviceDefault.NoActionBar">
<activity
android:name=".MainActivity"
android:exported="true">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
</manifest>

View File

@@ -0,0 +1,96 @@
package com.desineuron.velocity.edgephone
import android.os.Bundle
import androidx.activity.ComponentActivity
import androidx.activity.compose.setContent
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Surface
import androidx.compose.runtime.Composable
import androidx.compose.runtime.getValue
import androidx.navigation.NavDestination.Companion.hierarchy
import androidx.navigation.NavGraph.Companion.findStartDestination
import androidx.navigation.compose.NavHost
import androidx.navigation.compose.composable
import androidx.navigation.compose.currentBackStackEntryAsState
import androidx.navigation.compose.rememberNavController
import androidx.compose.material3.NavigationBar
import androidx.compose.material3.NavigationBarItem
import androidx.compose.material3.Scaffold
import androidx.compose.material3.Text
import androidx.compose.ui.Modifier
import com.desineuron.velocity.edgephone.features.AlertsScreen
import com.desineuron.velocity.edgephone.features.CommunicationsScreen
import com.desineuron.velocity.edgephone.features.LeadSummaryScreen
import com.desineuron.velocity.edgephone.features.NotesScreen
import com.desineuron.velocity.edgephone.features.SettingsScreen
import com.desineuron.velocity.edgephone.features.TranscriptionsScreen
import com.desineuron.velocity.edgephone.ui.theme.VelocityEdgePhoneTheme
class MainActivity : ComponentActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContent {
VelocityEdgePhoneTheme {
Surface(modifier = Modifier.fillMaxSize(), color = MaterialTheme.colorScheme.background) {
EdgePhoneApp()
}
}
}
}
}
private data class PhoneDestination(val route: String, val label: String)
private val phoneDestinations = listOf(
PhoneDestination("alerts", "Alerts"),
PhoneDestination("lead-summary", "Lead"),
PhoneDestination("communications", "Comms"),
PhoneDestination("notes", "Notes"),
PhoneDestination("transcriptions", "Transcripts"),
PhoneDestination("settings", "Settings"),
)
@Composable
private fun EdgePhoneApp() {
val navController = rememberNavController()
val backStackEntry by navController.currentBackStackEntryAsState()
val currentDestination = backStackEntry?.destination
Scaffold(
bottomBar = {
NavigationBar {
phoneDestinations.forEach { destination ->
val selected = currentDestination?.hierarchy?.any { it.route == destination.route } == true
NavigationBarItem(
selected = selected,
onClick = {
navController.navigate(destination.route) {
popUpTo(navController.graph.findStartDestination().id) {
saveState = true
}
launchSingleTop = true
restoreState = true
}
},
icon = {},
label = { Text(destination.label) },
)
}
}
},
) { innerPadding ->
NavHost(
navController = navController,
startDestination = "alerts",
modifier = Modifier.fillMaxSize(),
) {
composable("alerts") { AlertsScreen(innerPadding) }
composable("lead-summary") { LeadSummaryScreen(innerPadding) }
composable("communications") { CommunicationsScreen(innerPadding) }
composable("notes") { NotesScreen(innerPadding) }
composable("transcriptions") { TranscriptionsScreen(innerPadding) }
composable("settings") { SettingsScreen(innerPadding) }
}
}
}

View File

@@ -0,0 +1,14 @@
package com.desineuron.velocity.edgephone.features
import androidx.compose.foundation.layout.PaddingValues
import androidx.compose.runtime.Composable
@Composable
fun AlertsScreen(paddingValues: PaddingValues) {
PhoneScaffold(
paddingValues = paddingValues,
title = "Alerts",
subtitle = "High-urgency nudges for unread responses, callbacks, and showroom events.",
actionLabel = "Respond to whale-lead unread thread",
)
}

View File

@@ -0,0 +1,14 @@
package com.desineuron.velocity.edgephone.features
import androidx.compose.foundation.layout.PaddingValues
import androidx.compose.runtime.Composable
@Composable
fun CommunicationsScreen(paddingValues: PaddingValues) {
PhoneScaffold(
paddingValues = paddingValues,
title = "Communications",
subtitle = "Call, WhatsApp, and operator-import touchpoints on a single edge rail.",
actionLabel = "Log a manual note after callback",
)
}

View File

@@ -0,0 +1,14 @@
package com.desineuron.velocity.edgephone.features
import androidx.compose.foundation.layout.PaddingValues
import androidx.compose.runtime.Composable
@Composable
fun LeadSummaryScreen(paddingValues: PaddingValues) {
PhoneScaffold(
paddingValues = paddingValues,
title = "Lead Summary",
subtitle = "Compact account memory, qualification, and next-best action.",
actionLabel = "Review Mohammed Al-Rashid context",
)
}

View File

@@ -0,0 +1,14 @@
package com.desineuron.velocity.edgephone.features
import androidx.compose.foundation.layout.PaddingValues
import androidx.compose.runtime.Composable
@Composable
fun NotesScreen(paddingValues: PaddingValues) {
PhoneScaffold(
paddingValues = paddingValues,
title = "Notes",
subtitle = "Fast capture for memory facts, objections, and promised follow-ups.",
actionLabel = "Create note with memory extraction hint",
)
}

View File

@@ -0,0 +1,52 @@
package com.desineuron.velocity.edgephone.features
import androidx.compose.foundation.background
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.PaddingValues
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.unit.dp
@Composable
fun PhoneScaffold(
paddingValues: PaddingValues,
title: String,
subtitle: String,
actionLabel: String,
) {
Column(
modifier = Modifier
.fillMaxSize()
.background(Color(0xFF05070B))
.padding(paddingValues)
.padding(18.dp),
verticalArrangement = Arrangement.spacedBy(16.dp),
) {
Text(title, style = MaterialTheme.typography.headlineSmall, color = Color.White)
Text(subtitle, style = MaterialTheme.typography.bodyMedium, color = Color(0xFF94A3B8))
Column(
modifier = Modifier
.fillMaxWidth()
.background(Color(0xFF0B1220), RoundedCornerShape(24.dp))
.padding(18.dp),
verticalArrangement = Arrangement.spacedBy(10.dp),
) {
Text("Edge action", style = MaterialTheme.typography.labelLarge, color = Color(0xFF38BDF8))
Text(actionLabel, style = MaterialTheme.typography.titleMedium, color = Color.White)
Text(
"This narrow surface is ready for backend hookup to `/api/mobile-edge` once auth and install registration are connected.",
style = MaterialTheme.typography.bodySmall,
color = Color(0xFF94A3B8),
)
}
}
}

View File

@@ -0,0 +1,14 @@
package com.desineuron.velocity.edgephone.features
import androidx.compose.foundation.layout.PaddingValues
import androidx.compose.runtime.Composable
@Composable
fun SettingsScreen(paddingValues: PaddingValues) {
PhoneScaffold(
paddingValues = paddingValues,
title = "Settings",
subtitle = "Install registration, operator identity, and API connection state.",
actionLabel = "Verify surface heartbeat and app version",
)
}

View File

@@ -0,0 +1,14 @@
package com.desineuron.velocity.edgephone.features
import androidx.compose.foundation.layout.PaddingValues
import androidx.compose.runtime.Composable
@Composable
fun TranscriptionsScreen(paddingValues: PaddingValues) {
PhoneScaffold(
paddingValues = paddingValues,
title = "Transcriptions",
subtitle = "Imported voice artifacts and segment-level summaries for the field operator.",
actionLabel = "Review pending recording import",
)
}

View File

@@ -0,0 +1,26 @@
package com.desineuron.velocity.edgephone.ui.theme
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.darkColorScheme
import androidx.compose.runtime.Composable
import androidx.compose.ui.graphics.Color
private val EdgeColors = darkColorScheme(
primary = Color(0xFF38BDF8),
secondary = Color(0xFF14B8A6),
tertiary = Color(0xFF22C55E),
background = Color(0xFF05070B),
surface = Color(0xFF0B1220),
onPrimary = Color.White,
onSecondary = Color.White,
onBackground = Color.White,
onSurface = Color.White,
)
@Composable
fun VelocityEdgePhoneTheme(content: @Composable () -> Unit) {
MaterialTheme(
colorScheme = EdgeColors,
content = content,
)
}

View File

@@ -0,0 +1,5 @@
plugins {
id("com.android.application") version "8.7.3" apply false
id("org.jetbrains.kotlin.android") version "2.0.21" apply false
id("org.jetbrains.kotlin.plugin.compose") version "2.0.21" apply false
}

View File

@@ -0,0 +1,4 @@
org.gradle.jvmargs=-Xmx2048m -Dfile.encoding=UTF-8
android.useAndroidX=true
kotlin.code.style=official
android.nonTransitiveRClass=true

View File

@@ -0,0 +1,18 @@
pluginManagement {
repositories {
google()
mavenCentral()
gradlePluginPortal()
}
}
dependencyResolutionManagement {
repositoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_REPOS)
repositories {
google()
mavenCentral()
}
}
rootProject.name = "velocity-android-edge-phone"
include(":app")