Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -623,9 +623,11 @@ class SettingsRepository(
const val KEY_ISLAND_MEDIA_SHOW_PREVIOUS = "island_media_show_previous"
const val KEY_ISLAND_MEDIA_SHOW_LIKE = "island_media_show_like"
const val KEY_ISLAND_NOTIF_COMPACT_HEADS_UP = "island_notif_compact_heads_up"
const val KEY_ISLAND_NOTIF_CONDENSED_INFO = "island_notif_condensed_info"
const val KEY_ISLAND_NOTIF_KEEP_PROGRESS = "island_notif_keep_progress"
const val KEY_ISLAND_NOTIF_QUEUE = "island_notif_queue"
const val KEY_ISLAND_NOTIF_SKIP_SILENT = "island_notif_skip_silent"
const val KEY_ISLAND_NOTIF_FOLLOW_DND = "island_notif_follow_dnd"
const val KEY_ISLAND_NOTIF_FILTER_APPS = "island_notif_filter_apps"
const val KEY_ISLAND_NOTIF_FILTER_APPS_LIST = "island_notif_filter_apps_list"
const val KEY_ISLAND_SHOW_NOTIFICATIONS = "island_show_notifications"
Expand Down Expand Up @@ -4163,6 +4165,9 @@ class SettingsRepository(
fun isIslandNotifSkipSilentEnabled(): Boolean = getBoolean(KEY_ISLAND_NOTIF_SKIP_SILENT, true)
fun setIslandNotifSkipSilentEnabled(enabled: Boolean) = putBoolean(KEY_ISLAND_NOTIF_SKIP_SILENT, enabled)

fun isIslandNotifFollowDndEnabled(): Boolean = getBoolean(KEY_ISLAND_NOTIF_FOLLOW_DND, true)
fun setIslandNotifFollowDndEnabled(enabled: Boolean) = putBoolean(KEY_ISLAND_NOTIF_FOLLOW_DND, enabled)

fun isIslandNotifFilterAppsEnabled(): Boolean = getBoolean(KEY_ISLAND_NOTIF_FILTER_APPS, false)
fun setIslandNotifFilterAppsEnabled(enabled: Boolean) = putBoolean(KEY_ISLAND_NOTIF_FILTER_APPS, enabled)

Expand All @@ -4177,6 +4182,9 @@ class SettingsRepository(
fun isIslandNotifCompactHeadsUpEnabled(): Boolean = getBoolean(KEY_ISLAND_NOTIF_COMPACT_HEADS_UP, true)
fun setIslandNotifCompactHeadsUpEnabled(enabled: Boolean) = putBoolean(KEY_ISLAND_NOTIF_COMPACT_HEADS_UP, enabled)

fun isIslandNotifCondensedInfoEnabled(): Boolean = getBoolean(KEY_ISLAND_NOTIF_CONDENSED_INFO, false)
fun setIslandNotifCondensedInfoEnabled(enabled: Boolean) = putBoolean(KEY_ISLAND_NOTIF_CONDENSED_INFO, enabled)

fun isIslandNotifKeepProgressEnabled(): Boolean = getBoolean(KEY_ISLAND_NOTIF_KEEP_PROGRESS, true)
fun setIslandNotifKeepProgressEnabled(enabled: Boolean) = putBoolean(KEY_ISLAND_NOTIF_KEEP_PROGRESS, enabled)

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,5 +27,6 @@ data class ActiveNotificationAlert(
val actions: List<NotificationActionItem> = emptyList(),
val chatIcon: Bitmap? = null,
val isSilent: Boolean = false,
val blockedByDnd: Boolean = false,
)

Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ package com.sameerasw.essentials.domain.registry

import com.sameerasw.essentials.ui.features.display.ISLAND_BEHAVIOR_FEATURE_ID
import com.sameerasw.essentials.ui.features.display.ISLAND_DURATION_FEATURE_ID
import com.sameerasw.essentials.ui.features.display.ISLAND_NOTIFICATIONS_FEATURE_ID
import com.sameerasw.essentials.ui.features.display.ISLAND_PLACEMENT_FEATURE_ID
import com.sameerasw.essentials.ui.features.display.ISLAND_VISUALS_FEATURE_ID
import android.content.Context
Expand Down Expand Up @@ -819,26 +820,6 @@ object FeatureRegistry {
R.string.island_call_incoming,
"island_show_calls",
),
SearchSetting(
R.string.island_notif_queue_title,
R.string.island_notif_queue_title,
"island_notif_queue",
),
SearchSetting(
R.string.island_notif_compact_heads_up_title,
R.string.island_notif_compact_heads_up_desc,
"island_notif_compact_heads_up",
),
SearchSetting(
R.string.island_notif_skip_silent_title,
R.string.island_notification_options_title,
"island_notif_skip_silent",
),
SearchSetting(
R.string.island_notif_filter_apps_title,
R.string.island_notification_options_title,
"island_notif_filter_apps",
),
SearchSetting(
R.string.island_media_peek_song_change_title,
R.string.island_media_peek_song_change_desc,
Expand Down Expand Up @@ -976,6 +957,72 @@ object FeatureRegistry {
enabled: Boolean,
) {}
},
object : Feature(
id = ISLAND_NOTIFICATIONS_FEATURE_ID,
title = R.string.island_section_notifications,
iconRes = R.drawable.rounded_notifications_unread_24,
category = R.string.cat_interface,
description = R.string.island_notification_options_title,
showToggle = false,
parentFeatureId = "Island",
isVisibleInMain = false,
searchableSettings =
listOf(
SearchSetting(
R.string.island_notif_filter_apps_title,
R.string.island_notif_filter_apps_desc,
"island_notif_filter_apps",
),
SearchSetting(
R.string.island_notif_skip_silent_title,
R.string.island_notif_skip_silent_desc,
"island_notif_skip_silent",
),
SearchSetting(
R.string.island_notif_follow_dnd_title,
R.string.island_notif_follow_dnd_desc,
"island_notif_follow_dnd",
),
SearchSetting(
R.string.island_notif_keep_progress_title,
R.string.island_notif_keep_progress_desc,
"island_notif_keep_progress",
),
SearchSetting(
R.string.island_notif_compact_heads_up_title,
R.string.island_notif_compact_heads_up_desc,
"island_notif_compact_heads_up",
),
SearchSetting(
R.string.island_notif_condensed_info_title,
R.string.island_notif_condensed_info_desc,
"island_notif_condensed_info",
),
SearchSetting(
R.string.island_notif_queue_title,
R.string.island_notif_queue_desc,
"island_notif_queue",
),
SearchSetting(
R.string.island_notif_tap_to_open_title,
R.string.island_notif_tap_to_open_desc,
"island_notif_tap_to_open",
),
SearchSetting(
R.string.island_catch_up_title,
R.string.island_catch_up_desc,
"island_catch_up",
),
),
) {
override fun isEnabled(viewModel: MainViewModel) = viewModel.isIslandEnabled.value

override fun onToggle(
viewModel: MainViewModel,
context: Context,
enabled: Boolean,
) {}
},
object : Feature(
id = "Maps power saving mode",
title = R.string.feat_maps_power_saving_title,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,8 @@ class LineContent(
val end: String,
val endSlot: (@Composable () -> Unit)? = null,
val showLeftIcon: Boolean = true,
// Icon + title only on line peek
val condensed: Boolean = false,
)

interface IslandExpandedScope {
Expand Down Expand Up @@ -123,6 +125,9 @@ class IslandItem(
val sourcePackage: String? = null,
// Temporary priority while the item's state is urgent; null falls back to `priority`.
val priorityOverride: Int? = null,
// Identifies which piece of content the item is currently showing. The item key stays put while a plugin cycles
// through its own content, so this is what tells the island a genuinely new thing arrived and it should pulse.
val contentId: String? = null,

val compactVisible: Boolean = true,
val needsCompanyAtCenter: Boolean = false,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,9 +37,12 @@ class NotificationsPlugin : BaseIslandPlugin() {
override val settingKeys = setOf(
SettingsRepository.KEY_ISLAND_CATCH_UP_ENABLED,
SettingsRepository.KEY_ISLAND_NOTIF_COMPACT_HEADS_UP,
SettingsRepository.KEY_ISLAND_NOTIF_CONDENSED_INFO,
SettingsRepository.KEY_ISLAND_LINE_STAGE_ENABLED,
SettingsRepository.KEY_ISLAND_SHOW_GLOW,
SettingsRepository.KEY_ISLAND_NOTIF_QUEUE,
SettingsRepository.KEY_ISLAND_NOTIF_SKIP_SILENT,
SettingsRepository.KEY_ISLAND_NOTIF_FOLLOW_DND,
SettingsRepository.KEY_ISLAND_NOTIF_FILTER_APPS,
SettingsRepository.KEY_ISLAND_NOTIF_FILTER_APPS_LIST,
SettingsRepository.KEY_ISLAND_NOTIF_TAP_TO_OPEN,
Expand Down Expand Up @@ -160,6 +163,7 @@ class NotificationsPlugin : BaseIslandPlugin() {

private fun passesFilters(alert: ActiveNotificationAlert): Boolean {
if (alert.isSilent && settings.isIslandNotifSkipSilentEnabled()) return false
if (alert.blockedByDnd && settings.isIslandNotifFollowDndEnabled()) return false
if (!settings.isIslandNotifFilterAppsEnabled()) return true
return settings.loadIslandNotifFilterApps().any { it.isEnabled && it.packageName == alert.packageName }
}
Expand Down Expand Up @@ -333,6 +337,9 @@ class NotificationsPlugin : BaseIslandPlugin() {

private fun queueEnabled() = settings.isIslandNotifQueueEnabled()

private fun condensedLine() = settings.isIslandNotifCondensedInfoEnabled() &&
settings.isIslandLineStageEnabled() && settings.isIslandNotifCompactHeadsUpEnabled()

private fun itemFor(alert: ActiveNotificationAlert): IslandItem {
if (concealed()) return concealedItemFor(alert)
val (sender, message) = senderAndMessage(context, alert)
Expand All @@ -359,6 +366,7 @@ class NotificationsPlugin : BaseIslandPlugin() {
icon = { IslandBitmap(icon, 24.dp, fallbackRes = R.drawable.rounded_notifications_unread_24) },
start = sender,
end = message,
condensed = condensedLine(),
),
expanded = ExpandedContent { scope ->
NotificationExpanded(
Expand All @@ -383,6 +391,7 @@ class NotificationsPlugin : BaseIslandPlugin() {
popCurrent(reExpand = false)
},
sourcePackage = alert.packageName,
contentId = alert.key,
)
}

Expand Down Expand Up @@ -414,6 +423,7 @@ class NotificationsPlugin : BaseIslandPlugin() {
icon = { IslandBitmap(icon, 24.dp, fallbackRes = R.drawable.rounded_notifications_unread_24) },
start = appNameFor(context, alert),
end = "",
condensed = condensedLine(),
),
accent = alert.appColor?.let { Color(soften(it)) },
dismissible = true,
Expand All @@ -424,6 +434,7 @@ class NotificationsPlugin : BaseIslandPlugin() {
onOpen = open,
interactions = InteractionOverrides(onTap = { open(); true }),
sourcePackage = alert.packageName,
contentId = alert.key,
)
}

Expand All @@ -448,6 +459,7 @@ class NotificationsPlugin : BaseIslandPlugin() {
interactions = interactions,
queue = queue,
sourcePackage = sourcePackage,
contentId = contentId,
stack = stack,
compactVisible = sideBubble == null,
sideBubble = sideBubble,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -206,7 +206,7 @@ fun IslandRoot(
?.takeIf { outlineAlpha > 0f && fade > 0f }
?.let { it.copy(alpha = it.alpha * outlineAlpha * fade) }
val pulse = remember { Animatable(0f) }
LaunchedEffect(state.focusedKey, spec.pulseShadow) {
LaunchedEffect(state.focusedKey, state.items[state.focusedKey]?.contentId, spec.pulseShadow) {
pulse.snapTo(0f)
if (!spec.pulseShadow || state.focusedKey == null) return@LaunchedEffect
pulse.animateTo(1f, tween(250, easing = LinearEasing))
Expand Down Expand Up @@ -410,11 +410,9 @@ fun IslandRoot(
if (spec.growDirection == 0 && hasCompactCells) catchUpAnim.value.coerceAtLeast(0f) * (bubbleSizePx + bubbleGapPx) / 2f else 0f
val lineShift = remember { Animatable(0f) }
val liveSurfaceHeight = remember { mutableIntStateOf(0) }
fun surfaceLeft(width: Int): Int = windowWidth / 2 + lineShift.value.roundToInt() + catchShiftPx().roundToInt() - when {
spec.growDirection > 0 -> cameraSlotPx / 2
spec.growDirection < 0 -> width - cameraSlotPx / 2
else -> width / 2
}
fun surfaceShiftFor(width: Int): Int = spec.growDirection * (width - cameraSlotPx) / 2
fun surfaceLeft(width: Int): Int = windowWidth / 2 - width / 2 + surfaceShiftFor(width) +
lineShift.value.roundToInt() + catchShiftPx().roundToInt()
fun bubbleX(width: Int): Int =
if (spec.growDirection > 0) surfaceLeft(width) + width + bubbleGapPx else surfaceLeft(width) - bubbleGapPx - bubbleSizePx
val focusedItem = state.focused
Expand All @@ -433,8 +431,13 @@ fun IslandRoot(
val lineInsetActive = queueShown && stage == IslandStage.Line
val lineInset = if (lineInsetActive) spec.compactHeight + spec.cameraGap else 0.dp
val lineInsets = if (spec.growDirection > 0) 0.dp to lineInset else lineInset to 0.dp
LaunchedEffect(lineInsetActive, spec.growDirection) {
val shift = if (lineInsetActive && spec.growDirection == 0) (bubbleSizePx + bubbleGapPx) / 2f else 0f
val condensedLineActive = spec.growDirection == 0 && stage == IslandStage.Line && focusedItem?.line?.condensed == true
LaunchedEffect(lineInsetActive, spec.growDirection, condensedLineActive) {
val shift = if (lineInsetActive && spec.growDirection == 0 && !condensedLineActive) {
(bubbleSizePx + bubbleGapPx) / 2f
} else {
0f
}
lineShift.animateTo(shift, IslandMotion.float())
}
var lastQueuedIcons by remember { mutableStateOf(emptyList<StackIcon>()) }
Expand All @@ -459,15 +462,18 @@ fun IslandRoot(
}
}

LaunchedEffect(target, windowWidth, stage, queueShown, pillSize, lineInsetActive, catchUpShown, hasCompactCells, bubbleOnlyLayout) {
LaunchedEffect(
target, windowWidth, stage, queueShown, pillSize, lineInsetActive, catchUpShown, hasCompactCells,
bubbleOnlyLayout, condensedLineActive,
) {
if (target == IntSize.Zero || windowWidth == 0) return@LaunchedEffect
val g = if (stage == IslandStage.Expanded) outsetPx.roundToInt() else 0
val shift = if ((lineInsetActive || (catchUpShown && hasCompactCells)) && spec.growDirection == 0) (bubbleSizePx + bubbleGapPx) / 2 else 0
val left = windowWidth / 2 + shift - when {
spec.growDirection > 0 -> cameraSlotPx / 2
spec.growDirection < 0 -> target.width - cameraSlotPx / 2
else -> target.width / 2
val shift = if ((lineInsetActive || (catchUpShown && hasCompactCells)) && spec.growDirection == 0 && !condensedLineActive) {
(bubbleSizePx + bubbleGapPx) / 2
} else {
0
}
val left = windowWidth / 2 - target.width / 2 + surfaceShiftFor(target.width) + shift
val top = (surfaceTopPx - g).coerceAtLeast(0)
var bounds = IntRect(left, top, left + target.width, surfaceTopPx - g + target.height)
if (queueShown && stage == IslandStage.Line) {
Expand Down Expand Up @@ -635,7 +641,7 @@ fun IslandRoot(
.padding(top = spec.surfaceTop)
.layout { measurable, constraints ->
val p = measurable.measure(constraints)
val dx = spec.growDirection * (p.width - cameraSlotPx) / 2 + lineShift.value.roundToInt() + catchShiftPx().roundToInt()
val dx = surfaceShiftFor(p.width) + lineShift.value.roundToInt() + catchShiftPx().roundToInt()
layout(p.width, p.height) { p.place(dx, 0) }
}
.offset { IntOffset(0, (squashPx / 2f * squash.value - edgeShift.floatValue - surfaceTopPx * bond).roundToInt()) }
Expand Down
Loading
Loading