diff --git a/zeapp/android/src/main/java/de/berlindroid/zeapp/ZeMainActivity.kt b/zeapp/android/src/main/java/de/berlindroid/zeapp/ZeMainActivity.kt index 3dc1ddbd..f21d3ccb 100644 --- a/zeapp/android/src/main/java/de/berlindroid/zeapp/ZeMainActivity.kt +++ b/zeapp/android/src/main/java/de/berlindroid/zeapp/ZeMainActivity.kt @@ -10,6 +10,7 @@ import androidx.activity.compose.setContent import androidx.activity.viewModels import androidx.compose.animation.core.animateFloatAsState import androidx.compose.animation.core.tween +import androidx.compose.foundation.BorderStroke import androidx.compose.foundation.background import androidx.compose.foundation.clickable import androidx.compose.foundation.layout.Column @@ -24,12 +25,14 @@ import androidx.compose.foundation.layout.wrapContentHeight import androidx.compose.foundation.lazy.LazyListState import androidx.compose.foundation.lazy.items import androidx.compose.foundation.lazy.rememberLazyListState +import androidx.compose.foundation.shape.RoundedCornerShape import androidx.compose.material.icons.Icons import androidx.compose.material.icons.filled.Close import androidx.compose.material.icons.filled.Edit import androidx.compose.material.icons.filled.Info import androidx.compose.material.icons.filled.Refresh import androidx.compose.material.icons.filled.Send +import androidx.compose.material3.CardDefaults import androidx.compose.material3.ExperimentalMaterial3Api import androidx.compose.material3.MaterialTheme import androidx.compose.material3.Snackbar @@ -46,6 +49,8 @@ import androidx.compose.runtime.remember import androidx.compose.runtime.setValue import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier +import androidx.compose.ui.draw.clip +import androidx.compose.ui.graphics.StrokeCap import androidx.compose.ui.graphics.asImageBitmap import androidx.compose.ui.graphics.graphicsLayer import androidx.compose.ui.platform.LocalConfiguration @@ -60,6 +65,7 @@ import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.tooling.preview.PreviewParameter import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.sp +import androidx.compose.ui.zIndex import dagger.hilt.android.AndroidEntryPoint import de.berlindroid.zeapp.zemodels.ZeConfiguration import de.berlindroid.zeapp.zemodels.ZeEditor @@ -78,6 +84,8 @@ import de.berlindroid.zeapp.zeui.ZeCameraEditor import de.berlindroid.zeapp.zeui.ZeImageDrawEditorDialog import de.berlindroid.zeapp.zeui.ZeNavigationPad import de.berlindroid.zeapp.zeui.zetheme.ZeBadgeAppTheme +import de.berlindroid.zeapp.zeui.zetheme.ZeBlack +import de.berlindroid.zeapp.zeui.zetheme.ZeWhite import de.berlindroid.zeapp.zevm.ZeBadgeViewModel import de.berlindroid.zekompanion.getPlatform import timber.log.Timber @@ -102,7 +110,6 @@ import androidx.compose.material3.Text as ZeText import androidx.compose.material3.TopAppBar as ZeTopAppBar import androidx.compose.ui.Alignment as ZeAlignment import androidx.compose.ui.Modifier as ZeModifier -import androidx.compose.ui.graphics.Color as ZeColor import androidx.compose.ui.graphics.FilterQuality as ZeFilterQuality import androidx.compose.ui.graphics.painter.BitmapPainter as ZeBitmapPainter import androidx.compose.ui.layout.ContentScale as ZeContentScale @@ -117,7 +124,7 @@ class ZeMainActivity : ComponentActivity() { private val vm: ZeBadgeViewModel by viewModels() /** - * Once created, use the main view composables. + * Once created, use the main view composable. */ override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) @@ -193,18 +200,6 @@ private fun ZeScreen(vm: ZeBadgeViewModel, modifier: Modifier = Modifier) { ZeNavigationPad(lazyListState) } }, - snackbarHost = { - SnackbarHost( - hostState = vm.snackbarHostState, - ) { - vm.snackbarHostState.currentSnackbarData?.let { data -> - Snackbar( - snackbarData = data, - shape = ZeRoundedCornerShape(ZeDimen.One), - ) - } - } - }, topBar = { ZeTopBar( onRandomClick = vm::sendRandomPageToDevice, @@ -437,7 +432,12 @@ private fun InfoBar( ZeCard( modifier = ZeModifier .padding(horizontal = ZeDimen.One, vertical = ZeDimen.One) - .background(ZeColor.Black, ZeRoundedCornerShape(ZeDimen.One)), + .background(ZeWhite, ZeRoundedCornerShape(ZeDimen.One)) + .zIndex(10.0f), + colors = CardDefaults.cardColors( + containerColor = ZeWhite, + contentColor = ZeBlack, + ), ) { ZeRow( modifier = ZeModifier.padding(horizontal = ZeDimen.Two, vertical = ZeDimen.One), @@ -447,7 +447,7 @@ private fun InfoBar( modifier = ZeModifier.weight(1.0f), fontSize = 20.sp, fontFamily = FontFamily.Monospace, - color = ZeColor.White, + color = ZeBlack, text = message, ) @@ -462,7 +462,12 @@ private fun InfoBar( } ZeLinearProgressIndicator( - modifier = ZeModifier.fillMaxWidth(), + modifier = ZeModifier + .fillMaxWidth() + .padding(start = 12.dp, end = 12.dp, top = 0.dp, bottom = 4.dp), + strokeCap = StrokeCap.Round, + trackColor = ZeWhite, + color = ZeBlack, progress = progress, ) } @@ -490,13 +495,13 @@ private fun SelectedEditor( config = config, dismissed = { vm.slotConfigured(editor.slot, null) }, accepted = { newConfig -> vm.slotConfigured(editor.slot, newConfig) }, - snackbarMessage = vm::showSnackBar, + snackbarMessage = vm::showMessage, ) is ZeConfiguration.Picture -> PictureEditorDialog( dismissed = { vm.slotConfigured(null, null) }, accepted = { newConfig -> vm.slotConfigured(editor.slot, newConfig) }, - snackbarMessage = vm::showSnackBar, + snackbarMessage = vm::showMessage, ) is ZeConfiguration.ImageGen -> ImageGenerationEditorDialog( @@ -506,7 +511,7 @@ private fun SelectedEditor( ) is ZeConfiguration.Schedule -> { - vm.showSnackBar(message = "Not added by you yet, please feel free to contribute this editor") + vm.showMessage(message = "Not added by you yet, please feel free to contribute this editor") vm.slotConfigured(null, null) } @@ -514,7 +519,7 @@ private fun SelectedEditor( config = config, dismissed = { vm.slotConfigured(null, null) }, accepted = { newConfig -> vm.slotConfigured(editor.slot, newConfig) }, - snackbarMessage = vm::showSnackBar, + snackbarMessage = vm::showMessage, ) is ZeConfiguration.Quote -> { @@ -522,14 +527,14 @@ private fun SelectedEditor( accepted = { vm.slotConfigured(editor.slot, it) }, dismissed = { vm.slotConfigured(null, null) }, config = config, - snackbarMessage = vm::showSnackBar, + snackbarMessage = vm::showMessage, ) } is ZeConfiguration.QRCode -> QRCodeEditorDialog( config = config, dismissed = { vm.slotConfigured(editor.slot, null) }, - snackbarMessage = vm::showSnackBar, + snackbarMessage = vm::showMessage, accepted = { newConfig -> vm.slotConfigured(editor.slot, newConfig) }, ) @@ -557,7 +562,7 @@ private fun SelectedEditor( is ZeConfiguration.CustomPhrase -> CustomPhraseEditorDialog( config = config, dismissed = { vm.slotConfigured(editor.slot, null) }, - snackbarMessage = vm::showSnackBar, + snackbarMessage = vm::showMessage, accepted = { newConfig -> vm.slotConfigured(editor.slot, newConfig) }, ) } @@ -612,12 +617,18 @@ private fun PagePreview( ZeCard( modifier = modifier .padding(ZeDimen.Quarter), + colors = CardDefaults.cardColors( + containerColor = ZeBlack, + contentColor = ZeWhite, + ), + border = BorderStroke(1.dp, ZeWhite), ) { ZeImage( modifier = ZeModifier .fillMaxWidth() .wrapContentHeight(unbounded = true) - .padding(horizontal = ZeDimen.One, vertical = ZeDimen.One), + .padding(horizontal = ZeDimen.One, vertical = ZeDimen.One) + .clip(RoundedCornerShape(4.dp)), painter = ZeBitmapPainter( image = bitmap.asImageBitmap(), filterQuality = ZeFilterQuality.None, @@ -632,7 +643,6 @@ private fun PagePreview( modifier = Modifier .align(ZeAlignment.CenterVertically) .padding(start = ZeDimen.One), - color = MaterialTheme.colorScheme.onSurface, ) if (resetThisPage != null || customizeThisPage != null || sendToDevice != null) { ZeLazyRow( diff --git a/zeapp/android/src/main/java/de/berlindroid/zeapp/zeui/ZeVloatingScroller.kt b/zeapp/android/src/main/java/de/berlindroid/zeapp/zeui/ZeFloatingScroller.kt similarity index 60% rename from zeapp/android/src/main/java/de/berlindroid/zeapp/zeui/ZeVloatingScroller.kt rename to zeapp/android/src/main/java/de/berlindroid/zeapp/zeui/ZeFloatingScroller.kt index be07551b..25df397f 100644 --- a/zeapp/android/src/main/java/de/berlindroid/zeapp/zeui/ZeVloatingScroller.kt +++ b/zeapp/android/src/main/java/de/berlindroid/zeapp/zeui/ZeFloatingScroller.kt @@ -1,12 +1,18 @@ package de.berlindroid.zeapp.zeui +import androidx.compose.foundation.border import androidx.compose.foundation.gestures.animateScrollBy +import androidx.compose.foundation.layout.padding import androidx.compose.foundation.lazy.LazyListState +import androidx.compose.foundation.shape.RoundedCornerShape import androidx.compose.material3.FloatingActionButton -import androidx.compose.material3.MaterialTheme import androidx.compose.runtime.Composable +import androidx.compose.ui.Modifier import androidx.compose.ui.text.style.TextAlign +import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.sp +import de.berlindroid.zeapp.zeui.zetheme.ZeBlack +import de.berlindroid.zeapp.zeui.zetheme.ZeWhite import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.launch import androidx.compose.material3.Text as ZeText @@ -19,7 +25,14 @@ fun ZeFloatingScroller( text: String, ) { FloatingActionButton( - containerColor = MaterialTheme.colorScheme.secondary, + containerColor = ZeBlack, + modifier = Modifier + .padding(16.dp) + .border( + width = 1.dp, + color = ZeWhite, + shape = RoundedCornerShape(16.dp), + ), onClick = { coroutineScope.launch { lazyListState.animateScrollBy(scrollLength) @@ -28,7 +41,7 @@ fun ZeFloatingScroller( ) { ZeText( text = text, - color = MaterialTheme.colorScheme.primary, + color = ZeWhite, fontSize = 32.sp, textAlign = TextAlign.Center, ) diff --git a/zeapp/android/src/main/java/de/berlindroid/zeapp/zeui/zetheme/ZeColor.kt b/zeapp/android/src/main/java/de/berlindroid/zeapp/zeui/zetheme/ZeColor.kt index e121fc0c..23c74c4e 100644 --- a/zeapp/android/src/main/java/de/berlindroid/zeapp/zeui/zetheme/ZeColor.kt +++ b/zeapp/android/src/main/java/de/berlindroid/zeapp/zeui/zetheme/ZeColor.kt @@ -2,13 +2,5 @@ package de.berlindroid.zeapp.zeui.zetheme import androidx.compose.ui.graphics.Color -val DroidConPrimary = Color(0xFFFFFFFF) -val DroidConOnPrimary = Color(0xFF000000) -val DroidConPrimaryVariant = Color(0xFF808080) -val DroidConSecondary = Color(0xFF000000) -val DroidConOnSecondary = Color(0xFFFFFFFF) -val DroidConSecondaryVariant = Color(0xFF404040) -val DroidConError = Color(0xFFFA6E50) -val DroidConOnError = Color(0xFF000000) -val DroidConBackground = Color(0xFF202020) -val DroidConOnBackground = Color(0xFF808080) +val ZeWhite = Color(0xFFFFFFFF) +val ZeBlack = Color(0xFF000000) diff --git a/zeapp/android/src/main/java/de/berlindroid/zeapp/zeui/zetheme/ZeTheme.kt b/zeapp/android/src/main/java/de/berlindroid/zeapp/zeui/zetheme/ZeTheme.kt index f70df671..80c93cf9 100644 --- a/zeapp/android/src/main/java/de/berlindroid/zeapp/zeui/zetheme/ZeTheme.kt +++ b/zeapp/android/src/main/java/de/berlindroid/zeapp/zeui/zetheme/ZeTheme.kt @@ -4,23 +4,21 @@ import android.app.Activity import androidx.compose.foundation.isSystemInDarkTheme import androidx.compose.material3.MaterialTheme import androidx.compose.material3.darkColorScheme -import androidx.compose.material3.lightColorScheme import androidx.compose.runtime.Composable import androidx.compose.runtime.SideEffect -import androidx.compose.ui.graphics.Color import androidx.compose.ui.graphics.toArgb import androidx.compose.ui.platform.LocalView import androidx.core.view.WindowCompat private val DarkColorScheme = darkColorScheme( - primary = DroidConPrimary, - secondary = DroidConSecondary, - onPrimary = DroidConOnPrimary, - onSecondary = DroidConOnSecondary, - error = DroidConError, - onError = DroidConOnError, - background = DroidConBackground, - onBackground = DroidConOnBackground, + primary = ZeWhite, + secondary = ZeBlack, + onPrimary = ZeBlack, + onSecondary = ZeWhite, + error = ZeWhite, + onError = ZeBlack, + background = ZeWhite, + onBackground = ZeBlack, ) @Composable @@ -34,7 +32,7 @@ fun ZeBadgeAppTheme( if (!view.isInEditMode) { SideEffect { val window = (view.context as Activity).window - window.statusBarColor = colorScheme.primary.toArgb() + window.statusBarColor = ZeBlack.toArgb() WindowCompat.getInsetsController(window, view).isAppearanceLightStatusBars = !darkTheme } } diff --git a/zeapp/android/src/main/java/de/berlindroid/zeapp/zeui/zetheme/ZeType.kt b/zeapp/android/src/main/java/de/berlindroid/zeapp/zeui/zetheme/ZeType.kt index 325e726e..cd13aba1 100644 --- a/zeapp/android/src/main/java/de/berlindroid/zeapp/zeui/zetheme/ZeType.kt +++ b/zeapp/android/src/main/java/de/berlindroid/zeapp/zeui/zetheme/ZeType.kt @@ -21,14 +21,4 @@ val Typography = Typography( lineHeight = 28.sp, letterSpacing = 0.sp, ), - /* Other default text styles to override - - labelSmall = TextStyle( - fontFamily = FontFamily.Default, - fontWeight = FontWeight.Medium, - fontSize = 12.sp, - lineHeight = 16.sp, - letterSpacing = 0.5.sp - ) - */ ) diff --git a/zeapp/android/src/main/java/de/berlindroid/zeapp/zevm/ZeBadgeViewModel.kt b/zeapp/android/src/main/java/de/berlindroid/zeapp/zevm/ZeBadgeViewModel.kt index f666a04d..6998d290 100644 --- a/zeapp/android/src/main/java/de/berlindroid/zeapp/zevm/ZeBadgeViewModel.kt +++ b/zeapp/android/src/main/java/de/berlindroid/zeapp/zevm/ZeBadgeViewModel.kt @@ -1,8 +1,6 @@ package de.berlindroid.zeapp.zevm import android.graphics.Bitmap -import androidx.compose.material3.SnackbarDuration -import androidx.compose.material3.SnackbarHostState import androidx.lifecycle.ViewModel import androidx.lifecycle.viewModelScope import dagger.hilt.android.lifecycle.HiltViewModel @@ -52,17 +50,6 @@ class ZeBadgeViewModel @Inject constructor( contributorsService: ZeContributorsService, ) : ViewModel() { - val snackbarHostState = SnackbarHostState() - - fun showSnackBar( - message: String, - duration: SnackbarDuration = SnackbarDuration.Long, - ) { - viewModelScope.launch { - snackbarHostState.showSnackbar(message = message, duration = duration) - } - } - private val _uiState: MutableStateFlow = MutableStateFlow(getInitialUIState()) val uiState: StateFlow = _uiState.asStateFlow() @@ -70,24 +57,23 @@ class ZeBadgeViewModel @Inject constructor( private var hideMessageJob: Job? = null private var messageProgressJob: Job? = null - private fun badgeFailure(error: String) { + fun showMessage( + message: String, + duration: Long = MESSAGE_DISPLAY_DURATION, + ) { _uiState.update { - it.copy(message = "❗$error ❗️") + it.copy(message = message) } - scheduleMessageDisappearance() - } - private fun badgeSuccess(bytesSent: Int) { - _uiState.update { - it.copy(message = "$bytesSent bytes were sent.") - } - scheduleMessageDisappearance() + scheduleMessageDisappearance(duration) } - private fun scheduleMessageDisappearance() { + private fun scheduleMessageDisappearance( + duration: Long = MESSAGE_DISPLAY_DURATION, + ) { hideMessageJob?.cancel() hideMessageJob = viewModelScope.launch { - delay(MESSAGE_DISPLAY_DURATION) + delay(duration) _uiState.update { it.copy(message = "") } @@ -95,11 +81,11 @@ class ZeBadgeViewModel @Inject constructor( messageProgressJob?.cancel() messageProgressJob = viewModelScope.launch { - for (progress in 0 until 10) { + for (progress in 0 until MESSAGE_DISPLAY_UPDATES) { _uiState.update { it.copy(messageProgress = 1.0f - progress / MESSAGE_DISPLAY_UPDATES.toFloat()) } - delay(MESSAGE_DISPLAY_DURATION / MESSAGE_DISPLAY_UPDATES) + delay(duration / MESSAGE_DISPLAY_UPDATES) } } } @@ -117,6 +103,7 @@ class ZeBadgeViewModel @Inject constructor( _uiState.update { it.copy(message = "") } + val slots = _uiState.value.slots val configuration = slots.getOrElse(slot) { @@ -125,7 +112,7 @@ class ZeBadgeViewModel @Inject constructor( } ?: return if (!badgeManager.isConnected()) { - showSnackBar("Please connect a badge.") + showMessage("Please connect a badge.") return } @@ -133,12 +120,12 @@ class ZeBadgeViewModel @Inject constructor( if (bitmap.isBinary()) { viewModelScope.launch { badgeManager.sendPage(slot.name, bitmap).fold( - onSuccess = { badgeSuccess(it) }, - onFailure = { badgeFailure(it.message ?: "Unknown error") }, + onSuccess = { showMessage("$it bytes were sent.") }, + onFailure = { showMessage("❗${it.message ?: "Unknown error"} ❗") }, ) } } else { - showSnackBar("Please give binary image for page '${slot.name}'.") + showMessage("Please give binary image for page '${slot.name}'.") } } @@ -399,7 +386,7 @@ class ZeBadgeViewModel @Inject constructor( fun sendRandomPageToDevice() { val slots = _uiState.value.slots if (slots.keys.isEmpty()) { - badgeFailure("No Slot Keys are available!") + showMessage("No Slot Keys are available!") } else { sendPageToDevice(slots.keys.random()) } @@ -417,7 +404,7 @@ class ZeBadgeViewModel @Inject constructor( fun copyInfoToClipboard() { clipboardService.copyToClipboard(_uiState.value.message) - showSnackBar("Copied") + showMessage("Copied") } /** diff --git a/zeapp/android/src/main/res/values/themes.xml b/zeapp/android/src/main/res/values/themes.xml index 5fc813c6..e55969a0 100644 --- a/zeapp/android/src/main/res/values/themes.xml +++ b/zeapp/android/src/main/res/values/themes.xml @@ -1,4 +1,4 @@