Skip to content
Merged
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 @@ -283,7 +283,7 @@ object StatusBarIconRegistry {
displayNameRes = R.string.icon_network_speed,
blacklistNames = listOf("network_speed"),
categoryRes = CAT_SYSTEM_STATUS,
iconRes = null
iconRes = R.drawable.rounded_shutter_speed_24
),

// --- OEM Specific ---
Expand Down Expand Up @@ -312,21 +312,21 @@ object StatusBarIconRegistry {
displayNameRes = R.string.icon_glove_mode,
blacklistNames = listOf("glove_mode", "glove"),
categoryRes = CAT_OEM_SPECIFIC,
iconRes = null
iconRes = R.drawable.rounded_touch_app_24
),
StatusBarIcon(
id = "frame_rate",
displayNameRes = R.string.icon_frame_rate,
blacklistNames = listOf("frame_rate_mode"),
categoryRes = CAT_OEM_SPECIFIC,
iconRes = null
iconRes = R.drawable.rounded_shutter_speed_24
),
StatusBarIcon(
id = "no_sim",
displayNameRes = R.string.icon_no_sim,
blacklistNames = listOf("nosim"),
categoryRes = CAT_PHONE_NETWORK,
iconRes = null
iconRes = R.drawable.rounded_signal_cellular_alt_24
),
StatusBarIcon(
id = "samsung_services",
Expand Down
41 changes: 41 additions & 0 deletions app/src/main/java/com/sameerasw/essentials/domain/diy/Action.kt
Original file line number Diff line number Diff line change
Expand Up @@ -336,5 +336,46 @@ sealed interface Action {
override val permissions: List<String> = listOf("SHIZUKU", "ROOT")
override val isConfigurable: Boolean = true
}

@Keep
enum class SettingsTable {
@SerializedName("SYSTEM")
SYSTEM,

@SerializedName("SECURE")
SECURE,

@SerializedName("GLOBAL")
GLOBAL
}

@Keep
data class SettingsEntry(
@SerializedName("table") val table: SettingsTable = SettingsTable.SYSTEM,
@SerializedName("key") val key: String = "",
@SerializedName("value") val value: String = ""
)

@Keep
data class CustomSettings(
@SerializedName("entries") val entries: List<SettingsEntry> = emptyList()
) : Action {
override val title: Int get() = R.string.diy_action_custom_settings
override val icon: Int get() = R.drawable.rounded_settings_24
override val isConfigurable: Boolean = true
override val permissions: List<String>
get() {
val perms = mutableSetOf<String>()
for (entry in entries) {
when (entry.table) {
SettingsTable.SYSTEM -> perms.add("WRITE_SETTINGS")
SettingsTable.SECURE -> perms.add("WRITE_SECURE_SETTINGS")
SettingsTable.GLOBAL -> perms.add("WRITE_SECURE_SETTINGS")
}
}
return perms.toList()
}
}
}


