Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
45 commits
Select commit Hold shift + click to select a range
e9299fb
New translations strings.xml (Italian)
sameerasw Jun 12, 2026
b4744f4
feat: add configurable restoration delay for Shut-Up! settings
sameerasw Jun 12, 2026
f86f9da
feat: #469 add shape selection bottom sheet for notification lighting…
sameerasw Jun 12, 2026
c997351
New translations strings.xml (Arabic)
sameerasw Jun 12, 2026
40dc6c7
New translations strings.xml (Italian)
sameerasw Jun 12, 2026
0dd7bec
New translations strings.xml (Polish)
sameerasw Jun 12, 2026
8bfd6b0
New translations strings.xml (French)
sameerasw Jun 12, 2026
99cb7fe
New translations strings.xml (Spanish)
sameerasw Jun 12, 2026
cdea9cc
New translations strings.xml (Turkish)
sameerasw Jun 12, 2026
1c73514
New translations strings.xml (Indonesian)
sameerasw Jun 12, 2026
696b71a
New translations strings.xml (Romanian)
sameerasw Jun 12, 2026
3d551ab
New translations strings.xml (Afrikaans)
sameerasw Jun 12, 2026
e4b31d7
New translations strings.xml (Catalan)
sameerasw Jun 12, 2026
ce4cdb8
New translations strings.xml (Czech)
sameerasw Jun 12, 2026
7cb92ed
New translations strings.xml (Danish)
sameerasw Jun 12, 2026
31d4654
New translations strings.xml (German)
sameerasw Jun 12, 2026
ffbd767
New translations strings.xml (Greek)
sameerasw Jun 12, 2026
f10dd33
New translations strings.xml (Finnish)
sameerasw Jun 12, 2026
75d1dc1
New translations strings.xml (Hebrew)
sameerasw Jun 12, 2026
d08c995
New translations strings.xml (Hungarian)
sameerasw Jun 12, 2026
57003bb
New translations strings.xml (Japanese)
sameerasw Jun 12, 2026
504b588
New translations strings.xml (Korean)
sameerasw Jun 12, 2026
fa1e97f
New translations strings.xml (Dutch)
sameerasw Jun 12, 2026
a870eac
New translations strings.xml (Norwegian)
sameerasw Jun 12, 2026
1e1099e
New translations strings.xml (Portuguese)
sameerasw Jun 12, 2026
6f3f8ed
New translations strings.xml (Russian)
sameerasw Jun 12, 2026
6ae6f61
New translations strings.xml (Serbian (Cyrillic))
sameerasw Jun 12, 2026
961c289
New translations strings.xml (Swedish)
sameerasw Jun 12, 2026
c81ee4f
New translations strings.xml (Ukrainian)
sameerasw Jun 12, 2026
162820b
New translations strings.xml (Chinese Simplified)
sameerasw Jun 12, 2026
f263182
New translations strings.xml (Chinese Traditional)
sameerasw Jun 12, 2026
42542e8
New translations strings.xml (English)
sameerasw Jun 12, 2026
9e4d658
New translations strings.xml (Vietnamese)
sameerasw Jun 12, 2026
05cdb87
New translations strings.xml (Portuguese, Brazilian)
sameerasw Jun 12, 2026
94bbd6d
New translations strings.xml (Sinhala)
sameerasw Jun 12, 2026
203c359
New translations strings.xml (Acholi)
sameerasw Jun 12, 2026
3af7c44
Update source file strings.xml
sameerasw Jun 12, 2026
bf1687d
New translations strings.xml (Spanish)
sameerasw Jun 12, 2026
cb3c07e
New translations strings.xml (Italian)
sameerasw Jun 12, 2026
75b7174
New translations strings.xml (Italian)
sameerasw Jun 15, 2026
46e0013
New translations strings.xml (Turkish)
sameerasw Jun 15, 2026
be9d18b
New translations strings.xml (Indonesian)
sameerasw Jun 16, 2026
839c5a4
Merge branch 'develop' into l10n_develop
sameerasw Jun 18, 2026
e0ac1a1
New Crowdin updates (#502)
sameerasw Jun 18, 2026
bf075dc
Merge branch 'main' into develop
sameerasw Jun 18, 2026
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 @@ -236,6 +236,8 @@ class SettingsRepository(private val context: Context) {
const val KEY_SHUT_UP_SELECTED_APPS = "shut_up_selected_apps"
const val KEY_SHUT_UP_ORIGINAL_SETTINGS = "shut_up_original_settings"
const val KEY_SHUT_UP_ATTEMPT_SHIZUKU_RESTART = "shut_up_attempt_shizuku_restart"
const val KEY_SHUT_UP_RESTORE_DELAY = "shut_up_restore_delay"
const val KEY_EDGE_LIGHTING_SWEEP_SELECTED_SHAPES = "edge_lighting_sweep_selected_shapes"
const val KEY_DISABLE_ROTATION_SUGGESTION = "disable_rotation_suggestion"

const val KEY_LOCK_SCREEN_CLOCK_WEIGHT = "lock_screen_clock_weight"
Expand Down Expand Up @@ -860,6 +862,31 @@ class SettingsRepository(private val context: Context) {
fun setShutUpAttemptShizukuRestartEnabled(enabled: Boolean) =
putBoolean(KEY_SHUT_UP_ATTEMPT_SHIZUKU_RESTART, enabled)

fun getShutUpRestoreDelay(): Int =
getInt(KEY_SHUT_UP_RESTORE_DELAY, 10)

fun setShutUpRestoreDelay(delaySeconds: Int) =
putInt(KEY_SHUT_UP_RESTORE_DELAY, delaySeconds)

fun getEdgeLightingSweepSelectedShapes(): Set<String> {
val defaultShapes = com.sameerasw.essentials.utils.AmbientMusicShapeHelper.allShapesWithNames.map { it.first }.toSet()
val json = prefs.getString(KEY_EDGE_LIGHTING_SWEEP_SELECTED_SHAPES, null)
return if (json != null) {
try {
gson.fromJson(json, Array<String>::class.java).toSet()
} catch (e: Exception) {
defaultShapes
}
} else {
defaultShapes
}
}

fun saveEdgeLightingSweepSelectedShapes(shapes: Set<String>) {
val json = gson.toJson(shapes)
putString(KEY_EDGE_LIGHTING_SWEEP_SELECTED_SHAPES, json)
}

fun removeTrackedRepo(fullName: String) {
val current = getTrackedRepos().toMutableList()
current.removeAll { it.fullName == fullName }
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -623,7 +623,8 @@ class AppFlowHandler(

scope.launch {
// Delay to ensure the app has fully settled before restoring system settings
delay(2000)
val delaySeconds = repository.getShutUpRestoreDelay()
delay(delaySeconds * 1000L)

val canWriteSecure =
com.sameerasw.essentials.utils.PermissionUtils.canWriteSecureSettings(context)
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,145 @@
package com.sameerasw.essentials.ui.components.sheets

import androidx.compose.foundation.background
import androidx.compose.foundation.clickable
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.aspectRatio
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.height
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.size
import androidx.compose.foundation.lazy.grid.GridCells
import androidx.compose.foundation.lazy.grid.LazyVerticalGrid
import androidx.compose.foundation.lazy.grid.items
import androidx.compose.material3.Button
import androidx.compose.material3.ExperimentalMaterial3Api
import androidx.compose.material3.Icon
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.ModalBottomSheet
import androidx.compose.material3.OutlinedButton
import androidx.compose.material3.Text
import androidx.compose.material3.rememberModalBottomSheetState
import androidx.compose.material3.toShape
import androidx.compose.runtime.Composable
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
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.platform.LocalContext
import androidx.compose.ui.platform.LocalView
import androidx.compose.ui.res.painterResource
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.unit.dp
import com.sameerasw.essentials.R
import com.sameerasw.essentials.utils.AmbientMusicShapeHelper
import com.sameerasw.essentials.utils.HapticUtil
import com.sameerasw.essentials.viewmodels.MainViewModel

@OptIn(ExperimentalMaterial3Api::class)
@Composable
fun SweepShapesBottomSheet(
viewModel: MainViewModel,
onDismissRequest: () -> Unit
) {
val context = LocalContext.current
val view = LocalView.current
val sheetState = rememberModalBottomSheetState(skipPartiallyExpanded = true)

// Loaded selection
val initiallySelected = remember { viewModel.edgeLightingSweepSelectedShapes.value }
var selectedShapes by remember { mutableStateOf(initiallySelected) }

ModalBottomSheet(
onDismissRequest = onDismissRequest,
sheetState = sheetState,
containerColor = MaterialTheme.colorScheme.surfaceContainerHigh
) {
Column(
modifier = Modifier
.fillMaxWidth()
.padding(horizontal = 24.dp)
.padding(bottom = 8.dp),
horizontalAlignment = Alignment.CenterHorizontally,
verticalArrangement = Arrangement.spacedBy(16.dp)
) {
Text(
text = stringResource(R.string.notification_lighting_sweep_select_shapes_title),
style = MaterialTheme.typography.headlineSmall,
color = MaterialTheme.colorScheme.onSurface
)

LazyVerticalGrid(
columns = GridCells.Fixed(4),
horizontalArrangement = Arrangement.spacedBy(8.dp),
verticalArrangement = Arrangement.spacedBy(8.dp),
modifier = Modifier
.fillMaxWidth()
.weight(1f, fill = false)
) {
items(AmbientMusicShapeHelper.allShapesWithNames) { (name, polygon) ->
val isSelected = selectedShapes.contains(name)
Box(
modifier = Modifier
.aspectRatio(1f)
.clip(polygon.toShape())
.background(
if (isSelected) MaterialTheme.colorScheme.primary
else MaterialTheme.colorScheme.surfaceBright
)
.clickable {
HapticUtil.performVirtualKeyHaptic(view)
selectedShapes = if (isSelected) {
selectedShapes - name
} else {
selectedShapes + name
}
},
contentAlignment = Alignment.Center
) {
if (isSelected) {
Icon(
painter = painterResource(id = R.drawable.rounded_check_24),
contentDescription = null,
tint = MaterialTheme.colorScheme.onPrimary,
modifier = Modifier.size(24.dp)
)
}
}
}
}

Row(
modifier = Modifier.fillMaxWidth(),
horizontalArrangement = Arrangement.spacedBy(12.dp)
) {
OutlinedButton(
onClick = {
HapticUtil.performVirtualKeyHaptic(view)
val allNames = AmbientMusicShapeHelper.allShapesWithNames.map { it.first }.toSet()
selectedShapes = allNames - selectedShapes
},
modifier = Modifier.weight(1f)
) {
Text(stringResource(R.string.action_invert_selection))
}

Button(
onClick = {
HapticUtil.performHeavyHaptic(view)
viewModel.saveEdgeLightingSweepSelectedShapes(selectedShapes)
onDismissRequest()
},
modifier = Modifier.weight(1f)
) {
Text(stringResource(R.string.action_save))
}
}
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,8 @@ import com.sameerasw.essentials.ui.components.pickers.NotificationLightingSystem
import com.sameerasw.essentials.ui.components.sheets.AppSelectionSheet
import com.sameerasw.essentials.ui.components.sheets.PermissionItem
import com.sameerasw.essentials.ui.components.sheets.PermissionsBottomSheet
import com.sameerasw.essentials.ui.components.sheets.SweepShapesBottomSheet
import com.sameerasw.essentials.ui.components.cards.FeatureCard
import com.sameerasw.essentials.ui.components.sliders.ConfigSliderItem
import com.sameerasw.essentials.ui.modifiers.highlight
import com.sameerasw.essentials.utils.HapticUtil
Expand All @@ -79,6 +81,7 @@ fun NotificationLightingSettingsUI(
// App selection Logic
var showAppSelectionSheet by remember { mutableStateOf(false) }
var showPermissionsSheet by remember { mutableStateOf(false) }
var showSweepShapesSheet by remember { mutableStateOf(false) }

// Corner radius state

Expand Down Expand Up @@ -414,6 +417,22 @@ fun NotificationLightingSettingsUI(
}
)

if (viewModel.notificationLightingSweepRandomShapes.value) {
FeatureCard(
title = stringResource(R.string.notification_lighting_sweep_select_shapes_title),
description = stringResource(R.string.notification_lighting_sweep_select_shapes_desc),
iconRes = R.drawable.rounded_circles_24,
isEnabled = true,
showToggle = false,
hasMoreSettings = true,
onToggle = {},
onClick = {
HapticUtil.performVirtualKeyHaptic(view)
showSweepShapesSheet = true
}
)
}

ConfigSliderItem(
title = stringResource(R.string.notification_lighting_sweep_thickness_title),
value = viewModel.notificationLightingSweepThickness.floatValue,
Expand Down Expand Up @@ -806,6 +825,13 @@ fun NotificationLightingSettingsUI(
)
}

if (showSweepShapesSheet) {
SweepShapesBottomSheet(
viewModel = viewModel,
onDismissRequest = { showSweepShapesSheet = false }
)
}

if (showPermissionsSheet) {
PermissionsBottomSheet(
onDismissRequest = { showPermissionsSheet = false },
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ import com.sameerasw.essentials.ui.components.containers.RoundedCardContainer
import com.sameerasw.essentials.ui.components.menus.SegmentedDropdownMenuItem
import com.sameerasw.essentials.ui.components.sheets.AppSelectionSheet
import com.sameerasw.essentials.ui.components.sheets.ShutUpPerAppSettingsSheet
import com.sameerasw.essentials.ui.components.sliders.ConfigSliderItem
import com.sameerasw.essentials.utils.AppUtil
import com.sameerasw.essentials.viewmodels.MainViewModel

Expand Down Expand Up @@ -64,6 +65,17 @@ fun ShutUpSettingsUI(
onToggle = {},
onClick = { isAppSelectionSheetOpen = true }
)

ConfigSliderItem(
title = stringResource(R.string.shut_up_restore_delay_title),
value = viewModel.shutUpRestoreDelay.intValue.toFloat(),
onValueChange = { viewModel.setShutUpRestoreDelay(it.toInt()) },
valueRange = 2f..60f,
increment = 1f,
valueFormatter = { "${it.toInt()}s" },
iconRes = R.drawable.rounded_timer_24,
subtitle = stringResource(R.string.shut_up_restore_delay_desc)
)
}


Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,37 +8,46 @@ import java.util.Random

object AmbientMusicShapeHelper {

private val allShapes = listOf(
MaterialShapes.Circle,
MaterialShapes.Square,
MaterialShapes.Slanted,
MaterialShapes.Arch,
MaterialShapes.Oval,
MaterialShapes.Pill,
MaterialShapes.Triangle,
MaterialShapes.Arrow,
MaterialShapes.Diamond,
MaterialShapes.ClamShell,
MaterialShapes.Pentagon,
MaterialShapes.Gem,
MaterialShapes.Sunny,
MaterialShapes.VerySunny,
MaterialShapes.Cookie4Sided,
MaterialShapes.Cookie6Sided,
MaterialShapes.Cookie7Sided,
MaterialShapes.Cookie9Sided,
MaterialShapes.Cookie12Sided,
MaterialShapes.Clover4Leaf,
MaterialShapes.Clover8Leaf,
MaterialShapes.SoftBurst,
MaterialShapes.Flower,
MaterialShapes.PuffyDiamond,
MaterialShapes.Ghostish,
MaterialShapes.PixelCircle,
MaterialShapes.Bun,
MaterialShapes.Heart
val allShapesWithNames = listOf(
"Circle" to MaterialShapes.Circle,
"Square" to MaterialShapes.Square,
"Slanted" to MaterialShapes.Slanted,
"Arch" to MaterialShapes.Arch,
"Oval" to MaterialShapes.Oval,
"Pill" to MaterialShapes.Pill,
"Triangle" to MaterialShapes.Triangle,
"Arrow" to MaterialShapes.Arrow,
"Diamond" to MaterialShapes.Diamond,
"ClamShell" to MaterialShapes.ClamShell,
"Pentagon" to MaterialShapes.Pentagon,
"Gem" to MaterialShapes.Gem,
"Sunny" to MaterialShapes.Sunny,
"VerySunny" to MaterialShapes.VerySunny,
"Cookie4Sided" to MaterialShapes.Cookie4Sided,
"Cookie6Sided" to MaterialShapes.Cookie6Sided,
"Cookie7Sided" to MaterialShapes.Cookie7Sided,
"Cookie9Sided" to MaterialShapes.Cookie9Sided,
"Cookie12Sided" to MaterialShapes.Cookie12Sided,
"Clover4Leaf" to MaterialShapes.Clover4Leaf,
"Clover8Leaf" to MaterialShapes.Clover8Leaf,
"SoftBurst" to MaterialShapes.SoftBurst,
"Flower" to MaterialShapes.Flower,
"PuffyDiamond" to MaterialShapes.PuffyDiamond,
"Ghostish" to MaterialShapes.Ghostish,
"PixelCircle" to MaterialShapes.PixelCircle,
"Bun" to MaterialShapes.Bun,
"Heart" to MaterialShapes.Heart
)

private val allShapes = allShapesWithNames.map { it.second }

fun getRandomPolygonFromSet(selectedNames: Set<String>): RoundedPolygon {
val filtered = allShapesWithNames.filter { selectedNames.contains(it.first) }
if (filtered.isEmpty()) return MaterialShapes.Cookie12Sided
val random = Random()
return filtered[random.nextInt(filtered.size)].second
}

fun getShapePath(seed: String?, size: Float, isRandomEnabled: Boolean = true): Path {
return getPolygon(seed, isRandomEnabled).toAndroidPath(size)
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ import androidx.savedstate.SavedStateRegistryOwner
import androidx.savedstate.setViewTreeSavedStateRegistryOwner
import com.sameerasw.essentials.domain.model.NotificationLightingSide
import com.sameerasw.essentials.domain.model.NotificationLightingStyle
import com.sameerasw.essentials.data.repository.SettingsRepository
import androidx.compose.ui.graphics.Color as ComposeColor

/**
Expand Down Expand Up @@ -239,7 +240,8 @@ object OverlayHelper {
overlay.setBackgroundColor(Color.BLACK)
}

val sweepView = SweepShapeView(context, color, strokeDp, randomShapes).apply {
val selectedShapes = SettingsRepository(context).getEdgeLightingSweepSelectedShapes()
val sweepView = SweepShapeView(context, color, strokeDp, randomShapes, selectedShapes).apply {
tag = "sweep_view"
alpha = 0f
layoutParams = FrameLayout.LayoutParams(
Expand All @@ -256,13 +258,14 @@ object OverlayHelper {
context: Context,
val color: Int,
val strokeDp: Float,
val useRandomShapes: Boolean
val useRandomShapes: Boolean,
val selectedShapes: Set<String>
) : View(context) {
var centerX: Float = 0f
var centerY: Float = 0f

private val polygon = if (useRandomShapes) {
AmbientMusicShapeHelper.getRandomPolygon()
AmbientMusicShapeHelper.getRandomPolygonFromSet(selectedShapes)
} else null

private val paint = android.graphics.Paint(android.graphics.Paint.ANTI_ALIAS_FLAG).apply {
Expand Down
Loading