diff --git a/app/src/main/java/com/sameerasw/essentials/data/repository/SettingsRepository.kt b/app/src/main/java/com/sameerasw/essentials/data/repository/SettingsRepository.kt index 1879056d5b..7f65e1852e 100644 --- a/app/src/main/java/com/sameerasw/essentials/data/repository/SettingsRepository.kt +++ b/app/src/main/java/com/sameerasw/essentials/data/repository/SettingsRepository.kt @@ -560,6 +560,12 @@ class SettingsRepository( const val KEY_ISLAND_SHOW_CONSCIOUS_GATE = "island_show_conscious_gate" const val KEY_ISLAND_SHOW_TIME_BATTERY = "island_show_time_battery" const val KEY_ISLAND_TIME_SHOW_SECONDS = "island_time_show_seconds" + const val KEY_ISLAND_THEMED_TEXT = "island_themed_text" + const val KEY_ISLAND_ICON_COLOR_MODE = "island_icon_color_mode" + const val KEY_ISLAND_ICON_COLOR_CUSTOM = "island_icon_color_custom" + const val KEY_ISLAND_ICON_MATERIAL_YOU = "island_icon_material_you" + const val ISLAND_ICON_COLOR_DYNAMIC = "dynamic" + const val ISLAND_ICON_COLOR_CUSTOM = "custom" const val KEY_ISLAND_TIME_FORMAT = "island_time_format" const val KEY_ISLAND_TIME_PERIOD = "island_time_period" const val KEY_ISLAND_TIME_LEADING_ZERO = "island_time_leading_zero" @@ -704,9 +710,10 @@ class SettingsRepository( const val KEY_ISLAND_BORDER_OUTLINE_THICKNESS = "island_border_outline_thickness" const val KEY_ISLAND_BORDER_OUTLINE_HIDE_EXPANDED = "island_border_outline_hide_expanded" const val KEY_ISLAND_PULSE_SHADOW_ON_NOTIFICATION = "island_pulse_shadow_on_notification" - const val KEY_ISLAND_PULSE_SHADOW_SIZE = "island_pulse_shadow_size" - const val KEY_ISLAND_PULSE_SHADOW_Y_SHIFT = "island_pulse_shadow_y_shift" - const val KEY_ISLAND_PULSE_SHADOW_SPREAD = "island_pulse_shadow_spread" + const val KEY_ISLAND_PULSE_SHADOW_BLUR = "island_pulse_shadow_blur" + const val KEY_ISLAND_PULSE_SHADOW_SPREAD_DP = "island_pulse_shadow_spread_dp" + const val KEY_ISLAND_PULSE_SHADOW_OFFSET_Y = "island_pulse_shadow_offset_y" + const val KEY_ISLAND_PULSE_SHADOW_OPACITY = "island_pulse_shadow_opacity" const val KEY_ISLAND_PULSE_SHADOW_DURATION_MS = "island_pulse_shadow_duration_ms" const val ISLAND_BORDER_OUTLINE_DEFAULT_COLOR = "#202020" @@ -4072,14 +4079,17 @@ class SettingsRepository( fun isIslandPulseShadowEnabled(): Boolean = getBoolean(KEY_ISLAND_PULSE_SHADOW_ON_NOTIFICATION, false) fun setIslandPulseShadowEnabled(enabled: Boolean) = putBoolean(KEY_ISLAND_PULSE_SHADOW_ON_NOTIFICATION, enabled) - fun getIslandPulseShadowSize(): Float = getFloat(KEY_ISLAND_PULSE_SHADOW_SIZE, 0.5f) - fun setIslandPulseShadowSize(value: Float) = putFloat(KEY_ISLAND_PULSE_SHADOW_SIZE, value) + fun getIslandPulseShadowBlur(): Float = getFloat(KEY_ISLAND_PULSE_SHADOW_BLUR, 20f) + fun setIslandPulseShadowBlur(value: Float) = putFloat(KEY_ISLAND_PULSE_SHADOW_BLUR, value) - fun getIslandPulseShadowYShift(): Float = getFloat(KEY_ISLAND_PULSE_SHADOW_Y_SHIFT, 0.35f) - fun setIslandPulseShadowYShift(value: Float) = putFloat(KEY_ISLAND_PULSE_SHADOW_Y_SHIFT, value) + fun getIslandPulseShadowSpread(): Float = getFloat(KEY_ISLAND_PULSE_SHADOW_SPREAD_DP, 6f) + fun setIslandPulseShadowSpread(value: Float) = putFloat(KEY_ISLAND_PULSE_SHADOW_SPREAD_DP, value) - fun getIslandPulseShadowSpread(): Float = getFloat(KEY_ISLAND_PULSE_SHADOW_SPREAD, 2f) - fun setIslandPulseShadowSpread(value: Float) = putFloat(KEY_ISLAND_PULSE_SHADOW_SPREAD, value) + fun getIslandPulseShadowOffsetY(): Float = getFloat(KEY_ISLAND_PULSE_SHADOW_OFFSET_Y, 1f) + fun setIslandPulseShadowOffsetY(value: Float) = putFloat(KEY_ISLAND_PULSE_SHADOW_OFFSET_Y, value) + + fun getIslandPulseShadowOpacity(): Float = getFloat(KEY_ISLAND_PULSE_SHADOW_OPACITY, 0.35f) + fun setIslandPulseShadowOpacity(value: Float) = putFloat(KEY_ISLAND_PULSE_SHADOW_OPACITY, value) fun getIslandPulseShadowDurationMs(): Float = getFloat(KEY_ISLAND_PULSE_SHADOW_DURATION_MS, 1450f) fun setIslandPulseShadowDurationMs(value: Float) = putFloat(KEY_ISLAND_PULSE_SHADOW_DURATION_MS, value) diff --git a/app/src/main/java/com/sameerasw/essentials/island/plugins/brief/BriefPlugin.kt b/app/src/main/java/com/sameerasw/essentials/island/plugins/brief/BriefPlugin.kt index 9d367f4b30..84bd83d832 100644 --- a/app/src/main/java/com/sameerasw/essentials/island/plugins/brief/BriefPlugin.kt +++ b/app/src/main/java/com/sameerasw/essentials/island/plugins/brief/BriefPlugin.kt @@ -109,6 +109,7 @@ import com.sameerasw.essentials.island.model.IslandItem import com.sameerasw.essentials.island.model.IslandPriority import com.sameerasw.essentials.island.plugins.BaseIslandPlugin import com.sameerasw.essentials.island.ui.IslandTextStyles +import com.sameerasw.essentials.island.ui.islandTextColor import com.sameerasw.essentials.island.ui.components.BatteryGlyph import com.sameerasw.essentials.island.ui.components.BatteryRing import com.sameerasw.essentials.island.ui.components.CameraRow @@ -584,7 +585,7 @@ private fun BriefEventRow(event: UpcomingCalendarEvent, now: Long, accent: Color Column(Modifier.weight(1f)) { Text( text = event.title, - style = IslandTextStyles.body.copy(color = Color.White, fontSize = 15.sp), + style = IslandTextStyles.body.copy(color = islandTextColor(), fontSize = 15.sp), maxLines = 1, overflow = TextOverflow.Ellipsis, ) @@ -628,7 +629,7 @@ private fun BriefPlayer(media: MediaSnapshot, artwork: ImageBitmap?, onClick: () } Spacer(Modifier.width(12.dp)) Column(Modifier.weight(1f)) { - MarqueeText(text = media.title, style = IslandTextStyles.body.copy(color = Color.White, fontSize = 15.sp)) + MarqueeText(text = media.title, style = IslandTextStyles.body.copy(color = islandTextColor(), fontSize = 15.sp)) MarqueeText(text = media.artist, style = IslandTextStyles.body) } media.actions.like?.let { diff --git a/app/src/main/java/com/sameerasw/essentials/island/plugins/calendar/CalendarExpanded.kt b/app/src/main/java/com/sameerasw/essentials/island/plugins/calendar/CalendarExpanded.kt index 9c96518c79..3834bc48d0 100644 --- a/app/src/main/java/com/sameerasw/essentials/island/plugins/calendar/CalendarExpanded.kt +++ b/app/src/main/java/com/sameerasw/essentials/island/plugins/calendar/CalendarExpanded.kt @@ -35,6 +35,7 @@ import com.sameerasw.essentials.R import com.sameerasw.essentials.island.model.IslandExpandedScope import com.sameerasw.essentials.island.plugins.soften import com.sameerasw.essentials.island.ui.IslandTextStyles +import com.sameerasw.essentials.island.ui.islandTextColor import com.sameerasw.essentials.island.ui.components.CameraRow import com.sameerasw.essentials.island.ui.components.ConnectedButtonRow import com.sameerasw.essentials.island.ui.components.ConnectedItem @@ -68,7 +69,7 @@ fun CalendarExpanded( "${timeFormat.format(Date(event.startTimeMillis))} – ${timeFormat.format(Date(event.endTimeMillis))}" else -> timeFormat.format(Date(event.startTimeMillis)) } - val detailStyle = IslandTextStyles.body.copy(color = Color.White, fontSize = 15.sp, lineHeight = 20.sp) + val detailStyle = IslandTextStyles.body.copy(color = islandTextColor(), fontSize = 15.sp, lineHeight = 20.sp) Box(propagateMinConstraints = true) { if (drawBackground && !SurfaceBackdrop { Box(Modifier.fillMaxSize().accentGlow(calendarColor, showGlow, scope.cameraClearance)) }) { diff --git a/app/src/main/java/com/sameerasw/essentials/island/plugins/navigation/NavigationExpanded.kt b/app/src/main/java/com/sameerasw/essentials/island/plugins/navigation/NavigationExpanded.kt index 1d9eefe7cd..5bca0c4a81 100644 --- a/app/src/main/java/com/sameerasw/essentials/island/plugins/navigation/NavigationExpanded.kt +++ b/app/src/main/java/com/sameerasw/essentials/island/plugins/navigation/NavigationExpanded.kt @@ -21,6 +21,7 @@ import com.sameerasw.essentials.domain.model.NavigationNotificationData import com.sameerasw.essentials.island.model.IslandExpandedScope import com.sameerasw.essentials.island.ui.IslandLayoutSpec import com.sameerasw.essentials.island.ui.IslandTextStyles +import com.sameerasw.essentials.island.ui.islandTextColor import com.sameerasw.essentials.island.ui.components.CameraRow import com.sameerasw.essentials.island.ui.components.ConnectedButtonRow import com.sameerasw.essentials.island.ui.components.ConnectedItem @@ -53,7 +54,7 @@ fun NavigationExpanded( Spacer(Modifier.height(8.dp)) Text( text = data.instruction, - style = IslandTextStyles.title.copy(color = Color.White, fontSize = 20.sp, lineHeight = 25.sp), + style = IslandTextStyles.title.copy(color = islandTextColor(), fontSize = 20.sp, lineHeight = 25.sp), maxLines = 2, overflow = TextOverflow.Ellipsis, modifier = Modifier.fillMaxWidth().padding(horizontal = sidePadding), @@ -63,7 +64,7 @@ fun NavigationExpanded( Spacer(Modifier.height(2.dp)) Text( text = data.eta, - style = IslandTextStyles.body.copy(color = Color.White.copy(alpha = 0.7f)), + style = IslandTextStyles.body.copy(color = islandTextColor(0.7f)), maxLines = 1, overflow = TextOverflow.Ellipsis, modifier = Modifier.fillMaxWidth().padding(horizontal = sidePadding), diff --git a/app/src/main/java/com/sameerasw/essentials/island/plugins/notifications/NotificationExpanded.kt b/app/src/main/java/com/sameerasw/essentials/island/plugins/notifications/NotificationExpanded.kt index 8a216a644a..ff3f243f6c 100644 --- a/app/src/main/java/com/sameerasw/essentials/island/plugins/notifications/NotificationExpanded.kt +++ b/app/src/main/java/com/sameerasw/essentials/island/plugins/notifications/NotificationExpanded.kt @@ -54,6 +54,7 @@ import com.sameerasw.essentials.domain.model.ActiveNotificationAlert import com.sameerasw.essentials.domain.model.NotificationActionItem import com.sameerasw.essentials.island.model.IslandExpandedScope import com.sameerasw.essentials.island.ui.IslandTextStyles +import com.sameerasw.essentials.island.ui.islandTextColor import com.sameerasw.essentials.island.ui.components.CameraRow import com.sameerasw.essentials.island.ui.components.ConnectedButtonRow import com.sameerasw.essentials.island.ui.components.ConnectedItem @@ -111,7 +112,7 @@ fun NotificationExpanded( Spacer(Modifier.height(4.dp)) Text( text = message, - style = IslandTextStyles.body.copy(color = Color.White, fontSize = 15.sp, lineHeight = 20.sp), + style = IslandTextStyles.body.copy(color = islandTextColor(), fontSize = 15.sp, lineHeight = 20.sp), maxLines = 7, overflow = TextOverflow.Ellipsis, modifier = Modifier.fillMaxWidth().padding(horizontal = sidePadding), @@ -205,7 +206,7 @@ private fun ReplyField( scope.keepAlive() }, singleLine = true, - textStyle = IslandTextStyles.body.copy(color = Color.White, fontSize = 15.sp), + textStyle = IslandTextStyles.body.copy(color = islandTextColor(), fontSize = 15.sp), cursorBrush = SolidColor(accent), keyboardOptions = KeyboardOptions(imeAction = ImeAction.Send, capitalization = KeyboardCapitalization.Sentences), keyboardActions = KeyboardActions(onSend = { send() }), diff --git a/app/src/main/java/com/sameerasw/essentials/island/plugins/progress/ProgressExpanded.kt b/app/src/main/java/com/sameerasw/essentials/island/plugins/progress/ProgressExpanded.kt index 4c8d6bbd96..9e4383d3bc 100644 --- a/app/src/main/java/com/sameerasw/essentials/island/plugins/progress/ProgressExpanded.kt +++ b/app/src/main/java/com/sameerasw/essentials/island/plugins/progress/ProgressExpanded.kt @@ -20,6 +20,7 @@ import androidx.compose.ui.unit.sp import com.sameerasw.essentials.R import com.sameerasw.essentials.island.model.IslandExpandedScope import com.sameerasw.essentials.island.ui.IslandTextStyles +import com.sameerasw.essentials.island.ui.islandTextColor import com.sameerasw.essentials.island.ui.components.CameraRow import com.sameerasw.essentials.island.ui.components.ConnectedButtonRow import com.sameerasw.essentials.island.ui.components.ConnectedItem @@ -51,14 +52,14 @@ fun ProgressExpanded( MarqueeText(text = title, style = IslandTextStyles.title, modifier = Modifier.weight(1f)) }, end = { - if (!indeterminate) Text("${(progress * 100).toInt()}%", style = IslandTextStyles.body.copy(color = Color.White)) + if (!indeterminate) Text("${(progress * 100).toInt()}%", style = IslandTextStyles.body.copy(color = islandTextColor())) }, ) if (!text.isNullOrBlank()) { Spacer(Modifier.height(4.dp)) Text( text = text, - style = IslandTextStyles.body.copy(color = Color.White, fontSize = 15.sp, lineHeight = 20.sp), + style = IslandTextStyles.body.copy(color = islandTextColor(), fontSize = 15.sp, lineHeight = 20.sp), maxLines = 3, overflow = TextOverflow.Ellipsis, modifier = Modifier.fillMaxWidth().padding(horizontal = sidePadding), diff --git a/app/src/main/java/com/sameerasw/essentials/island/plugins/signal/SignalBars.kt b/app/src/main/java/com/sameerasw/essentials/island/plugins/signal/SignalBars.kt index b91e8790d1..b5f4b7e984 100644 --- a/app/src/main/java/com/sameerasw/essentials/island/plugins/signal/SignalBars.kt +++ b/app/src/main/java/com/sameerasw/essentials/island/plugins/signal/SignalBars.kt @@ -24,6 +24,7 @@ import androidx.compose.ui.text.rememberTextMeasurer import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.sp import com.sameerasw.essentials.island.ui.IslandTextStyles +import com.sameerasw.essentials.island.ui.components.resolveIconTint private const val LABEL_SHIFT_X = 0.15f private const val LABEL_SHIFT_Y = 0.15f @@ -64,7 +65,8 @@ fun SignalBars(level: Int, color: Color, label: String?, modifier: Modifier = Mo } @Composable -fun SignalIndicator(wifiLevel: Int?, mobileLevel: Int, color: Color, label: String?, modifier: Modifier = Modifier) { +fun SignalIndicator(wifiLevel: Int?, mobileLevel: Int, rawColor: Color, label: String?, modifier: Modifier = Modifier) { + val color = resolveIconTint(rawColor) AnimatedContent( targetState = wifiLevel, transitionSpec = { diff --git a/app/src/main/java/com/sameerasw/essentials/island/plugins/travel/TravelPlugin.kt b/app/src/main/java/com/sameerasw/essentials/island/plugins/travel/TravelPlugin.kt index 989e4a4f82..240ba7a20a 100644 --- a/app/src/main/java/com/sameerasw/essentials/island/plugins/travel/TravelPlugin.kt +++ b/app/src/main/java/com/sameerasw/essentials/island/plugins/travel/TravelPlugin.kt @@ -29,6 +29,7 @@ import com.sameerasw.essentials.island.model.IslandPriority import com.sameerasw.essentials.island.model.LineContent import com.sameerasw.essentials.island.plugins.BaseIslandPlugin import com.sameerasw.essentials.island.ui.IslandTextStyles +import com.sameerasw.essentials.island.ui.islandTextColor import com.sameerasw.essentials.island.ui.components.CameraRow import com.sameerasw.essentials.island.ui.components.ConnectedButtonRow import com.sameerasw.essentials.island.ui.components.ConnectedItem @@ -148,7 +149,7 @@ class TravelPlugin : BaseIslandPlugin() { Spacer(Modifier.height(4.dp)) Text( text = trip.time, - style = IslandTextStyles.body.copy(color = Color.White, fontSize = 15.sp, lineHeight = 20.sp), + style = IslandTextStyles.body.copy(color = islandTextColor(), fontSize = 15.sp, lineHeight = 20.sp), modifier = Modifier.fillMaxWidth().padding(horizontal = sidePadding), ) } diff --git a/app/src/main/java/com/sameerasw/essentials/island/remote/RemoteBriefCards.kt b/app/src/main/java/com/sameerasw/essentials/island/remote/RemoteBriefCards.kt index 833cb79926..e51a6ee599 100644 --- a/app/src/main/java/com/sameerasw/essentials/island/remote/RemoteBriefCards.kt +++ b/app/src/main/java/com/sameerasw/essentials/island/remote/RemoteBriefCards.kt @@ -19,6 +19,7 @@ import androidx.compose.ui.text.style.TextOverflow import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.sp import com.sameerasw.essentials.island.ui.IslandTextStyles +import com.sameerasw.essentials.island.ui.islandTextColor import com.sameerasw.island.sdk.BriefCardPayload import com.sameerasw.island.sdk.IslandSurfaceKey import kotlinx.coroutines.flow.MutableStateFlow @@ -66,7 +67,7 @@ fun RemoteBriefCardRow(card: RemoteBriefCard, onClick: () -> Unit, modifier: Mod Spacer(Modifier.width(12.dp)) Text( text = payload.subtitle.orEmpty(), - style = IslandTextStyles.body.copy(color = Color.White, fontSize = 14.sp), + style = IslandTextStyles.body.copy(color = islandTextColor(), fontSize = 14.sp), maxLines = 2, overflow = TextOverflow.Ellipsis, modifier = Modifier.weight(1f), diff --git a/app/src/main/java/com/sameerasw/essentials/island/service/IslandCoordinator.kt b/app/src/main/java/com/sameerasw/essentials/island/service/IslandCoordinator.kt index 6fc070e785..c95765217c 100644 --- a/app/src/main/java/com/sameerasw/essentials/island/service/IslandCoordinator.kt +++ b/app/src/main/java/com/sameerasw/essentials/island/service/IslandCoordinator.kt @@ -670,6 +670,8 @@ class IslandCoordinator( val scale = if (flatExpanded) 1f else settings.getIslandExpandedScale().coerceIn(1f, 1.3f) val lineWidth = minOf(settings.getIslandMaxWidth(), available) val expandedWidth = minOf(settings.getIslandExpandedWidth(), available / scale) + val iconCustomMode = settings.getString(SettingsRepository.KEY_ISLAND_ICON_COLOR_MODE, null) == SettingsRepository.ISLAND_ICON_COLOR_CUSTOM + val iconMaterialYou = settings.getBoolean(SettingsRepository.KEY_ISLAND_ICON_MATERIAL_YOU, true) spec.value = IslandLayoutSpec( cameraDiameter = (geo.diameter / density).dp, cameraGap = (geo.gap / density).dp, @@ -700,15 +702,26 @@ class IslandCoordinator( outlineThickness = settings.getIslandBorderOutlineThickness().coerceIn(1f, 5f).dp, outlineHiddenWhenExpanded = settings.isIslandBorderOutlineHiddenWhenExpanded(), pulseShadow = settings.isIslandPulseShadowEnabled(), - pulseSize = settings.getIslandPulseShadowSize().coerceIn(0.2f, 1f), - pulseYShift = settings.getIslandPulseShadowYShift().coerceIn(0f, 1f), - pulseSpread = settings.getIslandPulseShadowSpread().coerceIn(1f, 4f), + pulseBlur = settings.getIslandPulseShadowBlur().coerceIn(0f, 48f).dp, + pulseSpread = settings.getIslandPulseShadowSpread().coerceIn(0f, 24f).dp, + pulseOffsetY = settings.getIslandPulseShadowOffsetY().coerceIn(-8f, 16f).dp, + pulseOpacity = settings.getIslandPulseShadowOpacity().coerceIn(0.1f, 1f), pulseDurationMs = settings.getIslandPulseShadowDurationMs().coerceIn(300f, 4000f).toInt(), queueStyle = when (settings.getIslandNotifQueueStyle()) { SettingsRepository.ISLAND_NOTIF_QUEUE_STYLE_OVERLAP -> QueueStyle.Overlap else -> QueueStyle.Stack }, queueInline = settings.isIslandNotifQueueInlineEnabled(), + iconColorCustom = if (iconCustomMode && !iconMaterialYou) { + runCatching { + Color(AndroidColor.parseColor(settings.getString(SettingsRepository.KEY_ISLAND_ICON_COLOR_CUSTOM, null) ?: "#FFFFFF")) + }.getOrDefault(Color.White) + } else { + null + }, + iconDynamic = !iconCustomMode, + themedText = settings.getBoolean(SettingsRepository.KEY_ISLAND_THEMED_TEXT, false), + iconMaterialYou = iconMaterialYou, ) windowHost.maxWidthPx = (maxOf(lineWidth, expandedWidth * scale) * density).toInt() windowHost.updateGeometry(geo) @@ -819,15 +832,20 @@ class IslandCoordinator( SettingsRepository.KEY_ISLAND_MAX_WIDTH, SettingsRepository.KEY_ISLAND_CUTOUT_GAP, SettingsRepository.KEY_ISLAND_EXPANDED_WIDTH, + SettingsRepository.KEY_ISLAND_ICON_COLOR_MODE, + SettingsRepository.KEY_ISLAND_ICON_COLOR_CUSTOM, + SettingsRepository.KEY_ISLAND_ICON_MATERIAL_YOU, + SettingsRepository.KEY_ISLAND_THEMED_TEXT, SettingsRepository.KEY_ISLAND_BORDER_OUTLINE_ENABLED, SettingsRepository.KEY_ISLAND_BORDER_OUTLINE_COLOR, SettingsRepository.KEY_ISLAND_BORDER_OUTLINE_DYNAMIC, SettingsRepository.KEY_ISLAND_BORDER_OUTLINE_THICKNESS, SettingsRepository.KEY_ISLAND_BORDER_OUTLINE_HIDE_EXPANDED, SettingsRepository.KEY_ISLAND_PULSE_SHADOW_ON_NOTIFICATION, - SettingsRepository.KEY_ISLAND_PULSE_SHADOW_SIZE, - SettingsRepository.KEY_ISLAND_PULSE_SHADOW_Y_SHIFT, - SettingsRepository.KEY_ISLAND_PULSE_SHADOW_SPREAD, + SettingsRepository.KEY_ISLAND_PULSE_SHADOW_BLUR, + SettingsRepository.KEY_ISLAND_PULSE_SHADOW_SPREAD_DP, + SettingsRepository.KEY_ISLAND_PULSE_SHADOW_OFFSET_Y, + SettingsRepository.KEY_ISLAND_PULSE_SHADOW_OPACITY, SettingsRepository.KEY_ISLAND_PULSE_SHADOW_DURATION_MS, SettingsRepository.KEY_ISLAND_EXPANDED_ROUNDNESS, SettingsRepository.KEY_ISLAND_EXPANDED_PADDING, diff --git a/app/src/main/java/com/sameerasw/essentials/island/ui/IslandLayoutSpec.kt b/app/src/main/java/com/sameerasw/essentials/island/ui/IslandLayoutSpec.kt index ec64f347db..046db4583e 100644 --- a/app/src/main/java/com/sameerasw/essentials/island/ui/IslandLayoutSpec.kt +++ b/app/src/main/java/com/sameerasw/essentials/island/ui/IslandLayoutSpec.kt @@ -34,12 +34,17 @@ data class IslandLayoutSpec( val outlineThickness: Dp = 1.dp, val outlineHiddenWhenExpanded: Boolean = false, val pulseShadow: Boolean = false, - val pulseSize: Float = 0.5f, - val pulseYShift: Float = 0.35f, - val pulseSpread: Float = 2f, + val pulseBlur: Dp = 20.dp, + val pulseSpread: Dp = 6.dp, + val pulseOffsetY: Dp = 1.dp, + val pulseOpacity: Float = 0.35f, val pulseDurationMs: Int = 1450, val queueStyle: QueueStyle = QueueStyle.Stack, val queueInline: Boolean = false, + val iconColorCustom: Color? = null, + val iconDynamic: Boolean = true, + val themedText: Boolean = false, + val iconMaterialYou: Boolean = true, ) { val compactHeight: Dp get() = cameraDiameter + verticalGap * 2 val cameraSlotWidth: Dp get() = (cameraDiameter + cameraGap * 2) * cameraPresence diff --git a/app/src/main/java/com/sameerasw/essentials/island/ui/IslandRoot.kt b/app/src/main/java/com/sameerasw/essentials/island/ui/IslandRoot.kt index 7dcc045105..658c436ac8 100644 --- a/app/src/main/java/com/sameerasw/essentials/island/ui/IslandRoot.kt +++ b/app/src/main/java/com/sameerasw/essentials/island/ui/IslandRoot.kt @@ -35,8 +35,6 @@ import androidx.compose.ui.graphics.Outline import androidx.compose.ui.graphics.Shape import androidx.compose.ui.unit.Density import androidx.compose.ui.unit.LayoutDirection -import androidx.compose.ui.graphics.Brush -import androidx.compose.ui.graphics.drawscope.scale import com.sameerasw.essentials.R import androidx.compose.ui.unit.Dp import androidx.compose.ui.res.stringResource @@ -68,6 +66,7 @@ import androidx.compose.ui.graphics.Path import androidx.compose.ui.geometry.Rect import androidx.compose.runtime.Composable import androidx.compose.runtime.CompositionLocalProvider +import com.sameerasw.essentials.island.ui.components.LocalIslandIconColor import androidx.compose.runtime.compositionLocalOf import androidx.compose.runtime.LaunchedEffect import androidx.compose.runtime.derivedStateOf @@ -84,6 +83,9 @@ import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.animation.animateColorAsState import androidx.compose.ui.graphics.Color +import androidx.compose.ui.graphics.nativeCanvas +import androidx.compose.ui.graphics.toArgb +import android.graphics.BlurMaskFilter import androidx.compose.ui.graphics.graphicsLayer import androidx.compose.ui.input.pointer.pointerInput import androidx.compose.ui.input.pointer.util.VelocityTracker @@ -141,6 +143,34 @@ fun IslandRoot( onTargetBoundsChanged: (IntRect) -> Unit, registerCollapseAnimator: (((() -> Unit) -> Unit)?) -> Unit = {}, showCameraRing: Boolean = false, +) { + val primary = MaterialTheme.colorScheme.primary + val focused = state.items[state.focusedKey] + val dynamicAccent = (focused?.outlineAccent ?: focused?.accent) + ?: state.arrangement.visibleItems.firstNotNullOfOrNull { key -> state.items[key]?.let { it.outlineAccent ?: it.accent } } + val iconBase = if (targetSpec.iconMaterialYou) primary else Color.White + val iconTarget = if (targetSpec.iconDynamic) { + dynamicAccent ?: iconBase + } else { + targetSpec.iconColorCustom ?: iconBase + } + val iconColor by animateColorAsState(iconTarget, label = "islandIconColor") + CompositionLocalProvider( + LocalIslandIconColor provides iconColor, + LocalIslandTextColor provides if (targetSpec.themedText) pastelOf(iconColor) else null, + ) { + IslandRootContent(state, targetSpec, actions, onTargetBoundsChanged, registerCollapseAnimator, showCameraRing) + } +} + +@Composable +private fun IslandRootContent( + state: IslandUiState, + targetSpec: IslandLayoutSpec, + actions: IslandActions, + onTargetBoundsChanged: (IntRect) -> Unit, + registerCollapseAnimator: (((() -> Unit) -> Unit)?) -> Unit = {}, + showCameraRing: Boolean = false, ) { val view = LocalView.current val density = LocalDensity.current @@ -194,6 +224,10 @@ fun IslandRoot( ) val pulseAccent = state.items[state.focusedKey]?.accent + val pulsePaint = remember { android.graphics.Paint(android.graphics.Paint.ANTI_ALIAS_FLAG) } + val pulseBlur = remember(spec.pulseBlur, density) { + with(density) { spec.pulseBlur.toPx() }.takeIf { it > 0f }?.let { BlurMaskFilter(it * 0.866f, BlurMaskFilter.Blur.NORMAL) } + } val dynamicOutline: Color? = if (spec.outlineDynamic) { val focused = state.items[state.focusedKey] (focused?.outlineAccent ?: focused?.accent) @@ -212,7 +246,7 @@ fun IslandRoot( pulse.snapTo(0f) if (!spec.pulseShadow || state.focusedKey == null) return@LaunchedEffect pulse.animateTo(1f, tween(250, easing = LinearEasing)) - pulse.animateTo(0f, tween(1200, easing = LinearEasing)) + pulse.animateTo(0f, tween((spec.pulseDurationMs - 250).coerceAtLeast(100), easing = LinearEasing)) } val minSurfaceWidth = with(density) { spec.cameraDiameter.roundToPx() } val minSurfaceHeight = with(density) { spec.compactHeight.roundToPx() } @@ -843,23 +877,14 @@ fun IslandRoot( .drawBehind { val p = pulse.value if (pulseAccent == null || p <= 0f || !visible) return@drawBehind - val w = size.width * spec.pulseSize - val h = size.height * spec.pulseSize - val center = Offset(size.width / 2f, size.height / 2f + h * spec.pulseYShift) - val radius = h / 2f * spec.pulseSpread - scale(scaleX = w / h, scaleY = 1f, pivot = center) { - drawCircle( - brush = Brush.radialGradient( - 0f to pulseAccent.copy(alpha = 0.95f * p), - 0.45f to pulseAccent.copy(alpha = 0.55f * p), - 1f to Color.Transparent, - center = center, - radius = radius, - ), - radius = radius, - center = center, - ) - } + val spread = spec.pulseSpread.toPx() + val dy = spec.pulseOffsetY.toPx() + val r = surfaceCornerPx(size.height, compactHeightPx, expandedCornerPx) + spread + pulsePaint.color = pulseAccent.copy(alpha = spec.pulseOpacity * p).toArgb() + pulsePaint.maskFilter = pulseBlur + drawContext.canvas.nativeCanvas.drawRoundRect( + -spread, -spread + dy, size.width + spread, size.height + spread + dy, r, r, pulsePaint, + ) } .graphicsLayer { alpha = (if (visible) 1f else 0f) * (1f - if (bubbleOnlyLayout) catchUpAnim.value.coerceIn(0f, 1f) else 0f) diff --git a/app/src/main/java/com/sameerasw/essentials/island/ui/IslandStack.kt b/app/src/main/java/com/sameerasw/essentials/island/ui/IslandStack.kt index 5d76ceae7f..a2680518e7 100644 --- a/app/src/main/java/com/sameerasw/essentials/island/ui/IslandStack.kt +++ b/app/src/main/java/com/sameerasw/essentials/island/ui/IslandStack.kt @@ -1,6 +1,8 @@ package com.sameerasw.essentials.island.ui import com.sameerasw.essentials.island.model.SideBubble +import androidx.compose.ui.graphics.lerp +import com.sameerasw.essentials.island.ui.components.LocalIslandIconColor import com.sameerasw.essentials.island.model.CompactCell import androidx.compose.animation.AnimatedVisibility import androidx.compose.animation.core.MutableTransitionState @@ -195,6 +197,9 @@ private fun queueVisible(icons: List, max: Int): List { private const val OVERFLOW_KEY = "queue_overflow" +@Composable +private fun overflowBackground(): Color = lerp(LocalIslandIconColor.current ?: Color.White, Color.Black, 0.65f) + private fun queueOverflowIcon(count: Int) = StackIcon(OVERFLOW_KEY) { size -> QueueOverflowCounter(count, size) } @Composable @@ -203,7 +208,7 @@ private fun QueueOverflowCounter(count: Int, size: Dp) { Modifier .size(size) .clip(CircleShape) - .background(Color.White.copy(alpha = 0.18f)), + .background(overflowBackground()), contentAlignment = Alignment.Center, ) { AnimatedContent( @@ -385,7 +390,7 @@ fun IslandStackPill( .padding(4.dp) .size(iconSize) .clip(CircleShape) - .background(Color.White.copy(alpha = 0.18f)), + .background(overflowBackground()), contentAlignment = Alignment.Center, ) { Text( diff --git a/app/src/main/java/com/sameerasw/essentials/island/ui/LineTemplate.kt b/app/src/main/java/com/sameerasw/essentials/island/ui/LineTemplate.kt index 66211c80f0..c32fdd9d0b 100644 --- a/app/src/main/java/com/sameerasw/essentials/island/ui/LineTemplate.kt +++ b/app/src/main/java/com/sameerasw/essentials/island/ui/LineTemplate.kt @@ -25,6 +25,8 @@ import androidx.compose.runtime.Composable import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.graphics.Color +import androidx.compose.ui.graphics.toArgb +import androidx.compose.runtime.compositionLocalOf import androidx.compose.runtime.remember import androidx.compose.ui.platform.LocalDensity import androidx.compose.ui.text.AnnotatedString @@ -233,15 +235,32 @@ private fun flexFont(weight: Int) = Font( val IslandFontFamily = FontFamily(flexFont(400), flexFont(500), flexFont(600), flexFont(700)) +val LocalIslandTextColor = compositionLocalOf { null } + +@Composable +fun islandTextColor(alpha: Float = 1f): Color = (LocalIslandTextColor.current ?: Color.White).let { it.copy(alpha = it.alpha * alpha) } + +fun pastelOf(color: Color): Color { + val hsv = FloatArray(3) + android.graphics.Color.colorToHSV(color.toArgb(), hsv) + hsv[1] = minOf(hsv[1], 0.4f) + hsv[2] = 1f + return Color(android.graphics.Color.HSVToColor(hsv)) +} + object IslandTextStyles { - val line = TextStyle(color = Color.White, fontSize = 13.sp, fontFamily = IslandFontFamily, fontWeight = FontWeight.Medium) - val compact = TextStyle( - color = Color.White, - fontSize = 14.sp, - fontFamily = IslandFontFamily, - fontWeight = FontWeight.SemiBold, - fontFeatureSettings = "tnum", - ) - val title = TextStyle(color = Color.White, fontSize = 15.sp, fontFamily = IslandFontFamily, fontWeight = FontWeight.SemiBold) - val body = TextStyle(color = Color.White.copy(alpha = 0.72f), fontSize = 13.sp, fontFamily = IslandFontFamily) + val line: TextStyle + @Composable get() = TextStyle(color = islandTextColor(), fontSize = 13.sp, fontFamily = IslandFontFamily, fontWeight = FontWeight.Medium) + val compact: TextStyle + @Composable get() = TextStyle( + color = islandTextColor(), + fontSize = 14.sp, + fontFamily = IslandFontFamily, + fontWeight = FontWeight.SemiBold, + fontFeatureSettings = "tnum", + ) + val title: TextStyle + @Composable get() = TextStyle(color = islandTextColor(), fontSize = 15.sp, fontFamily = IslandFontFamily, fontWeight = FontWeight.SemiBold) + val body: TextStyle + @Composable get() = TextStyle(color = islandTextColor(0.72f), fontSize = 13.sp, fontFamily = IslandFontFamily) } diff --git a/app/src/main/java/com/sameerasw/essentials/island/ui/components/IslandComponents.kt b/app/src/main/java/com/sameerasw/essentials/island/ui/components/IslandComponents.kt index aee81ee225..73e380be79 100644 --- a/app/src/main/java/com/sameerasw/essentials/island/ui/components/IslandComponents.kt +++ b/app/src/main/java/com/sameerasw/essentials/island/ui/components/IslandComponents.kt @@ -19,6 +19,7 @@ import androidx.compose.foundation.shape.CircleShape import androidx.compose.foundation.shape.RoundedCornerShape import androidx.compose.material3.Icon import androidx.compose.runtime.Composable +import androidx.compose.runtime.compositionLocalOf import androidx.compose.ui.platform.LocalDensity import androidx.compose.ui.layout.onSizeChanged import androidx.compose.runtime.setValue @@ -87,9 +88,18 @@ fun IslandBitmap( } } +val LocalIslandIconColor = compositionLocalOf { null } + +@Composable +fun resolveIconTint(tint: Color): Color { + val override = LocalIslandIconColor.current ?: return tint + if (tint.red == 0f && tint.green == 0f && tint.blue == 0f) return tint + return override.copy(alpha = override.alpha * tint.alpha) +} + @Composable fun IslandIcon(res: Int, tint: Color = Color.White, size: Dp = 20.dp, modifier: Modifier = Modifier) { - Icon(painterResource(res), contentDescription = null, tint = tint, modifier = modifier.squareFit(size)) + Icon(painterResource(res), contentDescription = null, tint = resolveIconTint(tint), modifier = modifier.squareFit(size)) } @Composable @@ -131,7 +141,7 @@ fun EqualizerBars( @Composable fun BatteryRing(level: Int, color: Color, modifier: Modifier = Modifier, showLevel: Boolean = false, size: Dp = if (showLevel) 24.dp else 18.dp) { val sweep by animateFloatAsState(360f * level.coerceIn(0, 100) / 100f, IslandMotion.float(), label = "batterySweep") - val ringColor by animateColorAsState(color, label = "batteryColor") + val ringColor by animateColorAsState(resolveIconTint(color), label = "batteryColor") var ringPx by remember { mutableStateOf(0) } val density = LocalDensity.current Box(modifier.squareFit(size).onSizeChanged { ringPx = minOf(it.width, it.height) }, contentAlignment = Alignment.Center) { diff --git a/app/src/main/java/com/sameerasw/essentials/services/NotificationListener.kt b/app/src/main/java/com/sameerasw/essentials/services/NotificationListener.kt index 7045073cdf..a705aae64b 100644 --- a/app/src/main/java/com/sameerasw/essentials/services/NotificationListener.kt +++ b/app/src/main/java/com/sameerasw/essentials/services/NotificationListener.kt @@ -1085,7 +1085,9 @@ class NotificationListener : NotificationListenerService() { scheduleProgressRefresh() } - if (!isRepost && isHeadsUpNotification(sbn, rankingMap, allowSilent = true)) { + if (isHandledAsProgress(sbn)) { + // Shown by the progress plugin instead + } else if (!isRepost && isHeadsUpNotification(sbn, rankingMap, allowSilent = true)) { val alert = extractNotificationAlert(sbn)?.copy( isSilent = isSilentNotification(sbn, rankingMap), blockedByDnd = isBlockedByDnd(sbn, rankingMap), @@ -2098,6 +2100,7 @@ class NotificationListener : NotificationListenerService() { private fun hubAlertOf(sbn: StatusBarNotification, rankingMap: RankingMap?): ActiveNotificationAlert? { if (sbn.packageName == packageName || !hasReadableExtras(sbn) || isMediaNotification(sbn)) return null + if (isHandledAsProgress(sbn)) return null if ((sbn.notification.flags and Notification.FLAG_GROUP_SUMMARY) != 0 && !isStandaloneSummary(sbn)) return null return extractNotificationAlert(sbn)?.copy( isSilent = isSilentNotification(sbn, rankingMap), @@ -2109,6 +2112,13 @@ class NotificationListener : NotificationListenerService() { ) } + private fun isHandledAsProgress(sbn: StatusBarNotification): Boolean { + if (!SettingsRepository(applicationContext).isIslandNotifKeepProgressEnabled()) return false + val extras = sbn.notification?.extras ?: return false + return extras.getInt(Notification.EXTRA_PROGRESS_MAX, 0) > 0 || + extras.getBoolean(Notification.EXTRA_PROGRESS_INDETERMINATE, false) + } + fun hubAlerts(): List = safeActiveNotifications().orEmpty().mapNotNull { hubAlertOf(it, null) }.sortedByDescending { it.timestamp } diff --git a/app/src/main/java/com/sameerasw/essentials/ui/core/pickers/ColorSwatchPicker.kt b/app/src/main/java/com/sameerasw/essentials/ui/core/pickers/ColorSwatchPicker.kt index 81b8ef97af..ecc5696b8a 100644 --- a/app/src/main/java/com/sameerasw/essentials/ui/core/pickers/ColorSwatchPicker.kt +++ b/app/src/main/java/com/sameerasw/essentials/ui/core/pickers/ColorSwatchPicker.kt @@ -61,6 +61,25 @@ val DUO_PRESET_COLORS = "#FF1744", // Bright Red ) +val ISLAND_ICON_PASTEL_COLORS = + listOf( + "#FFFFFF", + "#FFB3BA", + "#FFDFBA", + "#FFFFBA", + "#BAFFC9", + "#A0E7E5", + "#BAE1FF", + "#C7CEEA", + "#D5BAFF", + "#E0BBE4", + "#FFC8DD", + "#FFDAC1", + "#CDEAC0", + "#B4F8C8", + "#FBE7C6", + ) + @OptIn(ExperimentalMaterial3Api::class) @Composable fun ColorSwatchPicker( diff --git a/app/src/main/java/com/sameerasw/essentials/ui/features/display/IslandSubSettingsUI.kt b/app/src/main/java/com/sameerasw/essentials/ui/features/display/IslandSubSettingsUI.kt index adff40db50..3183dadf23 100644 --- a/app/src/main/java/com/sameerasw/essentials/ui/features/display/IslandSubSettingsUI.kt +++ b/app/src/main/java/com/sameerasw/essentials/ui/features/display/IslandSubSettingsUI.kt @@ -47,6 +47,7 @@ import com.sameerasw.essentials.ui.components.sliders.ConfigSliderItem import com.sameerasw.essentials.ui.core.cards.IconToggleItem import com.sameerasw.essentials.ui.core.containers.RoundedCardContainer import com.sameerasw.essentials.ui.core.pickers.ColorSwatchPicker +import com.sameerasw.essentials.ui.core.pickers.ISLAND_ICON_PASTEL_COLORS import com.sameerasw.essentials.ui.core.pickers.SegmentedPicker import com.sameerasw.essentials.ui.core.sheets.AppSelectionSheet import com.sameerasw.essentials.ui.core.sheets.PermissionsBottomSheet @@ -485,6 +486,69 @@ fun IslandVisualsSettingsUI( modifier = Modifier.highlight(highlightSetting == "island_pulse_shadow_on_notification"), ) } + + IslandSettingsSection(R.string.island_section_icon_color) { + val iconSettings = remember { SettingsRepository(context) } + var colorMode by remember { + mutableStateOf(iconSettings.getString(SettingsRepository.KEY_ISLAND_ICON_COLOR_MODE, null) ?: SettingsRepository.ISLAND_ICON_COLOR_DYNAMIC) + } + var materialYou by remember { mutableStateOf(iconSettings.getBoolean(SettingsRepository.KEY_ISLAND_ICON_MATERIAL_YOU, true)) } + var customColor by remember { + mutableStateOf(iconSettings.getString(SettingsRepository.KEY_ISLAND_ICON_COLOR_CUSTOM, null) ?: "#FFFFFF") + } + val modeLabels = mapOf( + SettingsRepository.ISLAND_ICON_COLOR_DYNAMIC to stringResource(R.string.island_icon_color_dynamic), + SettingsRepository.ISLAND_ICON_COLOR_CUSTOM to stringResource(R.string.island_icon_color_custom), + ) + SegmentedPicker( + items = modeLabels.keys.toList(), + selectedItem = colorMode, + onItemSelected = { + HapticUtil.performVirtualKeyHaptic(view) + colorMode = it + iconSettings.putString(SettingsRepository.KEY_ISLAND_ICON_COLOR_MODE, it) + }, + labelProvider = { modeLabels[it].orEmpty() }, + title = R.string.island_section_icon_color, + modifier = Modifier.fillMaxWidth().highlight(highlightSetting == "island_icon_color_mode"), + ) + IconToggleItem( + iconRes = R.drawable.rounded_palette_24, + title = stringResource(R.string.island_icon_material_you_title), + isChecked = materialYou, + onCheckedChange = { checked -> + HapticUtil.performVirtualKeyHaptic(view) + materialYou = checked + iconSettings.putBoolean(SettingsRepository.KEY_ISLAND_ICON_MATERIAL_YOU, checked) + }, + ) + AnimatedVisibility( + visible = colorMode == SettingsRepository.ISLAND_ICON_COLOR_CUSTOM && !materialYou, + enter = fadeIn() + expandVertically(), + exit = fadeOut() + shrinkVertically(), + ) { + ColorSwatchPicker( + selectedColorHex = customColor, + onColorSelected = { + customColor = it + iconSettings.putString(SettingsRepository.KEY_ISLAND_ICON_COLOR_CUSTOM, it) + }, + colors = ISLAND_ICON_PASTEL_COLORS, + ) + } + + var themedText by remember { mutableStateOf(iconSettings.getBoolean(SettingsRepository.KEY_ISLAND_THEMED_TEXT, false)) } + IconToggleItem( + iconRes = R.drawable.rounded_palette_24, + title = stringResource(R.string.island_themed_text_title), + isChecked = themedText, + onCheckedChange = { checked -> + HapticUtil.performVirtualKeyHaptic(view) + themedText = checked + iconSettings.putBoolean(SettingsRepository.KEY_ISLAND_THEMED_TEXT, checked) + }, + ) + } } if (showBorderOutlineSheet) { diff --git a/app/src/main/java/com/sameerasw/essentials/ui/features/display/sheets/IslandPulseShadowOptionsBottomSheet.kt b/app/src/main/java/com/sameerasw/essentials/ui/features/display/sheets/IslandPulseShadowOptionsBottomSheet.kt index 592d165ba1..a0f3e4580a 100644 --- a/app/src/main/java/com/sameerasw/essentials/ui/features/display/sheets/IslandPulseShadowOptionsBottomSheet.kt +++ b/app/src/main/java/com/sameerasw/essentials/ui/features/display/sheets/IslandPulseShadowOptionsBottomSheet.kt @@ -18,7 +18,7 @@ import com.sameerasw.essentials.ui.core.containers.RoundedCardContainer import com.sameerasw.essentials.ui.core.sheets.EssentialsBottomSheet import com.sameerasw.essentials.utils.HapticUtil import com.sameerasw.essentials.viewmodels.MainViewModel -import java.util.Locale +import kotlin.math.roundToInt @OptIn(ExperimentalMaterial3Api::class) @Composable @@ -45,42 +45,55 @@ fun IslandPulseShadowOptionsBottomSheet( RoundedCardContainer(spacing = 2.dp, cornerRadius = 24.dp) { ConfigSliderItem( - title = stringResource(R.string.island_pulse_shadow_size_title), - value = viewModel.islandPulseShadowSize.floatValue, + title = stringResource(R.string.island_pulse_shadow_blur_title), + value = viewModel.islandPulseShadowBlur.floatValue, onValueChange = { HapticUtil.performUIHaptic(view) - viewModel.setIslandPulseShadowSize(it) + viewModel.setIslandPulseShadowBlur(it) }, - valueRange = 0.2f..1f, - increment = 0.05f, + valueRange = 0f..48f, + increment = 1f, + iconRes = R.drawable.rounded_blur_on_24, + valueFormatter = { "${it.toInt()} dp" }, + ) + + ConfigSliderItem( + title = stringResource(R.string.island_pulse_shadow_spread_title), + value = viewModel.islandPulseShadowSpread.floatValue, + onValueChange = { + HapticUtil.performUIHaptic(view) + viewModel.setIslandPulseShadowSpread(it) + }, + valueRange = 0f..24f, + increment = 1f, iconRes = R.drawable.rounded_magnify_fullscreen_24, - valueFormatter = { "${(it * 100).toInt()}%" }, + valueFormatter = { "${it.toInt()} dp" }, ) ConfigSliderItem( - title = stringResource(R.string.island_pulse_shadow_y_shift_title), - value = viewModel.islandPulseShadowYShift.floatValue, + title = stringResource(R.string.island_pulse_shadow_offset_y_title), + value = viewModel.islandPulseShadowOffsetY.floatValue, onValueChange = { HapticUtil.performUIHaptic(view) - viewModel.setIslandPulseShadowYShift(it) + viewModel.setIslandPulseShadowOffsetY(it) }, - valueRange = 0f..1f, - increment = 0.05f, + valueRange = -8f..16f, + increment = 1f, iconRes = R.drawable.rounded_screenshot_region_24, - valueFormatter = { "${(it * 100).toInt()}%" }, + valueFormatter = { "${it.toInt()} dp" }, ) ConfigSliderItem( - title = stringResource(R.string.island_pulse_shadow_spread_title), - value = viewModel.islandPulseShadowSpread.floatValue, + title = stringResource(R.string.island_pulse_shadow_opacity_title), + value = viewModel.islandPulseShadowOpacity.floatValue, onValueChange = { HapticUtil.performUIHaptic(view) - viewModel.setIslandPulseShadowSpread(it) + viewModel.setIslandPulseShadowOpacity(it) }, - valueRange = 1f..4f, - increment = 0.1f, - iconRes = R.drawable.rounded_blur_on_24, - valueFormatter = { String.format(Locale.US, "%.1fx", it) }, + valueRange = 0.1f..1f, + increment = 0.02f, + iconRes = R.drawable.rounded_invert_colors_24, + valueFormatter = { "${(it * 100).roundToInt()}%" }, ) ConfigSliderItem( diff --git a/app/src/main/java/com/sameerasw/essentials/viewmodels/MainViewModel.kt b/app/src/main/java/com/sameerasw/essentials/viewmodels/MainViewModel.kt index e99c0317ae..e0427c22f2 100644 --- a/app/src/main/java/com/sameerasw/essentials/viewmodels/MainViewModel.kt +++ b/app/src/main/java/com/sameerasw/essentials/viewmodels/MainViewModel.kt @@ -306,9 +306,10 @@ class MainViewModel : ViewModel() { val islandBorderOutlineThickness = mutableFloatStateOf(1f) val isIslandBorderOutlineHiddenWhenExpanded = mutableStateOf(false) val isIslandPulseShadow = mutableStateOf(false) - val islandPulseShadowSize = mutableFloatStateOf(0.5f) - val islandPulseShadowYShift = mutableFloatStateOf(0.35f) - val islandPulseShadowSpread = mutableFloatStateOf(2f) + val islandPulseShadowBlur = mutableFloatStateOf(20f) + val islandPulseShadowSpread = mutableFloatStateOf(6f) + val islandPulseShadowOffsetY = mutableFloatStateOf(1f) + val islandPulseShadowOpacity = mutableFloatStateOf(0.35f) val islandPulseShadowDurationMs = mutableFloatStateOf(1450f) val isIslandShowMedia = mutableStateOf(true) val isIslandShowCalendar = mutableStateOf(false) @@ -2585,9 +2586,10 @@ class MainViewModel : ViewModel() { islandBorderOutlineThickness.floatValue = settingsRepository.getIslandBorderOutlineThickness() isIslandBorderOutlineHiddenWhenExpanded.value = settingsRepository.isIslandBorderOutlineHiddenWhenExpanded() isIslandPulseShadow.value = settingsRepository.isIslandPulseShadowEnabled() - islandPulseShadowSize.floatValue = settingsRepository.getIslandPulseShadowSize() - islandPulseShadowYShift.floatValue = settingsRepository.getIslandPulseShadowYShift() + islandPulseShadowBlur.floatValue = settingsRepository.getIslandPulseShadowBlur() islandPulseShadowSpread.floatValue = settingsRepository.getIslandPulseShadowSpread() + islandPulseShadowOffsetY.floatValue = settingsRepository.getIslandPulseShadowOffsetY() + islandPulseShadowOpacity.floatValue = settingsRepository.getIslandPulseShadowOpacity() islandPulseShadowDurationMs.floatValue = settingsRepository.getIslandPulseShadowDurationMs() isIslandShowMedia.value = settingsRepository.isIslandShowMediaEnabled() isIslandShowCalendar.value = settingsRepository.isIslandShowCalendarEnabled() @@ -6195,14 +6197,19 @@ class MainViewModel : ViewModel() { settingsRepository.setIslandPulseShadowEnabled(enabled) } - fun setIslandPulseShadowSize(value: Float) { - islandPulseShadowSize.floatValue = value - settingsRepository.setIslandPulseShadowSize(value) + fun setIslandPulseShadowBlur(value: Float) { + islandPulseShadowBlur.floatValue = value + settingsRepository.setIslandPulseShadowBlur(value) } - fun setIslandPulseShadowYShift(value: Float) { - islandPulseShadowYShift.floatValue = value - settingsRepository.setIslandPulseShadowYShift(value) + fun setIslandPulseShadowOffsetY(value: Float) { + islandPulseShadowOffsetY.floatValue = value + settingsRepository.setIslandPulseShadowOffsetY(value) + } + + fun setIslandPulseShadowOpacity(value: Float) { + islandPulseShadowOpacity.floatValue = value + settingsRepository.setIslandPulseShadowOpacity(value) } fun setIslandPulseShadowSpread(value: Float) { diff --git a/app/src/main/res/values-es/strings.xml b/app/src/main/res/values-es/strings.xml index 2463dc523f..67c5b38dcd 100644 --- a/app/src/main/res/values-es/strings.xml +++ b/app/src/main/res/values-es/strings.xml @@ -1806,8 +1806,6 @@ Requiere permiso de administrador del dispositivo si se utiliza el bloqueo.Ocultar al Expandir Solo delinear la isla compacta y de vista previa Muestra una línea alrededor de la isla - Tamaño del Brillo - Desplazamiento vertical Ondas de Brillo Duración de la Animación Número máximo de elementos a mostrar diff --git a/app/src/main/res/values-nl/strings.xml b/app/src/main/res/values-nl/strings.xml index de5744571e..d764d71f7f 100644 --- a/app/src/main/res/values-nl/strings.xml +++ b/app/src/main/res/values-nl/strings.xml @@ -1656,8 +1656,6 @@ Toon accentkleurige gloed Toon puls schaduw tijdens meldingen Toont een gloed achter het eiland in de appkleuren - Gloed grootte - Verticale positie Snelheid gloed Puls duur Duur diff --git a/app/src/main/res/values-vi/strings.xml b/app/src/main/res/values-vi/strings.xml index 26eedb5667..0d8d25f067 100644 --- a/app/src/main/res/values-vi/strings.xml +++ b/app/src/main/res/values-vi/strings.xml @@ -1916,8 +1916,6 @@ Nút Tiếp tục sẽ bị vô hiệu hóa trong vài giây để bạn có th Chỉ cần phác thảo đường viền nhỏ gọn và nhìn thoáng qua island Độ dày đường viền Ẩn nội dung thông báo - Kích thước phát sáng - Dịch chuyển theo chiều dọc Ánh sáng lan tỏa Thời lượng xung Bật Duo diff --git a/app/src/main/res/values-zh/strings.xml b/app/src/main/res/values-zh/strings.xml index aa99f88eb5..030f12be69 100644 --- a/app/src/main/res/values-zh/strings.xml +++ b/app/src/main/res/values-zh/strings.xml @@ -1645,7 +1645,6 @@ 自适应(随播放专辑主题色同步变化) 灵动岛展开后隐藏边框 边框加粗 - 边框发散光影 持续时间 扩散范围 平移 diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index c5d9b17245..c5360e7222 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -3174,6 +3174,11 @@ Open app Tap action Time + Icon color + Themed text color + Dynamic + Custom + Use Material You colors Time format System 12 hr @@ -3219,9 +3224,10 @@ Only outline the compact and peek island Show pulse shadow on notification Briefly glows behind the island in the app color - Glow size - Vertical shift - Glow spread + Blur + Vertical offset + Spread + Opacity Pulse duration App based color glow Expanded width