Skip to content

Commit

Permalink
new release
Browse files Browse the repository at this point in the history
  • Loading branch information
robinsrk committed Dec 8, 2024
1 parent 83dbea9 commit e59b8d3
Show file tree
Hide file tree
Showing 21 changed files with 225 additions and 184 deletions.
1 change: 0 additions & 1 deletion app/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,6 @@
android:fullBackupContent="@xml/backup_rules"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="@style/Theme.Flip_2_DND"
tools:targetApi="31">
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ private const val PREFS_NAME = "flip_2_dnd_settings"
private const val KEY_SCREEN_OFF_ONLY = "screen_off_only"
private const val KEY_VIBRATION = "vibration"
private const val KEY_SOUND = "sound"
private const val KEY_PRIORITY_DND = "priority_dnd"

@Singleton
class SettingsRepositoryImpl @Inject constructor(
Expand All @@ -27,15 +28,10 @@ class SettingsRepositoryImpl @Inject constructor(
private val screenOffOnlyEnabled = MutableStateFlow(prefs.getBoolean(KEY_SCREEN_OFF_ONLY, false))
private val vibrationEnabled = MutableStateFlow(prefs.getBoolean(KEY_VIBRATION, true))
private val soundEnabled = MutableStateFlow(prefs.getBoolean(KEY_SOUND, true))
private val priorityDndEnabled = MutableStateFlow(prefs.getBoolean(KEY_PRIORITY_DND, false))

override fun getScreenOffOnlyEnabled(): Flow<Boolean> = screenOffOnlyEnabled

override suspend fun setScreenOffOnlyEnabled(enabled: Boolean) {
prefs.edit().putBoolean(KEY_SCREEN_OFF_ONLY, enabled).apply()
screenOffOnlyEnabled.value = enabled

private fun restartFlipDetectorService() {
try {
// Restart the FlipDetectorService
val serviceIntent = Intent(appContext, FlipDetectorService::class.java)
appContext.stopService(serviceIntent)
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
Expand All @@ -49,17 +45,35 @@ class SettingsRepositoryImpl @Inject constructor(
}
}

override fun getScreenOffOnlyEnabled(): Flow<Boolean> = screenOffOnlyEnabled

override suspend fun setScreenOffOnlyEnabled(enabled: Boolean) {
prefs.edit().putBoolean(KEY_SCREEN_OFF_ONLY, enabled).apply()
screenOffOnlyEnabled.value = enabled
restartFlipDetectorService()
}

override fun getVibrationEnabled(): Flow<Boolean> = vibrationEnabled

override suspend fun setVibrationEnabled(enabled: Boolean) {
prefs.edit().putBoolean(KEY_VIBRATION, enabled).apply()
vibrationEnabled.value = enabled
restartFlipDetectorService()
}

override fun getSoundEnabled(): Flow<Boolean> = soundEnabled

override suspend fun setSoundEnabled(enabled: Boolean) {
prefs.edit().putBoolean(KEY_SOUND, enabled).apply()
soundEnabled.value = enabled
restartFlipDetectorService()
}

override fun getPriorityDndEnabled(): Flow<Boolean> = priorityDndEnabled

override suspend fun setPriorityDndEnabled(enabled: Boolean) {
prefs.edit().putBoolean(KEY_PRIORITY_DND, enabled).apply()
priorityDndEnabled.value = enabled
restartFlipDetectorService()
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -9,4 +9,6 @@ interface SettingsRepository {
suspend fun setVibrationEnabled(enabled: Boolean)
fun getSoundEnabled(): Flow<Boolean>
suspend fun setSoundEnabled(enabled: Boolean)
fun getPriorityDndEnabled(): Flow<Boolean>
suspend fun setPriorityDndEnabled(enabled: Boolean)
}
Original file line number Diff line number Diff line change
@@ -1,14 +1,11 @@
package dev.robin.flip_2_dnd.presentation.settings

import android.content.Intent
import android.net.Uri
import androidx.compose.foundation.layout.*
import androidx.compose.material3.*
import androidx.compose.runtime.*
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.res.painterResource
import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.unit.dp
import androidx.hilt.navigation.compose.hiltViewModel
import androidx.navigation.NavController
Expand All @@ -17,21 +14,26 @@ import dev.robin.flip_2_dnd.R
@OptIn(ExperimentalMaterial3Api::class)
@Composable
fun SettingsScreen(
navController: NavController,
viewModel: SettingsViewModel = hiltViewModel()
viewModel: SettingsViewModel = hiltViewModel(),
navController: NavController? = null
) {
val state = viewModel.state
val soundEnabled by viewModel.soundEnabled.collectAsState()
val vibrationEnabled by viewModel.vibrationEnabled.collectAsState()
val screenOffOnly by viewModel.screenOffOnly.collectAsState()
val priorityDndEnabled by viewModel.priorityDndEnabled.collectAsState()

Scaffold(
topBar = {
TopAppBar(
title = { Text("Settings") },
navigationIcon = {
IconButton(onClick = { navController.popBackStack() }) {
Icon(
painter = painterResource(id = R.drawable.ic_arrow_back),
contentDescription = "Back"
)
if (navController != null) {
IconButton(onClick = { navController.popBackStack() }) {
Icon(
painter = painterResource(id = R.drawable.ic_arrow_back),
contentDescription = "Back"
)
}
}
}
)
Expand All @@ -41,105 +43,85 @@ fun SettingsScreen(
modifier = Modifier
.fillMaxSize()
.padding(paddingValues)
.padding(horizontal = 16.dp),
verticalArrangement = Arrangement.spacedBy(24.dp)
.padding(16.dp)
) {
// Behavior Settings Section
Text(
text = "Behavior",
style = MaterialTheme.typography.titleLarge,
modifier = Modifier.padding(vertical = 8.dp)
)

Column {
Text(
text = "Behavior",
style = MaterialTheme.typography.titleLarge,
fontWeight = FontWeight.Bold,
modifier = Modifier.padding(vertical = 8.dp)
SettingsSwitchItem(
title = "Screen Off Only",
description = "Enable DND only when screen is off",
checked = screenOffOnly,
onCheckedChange = { viewModel.setScreenOffOnly(it) }
)

// Screen Off Only Setting
Row(
modifier = Modifier
.fillMaxWidth()
.padding(vertical = 8.dp),
horizontalArrangement = Arrangement.SpaceBetween,
verticalAlignment = Alignment.CenterVertically
) {
Column {
Text(
text = "Screen Off Only",
style = MaterialTheme.typography.titleMedium
)
Text(
text = "Only turn off screen when flipped",
style = MaterialTheme.typography.bodyMedium,
color = MaterialTheme.colorScheme.onSurfaceVariant
)
}
Switch(
checked = state.isScreenOffOnly,
onCheckedChange = { viewModel.onScreenOffOnlyChange(it) }
)
}
SettingsSwitchItem(
title = "Priority DND",
description = "Enable Priority mode DND instead of Total Silence",
checked = priorityDndEnabled,
onCheckedChange = { viewModel.setPriorityDndEnabled(it) }
)
}

Divider()
Divider(modifier = Modifier.padding(vertical = 16.dp))

Text(
text = "Notifications",
style = MaterialTheme.typography.titleLarge,
modifier = Modifier.padding(vertical = 8.dp)
)

// Feedback Settings Section
Column {
Text(
text = "Feedback",
style = MaterialTheme.typography.titleLarge,
fontWeight = FontWeight.Bold,
modifier = Modifier.padding(vertical = 8.dp)
SettingsSwitchItem(
title = "Sound",
description = "Play sound when DND changes",
checked = soundEnabled,
onCheckedChange = { viewModel.setSoundEnabled(it) }
)

// Vibration Setting
Row(
modifier = Modifier
.fillMaxWidth()
.padding(vertical = 8.dp),
horizontalArrangement = Arrangement.SpaceBetween,
verticalAlignment = Alignment.CenterVertically
) {
Column {
Text(
text = "Vibration",
style = MaterialTheme.typography.titleMedium
)
Text(
text = "Vibrate when DND is toggled",
style = MaterialTheme.typography.bodyMedium,
color = MaterialTheme.colorScheme.onSurfaceVariant
)
}
Switch(
checked = state.isVibrationEnabled,
onCheckedChange = { viewModel.onVibrationChange(it) }
)
}

// Sound Setting
Row(
modifier = Modifier
.fillMaxWidth()
.padding(vertical = 8.dp),
horizontalArrangement = Arrangement.SpaceBetween,
verticalAlignment = Alignment.CenterVertically
) {
Column {
Text(
text = "Sound",
style = MaterialTheme.typography.titleMedium
)
Text(
text = "Play sound when DND is toggled",
style = MaterialTheme.typography.bodyMedium,
color = MaterialTheme.colorScheme.onSurfaceVariant
)
}
Switch(
checked = state.isSoundEnabled,
onCheckedChange = { viewModel.onSoundChange(it) }
)
}
SettingsSwitchItem(
title = "Vibration",
description = "Vibrate when DND changes",
checked = vibrationEnabled,
onCheckedChange = { viewModel.setVibrationEnabled(it) }
)
}
}
}
}

@Composable
fun SettingsSwitchItem(
title: String,
description: String,
checked: Boolean,
onCheckedChange: (Boolean) -> Unit
) {
Row(
modifier = Modifier
.fillMaxWidth()
.padding(vertical = 8.dp),
horizontalArrangement = Arrangement.SpaceBetween,
verticalAlignment = Alignment.CenterVertically
) {
Column {
Text(
text = title,
style = MaterialTheme.typography.titleMedium
)
Text(
text = description,
style = MaterialTheme.typography.bodyMedium,
color = MaterialTheme.colorScheme.onSurfaceVariant
)
}
Switch(
checked = checked,
onCheckedChange = onCheckedChange
)
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
package dev.robin.flip_2_dnd.presentation.settings

data class SettingsState(
val isScreenOffOnly: Boolean = false,
val isVibrationEnabled: Boolean = true,
val isSoundEnabled: Boolean = true,
val isPriorityDndEnabled: Boolean = false
)
Original file line number Diff line number Diff line change
@@ -1,12 +1,11 @@
package dev.robin.flip_2_dnd.presentation.settings

import android.app.Application
import androidx.compose.runtime.*
import androidx.lifecycle.AndroidViewModel
import androidx.lifecycle.viewModelScope
import dagger.hilt.android.lifecycle.HiltViewModel
import dev.robin.flip_2_dnd.domain.repository.SettingsRepository
import dev.robin.flip_2_dnd.presentation.main.MainState
import kotlinx.coroutines.flow.*
import kotlinx.coroutines.launch
import javax.inject.Inject

Expand All @@ -16,38 +15,62 @@ class SettingsViewModel @Inject constructor(
private val settingsRepository: SettingsRepository
) : AndroidViewModel(application) {

var state by mutableStateOf(MainState())
private set
private val _screenOffOnly = MutableStateFlow(false)
val screenOffOnly = _screenOffOnly.asStateFlow()

private val _soundEnabled = MutableStateFlow(true)
val soundEnabled = _soundEnabled.asStateFlow()

private val _vibrationEnabled = MutableStateFlow(true)
val vibrationEnabled = _vibrationEnabled.asStateFlow()

private val _priorityDndEnabled = MutableStateFlow(false)
val priorityDndEnabled = _priorityDndEnabled.asStateFlow()

init {
viewModelScope.launch {
settingsRepository.getScreenOffOnlyEnabled().collect { enabled ->
state = state.copy(isScreenOffOnly = enabled)
_screenOffOnly.value = enabled
}
}
viewModelScope.launch {
settingsRepository.getSoundEnabled().collect { enabled ->
_soundEnabled.value = enabled
}
}
viewModelScope.launch {
settingsRepository.getVibrationEnabled().collect { enabled ->
state = state.copy(isVibrationEnabled = enabled)
_vibrationEnabled.value = enabled
}
settingsRepository.getSoundEnabled().collect { enabled ->
state = state.copy(isSoundEnabled = enabled)
}
viewModelScope.launch {
settingsRepository.getPriorityDndEnabled().collect { enabled ->
_priorityDndEnabled.value = enabled
}
}
}

fun onScreenOffOnlyChange(enabled: Boolean) {
fun setScreenOffOnly(enabled: Boolean) {
viewModelScope.launch {
settingsRepository.setScreenOffOnlyEnabled(enabled)
}
}

fun onVibrationChange(enabled: Boolean) {
fun setPriorityDndEnabled(enabled: Boolean) {
viewModelScope.launch {
settingsRepository.setVibrationEnabled(enabled)
settingsRepository.setPriorityDndEnabled(enabled)
}
}

fun onSoundChange(enabled: Boolean) {
fun setSoundEnabled(enabled: Boolean) {
viewModelScope.launch {
settingsRepository.setSoundEnabled(enabled)
}
}

fun setVibrationEnabled(enabled: Boolean) {
viewModelScope.launch {
settingsRepository.setVibrationEnabled(enabled)
}
}
}
Loading

0 comments on commit e59b8d3

Please sign in to comment.