Original file line number Diff line number Diff line change
Expand Up @@ -135,14 +135,15 @@ fun initPermissionRegistry() {
// Safe Volume Warning feature
PermissionRegistry.register("WRITE_SECURE_SETTINGS", R.string.feat_safe_volume_title)

// Notification Snoozing feature
PermissionRegistry.register("WRITE_SECURE_SETTINGS", R.string.feat_notification_snoozing_title)

// Install unknown packages feature
// Watch Call Sync & Notification Sync
PermissionRegistry.register("READ_PHONE_STATE", R.string.watch_call_sync_title)
PermissionRegistry.register("ANSWER_PHONE_CALLS", R.string.watch_call_sync_title)
PermissionRegistry.register("READ_CONTACTS", R.string.watch_call_sync_title)
PermissionRegistry.register("READ_CALL_LOG", R.string.watch_call_sync_title)
PermissionRegistry.register("NOTIFICATION_LISTENER", R.string.watch_notif_sync_title)

// DIY Automations feature
PermissionRegistry.register("WRITE_SECURE_SETTINGS", R.string.tab_diy)
PermissionRegistry.register("WRITE_SETTINGS", R.string.tab_diy)
}
Original file line number Diff line number Diff line change
Expand Up @@ -16,12 +16,14 @@ import android.hardware.camera2.CameraManager
import android.media.AudioManager
import android.net.wifi.WifiManager
import android.os.Build
import android.provider.Settings
import android.view.KeyEvent
import android.widget.Toast
import com.sameerasw.essentials.domain.HapticFeedbackType
import com.sameerasw.essentials.domain.diy.Action
import com.sameerasw.essentials.services.tiles.ScreenOffAccessibilityService
import com.sameerasw.essentials.utils.DeviceLockUtils
import com.sameerasw.essentials.utils.ShellUtils
import com.sameerasw.essentials.utils.performHapticFeedback
import rikka.shizuku.ShizukuBinderWrapper
import rikka.shizuku.SystemServiceHelper
Expand Down Expand Up @@ -650,6 +652,29 @@ object CombinedActionExecutor {
com.sameerasw.essentials.utils.FreezeManager.unfreezeApp(context, pkg)
}
}
is Action.CustomSettings -> {
val resolver = context.contentResolver
for (entry in action.entries) {
val success = try {
when (entry.table) {
Action.SettingsTable.SYSTEM -> Settings.System.putString(resolver, entry.key, entry.value)
Action.SettingsTable.SECURE -> Settings.Secure.putString(resolver, entry.key, entry.value)
Action.SettingsTable.GLOBAL -> Settings.Global.putString(resolver, entry.key, entry.value)
}
} catch (e: Exception) {
false
}
if (!success) {
val tableArg = when (entry.table) {
Action.SettingsTable.SYSTEM -> "system"
Action.SettingsTable.SECURE -> "secure"
Action.SettingsTable.GLOBAL -> "global"
}
val safeValue = if (entry.value.contains(" ")) "\"${entry.value}\"" else entry.value
ShellUtils.runCommand(context, "settings put $tableArg ${entry.key} $safeValue")
}
}
}
}

}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,7 @@ import com.sameerasw.essentials.ui.core.containers.RoundedCardContainer
import com.sameerasw.essentials.ui.core.pickers.SegmentedPicker
import com.sameerasw.essentials.ui.core.sheets.AppSelectionSheet
import com.sameerasw.essentials.ui.core.sheets.BluetoothDeviceSelectionSheet
import com.sameerasw.essentials.ui.core.sheets.CustomSettingsSheet
import com.sameerasw.essentials.ui.core.sheets.DimWallpaperSettingsSheet
import com.sameerasw.essentials.ui.core.sheets.ScreenOffSettingsSheet
import com.sameerasw.essentials.ui.core.sheets.SingleAppSelectionSheet
Expand Down Expand Up @@ -265,6 +266,7 @@ class AutomationEditorActivity : ComponentActivity() {
var showTimeSettings by remember { mutableStateOf(false) }
var showBluetoothSettings by remember { mutableStateOf(false) }
var showWifiSettings by remember { mutableStateOf(false) }
var showCustomSettingsSettings by remember { mutableStateOf(false) }
var configAction by remember { mutableStateOf<Action?>(null) } // Generic config action

val isTriggerConfigured = when (val trigger = selectedTrigger) {
Expand Down Expand Up @@ -295,6 +297,7 @@ class AutomationEditorActivity : ComponentActivity() {

fun isActionConfigured(action: Action?): Boolean = when (action) {
is Action.OpenApp -> action.packageName.isNotBlank()
is Action.CustomSettings -> action.entries.isNotEmpty()
else -> true
}

Expand Down Expand Up @@ -910,6 +913,7 @@ class AutomationEditorActivity : ComponentActivity() {
Action.ToggleFlashlight,
Action.TurnOnLowPower,
Action.TurnOffLowPower,
Action.CustomSettings(),
Action.CircleToSearch,
Action.TakeScreenshot,
Action.ShowNotification,
Expand Down Expand Up @@ -996,6 +1000,7 @@ class AutomationEditorActivity : ComponentActivity() {
temporarySelectedAppsForAction = resolvedAction.packageNames
showFreezeAppsSettings = true
}
is Action.CustomSettings -> showCustomSettingsSettings = true
else -> {}
}
}
Expand Down Expand Up @@ -1279,6 +1284,27 @@ class AutomationEditorActivity : ComponentActivity() {
excludePackages = if (automationType == Automation.Type.APP) selectedApps else emptyList()
)
}

if (showCustomSettingsSettings && configAction is Action.CustomSettings) {
CustomSettingsSheet(
initialAction = configAction as Action.CustomSettings,
onDismiss = { showCustomSettingsSettings = false },
onSave = { newAction ->
showCustomSettingsSettings = false
when (automationType) {
Automation.Type.TRIGGER -> selectedAction = newAction
Automation.Type.ACTION_SHORTCUT, Automation.Type.PIXEL_SEARCHBAR -> selectedAction =
newAction

Automation.Type.STATE, Automation.Type.APP -> {
if (selectedActionTab == 0) selectedInAction = newAction
else selectedOutAction = newAction
}
}
configAction = null
}
)
}
}

