implement dark mode, force app to LTR

This commit is contained in:
2026-05-06 07:46:14 +03:30
parent 76da41654e
commit 8b5b07e71c
10 changed files with 126 additions and 36 deletions

View File

@@ -11,7 +11,7 @@
android:icon="@mipmap/ic_launcher" android:icon="@mipmap/ic_launcher"
android:label="@string/app_name" android:label="@string/app_name"
android:roundIcon="@mipmap/ic_launcher_round" android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true" android:supportsRtl="false"
android:theme="@style/Theme.PostHUB"> android:theme="@style/Theme.PostHUB">
<activity <activity
android:name=".MainActivity" android:name=".MainActivity"

View File

@@ -5,9 +5,11 @@ import android.graphics.BitmapFactory
import android.net.Uri import android.net.Uri
import android.os.Bundle import android.os.Bundle
import android.util.Base64 import android.util.Base64
import android.view.View
import androidx.activity.ComponentActivity import androidx.activity.ComponentActivity
import androidx.activity.compose.setContent import androidx.activity.compose.setContent
import androidx.activity.enableEdgeToEdge import androidx.activity.enableEdgeToEdge
import androidx.compose.foundation.isSystemInDarkTheme
import androidx.compose.foundation.BorderStroke import androidx.compose.foundation.BorderStroke
import androidx.compose.foundation.Image import androidx.compose.foundation.Image
import androidx.compose.foundation.background import androidx.compose.foundation.background
@@ -56,6 +58,7 @@ import androidx.compose.material3.SwitchDefaults
import androidx.compose.material3.Text import androidx.compose.material3.Text
import androidx.compose.material3.TextButton import androidx.compose.material3.TextButton
import androidx.compose.runtime.Composable import androidx.compose.runtime.Composable
import androidx.compose.runtime.CompositionLocalProvider
import androidx.compose.runtime.getValue import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember import androidx.compose.runtime.remember
@@ -69,6 +72,7 @@ import androidx.compose.ui.graphics.Color
import androidx.compose.ui.graphics.asImageBitmap import androidx.compose.ui.graphics.asImageBitmap
import androidx.compose.ui.layout.ContentScale import androidx.compose.ui.layout.ContentScale
import androidx.compose.ui.platform.LocalContext import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.platform.LocalLayoutDirection
import androidx.compose.ui.text.TextStyle import androidx.compose.ui.text.TextStyle
import androidx.compose.ui.text.font.FontFamily import androidx.compose.ui.text.font.FontFamily
import androidx.compose.ui.text.font.FontWeight import androidx.compose.ui.text.font.FontWeight
@@ -76,6 +80,7 @@ import androidx.compose.ui.text.input.PasswordVisualTransformation
import androidx.compose.ui.text.style.TextOverflow import androidx.compose.ui.text.style.TextOverflow
import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.Dp import androidx.compose.ui.unit.Dp
import androidx.compose.ui.unit.LayoutDirection
import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp import androidx.compose.ui.unit.sp
import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.Dispatchers
@@ -102,20 +107,31 @@ private const val EnvironmentKey = "environment_variables"
private const val FlowKey = "request_flow" private const val FlowKey = "request_flow"
private object AppColors { private object AppColors {
val Canvas = Color(0xFFF5F7F4) private val darkMode = mutableStateOf(false)
val Panel = Color(0xFFFFFFFF)
val PanelSoft = Color(0xFFF0F4F1) fun useDarkTheme(enabled: Boolean) {
val Ink = Color(0xFF17201C) if (darkMode.value != enabled) {
val Muted = Color(0xFF66736D) darkMode.value = enabled
val Border = Color(0xFFDDE4DF) }
val Primary = Color(0xFF006B5B) }
val PrimarySoft = Color(0xFFE3F4EF)
val Coral = Color(0xFFD84B35) private val isDark: Boolean get() = darkMode.value
val Amber = Color(0xFFC47A12)
val Green = Color(0xFF147A56) val Canvas: Color get() = if (isDark) Color(0xFF0E1513) else Color(0xFFF5F7F4)
val Red = Color(0xFFC7383D) val Panel: Color get() = if (isDark) Color(0xFF151D1A) else Color(0xFFFFFFFF)
val Code = Color(0xFF101715) val PanelSoft: Color get() = if (isDark) Color(0xFF1C2824) else Color(0xFFF0F4F1)
val CodeText = Color(0xFFEAF3EF) val Ink: Color get() = if (isDark) Color(0xFFEAF3EF) else Color(0xFF17201C)
val Muted: Color get() = if (isDark) Color(0xFFA2B2AB) else Color(0xFF66736D)
val Border: Color get() = if (isDark) Color(0xFF2E3B36) else Color(0xFFDDE4DF)
val Primary: Color get() = if (isDark) Color(0xFF5FE0C5) else Color(0xFF006B5B)
val OnPrimary: Color get() = if (isDark) Color(0xFF05201B) else Color.White
val PrimarySoft: Color get() = if (isDark) Color(0xFF14382F) else Color(0xFFE3F4EF)
val Coral: Color get() = if (isDark) Color(0xFFFF9A83) else Color(0xFFD84B35)
val Amber: Color get() = if (isDark) Color(0xFFE8B660) else Color(0xFFC47A12)
val Green: Color get() = if (isDark) Color(0xFF68D8A7) else Color(0xFF147A56)
val Red: Color get() = if (isDark) Color(0xFFFF8A8F) else Color(0xFFC7383D)
val Code: Color get() = if (isDark) Color(0xFF07100D) else Color(0xFF101715)
val CodeText: Color get() = Color(0xFFEAF3EF)
} }
private data class RequestField( private data class RequestField(
@@ -214,7 +230,7 @@ private data class FlowRunEntry(
val savedVariables: Int = 0 val savedVariables: Int = 0
) )
private val AppSections = listOf( private fun appSections() = listOf(
AppSection("request", "Request", "Composer", AppColors.Primary), AppSection("request", "Request", "Composer", AppColors.Primary),
AppSection("clients", "Clients", "MCI TCI", AppColors.Coral), AppSection("clients", "Clients", "MCI TCI", AppColors.Coral),
AppSection("flow", "Flow", "Sequence", AppColors.Amber), AppSection("flow", "Flow", "Sequence", AppColors.Amber),
@@ -226,14 +242,20 @@ class MainActivity : ComponentActivity() {
override fun onCreate(savedInstanceState: Bundle?) { override fun onCreate(savedInstanceState: Bundle?) {
setTheme(R.style.Theme_PostHUB) setTheme(R.style.Theme_PostHUB)
super.onCreate(savedInstanceState) super.onCreate(savedInstanceState)
window.decorView.layoutDirection = View.LAYOUT_DIRECTION_LTR
window.decorView.textDirection = View.TEXT_DIRECTION_LTR
enableEdgeToEdge() enableEdgeToEdge()
setContent { setContent {
PostHUBTheme(dynamicColor = false) { val darkTheme = isSystemInDarkTheme()
AppColors.useDarkTheme(darkTheme)
PostHUBTheme(darkTheme = darkTheme, dynamicColor = false) {
CompositionLocalProvider(LocalLayoutDirection provides LayoutDirection.Ltr) {
ApiClientApp() ApiClientApp()
} }
} }
} }
} }
}
@Composable @Composable
private fun ApiClientApp() { private fun ApiClientApp() {
@@ -617,6 +639,8 @@ private fun AppHomeHeader(
variables: Int, variables: Int,
onSectionChange: (String) -> Unit onSectionChange: (String) -> Unit
) { ) {
val sections = appSections()
PanelSurface { PanelSurface {
Column(verticalArrangement = Arrangement.spacedBy(14.dp)) { Column(verticalArrangement = Arrangement.spacedBy(14.dp)) {
Row( Row(
@@ -630,8 +654,8 @@ private fun AppHomeHeader(
) { ) {
Surface( Surface(
shape = RoundedCornerShape(8.dp), shape = RoundedCornerShape(8.dp),
color = AppColors.Ink, color = AppColors.Primary,
contentColor = Color.White contentColor = AppColors.OnPrimary
) { ) {
Text( Text(
text = "PH", text = "PH",
@@ -648,7 +672,7 @@ private fun AppHomeHeader(
fontWeight = FontWeight.Black fontWeight = FontWeight.Black
) )
Text( Text(
text = AppSections.firstOrNull { it.key == activeSection }?.meta ?: "Request client", text = sections.firstOrNull { it.key == activeSection }?.meta ?: "Request client",
color = AppColors.Muted, color = AppColors.Muted,
style = MaterialTheme.typography.bodySmall style = MaterialTheme.typography.bodySmall
) )
@@ -675,7 +699,7 @@ private fun AppHomeHeader(
.horizontalScroll(rememberScrollState()), .horizontalScroll(rememberScrollState()),
horizontalArrangement = Arrangement.spacedBy(8.dp) horizontalArrangement = Arrangement.spacedBy(8.dp)
) { ) {
AppSections.forEach { section -> sections.forEach { section ->
AppSectionChip( AppSectionChip(
section = section, section = section,
selected = activeSection == section.key, selected = activeSection == section.key,
@@ -942,7 +966,7 @@ private fun SendButton(
shape = RoundedCornerShape(8.dp), shape = RoundedCornerShape(8.dp),
colors = ButtonDefaults.buttonColors( colors = ButtonDefaults.buttonColors(
containerColor = AppColors.Primary, containerColor = AppColors.Primary,
contentColor = Color.White, contentColor = AppColors.OnPrimary,
disabledContainerColor = AppColors.Border, disabledContainerColor = AppColors.Border,
disabledContentColor = AppColors.Muted disabledContentColor = AppColors.Muted
) )
@@ -951,7 +975,7 @@ private fun SendButton(
CircularProgressIndicator( CircularProgressIndicator(
modifier = Modifier.size(18.dp), modifier = Modifier.size(18.dp),
strokeWidth = 2.dp, strokeWidth = 2.dp,
color = Color.White color = AppColors.OnPrimary
) )
Spacer(Modifier.width(8.dp)) Spacer(Modifier.width(8.dp))
Text("Sending") Text("Sending")
@@ -1167,13 +1191,18 @@ private fun FlowPanel(
onClick = onRun, onClick = onRun,
enabled = steps.isNotEmpty() && !isRunning, enabled = steps.isNotEmpty() && !isRunning,
shape = RoundedCornerShape(8.dp), shape = RoundedCornerShape(8.dp),
colors = ButtonDefaults.buttonColors(containerColor = AppColors.Primary) colors = ButtonDefaults.buttonColors(
containerColor = AppColors.Primary,
contentColor = AppColors.OnPrimary,
disabledContainerColor = AppColors.Border,
disabledContentColor = AppColors.Muted
)
) { ) {
if (isRunning) { if (isRunning) {
CircularProgressIndicator( CircularProgressIndicator(
modifier = Modifier.size(16.dp), modifier = Modifier.size(16.dp),
strokeWidth = 2.dp, strokeWidth = 2.dp,
color = Color.White color = AppColors.OnPrimary
) )
Spacer(Modifier.width(8.dp)) Spacer(Modifier.width(8.dp))
} }

View File

@@ -1,8 +1,8 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"> <shape xmlns:android="http://schemas.android.com/apk/res/android">
<solid android:color="#F7FAF7" /> <solid android:color="@color/posthub_widget_background" />
<corners android:radius="24dp" /> <corners android:radius="24dp" />
<stroke <stroke
android:width="1dp" android:width="1dp"
android:color="#DDE4DF" /> android:color="@color/posthub_border" />
</shape> </shape>

View File

@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"> <shape xmlns:android="http://schemas.android.com/apk/res/android">
<solid android:color="#E3F4EF" /> <solid android:color="@color/posthub_widget_pill" />
<corners android:radius="14dp" /> <corners android:radius="14dp" />
</shape> </shape>

View File

@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"> <shape xmlns:android="http://schemas.android.com/apk/res/android">
<solid android:color="#006B5B" /> <solid android:color="@color/posthub_widget_refresh" />
<corners android:radius="18dp" /> <corners android:radius="18dp" />
</shape> </shape>

View File

@@ -5,8 +5,10 @@
android:layout_height="match_parent" android:layout_height="match_parent"
android:background="@drawable/widget_bg" android:background="@drawable/widget_bg"
android:gravity="center_vertical" android:gravity="center_vertical"
android:layoutDirection="ltr"
android:orientation="vertical" android:orientation="vertical"
android:padding="16dp"> android:padding="16dp"
android:textDirection="ltr">
<LinearLayout <LinearLayout
android:layout_width="match_parent" android:layout_width="match_parent"
@@ -28,7 +30,7 @@
android:fontFamily="sans" android:fontFamily="sans"
android:maxLines="1" android:maxLines="1"
android:text="@string/widget_title" android:text="@string/widget_title"
android:textColor="#17201C" android:textColor="@color/posthub_widget_title"
android:textSize="16sp" android:textSize="16sp"
android:textStyle="bold" /> android:textStyle="bold" />
@@ -39,7 +41,7 @@
android:ellipsize="end" android:ellipsize="end"
android:maxLines="1" android:maxLines="1"
android:text="@string/widget_ready" android:text="@string/widget_ready"
android:textColor="#66736D" android:textColor="@color/posthub_widget_subtitle"
android:textSize="12sp" /> android:textSize="12sp" />
</LinearLayout> </LinearLayout>
@@ -76,7 +78,7 @@
android:paddingBottom="5dp" android:paddingBottom="5dp"
android:text="@string/widget_idle" android:text="@string/widget_idle"
android:textAlignment="center" android:textAlignment="center"
android:textColor="#006B5B" android:textColor="@color/posthub_widget_status"
android:textSize="11sp" android:textSize="11sp"
android:textStyle="bold" /> android:textStyle="bold" />
@@ -89,7 +91,7 @@
android:ellipsize="end" android:ellipsize="end"
android:maxLines="1" android:maxLines="1"
android:text="@string/widget_no_run" android:text="@string/widget_no_run"
android:textColor="#66736D" android:textColor="@color/posthub_widget_subtitle"
android:textSize="12sp" /> android:textSize="12sp" />
</LinearLayout> </LinearLayout>
@@ -104,7 +106,7 @@
android:gravity="top" android:gravity="top"
android:maxLines="4" android:maxLines="4"
android:text="@string/widget_empty_state" android:text="@string/widget_empty_state"
android:textColor="#17201C" android:textColor="@color/posthub_widget_title"
android:textSize="13sp" /> android:textSize="13sp" />
</LinearLayout> </LinearLayout>

View File

@@ -0,0 +1,16 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<style name="Theme.PostHUB.Starting" parent="android:style/Theme.Material.NoActionBar">
<item name="android:windowSplashScreenBackground">@color/posthub_canvas</item>
<item name="android:windowSplashScreenAnimatedIcon">@drawable/ic_splash_brand</item>
<item name="android:windowSplashScreenIconBackgroundColor">@color/posthub_primary_dark</item>
<item name="android:windowBackground">@drawable/splash_window_background</item>
<item name="android:windowNoTitle">true</item>
<item name="android:windowActionBar">false</item>
<item name="android:statusBarColor">@color/posthub_canvas</item>
<item name="android:navigationBarColor">@color/posthub_canvas</item>
<item name="android:windowLightStatusBar">false</item>
<item name="android:windowLightNavigationBar">false</item>
</style>
</resources>

View File

@@ -0,0 +1,16 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<color name="posthub_primary">#5FE0C5</color>
<color name="posthub_primary_dark">#14382F</color>
<color name="posthub_canvas">#0E1513</color>
<color name="posthub_surface">#151D1A</color>
<color name="posthub_border">#2E3B36</color>
<color name="posthub_coral">#FF9A83</color>
<color name="posthub_amber">#E8B660</color>
<color name="posthub_widget_background">#151D1A</color>
<color name="posthub_widget_refresh">#5FE0C5</color>
<color name="posthub_widget_pill">#14382F</color>
<color name="posthub_widget_title">#EAF3EF</color>
<color name="posthub_widget_subtitle">#A2B2AB</color>
<color name="posthub_widget_status">#5FE0C5</color>
</resources>

View File

@@ -0,0 +1,21 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<style name="Theme.PostHUB" parent="android:style/Theme.Material.NoActionBar">
<item name="android:fontFamily">sans</item>
<item name="android:windowNoTitle">true</item>
<item name="android:windowActionBar">false</item>
<item name="android:windowLightStatusBar">false</item>
<item name="android:statusBarColor">@color/posthub_canvas</item>
<item name="android:navigationBarColor">@color/posthub_canvas</item>
</style>
<style name="Theme.PostHUB.Starting" parent="android:style/Theme.Material.NoActionBar">
<item name="android:windowBackground">@drawable/splash_window_background</item>
<item name="android:windowNoTitle">true</item>
<item name="android:windowActionBar">false</item>
<item name="android:statusBarColor">@color/posthub_canvas</item>
<item name="android:navigationBarColor">@color/posthub_canvas</item>
<item name="android:windowLightStatusBar">false</item>
</style>
</resources>

View File

@@ -7,4 +7,10 @@
<color name="posthub_border">#DDE4DF</color> <color name="posthub_border">#DDE4DF</color>
<color name="posthub_coral">#D84B35</color> <color name="posthub_coral">#D84B35</color>
<color name="posthub_amber">#C47A12</color> <color name="posthub_amber">#C47A12</color>
<color name="posthub_widget_background">#F7FAF7</color>
<color name="posthub_widget_refresh">#006B5B</color>
<color name="posthub_widget_pill">#E3F4EF</color>
<color name="posthub_widget_title">#17201C</color>
<color name="posthub_widget_subtitle">#66736D</color>
<color name="posthub_widget_status">#006B5B</color>
</resources> </resources>