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 be508fa05..7f65e1852 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
@@ -710,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"
@@ -4078,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/service/IslandCoordinator.kt b/app/src/main/java/com/sameerasw/essentials/island/service/IslandCoordinator.kt
index 9f5fd291d..c95765217 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
@@ -702,9 +702,10 @@ 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
@@ -841,9 +842,10 @@ class IslandCoordinator(
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 36dc9c7ed..046db4583 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,9 +34,10 @@ 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,
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 a54c5eea0..658c436ac 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
@@ -85,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
@@ -223,6 +224,10 @@ private fun IslandRootContent(
)
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)
@@ -241,7 +246,7 @@ private fun IslandRootContent(
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() }
@@ -872,23 +877,14 @@ private fun IslandRootContent(
.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/ui/features/display/sheets/IslandPulseShadowOptionsBottomSheet.kt b/app/src/main/java/com/sameerasw/essentials/ui/features/display/sheets/IslandPulseShadowOptionsBottomSheet.kt
index 592d165ba..a0f3e4580 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 e99c0317a..e0427c22f 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 2463dc523..67c5b38dc 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 de5744571..d764d71f7 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 26eedb566..0d8d25f06 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 aa99f88eb..030f12be6 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 0f50484bf..c5360e722 100644
--- a/app/src/main/res/values/strings.xml
+++ b/app/src/main/res/values/strings.xml
@@ -3224,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