if (showPermissionSheet) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,16 +16,12 @@ import android.content.Context
import android.content.Intent
import android.provider.Settings
import androidx.activity.compose.BackHandler
import androidx.compose.animation.AnimatedContent
import androidx.compose.animation.AnimatedVisibility
import androidx.compose.animation.core.tween
import androidx.compose.animation.expandVertically
import androidx.compose.animation.fadeIn
import androidx.compose.animation.fadeOut
import androidx.compose.animation.shrinkVertically
import androidx.compose.animation.togetherWith
import androidx.compose.foundation.BorderStroke
import androidx.compose.foundation.Image
import androidx.compose.foundation.basicMarquee
import androidx.compose.foundation.clickable
import androidx.compose.foundation.layout.Arrangement
Expand Down Expand Up @@ -1047,14 +1043,6 @@ fun SetupFeatures(
val isSearchingViewModel = viewModel.isSearching.value
val recentSearches by viewModel.recentSearches

var showInstagramGraphic by rememberSaveable { mutableStateOf(true) }
LaunchedEffect(Unit) {
if (showInstagramGraphic) {
delay(5000)
showInstagramGraphic = false
}
}

LazyColumn(
state = lazyListState,
modifier = modifier.fillMaxSize(),
Expand Down Expand Up @@ -1090,55 +1078,38 @@ fun SetupFeatures(
verticalArrangement = Arrangement.Center
) {
Spacer(modifier = Modifier.height(statusBarPadding))
AnimatedContent(
targetState = showInstagramGraphic,
transitionSpec = {
fadeIn(animationSpec = tween(600)) togetherWith fadeOut(animationSpec = tween(600))
},
label = "InstagramTitleSwap"
) { isShowingInstagram ->
if (isShowingInstagram) {
Icon(
painter = painterResource(id = R.drawable.essentials_instagram),
contentDescription = null,
modifier = Modifier.height(28.dp),
tint = if (thresholdPassed) MaterialTheme.colorScheme.onPrimary else MaterialTheme.colorScheme.onSurface
)
} else {
Row(verticalAlignment = Alignment.CenterVertically) {
Box(
modifier = Modifier
.width(chevronWidth)
.graphicsLayer { alpha = chevronAlpha }
) {
Row(verticalAlignment = Alignment.CenterVertically) {
Box(
Icon(
imageVector = Icons.Rounded.KeyboardArrowDown,
contentDescription = null,
modifier = Modifier
.width(chevronWidth)
.graphicsLayer { alpha = chevronAlpha }
) {
Row(verticalAlignment = Alignment.CenterVertically) {
Icon(
imageVector = Icons.Rounded.KeyboardArrowDown,
contentDescription = null,
modifier = Modifier
.size(24.dp)
.graphicsLayer {
rotationZ =
(displayFraction * 180f).coerceIn(0f, 180f)
},
tint = contentColor
)
Spacer(modifier = Modifier.width(8.dp))
}
}
Text(
text = deviceInfo.deviceName,
style = MaterialTheme.typography.titleMedium.copy(
fontFamily = fontFamily
),
modifier = Modifier.graphicsLayer {
scaleX = textScale
scaleY = textScale
},
color = if (thresholdPassed) MaterialTheme.colorScheme.onPrimary else MaterialTheme.colorScheme.onSurface
.size(24.dp)
.graphicsLayer {
rotationZ =
(displayFraction * 180f).coerceIn(0f, 180f)
},
tint = contentColor
)
Spacer(modifier = Modifier.width(8.dp))
}
}
Text(
text = deviceInfo.deviceName,
style = MaterialTheme.typography.titleMedium.copy(
fontFamily = fontFamily
),
modifier = Modifier.graphicsLayer {
scaleX = textScale
scaleY = textScale
},
color = if (thresholdPassed) MaterialTheme.colorScheme.onPrimary else MaterialTheme.colorScheme.onSurface
)
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -152,23 +152,19 @@ fun FeatureCard(
)
} else if (iconRes != null) {
val context = LocalContext.current
val isValid = remember(iconRes) {
val validIconRes = remember(iconRes) {
try {
val value = android.util.TypedValue()
context.resources.getValue(iconRes, value, true)
val path = value.string?.toString() ?: ""
!path.endsWith(".gif", ignoreCase = true)
if (iconRes != 0 && context.resources.getResourceTypeName(iconRes) == "drawable") {
iconRes
} else {
R.drawable.rounded_settings_24
}
} catch (e: Throwable) {
false
R.drawable.rounded_settings_24
}
}
val painter = if (isValid) {
painterResource(id = iconRes)
} else {
painterResource(id = R.drawable.rounded_settings_accessibility_24)
}
Icon(
painter = painter,
painter = painterResource(id = validIconRes),
contentDescription = resolvedTitle,
modifier = Modifier.size(24.dp),
tint = ColorUtil.getVibrantColorFor(resolvedTitle)
Expand Down
Loading
Loading