Skip to content

Commit 1515c76

Browse files
authored
Merge pull request #5 from sameerasw/develop
Develop
2 parents b6aa02f + f934c8e commit 1515c76

39 files changed

+332
-216
lines changed

app/build.gradle.kts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,8 +14,8 @@ android {
1414
applicationId = "com.sameerasw.essentials"
1515
minSdk = 23
1616
targetSdk = 36
17-
versionCode = 3
18-
versionName = "3.0"
17+
versionCode = 4
18+
versionName = "3.1"
1919

2020
testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"
2121
}
15.6 KB
Loading

app/src/main/java/com/sameerasw/essentials/FeatureSettingsActivity.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,7 @@ class FeatureSettingsActivity : ComponentActivity() {
5353
val feature = intent.getStringExtra("feature") ?: "Feature"
5454
val featureDescriptions = mapOf(
5555
"Screen off widget" to "Invisible widget to turn the screen off",
56-
"Statusbar icons" to "Control the visibility of statusbar icons",
56+
"Statusbar icons" to "Control statusbar icons visibility",
5757
"Caffeinate" to "Keep the screen awake",
5858
"Edge lighting" to "Preview edge lighting effects on new notifications"
5959
)

app/src/main/java/com/sameerasw/essentials/MainActivity.kt

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,10 +16,12 @@ import androidx.compose.runtime.*
1616
import androidx.compose.ui.input.nestedscroll.nestedScroll
1717
import androidx.compose.ui.Modifier
1818
import androidx.compose.ui.platform.LocalContext
19+
import androidx.compose.ui.tooling.preview.Preview
1920
import com.sameerasw.essentials.ui.components.ReusableTopAppBar
2021
import com.sameerasw.essentials.ui.composables.SetupFeatures
2122
import com.sameerasw.essentials.ui.theme.EssentialsTheme
2223
import com.sameerasw.essentials.utils.ShizukuUtils
24+
import com.sameerasw.essentials.utils.HapticUtil
2325
import com.sameerasw.essentials.viewmodels.MainViewModel
2426

2527
@OptIn(ExperimentalMaterial3Api::class)
@@ -31,6 +33,8 @@ class MainActivity : ComponentActivity() {
3133
enableEdgeToEdge()
3234
// Initialize Shizuku
3335
ShizukuUtils.initialize()
36+
// Initialize HapticUtil with saved preferences
37+
HapticUtil.initialize(this)
3438
// initialize permission registry
3539
initPermissionRegistry()
3640
viewModel.check(this)

app/src/main/java/com/sameerasw/essentials/SettingsActivity.kt

Lines changed: 37 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,8 @@ import androidx.compose.material3.TopAppBarDefaults
2323
import androidx.compose.material3.rememberTopAppBarState
2424
import androidx.compose.runtime.Composable
2525
import androidx.compose.runtime.LaunchedEffect
26-
import androidx.compose.runtime.getValue
26+
import androidx.compose.runtime.mutableStateOf
27+
import androidx.compose.runtime.remember
2728
import androidx.compose.ui.Modifier
2829
import androidx.compose.ui.input.nestedscroll.nestedScroll
2930
import androidx.compose.ui.platform.LocalContext
@@ -33,12 +34,16 @@ import com.sameerasw.essentials.ui.theme.EssentialsTheme
3334
import androidx.compose.foundation.layout.Arrangement
3435
import androidx.compose.foundation.layout.Spacer
3536
import androidx.compose.foundation.layout.height
37+
import androidx.compose.foundation.layout.Spacer
38+
import androidx.compose.foundation.layout.height
39+
import androidx.compose.runtime.getValue
3640
import androidx.compose.ui.Alignment
3741
import androidx.compose.ui.unit.dp
3842
import androidx.core.app.ActivityCompat
3943
import com.sameerasw.essentials.ui.components.cards.PermissionCard
4044
import com.sameerasw.essentials.ui.components.dialogs.AboutSection
4145
import com.sameerasw.essentials.viewmodels.MainViewModel
46+
import com.sameerasw.essentials.utils.HapticUtil
4247
import rikka.shizuku.Shizuku
4348

4449
@OptIn(ExperimentalMaterial3Api::class)
@@ -115,6 +120,7 @@ fun SettingsContent(viewModel: MainViewModel, modifier: Modifier = Modifier) {
115120
val isOverlayPermissionGranted by viewModel.isOverlayPermissionGranted
116121
val isNotificationListenerEnabled by viewModel.isNotificationListenerEnabled
117122
val context = LocalContext.current
123+
val isAppHapticsEnabled = remember { mutableStateOf(HapticUtil.loadAppHapticsEnabled(context)) }
118124

119125
Column(
120126
modifier = modifier
@@ -124,6 +130,36 @@ fun SettingsContent(viewModel: MainViewModel, modifier: Modifier = Modifier) {
124130
verticalArrangement = Arrangement.spacedBy(4.dp),
125131
horizontalAlignment = Alignment.Start
126132
) {
133+
// App Settings Section
134+
androidx.compose.material3.Text(
135+
text = "App Settings",
136+
style = androidx.compose.material3.MaterialTheme.typography.titleMedium,
137+
modifier = Modifier.padding(start = 16.dp, top = 16.dp, bottom = 8.dp),
138+
color = androidx.compose.material3.MaterialTheme.colorScheme.onSurfaceVariant
139+
)
140+
141+
RoundedCardContainer {
142+
com.sameerasw.essentials.ui.components.cards.IconToggleItem(
143+
iconRes = R.drawable.rounded_mobile_vibrate_24,
144+
title = "Haptic Feedback",
145+
isChecked = isAppHapticsEnabled.value,
146+
onCheckedChange = { isChecked ->
147+
isAppHapticsEnabled.value = isChecked
148+
HapticUtil.saveAppHapticsEnabled(context, isChecked)
149+
}
150+
)
151+
}
152+
153+
Spacer(modifier = Modifier.height(16.dp))
154+
155+
// Permissions Section
156+
androidx.compose.material3.Text(
157+
text = "Permissions",
158+
style = androidx.compose.material3.MaterialTheme.typography.titleMedium,
159+
modifier = Modifier.padding(start = 16.dp, top = 16.dp, bottom = 8.dp),
160+
color = androidx.compose.material3.MaterialTheme.colorScheme.onSurfaceVariant
161+
)
162+
127163
RoundedCardContainer {
128164
PermissionCard(
129165
iconRes = R.drawable.rounded_settings_accessibility_24,

app/src/main/java/com/sameerasw/essentials/ui/components/ReusableTopAppBar.kt

Lines changed: 32 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,22 +1,28 @@
11
package com.sameerasw.essentials.ui.components
22

33
import androidx.compose.foundation.layout.Column
4+
import androidx.compose.foundation.layout.padding
45
import androidx.compose.foundation.layout.size
56
import androidx.compose.material3.ExperimentalMaterial3Api
67
import androidx.compose.material3.ExperimentalMaterial3ExpressiveApi
78
import androidx.compose.material3.Icon
89
import androidx.compose.material3.IconButton
10+
import androidx.compose.material3.IconButtonColors
11+
import androidx.compose.material3.IconButtonDefaults
912
import androidx.compose.material3.LargeFlexibleTopAppBar
1013
import androidx.compose.material3.Text
1114
import androidx.compose.material3.TopAppBarDefaults
1215
import androidx.compose.material3.TopAppBarScrollBehavior
1316
import androidx.compose.material3.MaterialTheme
1417
import androidx.compose.runtime.Composable
1518
import androidx.compose.ui.Modifier
19+
import androidx.compose.ui.platform.LocalView
1620
import androidx.compose.ui.res.painterResource
1721
import androidx.compose.ui.text.style.TextOverflow
22+
import androidx.compose.ui.tooling.preview.Preview
1823
import com.sameerasw.essentials.R
1924
import androidx.compose.ui.unit.dp
25+
import com.sameerasw.essentials.utils.HapticUtil
2026

2127
@OptIn(ExperimentalMaterial3Api::class, ExperimentalMaterial3ExpressiveApi::class)
2228
@Composable
@@ -38,6 +44,7 @@ fun ReusableTopAppBar(
3844
colors = TopAppBarDefaults.topAppBarColors(
3945
containerColor = MaterialTheme.colorScheme.surfaceContainer
4046
),
47+
modifier = Modifier.padding(horizontal = 8.dp),
4148
expandedHeight = if (subtitle != null) 200.dp else 160.dp,
4249
collapsedHeight = 64.dp,
4350

@@ -52,7 +59,7 @@ fun ReusableTopAppBar(
5259
)
5360
Text(
5461
subtitle,
55-
style = MaterialTheme.typography.bodySmall,
62+
style = MaterialTheme.typography.bodyMedium,
5663
color = MaterialTheme.colorScheme.onSurfaceVariant,
5764
maxLines = 1,
5865
overflow = TextOverflow.Ellipsis
@@ -69,7 +76,17 @@ fun ReusableTopAppBar(
6976
},
7077
navigationIcon = {
7178
if (hasBack) {
72-
IconButton(onClick = { onBackClick?.invoke() }, modifier = Modifier.size(64.dp)) {
79+
val view = LocalView.current
80+
IconButton(
81+
onClick = {
82+
HapticUtil.performVirtualKeyHaptic(view)
83+
onBackClick?.invoke()
84+
},
85+
colors = IconButtonDefaults.iconButtonColors(
86+
containerColor = MaterialTheme.colorScheme.surfaceBright
87+
),
88+
modifier = Modifier.size(48.dp)
89+
) {
7390
Icon(
7491
painter = painterResource(id = R.drawable.rounded_arrow_back_24),
7592
contentDescription = "Back",
@@ -80,10 +97,21 @@ fun ReusableTopAppBar(
8097
},
8198
actions = {
8299

100+
83101
if (hasSettings) {
84-
IconButton(onClick = { onSettingsClick?.invoke() }, modifier = Modifier.size(64.dp)) {
102+
val view = LocalView.current
103+
IconButton(
104+
onClick = {
105+
HapticUtil.performVirtualKeyHaptic(view)
106+
onSettingsClick?.invoke()
107+
},
108+
colors = IconButtonDefaults.iconButtonColors(
109+
containerColor = MaterialTheme.colorScheme.surfaceBright
110+
),
111+
modifier = Modifier.size(48.dp)
112+
) {
85113
Icon(
86-
painter = painterResource(id = R.drawable.rounded_settings_heart_24),
114+
painter = painterResource(id = R.drawable.ic_stat_name),
87115
contentDescription = "Settings",
88116
modifier = Modifier.size(32.dp)
89117
)

app/src/main/java/com/sameerasw/essentials/ui/components/cards/FeatureCard.kt

Lines changed: 19 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -18,9 +18,11 @@ import androidx.compose.material3.Text
1818
import androidx.compose.runtime.Composable
1919
import androidx.compose.ui.Alignment
2020
import androidx.compose.ui.Modifier
21+
import androidx.compose.ui.platform.LocalView
2122
import androidx.compose.ui.res.painterResource
2223
import androidx.compose.ui.unit.dp
2324
import com.sameerasw.essentials.R
25+
import com.sameerasw.essentials.utils.HapticUtil
2426

2527
@Composable
2628
fun FeatureCard(
@@ -35,12 +37,17 @@ fun FeatureCard(
3537
onDisabledToggleClick: (() -> Unit)? = null,
3638
description: String? = null
3739
) {
40+
val view = LocalView.current
41+
3842
Card(
3943
colors = CardDefaults.cardColors(
4044
containerColor = MaterialTheme.colorScheme.surfaceBright
4145
),
4246
shape = MaterialTheme.shapes.extraSmall,
43-
modifier = modifier.clickable { onClick() }) {
47+
modifier = modifier.clickable {
48+
HapticUtil.performVirtualKeyHaptic(view)
49+
onClick()
50+
}) {
4451
Box(modifier = Modifier
4552
.fillMaxWidth()
4653
.padding(16.dp)) {
@@ -69,7 +76,7 @@ fun FeatureCard(
6976
if (description != null) {
7077
Text(
7178
text = description,
72-
style = MaterialTheme.typography.bodySmall,
79+
style = MaterialTheme.typography.bodyMedium,
7380
color = MaterialTheme.colorScheme.onSurfaceVariant
7481
)
7582
}
@@ -92,13 +99,21 @@ fun FeatureCard(
9299
Box {
93100
Switch(
94101
checked = if (isToggleEnabled) isEnabled else false,
95-
onCheckedChange = { checked -> if (isToggleEnabled) onToggle(checked) },
102+
onCheckedChange = { checked ->
103+
if (isToggleEnabled) {
104+
HapticUtil.performVirtualKeyHaptic(view)
105+
onToggle(checked)
106+
}
107+
},
96108
enabled = isToggleEnabled
97109
)
98110

99111
if (!isToggleEnabled && onDisabledToggleClick != null) {
100112
// Invisible overlay catches taps even if the child consumes them
101-
Box(modifier = Modifier.matchParentSize().clickable { onDisabledToggleClick() })
113+
Box(modifier = Modifier.matchParentSize().clickable {
114+
HapticUtil.performVirtualKeyHaptic(view)
115+
onDisabledToggleClick()
116+
})
102117
}
103118
}
104119
}

app/src/main/java/com/sameerasw/essentials/ui/components/cards/IconToggleItem.kt

Lines changed: 15 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -18,8 +18,10 @@ import androidx.compose.material3.Text
1818
import androidx.compose.runtime.Composable
1919
import androidx.compose.ui.Alignment
2020
import androidx.compose.ui.Modifier
21+
import androidx.compose.ui.platform.LocalView
2122
import androidx.compose.ui.res.painterResource
2223
import androidx.compose.ui.unit.dp
24+
import com.sameerasw.essentials.utils.HapticUtil
2325

2426
@Composable
2527
fun IconToggleItem(
@@ -32,6 +34,8 @@ fun IconToggleItem(
3234
enabled: Boolean = true,
3335
onDisabledClick: (() -> Unit)? = null
3436
) {
37+
val view = LocalView.current
38+
3539
Row(
3640
modifier = modifier
3741
.fillMaxWidth()
@@ -60,7 +64,7 @@ fun IconToggleItem(
6064
)
6165
Text(
6266
text = description,
63-
style = MaterialTheme.typography.labelSmall,
67+
style = MaterialTheme.typography.labelMedium,
6468
color = MaterialTheme.colorScheme.onSurfaceVariant
6569
)
6670
}
@@ -75,12 +79,20 @@ fun IconToggleItem(
7579
Box {
7680
Switch(
7781
checked = if (enabled) isChecked else false,
78-
onCheckedChange = { checked -> if (enabled) onCheckedChange(checked) },
82+
onCheckedChange = { checked ->
83+
if (enabled) {
84+
HapticUtil.performVirtualKeyHaptic(view)
85+
onCheckedChange(checked)
86+
}
87+
},
7988
enabled = enabled
8089
)
8190

8291
if (!enabled && onDisabledClick != null) {
83-
Box(modifier = Modifier.matchParentSize().clickable { onDisabledClick() })
92+
Box(modifier = Modifier.matchParentSize().clickable {
93+
HapticUtil.performVirtualKeyHaptic(view)
94+
onDisabledClick()
95+
})
8496
}
8597
}
8698
}

0 commit comments

Comments
 (0)