From e280fb4f2d1ffd80a8377e99bf37e54b64d02f12 Mon Sep 17 00:00:00 2001 From: Sourav Das Date: Sat, 18 Mar 2023 18:50:58 +0600 Subject: [PATCH 01/16] Log notifications, Updated DB operations --- .../souravdas/hush/activities/MainActivity.kt | 4 +- .../java/dev/souravdas/hush/arch/AppLogDao.kt | 17 ++ .../souravdas/hush/arch/AppLogRepository.kt | 16 ++ .../dev/souravdas/hush/arch/MainActivityVM.kt | 54 +++-- .../dev/souravdas/hush/arch/SelectAppCache.kt | 8 +- .../dev/souravdas/hush/arch/SelectedAppDao.kt | 4 +- .../java/dev/souravdas/hush/base/HushDB.kt | 5 +- .../java/dev/souravdas/hush/base/Modules.kt | 12 + .../souravdas/hush/compose/main/AppList.kt | 104 +++++++++ .../UIKit.kt => compose/main/MainScreen.kt} | 210 +----------------- .../dev/souravdas/hush/compose/main/Modals.kt | 139 ++++++++++++ .../java/dev/souravdas/hush/models/AppLog.kt | 26 +++ .../dev/souravdas/hush/models/SelectedApp.kt | 20 +- .../souravdas/hush/services/HushService.kt | 28 ++- 14 files changed, 409 insertions(+), 238 deletions(-) create mode 100644 app/src/main/java/dev/souravdas/hush/arch/AppLogDao.kt create mode 100644 app/src/main/java/dev/souravdas/hush/arch/AppLogRepository.kt create mode 100644 app/src/main/java/dev/souravdas/hush/compose/main/AppList.kt rename app/src/main/java/dev/souravdas/hush/{activities/UIKit.kt => compose/main/MainScreen.kt} (81%) create mode 100644 app/src/main/java/dev/souravdas/hush/compose/main/Modals.kt create mode 100644 app/src/main/java/dev/souravdas/hush/models/AppLog.kt diff --git a/app/src/main/java/dev/souravdas/hush/activities/MainActivity.kt b/app/src/main/java/dev/souravdas/hush/activities/MainActivity.kt index a10a12e..dbbce39 100644 --- a/app/src/main/java/dev/souravdas/hush/activities/MainActivity.kt +++ b/app/src/main/java/dev/souravdas/hush/activities/MainActivity.kt @@ -16,7 +16,7 @@ import androidx.core.app.NotificationManagerCompat import androidx.lifecycle.lifecycleScope import dagger.hilt.android.AndroidEntryPoint import dev.sourav.emptycompose.ui.theme.HushTheme -import dev.souravdas.hush.activities.UIKit +import dev.souravdas.hush.compose.main.MainScreen import dev.souravdas.hush.arch.MainActivityVM import dev.souravdas.hush.others.Utils import dev.souravdas.hush.services.KeepAliveService @@ -37,7 +37,7 @@ class MainActivity : ComponentActivity() { viewModel.getSelectedApp() HushTheme() { - UIKit().MainActivityScreen(onNotificationPermissionGet = { + MainScreen().MainActivityScreen(onNotificationPermissionGet = { openNotificationAccessSettingsIfNeeded(this) }, checkNotificationPermission = { isNotificationListenerEnabled(this) diff --git a/app/src/main/java/dev/souravdas/hush/arch/AppLogDao.kt b/app/src/main/java/dev/souravdas/hush/arch/AppLogDao.kt new file mode 100644 index 0000000..f450054 --- /dev/null +++ b/app/src/main/java/dev/souravdas/hush/arch/AppLogDao.kt @@ -0,0 +1,17 @@ +package dev.souravdas.hush.arch + +import androidx.room.Dao +import androidx.room.Insert +import dev.souravdas.hush.models.AppLog + +/** + * Created by Sourav + * On 3/18/2023 12:39 PM + * For Hush! + */ +@Dao +interface AppLogDao { + + @Insert + suspend fun insertLog(appLog: AppLog) +} \ No newline at end of file diff --git a/app/src/main/java/dev/souravdas/hush/arch/AppLogRepository.kt b/app/src/main/java/dev/souravdas/hush/arch/AppLogRepository.kt new file mode 100644 index 0000000..ddefd7f --- /dev/null +++ b/app/src/main/java/dev/souravdas/hush/arch/AppLogRepository.kt @@ -0,0 +1,16 @@ +package dev.souravdas.hush.arch + +import dev.souravdas.hush.models.AppLog +import javax.inject.Inject + +/** + * Created by Sourav + * On 3/18/2023 12:39 PM + * For Hush! + */ +class AppLogRepository @Inject constructor(val appLogDao: AppLogDao) { + + suspend fun insertLog(appLog: AppLog) { + appLogDao.insertLog(appLog) + } +} \ No newline at end of file diff --git a/app/src/main/java/dev/souravdas/hush/arch/MainActivityVM.kt b/app/src/main/java/dev/souravdas/hush/arch/MainActivityVM.kt index 7569e1c..4029452 100644 --- a/app/src/main/java/dev/souravdas/hush/arch/MainActivityVM.kt +++ b/app/src/main/java/dev/souravdas/hush/arch/MainActivityVM.kt @@ -6,7 +6,7 @@ import androidx.lifecycle.viewModelScope import dagger.hilt.android.lifecycle.HiltViewModel import dev.sourav.base.datastore.DataStoreManager import dev.souravdas.hush.HushApp -import dev.souravdas.hush.activities.UIKit +import dev.souravdas.hush.compose.main.MainScreen import dev.souravdas.hush.base.BaseViewModel import dev.souravdas.hush.models.InstalledPackageInfo import dev.souravdas.hush.models.SelectedApp @@ -42,9 +42,10 @@ class MainActivityVM @Inject constructor( val selectedAppFromDB = selectAppRepository.getSelectedApp(selectedApp.packageName ?: "") if (selectedAppFromDB != null) { - selectAppRepository.delete(selectedAppFromDB) - } - selectAppRepository.addSelectedApp(selectedApp) + selectedAppFromDB.isComplete = false + selectAppRepository.update(selectedAppFromDB) + }else + selectAppRepository.addSelectedApp(selectedApp) } } @@ -127,29 +128,42 @@ class MainActivityVM @Inject constructor( fun addConfigInSelectedApp( app: SelectedApp, type: HushType, - startEndTime: UIKit.StartEndTime, + startEndTime: MainScreen.StartEndTime, duration: Long, daysList: List, - logNotification: Boolean + logNotificationvalue: Boolean ) { executedSuspendedCodeBlock { - val selectedApp = SelectedApp( - appName = app.appName, - packageName = app.packageName, - hushType = type, - durationInMinutes = duration, - muteDays = utils.getStringFromDaysList(daysList), - startTime = utils.toLocalTime(startEndTime.startTime), - endTime = utils.toLocalTime(startEndTime.endTime), - timeUpdated = System.currentTimeMillis(), - isComplete = true - ) - val selectedAppFromDB = selectAppRepository.getSelectedApp(app.packageName ?: "") if (selectedAppFromDB != null) { - selectAppRepository.delete(selectedAppFromDB) + with(selectedAppFromDB) { + appName = app.appName + packageName = app.packageName + hushType = type + durationInMinutes = duration + muteDays = utils.getStringFromDaysList(daysList) + startTime = utils.toLocalTime(startEndTime.startTime) + endTime = utils.toLocalTime(startEndTime.endTime) + timeUpdated = System.currentTimeMillis() + logNotification = logNotificationvalue + isComplete = true + } + selectAppRepository.update(selectedAppFromDB) + }else{ + val selectedApp = SelectedApp( + appName = app.appName, + packageName = app.packageName, + hushType = type, + durationInMinutes = duration, + muteDays = utils.getStringFromDaysList(daysList), + startTime = utils.toLocalTime(startEndTime.startTime), + endTime = utils.toLocalTime(startEndTime.endTime), + timeUpdated = System.currentTimeMillis(), + logNotification = logNotificationvalue, + isComplete = true + ) + selectAppRepository.addSelectedApp(selectedApp) } - selectAppRepository.addSelectedApp(selectedApp) } } diff --git a/app/src/main/java/dev/souravdas/hush/arch/SelectAppCache.kt b/app/src/main/java/dev/souravdas/hush/arch/SelectAppCache.kt index 5bd0c97..3fda51d 100644 --- a/app/src/main/java/dev/souravdas/hush/arch/SelectAppCache.kt +++ b/app/src/main/java/dev/souravdas/hush/arch/SelectAppCache.kt @@ -1,5 +1,6 @@ package dev.souravdas.hush.arch +import dev.souravdas.hush.models.AppLog import dev.souravdas.hush.models.SelectedApp import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.combine @@ -12,11 +13,16 @@ import javax.inject.Singleton * For Hush! */ @Singleton -class SelectAppCache @Inject constructor(private val repository: SelectAppRepository) { +class SelectAppCache @Inject constructor(private val repository: SelectAppRepository, private val logRepository: AppLogRepository) { private val selectedAppsFlow = repository.getSelectedAppsWithFlow() private val databaseUpdatesFlow = repository.getDBUpdatesWithFlow() fun getSelectedApps(): Flow> = combine(selectedAppsFlow, databaseUpdatesFlow) { selectedApps, _ -> selectedApps } + + suspend fun logNotification(appLog: AppLog){ + logRepository.insertLog(appLog) + } + } \ No newline at end of file diff --git a/app/src/main/java/dev/souravdas/hush/arch/SelectedAppDao.kt b/app/src/main/java/dev/souravdas/hush/arch/SelectedAppDao.kt index a24602a..50593bc 100644 --- a/app/src/main/java/dev/souravdas/hush/arch/SelectedAppDao.kt +++ b/app/src/main/java/dev/souravdas/hush/arch/SelectedAppDao.kt @@ -13,7 +13,7 @@ interface SelectedAppDao { @Query("SELECT * FROM selected_app") fun getAllSelectedAppsRaw(): List - @Update(entity = SelectedApp::class) + @Update(entity = SelectedApp::class, onConflict = OnConflictStrategy.REPLACE) suspend fun update(selectedApp: SelectedApp) @Query("SELECT * FROM selected_app") @@ -22,7 +22,7 @@ interface SelectedAppDao { @Insert(onConflict = OnConflictStrategy.REPLACE) suspend fun insert(selectedApp: SelectedApp) - @Delete + @Delete (entity = SelectedApp::class) suspend fun delete(selectedApp: SelectedApp) @Query("DELETE FROM selected_app WHERE isComplete= :isComplete") diff --git a/app/src/main/java/dev/souravdas/hush/base/HushDB.kt b/app/src/main/java/dev/souravdas/hush/base/HushDB.kt index 59d3a2d..7ada43d 100644 --- a/app/src/main/java/dev/souravdas/hush/base/HushDB.kt +++ b/app/src/main/java/dev/souravdas/hush/base/HushDB.kt @@ -3,12 +3,15 @@ package dev.souravdas.hush.base import androidx.room.Database import androidx.room.RoomDatabase import androidx.room.TypeConverters +import dev.souravdas.hush.arch.AppLogDao import dev.souravdas.hush.arch.SelectedAppDao +import dev.souravdas.hush.models.AppLog import dev.souravdas.hush.models.SelectedApp import dev.souravdas.hush.others.HushDBTypeConverters -@Database(entities = [SelectedApp::class], version = 1) +@Database(entities = [SelectedApp::class, AppLog::class], version = 1) @TypeConverters(HushDBTypeConverters::class) abstract class HushDB: RoomDatabase() { abstract fun selectAppDao(): SelectedAppDao + abstract fun appLogDao(): AppLogDao } \ No newline at end of file diff --git a/app/src/main/java/dev/souravdas/hush/base/Modules.kt b/app/src/main/java/dev/souravdas/hush/base/Modules.kt index 4b81950..e824da6 100644 --- a/app/src/main/java/dev/souravdas/hush/base/Modules.kt +++ b/app/src/main/java/dev/souravdas/hush/base/Modules.kt @@ -6,6 +6,8 @@ import dagger.Provides import dagger.hilt.InstallIn import dagger.hilt.android.qualifiers.ApplicationContext import dagger.hilt.components.SingletonComponent +import dev.souravdas.hush.arch.AppLogDao +import dev.souravdas.hush.arch.AppLogRepository import dev.souravdas.hush.arch.SelectAppRepository import dev.souravdas.hush.arch.SelectedAppDao import dev.souravdas.hush.others.Utils @@ -30,11 +32,21 @@ object Modules { return hushDB.selectAppDao() } + @Provides + fun provideAppLogDao(hushDB: HushDB): AppLogDao{ + return hushDB.appLogDao() + } + @Provides fun provideSelectAppRepository(selectedAppDao: SelectedAppDao): SelectAppRepository { return SelectAppRepository(selectedAppDao) } + @Provides + fun providesAppLogRepository(appLogDao: AppLogDao): AppLogRepository { + return AppLogRepository(appLogDao) + } + @Provides fun provideUtils(): Utils{ return Utils() diff --git a/app/src/main/java/dev/souravdas/hush/compose/main/AppList.kt b/app/src/main/java/dev/souravdas/hush/compose/main/AppList.kt new file mode 100644 index 0000000..318e76a --- /dev/null +++ b/app/src/main/java/dev/souravdas/hush/compose/main/AppList.kt @@ -0,0 +1,104 @@ +package dev.souravdas.hush.compose.main + +import androidx.compose.foundation.Image +import androidx.compose.foundation.background +import androidx.compose.foundation.clickable +import androidx.compose.foundation.layout.* +import androidx.compose.foundation.lazy.LazyColumn +import androidx.compose.foundation.lazy.itemsIndexed +import androidx.compose.foundation.lazy.rememberLazyListState +import androidx.compose.material.ExperimentalMaterialApi +import androidx.compose.material.ListItem +import androidx.compose.material3.MaterialTheme +import androidx.compose.material3.Text +import androidx.compose.runtime.Composable +import androidx.compose.runtime.rememberCoroutineScope +import androidx.compose.ui.Alignment +import androidx.compose.ui.Modifier +import androidx.compose.ui.platform.LocalContext +import androidx.compose.ui.text.style.TextAlign +import androidx.compose.ui.unit.dp +import androidx.core.content.ContextCompat +import com.google.accompanist.drawablepainter.rememberDrawablePainter +import dev.souravdas.hush.R +import dev.souravdas.hush.models.InstalledPackageInfo +import dev.souravdas.hush.models.SelectedApp +import kotlinx.coroutines.launch + +/** + * Created by Sourav + * On 3/18/2023 12:24 PM + * For Hush! + */ +@OptIn(ExperimentalMaterialApi::class) +@Composable +fun InstalledAppList( + items: List, + onItemClick: (SelectedApp) -> Unit = {}, +) { + val scope = rememberCoroutineScope() + val modifier = Modifier.padding(4.dp) + Box( + modifier = Modifier + .fillMaxHeight(fraction = 0.7f) + ) { + Column() { + Box( + modifier = Modifier + .height(56.dp) + .fillMaxWidth() + .background(color = MaterialTheme.colorScheme.primary) + ) { + Text( + text = "Swipe up to select an app", + modifier = Modifier.align(alignment = Alignment.Center), + color = MaterialTheme.colorScheme.onPrimary + ) + } + val lazyListState = rememberLazyListState() + LazyColumn( + state = lazyListState, + modifier = Modifier.background(color = MaterialTheme.colorScheme.background) + ) { + itemsIndexed(items = items) { index, item -> + + ListItem( + modifier = Modifier.clickable { + scope.launch { + onItemClick.invoke( + SelectedApp( + appName = item.appName, + packageName = item.packageName, + timeUpdated = System.currentTimeMillis(), + logNotification = false, + isComplete = false + ) + ) + } + }, + icon = { + Image( + painter = rememberDrawablePainter( + drawable = item.icon ?: ContextCompat.getDrawable( + LocalContext.current, R.mipmap.ic_launcher_round + ) + ), + contentDescription = "appIcon", + modifier = Modifier.size(40.dp) + ) + }, + text = { + Text( + text = item.appName, + textAlign = TextAlign.Center, + color = MaterialTheme.colorScheme.onBackground, + modifier = Modifier.padding(start = 4.dp) + ) + } + ) + } + } + } + + } +} \ No newline at end of file diff --git a/app/src/main/java/dev/souravdas/hush/activities/UIKit.kt b/app/src/main/java/dev/souravdas/hush/compose/main/MainScreen.kt similarity index 81% rename from app/src/main/java/dev/souravdas/hush/activities/UIKit.kt rename to app/src/main/java/dev/souravdas/hush/compose/main/MainScreen.kt index fde7b70..2c487ca 100644 --- a/app/src/main/java/dev/souravdas/hush/activities/UIKit.kt +++ b/app/src/main/java/dev/souravdas/hush/compose/main/MainScreen.kt @@ -1,4 +1,4 @@ -package dev.souravdas.hush.activities +package dev.souravdas.hush.compose.main import android.annotation.SuppressLint import android.widget.Toast @@ -11,18 +11,15 @@ import androidx.compose.foundation.clickable import androidx.compose.foundation.layout.* import androidx.compose.foundation.lazy.LazyColumn import androidx.compose.foundation.lazy.items -import androidx.compose.foundation.lazy.itemsIndexed -import androidx.compose.foundation.lazy.rememberLazyListState import androidx.compose.foundation.shape.CircleShape import androidx.compose.foundation.shape.RoundedCornerShape import androidx.compose.material.* +import androidx.compose.material.FabPosition import androidx.compose.material.SwitchDefaults import androidx.compose.material.icons.Icons import androidx.compose.material.icons.filled.Done -import androidx.compose.material.icons.filled.Warning import androidx.compose.material.icons.outlined.Edit import androidx.compose.material3.* -import androidx.compose.material3.Button import androidx.compose.material3.Checkbox import androidx.compose.material3.Icon import androidx.compose.material3.Text @@ -34,23 +31,17 @@ import androidx.compose.ui.Modifier import androidx.compose.ui.draw.clip import androidx.compose.ui.graphics.Color import androidx.compose.ui.graphics.toArgb -import androidx.compose.ui.platform.LocalContext import androidx.compose.ui.res.colorResource import androidx.compose.ui.res.painterResource import androidx.compose.ui.res.stringResource import androidx.compose.ui.text.font.FontWeight -import androidx.compose.ui.text.style.TextAlign import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.sp -import androidx.compose.ui.window.Dialog -import androidx.compose.ui.window.DialogProperties -import androidx.core.content.ContextCompat import androidx.lifecycle.viewmodel.compose.viewModel import com.google.accompanist.drawablepainter.rememberDrawablePainter import dev.souravdas.hush.HushApp import dev.souravdas.hush.R import dev.souravdas.hush.arch.MainActivityVM -import dev.souravdas.hush.models.InstalledPackageInfo import dev.souravdas.hush.models.SelectedApp import dev.souravdas.hush.models.SelectedAppForList import dev.souravdas.hush.others.Constants @@ -66,113 +57,7 @@ import androidx.compose.material3.MaterialTheme as MD3 * On 2/22/2023 11:45 PM * For Hush! */ -class UIKit() { - @OptIn(ExperimentalMaterialApi::class) - @Composable - fun InstalledAppList( - items: List, - onItemClick: (SelectedApp) -> Unit = {}, - ) { - val scope = rememberCoroutineScope() - val modifier = Modifier.padding(4.dp) - Box( - modifier = Modifier - .fillMaxHeight(fraction = 0.7f) - ) { - Column() { - Box( - modifier = Modifier - .height(56.dp) - .fillMaxWidth() - .background(color = MD3.colorScheme.primary) - ) { - Text( - text = "Swipe up to select an app", - modifier = Modifier.align(alignment = Alignment.Center), - color = MD3.colorScheme.onPrimary - ) - } - val lazyListState = rememberLazyListState() - LazyColumn( - state = lazyListState, - modifier = Modifier.background(color = MD3.colorScheme.background) - ) { - itemsIndexed(items = items) { index, item -> - - ListItem( - modifier = Modifier.clickable { - scope.launch { - onItemClick.invoke( - SelectedApp( - appName = item.appName, - packageName = item.packageName, - timeUpdated = System.currentTimeMillis(), - isComplete = false - ) - ) - } - }, - icon = { - Image( - painter = rememberDrawablePainter( - drawable = item.icon ?: ContextCompat.getDrawable( - LocalContext.current, R.mipmap.ic_launcher_round - ) - ), - contentDescription = "appIcon", - modifier = Modifier.size(40.dp) - ) - }, - text = { - Text( - text = item.appName, - textAlign = TextAlign.Center, - color = MD3.colorScheme.onBackground, - modifier = Modifier.padding(start = 4.dp) - ) - } - ) - } - } - } - - } - } - - @Composable - fun ShowAlertDialog( - onConfirmClick: () -> Unit - ) { - AlertDialog( - onDismissRequest = {}, - icon = { - Icon( - Icons.Default.Warning, - contentDescription = null, - modifier = Modifier.size(56.dp) - ) - }, - title = { - Text(text = "Notification Permission Necessary") - }, - text = { - Text(text = stringResource(id = R.string.notification_alert_dialog_body)) - }, - confirmButton = { - Button(onClick = { - onConfirmClick.invoke() - Toast.makeText( - HushApp.context, - "Please Select Hush! from the list", - Toast.LENGTH_LONG - ).show() - }) { - Text(text = stringResource(id = android.R.string.ok)) - } - } - ) - } - +class MainScreen() { @OptIn( ExperimentalMaterial3Api::class, ExperimentalMaterialApi::class, ExperimentalLayoutApi::class @@ -415,9 +300,11 @@ class UIKit() { fontColor = Color.White ) } else { - CustomChip( - title = selectedApp.selectedApp.hushType.label, - ) + selectedApp.selectedApp.hushType?.let { + CustomChip( + title = it.label, + ) + } } } } @@ -455,7 +342,7 @@ class UIKit() { } var logNotificationCb by remember { - mutableStateOf(false) //This will be true in the fututre + mutableStateOf(true) } val startEndTimePair by remember { mutableStateOf(StartEndTime("00:00", "23:59")) @@ -703,82 +590,6 @@ class UIKit() { } - @Composable - fun AddCancelButtonBar( - onAddClick: () -> Unit, - onCancelClick: () -> Unit = {} - ) { - Row() { - val modifier = - Modifier.padding(start = 16.dp, end = 8.dp, top = 8.dp, bottom = 8.dp) - Spacer(modifier = Modifier.weight(1f)) - - Text( - text = "Cancel", - color = MD3.colorScheme.onPrimaryContainer, - modifier = modifier - .clickable { - onCancelClick.invoke() - }) - - Text(text = "Add", - fontWeight = FontWeight.Medium, - color = MD3.colorScheme.onPrimaryContainer, - modifier = modifier - .clickable { - onAddClick.invoke() - }) - } - } - - @OptIn(ExperimentalMaterial3Api::class) - @Composable - fun ShowTimePicker( - time: Pair, - title: String, - onTimeSelected: (String) -> Unit, - onDialogDismiss: () -> Unit - ) { - val state = rememberTimePickerState(time.first, time.second) - - Dialog( - onDismissRequest = { onDialogDismiss.invoke() }, properties = DialogProperties( - dismissOnBackPress = false, - dismissOnClickOutside = false - ) - ) { - Surface( - modifier = Modifier - .clip(RoundedCornerShape(12.dp)) - .background(MD3.colorScheme.background) - .padding(16.dp) - ) { - Column( - Modifier.background(MD3.colorScheme.background), - horizontalAlignment = Alignment.CenterHorizontally, - ) { - Row( - horizontalArrangement = Arrangement.Start, - modifier = Modifier.fillMaxWidth() - ) { - Text( - text = title, - fontSize = 24.sp, - color = MD3.colorScheme.onBackground, - modifier = Modifier.padding(bottom = 16.dp) - ) - } - TimePicker(state = state) - AddCancelButtonBar(onAddClick = { - onTimeSelected.invoke(state.hour.toString() + ":" + state.minute) - }, onCancelClick = { - onDialogDismiss.invoke() - }) - } - } - } - } - @Composable fun ShowOptions( @SuppressLint("ModifierParameter") buttonModifier: Modifier, @@ -991,8 +802,7 @@ class UIKit() { }) } - - fun get12HrsFrom24Hrs(inputTime: String): String { + private fun get12HrsFrom24Hrs(inputTime: String): String { val timeFormat = SimpleDateFormat("hh:mm", Locale.getDefault()) val time = timeFormat.parse(inputTime) val outputFormat = SimpleDateFormat("hh:mm a", Locale.getDefault()) diff --git a/app/src/main/java/dev/souravdas/hush/compose/main/Modals.kt b/app/src/main/java/dev/souravdas/hush/compose/main/Modals.kt new file mode 100644 index 0000000..b78b6c6 --- /dev/null +++ b/app/src/main/java/dev/souravdas/hush/compose/main/Modals.kt @@ -0,0 +1,139 @@ +package dev.souravdas.hush.compose.main + +import android.widget.Toast +import androidx.compose.foundation.background +import androidx.compose.foundation.clickable +import androidx.compose.foundation.layout.* +import androidx.compose.foundation.shape.RoundedCornerShape +import androidx.compose.material.Surface +import androidx.compose.material.icons.Icons +import androidx.compose.material.icons.filled.Warning +import androidx.compose.material3.* +import androidx.compose.runtime.Composable +import androidx.compose.ui.Alignment +import androidx.compose.ui.Modifier +import androidx.compose.ui.draw.clip +import androidx.compose.ui.res.stringResource +import androidx.compose.ui.text.font.FontWeight +import androidx.compose.ui.unit.dp +import androidx.compose.ui.unit.sp +import androidx.compose.ui.window.Dialog +import androidx.compose.ui.window.DialogProperties +import dev.souravdas.hush.HushApp +import dev.souravdas.hush.R + +/** + * Created by Sourav + * On 3/18/2023 12:27 PM + * For Hush! + */ +@Composable +fun ShowAlertDialog( + onConfirmClick: () -> Unit +) { + AlertDialog( + onDismissRequest = {}, + icon = { + Icon( + Icons.Default.Warning, + contentDescription = null, + modifier = Modifier.size(56.dp) + ) + }, + title = { + Text(text = "Notification Permission Necessary") + }, + text = { + Text(text = stringResource(id = R.string.notification_alert_dialog_body)) + }, + confirmButton = { + Button(onClick = { + onConfirmClick.invoke() + Toast.makeText( + HushApp.context, + "Please Select Hush! from the list", + Toast.LENGTH_LONG + ).show() + }) { + Text(text = stringResource(id = android.R.string.ok)) + } + } + ) +} + +@OptIn(ExperimentalMaterial3Api::class) +@Composable +fun ShowTimePicker( + time: Pair, + title: String, + onTimeSelected: (String) -> Unit, + onDialogDismiss: () -> Unit +) { + val state = rememberTimePickerState(time.first, time.second) + + Dialog( + onDismissRequest = { onDialogDismiss.invoke() }, properties = DialogProperties( + dismissOnBackPress = false, + dismissOnClickOutside = false + ) + ) { + Surface( + modifier = Modifier + .clip(RoundedCornerShape(12.dp)) + .background(MaterialTheme.colorScheme.background) + .padding(16.dp) + ) { + Column( + Modifier.background(MaterialTheme.colorScheme.background), + horizontalAlignment = Alignment.CenterHorizontally, + ) { + Row( + horizontalArrangement = Arrangement.Start, + modifier = Modifier.fillMaxWidth() + ) { + Text( + text = title, + fontSize = 24.sp, + color = MaterialTheme.colorScheme.onBackground, + modifier = Modifier.padding(bottom = 16.dp) + ) + } + TimePicker(state = state) + AddCancelButtonBar(onAddClick = { + onTimeSelected.invoke(state.hour.toString() + ":" + state.minute) + }, onCancelClick = { + onDialogDismiss.invoke() + }) + } + } + } +} + + +@Composable +fun AddCancelButtonBar( + onAddClick: () -> Unit, + onCancelClick: () -> Unit = {} +) { + Row() { + val modifier = + Modifier.padding(start = 16.dp, end = 8.dp, top = 8.dp, bottom = 8.dp) + Spacer(modifier = Modifier.weight(1f)) + + Text( + text = "Cancel", + color = MaterialTheme.colorScheme.onPrimaryContainer, + modifier = modifier + .clickable { + onCancelClick.invoke() + }) + + Text(text = "Add", + fontWeight = FontWeight.Medium, + color = MaterialTheme.colorScheme.onPrimaryContainer, + modifier = modifier + .clickable { + onAddClick.invoke() + }) + } +} diff --git a/app/src/main/java/dev/souravdas/hush/models/AppLog.kt b/app/src/main/java/dev/souravdas/hush/models/AppLog.kt new file mode 100644 index 0000000..d95b79b --- /dev/null +++ b/app/src/main/java/dev/souravdas/hush/models/AppLog.kt @@ -0,0 +1,26 @@ +package dev.souravdas.hush.models + +import androidx.room.Entity +import androidx.room.ForeignKey +import androidx.room.PrimaryKey + +/** + * Created by Sourav + * On 3/18/2023 12:34 PM + * For Hush! + */ +@Entity( + tableName = "app_log", + foreignKeys = [ForeignKey( + entity = SelectedApp::class, + parentColumns = ["id"], + childColumns = ["selected_app_id"] + )] +) +data class AppLog( + @PrimaryKey(autoGenerate = true) val id: Long = 0, + val selected_app_id: Int, + val title: String?, + val body: String?, + val timeCreated: Long = System.currentTimeMillis() +) diff --git a/app/src/main/java/dev/souravdas/hush/models/SelectedApp.kt b/app/src/main/java/dev/souravdas/hush/models/SelectedApp.kt index 5d8f7d3..8439600 100644 --- a/app/src/main/java/dev/souravdas/hush/models/SelectedApp.kt +++ b/app/src/main/java/dev/souravdas/hush/models/SelectedApp.kt @@ -1,5 +1,6 @@ package dev.souravdas.hush.models +import android.service.notification.StatusBarNotification import androidx.room.Entity import androidx.room.PrimaryKey import dev.souravdas.hush.others.HushType @@ -10,14 +11,15 @@ import java.io.Serializable data class SelectedApp ( @PrimaryKey(autoGenerate = true) val id: Int = 0, - val appName: String, - val packageName: String, - val hushType: HushType? = null, - val durationInMinutes: Long? = null, - val muteDays: String? = null, - val startTime: LocalTime? = null, - val endTime: LocalTime? = null, + var appName: String, + var packageName: String, + var hushType: HushType? = null, + var durationInMinutes: Long? = null, + var muteDays: String? = null, + var startTime: LocalTime? = null, + var endTime: LocalTime? = null, val timeCreated: Long = System.currentTimeMillis(), - val timeUpdated: Long, - val isComplete: Boolean + var timeUpdated: Long, + var logNotification: Boolean, + var isComplete: Boolean ): Serializable diff --git a/app/src/main/java/dev/souravdas/hush/services/HushService.kt b/app/src/main/java/dev/souravdas/hush/services/HushService.kt index 314603f..5946f68 100644 --- a/app/src/main/java/dev/souravdas/hush/services/HushService.kt +++ b/app/src/main/java/dev/souravdas/hush/services/HushService.kt @@ -1,5 +1,6 @@ package dev.souravdas.hush.services +import android.app.Notification import android.app.NotificationManager import android.content.Context import android.os.Build @@ -12,6 +13,7 @@ import dagger.hilt.android.AndroidEntryPoint import dev.sourav.base.datastore.DataStoreManager import dev.souravdas.hush.HushApp import dev.souravdas.hush.arch.SelectAppCache +import dev.souravdas.hush.models.AppLog import dev.souravdas.hush.models.SelectedApp import dev.souravdas.hush.others.Constants import dev.souravdas.hush.others.HushType @@ -88,11 +90,11 @@ class HushService : NotificationListenerService() { when (app!!.hushType) { HushType.ALWAYS -> { - cancelNotification(notification.key) + cancelAndLog(notification, app!!) } HushType.DURATION -> { if (System.currentTimeMillis() <= app!!.timeUpdated + app!!.durationInMinutes!! * 60000) { - cancelNotification(notification.key) + cancelAndLog(notification, app!!) } else { Timber.tag(TAG).i("Time Expired. Notification will not be canceled") } @@ -102,7 +104,7 @@ class HushService : NotificationListenerService() { val now = LocalTime.now() app?.let { if (it.muteDays!!.contains(utils.getCurrentDayOfWeek()) && (it.startTime!!.isBefore(now) && it.endTime!!.isAfter(now))){ - cancelNotification(notification.key) + cancelAndLog(notification, app!!) } } @@ -118,6 +120,26 @@ class HushService : NotificationListenerService() { } } + private fun cancelAndLog(statusBarNotification: StatusBarNotification, app: SelectedApp) { + val tmp = statusBarNotification + cancelNotification(statusBarNotification.key) + logNotification(tmp, app) + } + + private fun logNotification(statusBarNotification: StatusBarNotification, app: SelectedApp) { + if (app.logNotification){ + scope.launch { + selectAppCache.logNotification( + AppLog( + selected_app_id = app.id, + title = statusBarNotification.notification.extras.getString(Notification.EXTRA_TITLE), + body = statusBarNotification.notification.extras.getString(Notification.EXTRA_TEXT), + ) + ) + } + } + } + @RequiresApi(Build.VERSION_CODES.M) fun enableDndModeFor4Seconds() { val notificationManager = From 1a34f44ec6e29debbbf61c291ac3c0a6968d4ce8 Mon Sep 17 00:00:00 2001 From: Sourav Das Date: Sat, 18 Mar 2023 19:14:26 +0600 Subject: [PATCH 02/16] properly remove, update and visual changes --- .../main/java/dev/souravdas/hush/arch/AppLogDao.kt | 4 ++++ .../dev/souravdas/hush/arch/AppLogRepository.kt | 4 ++++ .../java/dev/souravdas/hush/arch/MainActivityVM.kt | 14 +++++++++++++- .../dev/souravdas/hush/arch/SelectAppRepository.kt | 5 ++++- .../dev/souravdas/hush/compose/main/MainScreen.kt | 11 ++++++++--- .../java/dev/souravdas/hush/compose/main/Modals.kt | 9 ++++++--- 6 files changed, 39 insertions(+), 8 deletions(-) diff --git a/app/src/main/java/dev/souravdas/hush/arch/AppLogDao.kt b/app/src/main/java/dev/souravdas/hush/arch/AppLogDao.kt index f450054..82059be 100644 --- a/app/src/main/java/dev/souravdas/hush/arch/AppLogDao.kt +++ b/app/src/main/java/dev/souravdas/hush/arch/AppLogDao.kt @@ -2,6 +2,7 @@ package dev.souravdas.hush.arch import androidx.room.Dao import androidx.room.Insert +import androidx.room.Query import dev.souravdas.hush.models.AppLog /** @@ -14,4 +15,7 @@ interface AppLogDao { @Insert suspend fun insertLog(appLog: AppLog) + + @Query("DELETE FROM app_log WHERE selected_app_id= :selectedAppID") + suspend fun deleteAllByForeignKey(selectedAppID: Int) } \ No newline at end of file diff --git a/app/src/main/java/dev/souravdas/hush/arch/AppLogRepository.kt b/app/src/main/java/dev/souravdas/hush/arch/AppLogRepository.kt index ddefd7f..8275522 100644 --- a/app/src/main/java/dev/souravdas/hush/arch/AppLogRepository.kt +++ b/app/src/main/java/dev/souravdas/hush/arch/AppLogRepository.kt @@ -13,4 +13,8 @@ class AppLogRepository @Inject constructor(val appLogDao: AppLogDao) { suspend fun insertLog(appLog: AppLog) { appLogDao.insertLog(appLog) } + + suspend fun deleteAllBySelectedAppId(selectedAppId:Int){ + appLogDao.deleteAllByForeignKey(selectedAppId) + } } \ No newline at end of file diff --git a/app/src/main/java/dev/souravdas/hush/arch/MainActivityVM.kt b/app/src/main/java/dev/souravdas/hush/arch/MainActivityVM.kt index 4029452..51af08e 100644 --- a/app/src/main/java/dev/souravdas/hush/arch/MainActivityVM.kt +++ b/app/src/main/java/dev/souravdas/hush/arch/MainActivityVM.kt @@ -22,6 +22,7 @@ import javax.inject.Inject @HiltViewModel class MainActivityVM @Inject constructor( private val selectAppRepository: SelectAppRepository, + private val appLogRepository: AppLogRepository, private val dataStoreManager: DataStoreManager, private val utils: Utils ) : BaseViewModel() { @@ -121,6 +122,7 @@ class MainActivityVM @Inject constructor( fun removeApp(selectedApp: SelectedApp) { executedSuspendedCodeBlock { + appLogRepository.deleteAllBySelectedAppId(selectedApp.id) selectAppRepository.removedSelectedApp(selectedApp) } } @@ -134,7 +136,7 @@ class MainActivityVM @Inject constructor( logNotificationvalue: Boolean ) { executedSuspendedCodeBlock { - val selectedAppFromDB = selectAppRepository.getSelectedApp(app.packageName ?: "") + val selectedAppFromDB = selectAppRepository.getSelectedApp(app.packageName) if (selectedAppFromDB != null) { with(selectedAppFromDB) { appName = app.appName @@ -173,4 +175,14 @@ class MainActivityVM @Inject constructor( } } + fun updateComplete(app: SelectedAppForList){ + executedSuspendedCodeBlock { + val selectedAppFromDB = selectAppRepository.getSelectedApp(app.selectedApp.packageName) + if (selectedAppFromDB != null){ + selectedAppFromDB.isComplete = false + selectAppRepository.update(selectedAppFromDB) + } + } + } + } \ No newline at end of file diff --git a/app/src/main/java/dev/souravdas/hush/arch/SelectAppRepository.kt b/app/src/main/java/dev/souravdas/hush/arch/SelectAppRepository.kt index 6a52c92..2329c2b 100644 --- a/app/src/main/java/dev/souravdas/hush/arch/SelectAppRepository.kt +++ b/app/src/main/java/dev/souravdas/hush/arch/SelectAppRepository.kt @@ -14,7 +14,10 @@ class SelectAppRepository @Inject constructor(val selectedAppDao: SelectedAppDao suspend fun getSelectedApps(): List = selectedAppDao.getAllSelectedApps() fun getSelectedAppsRaw(): List = selectedAppDao.getAllSelectedAppsRaw() - suspend fun update(selectedApp: SelectedApp) = selectedAppDao.update(selectedApp) + suspend fun update(selectedApp: SelectedApp) { + selectedApp.timeUpdated = System.currentTimeMillis() + selectedAppDao.update(selectedApp) + } suspend fun delete(selectedApp: SelectedApp) = selectedAppDao.delete(selectedApp) suspend fun removedSelectedApp(selectedApp: SelectedApp) = selectedAppDao.delete(selectedApp); diff --git a/app/src/main/java/dev/souravdas/hush/compose/main/MainScreen.kt b/app/src/main/java/dev/souravdas/hush/compose/main/MainScreen.kt index 2c487ca..4916ed0 100644 --- a/app/src/main/java/dev/souravdas/hush/compose/main/MainScreen.kt +++ b/app/src/main/java/dev/souravdas/hush/compose/main/MainScreen.kt @@ -211,11 +211,12 @@ class MainScreen() { } } items(itemList.value, key = { - it.selectedApp.id + it.selectedApp.timeUpdated }) { app -> SelectedAppItem( selectedApp = app, onRemoveClick = onRemoveClick, + onEditClick = { viewModel.updateComplete(app) }, onConfigDone = { type: HushType, startEndTime: StartEndTime, duration: Long, daysList: List, logNotification: Boolean -> viewModel.addConfigInSelectedApp( app.selectedApp, @@ -238,6 +239,7 @@ class MainScreen() { fun SelectedAppItem( selectedApp: SelectedAppForList, onRemoveClick: (SelectedApp) -> Unit = {}, + onEditClick: (SelectedApp) -> Unit, onConfigDone: (type: HushType, startEndTime: StartEndTime, duration: Long, daysList: List, logNotification: Boolean) -> Unit, onCancelClick: () -> Unit ) { @@ -317,7 +319,7 @@ class MainScreen() { } AnimatedVisibility(showOptions) { - ShowOptions(buttonModifier, onRemoveClick, selectedApp) + ShowOptions(buttonModifier, onRemoveClick, onEditClick, selectedApp) } } } @@ -480,6 +482,7 @@ class MainScreen() { Icon( Icons.Outlined.Edit, contentDescription = "Edit", + tint = MD3.colorScheme.onPrimaryContainer, modifier = Modifier .size(20.dp) ) @@ -507,6 +510,7 @@ class MainScreen() { Icon( Icons.Outlined.Edit, contentDescription = "Edit", + tint = MD3.colorScheme.onPrimaryContainer, modifier = Modifier.size(20.dp) ) Text( @@ -594,6 +598,7 @@ class MainScreen() { fun ShowOptions( @SuppressLint("ModifierParameter") buttonModifier: Modifier, onRemoveClick: (SelectedApp) -> Unit = {}, + onEditClick: (SelectedApp) -> Unit, selectedApp: SelectedAppForList ) { Row( @@ -612,7 +617,7 @@ class MainScreen() { TextButton( modifier = buttonModifier, - onClick = { Constants.showNIY() }) { + onClick = { onEditClick.invoke(selectedApp.selectedApp) }) { Text("Edit", color = MD3.colorScheme.onSecondaryContainer) } diff --git a/app/src/main/java/dev/souravdas/hush/compose/main/Modals.kt b/app/src/main/java/dev/souravdas/hush/compose/main/Modals.kt index b78b6c6..b8c1ead 100644 --- a/app/src/main/java/dev/souravdas/hush/compose/main/Modals.kt +++ b/app/src/main/java/dev/souravdas/hush/compose/main/Modals.kt @@ -117,7 +117,7 @@ fun AddCancelButtonBar( ) { Row() { val modifier = - Modifier.padding(start = 16.dp, end = 8.dp, top = 8.dp, bottom = 8.dp) + Modifier.padding(vertical = 8.dp) Spacer(modifier = Modifier.weight(1f)) Text( @@ -126,14 +126,17 @@ fun AddCancelButtonBar( modifier = modifier .clickable { onCancelClick.invoke() - }) + } + .padding(8.dp)) + Spacer(modifier = Modifier.weight(0.05f)) Text(text = "Add", fontWeight = FontWeight.Medium, color = MaterialTheme.colorScheme.onPrimaryContainer, modifier = modifier .clickable { onAddClick.invoke() - }) + } + .padding(8.dp)) } } From 74fc4c7ae462e57d73ed2a7e8e6db02557b3cbeb Mon Sep 17 00:00:00 2001 From: Sourav Das Date: Sat, 18 Mar 2023 22:27:08 +0600 Subject: [PATCH 03/16] WIP nav componenets --- app/build.gradle | 20 +++++----- app/src/main/AndroidManifest.xml | 2 +- .../souravdas/hush/activities/MainActivity.kt | 40 +++++++++++++------ .../java/dev/souravdas/hush/nav/NavGraph.kt | 33 +++++++++++++++ .../java/dev/souravdas/hush/nav/Screens.kt | 11 +++++ 5 files changed, 83 insertions(+), 23 deletions(-) create mode 100644 app/src/main/java/dev/souravdas/hush/nav/NavGraph.kt create mode 100644 app/src/main/java/dev/souravdas/hush/nav/Screens.kt diff --git a/app/build.gradle b/app/build.gradle index cca57c8..3ed036d 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -97,16 +97,7 @@ dependencies { testImplementation 'junit:junit:4.13.2' implementation 'com.jakewharton.timber:timber:5.0.1' implementation 'com.google.accompanist:accompanist-drawablepainter:0.28.0' - androidTestImplementation 'androidx.test.ext:junit:1.1.5' - androidTestImplementation 'androidx.test.espresso:espresso-core:3.5.1' - androidTestImplementation platform('androidx.compose:compose-bom:2023.01.00') - androidTestImplementation 'androidx.compose.ui:ui-test-junit4' - debugImplementation 'androidx.compose.ui:ui-tooling' - debugImplementation 'androidx.compose.ui:ui-test-manifest' implementation 'com.jakewharton.threetenabp:threetenabp:1.4.4' - implementation "com.maxkeppeler.sheets-compose-dialogs:core:1.1.0" - implementation "com.maxkeppeler.sheets-compose-dialogs:clock:1.1.0" -// implementation "com.maxkeppeler.sheets-compose-dialogs:date_time:1.1.0" def room_version = "2.5.0" @@ -125,4 +116,15 @@ dependencies { implementation "androidx.lifecycle:lifecycle-viewmodel-compose:2.6.0-rc01" implementation "androidx.lifecycle:lifecycle-livedata-ktx:2.5.1" + def nav_version = "2.5.3" + + implementation "androidx.navigation:navigation-compose:$nav_version" + + androidTestImplementation 'androidx.test.ext:junit:1.1.5' + androidTestImplementation 'androidx.test.espresso:espresso-core:3.5.1' + androidTestImplementation platform('androidx.compose:compose-bom:2023.01.00') + androidTestImplementation 'androidx.compose.ui:ui-test-junit4' + debugImplementation 'androidx.compose.ui:ui-tooling' + debugImplementation 'androidx.compose.ui:ui-test-manifest' + } \ No newline at end of file diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index ddba471..daddf5e 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -22,7 +22,7 @@ android:hardwareAccelerated="true" tools:targetApi="31"> diff --git a/app/src/main/java/dev/souravdas/hush/activities/MainActivity.kt b/app/src/main/java/dev/souravdas/hush/activities/MainActivity.kt index dbbce39..b862645 100644 --- a/app/src/main/java/dev/souravdas/hush/activities/MainActivity.kt +++ b/app/src/main/java/dev/souravdas/hush/activities/MainActivity.kt @@ -1,4 +1,4 @@ -package dev.souravdas.hush +package dev.souravdas.hush.activities import android.app.Activity import android.content.Context @@ -14,10 +14,12 @@ import androidx.activity.compose.setContent import androidx.activity.viewModels import androidx.core.app.NotificationManagerCompat import androidx.lifecycle.lifecycleScope +import androidx.navigation.NavHostController +import androidx.navigation.compose.rememberNavController import dagger.hilt.android.AndroidEntryPoint import dev.sourav.emptycompose.ui.theme.HushTheme -import dev.souravdas.hush.compose.main.MainScreen import dev.souravdas.hush.arch.MainActivityVM +import dev.souravdas.hush.nav.NavGraph import dev.souravdas.hush.others.Utils import dev.souravdas.hush.services.KeepAliveService import kotlinx.coroutines.launch @@ -30,18 +32,23 @@ class MainActivity : ComponentActivity() { lateinit var utils: Utils private val viewModel: MainActivityVM by viewModels() private var doubleBackToExitPressedOnce = false + private lateinit var navController: NavHostController override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContent { viewModel.getSelectedApp() + navController = rememberNavController() + HushTheme() { - MainScreen().MainActivityScreen(onNotificationPermissionGet = { - openNotificationAccessSettingsIfNeeded(this) - }, checkNotificationPermission = { - isNotificationListenerEnabled(this) - }) + NavGraph( + navController = navController, + onNotificationPermissionGet = { + openNotificationAccessSettingsIfNeeded(this) + }, checkNotificationPermission = { + isNotificationListenerEnabled(this) + }) } } @@ -50,14 +57,19 @@ class MainActivity : ComponentActivity() { private fun checkService() { lifecycleScope.launch { - viewModel.getHushStatusAsFlow().collect() {value -> - if (value){ + viewModel.getHushStatusAsFlow().collect() { value -> + if (value) { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { - startForegroundService(Intent(this@MainActivity, KeepAliveService::class.java)) - }else{ + startForegroundService( + Intent( + this@MainActivity, + KeepAliveService::class.java + ) + ) + } else { startService(Intent(this@MainActivity, KeepAliveService::class.java)) } - }else{ + } else { stopService(Intent(this@MainActivity, KeepAliveService::class.java)) } } @@ -86,7 +98,9 @@ class MainActivity : ComponentActivity() { this.doubleBackToExitPressedOnce = true Toast.makeText(this, "Please click BACK again to exit", Toast.LENGTH_SHORT).show() - Handler(Looper.getMainLooper()).postDelayed(Runnable { doubleBackToExitPressedOnce = false }, 2000) + Handler(Looper.getMainLooper()).postDelayed(Runnable { + doubleBackToExitPressedOnce = false + }, 2000) } override fun onDestroy() { diff --git a/app/src/main/java/dev/souravdas/hush/nav/NavGraph.kt b/app/src/main/java/dev/souravdas/hush/nav/NavGraph.kt new file mode 100644 index 0000000..71cb2dd --- /dev/null +++ b/app/src/main/java/dev/souravdas/hush/nav/NavGraph.kt @@ -0,0 +1,33 @@ +package dev.souravdas.hush.nav + +import androidx.compose.runtime.Composable +import androidx.navigation.NavHostController +import androidx.navigation.compose.NavHost +import androidx.navigation.compose.composable +import dev.souravdas.hush.compose.main.MainScreen + +/** + * Created by Sourav + * On 3/18/2023 9:59 PM + * For Hush! + */ +@Composable +fun NavGraph( + navController: NavHostController, + checkNotificationPermission: () -> Boolean, + onNotificationPermissionGet: () -> Unit +) { + NavHost( + navController, + startDestination = Screens.MainScreen.route + ) { + composable( + route = Screens.MainScreen.route, + ) { + MainScreen().MainActivityScreen( + onNotificationPermissionGet = onNotificationPermissionGet, + checkNotificationPermission = checkNotificationPermission + ) + } + } +} \ No newline at end of file diff --git a/app/src/main/java/dev/souravdas/hush/nav/Screens.kt b/app/src/main/java/dev/souravdas/hush/nav/Screens.kt new file mode 100644 index 0000000..fcb6f7e --- /dev/null +++ b/app/src/main/java/dev/souravdas/hush/nav/Screens.kt @@ -0,0 +1,11 @@ +package dev.souravdas.hush.nav + +/** + * Created by Sourav + * On 3/18/2023 9:56 PM + * For Hush! + */ +sealed class Screens(val route: String){ + object MainScreen: Screens(route = "main_screen") + object LogScreen: Screens(route = "log_screen") +} From 067019f6691e035c5a5da376d62d4ce4eed8839e Mon Sep 17 00:00:00 2001 From: Sourav Das Date: Mon, 20 Mar 2023 17:30:06 +0600 Subject: [PATCH 04/16] bumped version code --- app/build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/build.gradle b/app/build.gradle index cca57c8..6a77ff2 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -14,7 +14,7 @@ android { minSdk 22 targetSdk 33 versionCode 1 - versionName "1.0" + versionName "0.1-alpha" testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" vectorDrawables { From 33504a830954aa1f7767f59e23bd8f7fe5f572df Mon Sep 17 00:00:00 2001 From: Sourav Das Date: Mon, 20 Mar 2023 17:34:35 +0600 Subject: [PATCH 05/16] fixed crashes for viewmodels --- app/build.gradle | 1 + .../main/java/dev/souravdas/hush/compose/main/MainScreen.kt | 3 ++- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/app/build.gradle b/app/build.gradle index 3ed036d..21aa5bf 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -119,6 +119,7 @@ dependencies { def nav_version = "2.5.3" implementation "androidx.navigation:navigation-compose:$nav_version" + implementation("androidx.hilt:hilt-navigation-compose:1.0.0") androidTestImplementation 'androidx.test.ext:junit:1.1.5' androidTestImplementation 'androidx.test.espresso:espresso-core:3.5.1' diff --git a/app/src/main/java/dev/souravdas/hush/compose/main/MainScreen.kt b/app/src/main/java/dev/souravdas/hush/compose/main/MainScreen.kt index 4916ed0..64f00ce 100644 --- a/app/src/main/java/dev/souravdas/hush/compose/main/MainScreen.kt +++ b/app/src/main/java/dev/souravdas/hush/compose/main/MainScreen.kt @@ -37,6 +37,7 @@ import androidx.compose.ui.res.stringResource import androidx.compose.ui.text.font.FontWeight import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.sp +import androidx.hilt.navigation.compose.hiltViewModel import androidx.lifecycle.viewmodel.compose.viewModel import com.google.accompanist.drawablepainter.rememberDrawablePainter import dev.souravdas.hush.HushApp @@ -64,7 +65,7 @@ class MainScreen() { ) @Composable fun MainActivityScreen( - viewModel: MainActivityVM = viewModel(), + viewModel: MainActivityVM = hiltViewModel(), checkNotificationPermission: () -> Boolean, onNotificationPermissionGet: () -> Unit ) { From b2a8ac8760af1a3855e9b9b6e70fd4433671d179 Mon Sep 17 00:00:00 2001 From: Sourav Das Date: Tue, 21 Mar 2023 17:07:47 +0600 Subject: [PATCH 06/16] wip --- .../dev/souravdas/hush/arch/MainActivityVM.kt | 41 +- .../souravdas/hush/compose/main/MainScreen.kt | 1304 +++++++++-------- .../java/dev/souravdas/hush/nav/NavGraph.kt | 4 +- .../dev/souravdas/hush/others/UIEvents.kt | 10 + 4 files changed, 684 insertions(+), 675 deletions(-) create mode 100644 app/src/main/java/dev/souravdas/hush/others/UIEvents.kt diff --git a/app/src/main/java/dev/souravdas/hush/arch/MainActivityVM.kt b/app/src/main/java/dev/souravdas/hush/arch/MainActivityVM.kt index 51af08e..0dbe723 100644 --- a/app/src/main/java/dev/souravdas/hush/arch/MainActivityVM.kt +++ b/app/src/main/java/dev/souravdas/hush/arch/MainActivityVM.kt @@ -6,8 +6,9 @@ import androidx.lifecycle.viewModelScope import dagger.hilt.android.lifecycle.HiltViewModel import dev.sourav.base.datastore.DataStoreManager import dev.souravdas.hush.HushApp -import dev.souravdas.hush.compose.main.MainScreen import dev.souravdas.hush.base.BaseViewModel +import dev.souravdas.hush.compose.main.AppConfig +import dev.souravdas.hush.compose.main.StartEndTime import dev.souravdas.hush.models.InstalledPackageInfo import dev.souravdas.hush.models.SelectedApp import dev.souravdas.hush.models.SelectedAppForList @@ -127,27 +128,21 @@ class MainActivityVM @Inject constructor( } } - fun addConfigInSelectedApp( - app: SelectedApp, - type: HushType, - startEndTime: MainScreen.StartEndTime, - duration: Long, - daysList: List, - logNotificationvalue: Boolean - ) { + fun addConfigInSelectedApp(appConfig: AppConfig) { executedSuspendedCodeBlock { + val app = appConfig.selectedApp val selectedAppFromDB = selectAppRepository.getSelectedApp(app.packageName) if (selectedAppFromDB != null) { with(selectedAppFromDB) { appName = app.appName packageName = app.packageName - hushType = type - durationInMinutes = duration - muteDays = utils.getStringFromDaysList(daysList) - startTime = utils.toLocalTime(startEndTime.startTime) - endTime = utils.toLocalTime(startEndTime.endTime) + hushType = appConfig.type + durationInMinutes = appConfig.duration + muteDays = utils.getStringFromDaysList(appConfig.daysList) + startTime = utils.toLocalTime(appConfig.startEndTime.startTime) + endTime = utils.toLocalTime(appConfig.startEndTime.endTime) timeUpdated = System.currentTimeMillis() - logNotification = logNotificationvalue + logNotification = appConfig.logNotification isComplete = true } selectAppRepository.update(selectedAppFromDB) @@ -155,13 +150,13 @@ class MainActivityVM @Inject constructor( val selectedApp = SelectedApp( appName = app.appName, packageName = app.packageName, - hushType = type, - durationInMinutes = duration, - muteDays = utils.getStringFromDaysList(daysList), - startTime = utils.toLocalTime(startEndTime.startTime), - endTime = utils.toLocalTime(startEndTime.endTime), + hushType = appConfig.type, + durationInMinutes = appConfig.duration, + muteDays = utils.getStringFromDaysList(appConfig.daysList), + startTime = utils.toLocalTime(appConfig.startEndTime.startTime), + endTime = utils.toLocalTime(appConfig.startEndTime.endTime), timeUpdated = System.currentTimeMillis(), - logNotification = logNotificationvalue, + logNotification = appConfig.logNotification, isComplete = true ) selectAppRepository.addSelectedApp(selectedApp) @@ -175,9 +170,9 @@ class MainActivityVM @Inject constructor( } } - fun updateComplete(app: SelectedAppForList){ + fun updateComplete(app: SelectedApp){ executedSuspendedCodeBlock { - val selectedAppFromDB = selectAppRepository.getSelectedApp(app.selectedApp.packageName) + val selectedAppFromDB = selectAppRepository.getSelectedApp(app.packageName) if (selectedAppFromDB != null){ selectedAppFromDB.isComplete = false selectAppRepository.update(selectedAppFromDB) diff --git a/app/src/main/java/dev/souravdas/hush/compose/main/MainScreen.kt b/app/src/main/java/dev/souravdas/hush/compose/main/MainScreen.kt index 64f00ce..2c591d6 100644 --- a/app/src/main/java/dev/souravdas/hush/compose/main/MainScreen.kt +++ b/app/src/main/java/dev/souravdas/hush/compose/main/MainScreen.kt @@ -1,7 +1,6 @@ package dev.souravdas.hush.compose.main import android.annotation.SuppressLint -import android.widget.Toast import androidx.compose.animation.AnimatedVisibility import androidx.compose.animation.animateContentSize import androidx.compose.animation.core.keyframes @@ -38,9 +37,7 @@ import androidx.compose.ui.text.font.FontWeight import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.sp import androidx.hilt.navigation.compose.hiltViewModel -import androidx.lifecycle.viewmodel.compose.viewModel import com.google.accompanist.drawablepainter.rememberDrawablePainter -import dev.souravdas.hush.HushApp import dev.souravdas.hush.R import dev.souravdas.hush.arch.MainActivityVM import dev.souravdas.hush.models.SelectedApp @@ -58,145 +55,143 @@ import androidx.compose.material3.MaterialTheme as MD3 * On 2/22/2023 11:45 PM * For Hush! */ -class MainScreen() { - @OptIn( - ExperimentalMaterial3Api::class, - ExperimentalMaterialApi::class, ExperimentalLayoutApi::class - ) - @Composable - fun MainActivityScreen( - viewModel: MainActivityVM = hiltViewModel(), - checkNotificationPermission: () -> Boolean, - onNotificationPermissionGet: () -> Unit - ) { - val scope = rememberCoroutineScope() - val scaffoldState = rememberBottomSheetScaffoldState() - val list = viewModel.appListSF.collectAsState() - viewModel.getInstalledApps() - - BottomSheetScaffold( - backgroundColor = MD3.colorScheme.background, - scaffoldState = scaffoldState, - sheetPeekHeight = 56.dp, - topBar = { - TopAppBar( - title = { - Text( - stringResource(id = R.string.app_name), - fontSize = 32.sp, - fontWeight = FontWeight.Medium, - color = MD3.colorScheme.onBackground - ) - } - ) - }, - sheetContent = { - InstalledAppList(items = list.value) { item -> - scope.launch { - scaffoldState.bottomSheetState.collapse() - }.invokeOnCompletion { - // TODO: insert here - viewModel.addOrUpdateSelectedApp(item) - } - } - }, - floatingActionButtonPosition = FabPosition.End, - floatingActionButton = { - androidx.compose.material.FloatingActionButton( - onClick = { - scope.launch { - if (scaffoldState.bottomSheetState.isExpanded) { - scaffoldState.bottomSheetState.collapse() - } else { - scaffoldState.bottomSheetState.expand() - } - } - }, - backgroundColor = MD3.colorScheme.secondary, - contentColor = MD3.colorScheme.onSecondary, - ) { - Icon( - painter = painterResource(id = R.drawable.twotone_add_24), - tint = MD3.colorScheme.onSecondary, - contentDescription = "Add Icon" +@OptIn( + ExperimentalMaterial3Api::class, + ExperimentalMaterialApi::class, ExperimentalLayoutApi::class +) +@Composable +fun MainActivityScreen( + viewModel: MainActivityVM = hiltViewModel(), + checkNotificationPermission: () -> Boolean, + onNotificationPermissionGet: () -> Unit +) { + viewModel.getInstalledApps() + val scope = rememberCoroutineScope() + val scaffoldState = rememberBottomSheetScaffoldState() + val list = viewModel.appListSF.collectAsState() + + BottomSheetScaffold( + backgroundColor = MD3.colorScheme.background, + scaffoldState = scaffoldState, + sheetPeekHeight = 56.dp, + topBar = { + TopAppBar( + title = { + Text( + stringResource(id = R.string.app_name), + fontSize = 32.sp, + fontWeight = FontWeight.Medium, + color = MD3.colorScheme.onBackground ) } - }, - modifier = Modifier.background(MD3.colorScheme.background) - ) { mo ->//HERE - val modifier = Modifier.consumeWindowInsets(mo) - val hushStatus = viewModel.getHushStatusAsFlow().collectAsState(initial = false) - var showNotificationPermissionAlertDialog by remember { - mutableStateOf(!checkNotificationPermission.invoke()) + ) + }, + sheetContent = { + InstalledAppList(items = list.value) { item -> + scope.launch { + scaffoldState.bottomSheetState.collapse() + }.invokeOnCompletion { + // TODO: insert here + viewModel.addOrUpdateSelectedApp(item) + } } + }, + floatingActionButtonPosition = FabPosition.End, + floatingActionButton = { + androidx.compose.material.FloatingActionButton( + onClick = { + scope.launch { + if (scaffoldState.bottomSheetState.isExpanded) { + scaffoldState.bottomSheetState.collapse() + } else { + scaffoldState.bottomSheetState.expand() + } + } + }, + backgroundColor = MD3.colorScheme.secondary, + contentColor = MD3.colorScheme.onSecondary, + ) { + Icon( + painter = painterResource(id = R.drawable.twotone_add_24), + tint = MD3.colorScheme.onSecondary, + contentDescription = "Add Icon" + ) + } + }, + modifier = Modifier.background(MD3.colorScheme.background) + ) { mo -> + val selectedList by viewModel.selectedAppsSF.collectAsState(emptyList()) + Timber.d(selectedList.size.toString()) + val modifier = Modifier.consumeWindowInsets(mo) + val hushStatus = viewModel.getHushStatusAsFlow().collectAsState(initial = false) + var showNotificationPermissionAlertDialog by remember { + mutableStateOf(!checkNotificationPermission.invoke()) + } - if (showNotificationPermissionAlertDialog) - ShowAlertDialog { - showNotificationPermissionAlertDialog = false - onNotificationPermissionGet.invoke() - } + val setHushStatus = remember<(Boolean) -> Unit> { + { status -> + if (checkNotificationPermission.invoke()) + viewModel.setHushStatus(status) + else + showNotificationPermissionAlertDialog = true + } + } + + val editAppLambda = remember<(SelectedApp) -> Unit> { + { app -> + viewModel.updateComplete(app) + } + } + val removeAppLambda = remember<(SelectedApp) -> Unit> { + { app -> + viewModel.removeApp(app) + } + } + + if (showNotificationPermissionAlertDialog) + ShowAlertDialog { + showNotificationPermissionAlertDialog = false + onNotificationPermissionGet.invoke() + } // <--- Hush Service Toggle ----> - Row( - horizontalArrangement = Arrangement.SpaceBetween, + Row( + horizontalArrangement = Arrangement.SpaceBetween, + modifier = Modifier + .fillMaxWidth() + .padding(8.dp) + .background( + color = if (hushStatus.value) MD3.colorScheme.primary else MD3.colorScheme.surfaceVariant, + shape = RoundedCornerShape(12.dp) + ) + .clickable { + if (checkNotificationPermission.invoke()) + viewModel.setHushStatus(!hushStatus.value) + else + showNotificationPermissionAlertDialog = true + } + ) + { + Text( + text = "Start Hush Service", + fontSize = 16.sp, + fontWeight = FontWeight.Bold, + color = if (hushStatus.value) MD3.colorScheme.onPrimary else MD3.colorScheme.onSurfaceVariant, modifier = Modifier - .fillMaxWidth() - .padding(8.dp) - .background( - color = if (hushStatus.value) MD3.colorScheme.primary else MD3.colorScheme.surfaceVariant, - shape = RoundedCornerShape(12.dp) - ) - .clickable { - if (checkNotificationPermission.invoke()) - viewModel.setHushStatus(!hushStatus.value) - else - showNotificationPermissionAlertDialog = true - } + .padding(start = 8.dp) + .align(alignment = Alignment.CenterVertically) ) - { - Text( - text = "Start Hush Service", - fontSize = 16.sp, - fontWeight = FontWeight.Bold, - color = if (hushStatus.value) MD3.colorScheme.onPrimary else MD3.colorScheme.onSurfaceVariant, - modifier = Modifier - .padding(start = 8.dp) - .align(alignment = Alignment.CenterVertically) - ) - Switch( - checked = hushStatus.value, - colors = SwitchDefaults.colors( - checkedThumbColor = MD3.colorScheme.primaryContainer - ), - onCheckedChange = { status -> - if (checkNotificationPermission.invoke()) - viewModel.setHushStatus(status) - else - showNotificationPermissionAlertDialog = true - }, - modifier = Modifier.padding(end = 8.dp) - ) - } - - ShowSelectedApps( - modifier = modifier, - viewModel, - onRemoveClick = { - viewModel.removeApp(it) - Toast.makeText(HushApp.context, "Item Removed", Toast.LENGTH_SHORT).show() - }) + Switch( + checked = hushStatus.value, + colors = SwitchDefaults.colors( + checkedThumbColor = MD3.colorScheme.primaryContainer + ), + onCheckedChange = setHushStatus, + modifier = Modifier.padding(end = 8.dp) + ) } - } - @Composable - fun ShowSelectedApps( - modifier: Modifier, - viewModel: MainActivityVM, - onRemoveClick: (SelectedApp) -> Unit - ) { - viewModel.getSelectedApp() - val itemList = viewModel.selectedAppsSF.collectAsState(initial = emptyList()) LazyColumn( modifier = modifier .padding(8.dp) @@ -211,23 +206,14 @@ class MainScreen() { ) } } - items(itemList.value, key = { + items(selectedList, key = { it.selectedApp.timeUpdated }) { app -> SelectedAppItem( selectedApp = app, - onRemoveClick = onRemoveClick, - onEditClick = { viewModel.updateComplete(app) }, - onConfigDone = { type: HushType, startEndTime: StartEndTime, duration: Long, daysList: List, logNotification: Boolean -> - viewModel.addConfigInSelectedApp( - app.selectedApp, - type, - startEndTime, - duration, - daysList, - logNotification - ) - }, + onRemoveClick = viewModel::removeApp, + onEditClick = viewModel::updateComplete, + onConfigDone = viewModel::addConfigInSelectedApp, onCancelClick = { viewModel.removeApp(app.selectedApp) } @@ -235,587 +221,605 @@ class MainScreen() { } } } +} + +@Composable +fun SelectedAppItem( + selectedApp: SelectedAppForList, + onRemoveClick: (SelectedApp) -> Unit = {}, + onEditClick: (SelectedApp) -> Unit, + onConfigDone: (AppConfig) -> Unit, + onCancelClick: () -> Unit +) { + var showOptions by remember { + mutableStateOf(false) + } + var showInitConfig by remember { + mutableStateOf(false) + } - @Composable - fun SelectedAppItem( - selectedApp: SelectedAppForList, - onRemoveClick: (SelectedApp) -> Unit = {}, - onEditClick: (SelectedApp) -> Unit, - onConfigDone: (type: HushType, startEndTime: StartEndTime, duration: Long, daysList: List, logNotification: Boolean) -> Unit, - onCancelClick: () -> Unit - ) { - var showOptions by remember { - mutableStateOf(false) - } - var showInitConfig by remember { - mutableStateOf(false) - } - - showInitConfig = !selectedApp.selectedApp.isComplete + showInitConfig = !selectedApp.selectedApp.isComplete - Column(modifier = Modifier - .fillMaxHeight() - .clickable { - if (!showInitConfig) { - showOptions = !showOptions - } + Column(modifier = Modifier + .fillMaxHeight() + .clickable { + if (!showInitConfig) { + showOptions = !showOptions } - .padding(bottom = 10.dp) - .background( - Color(androidx.compose.material3.MaterialTheme.colorScheme.primaryContainer.toArgb()), - RoundedCornerShape(12.dp) - )) { + } + .padding(bottom = 10.dp) + .background( + Color(androidx.compose.material3.MaterialTheme.colorScheme.primaryContainer.toArgb()), + RoundedCornerShape(12.dp) + )) { + Row( + verticalAlignment = Alignment.CenterVertically, + modifier = Modifier + .fillMaxWidth() + .padding(10.dp) + ) { + Image( + painter = rememberDrawablePainter( + drawable = selectedApp.icon + ), + contentDescription = "appIcon", + modifier = Modifier + .size(50.dp) + .clip(CircleShape) + ) Row( + horizontalArrangement = Arrangement.SpaceBetween, verticalAlignment = Alignment.CenterVertically, modifier = Modifier .fillMaxWidth() - .padding(10.dp) + .padding(start = 8.dp, end = 8.dp) ) { - Image( - painter = rememberDrawablePainter( - drawable = selectedApp.icon - ), - contentDescription = "appIcon", - modifier = Modifier - .size(50.dp) - .clip(CircleShape) + Text( + text = selectedApp.selectedApp.appName, + fontSize = 24.sp, + color = MD3.colorScheme.onPrimaryContainer ) - Row( - horizontalArrangement = Arrangement.SpaceBetween, - verticalAlignment = Alignment.CenterVertically, - modifier = Modifier - .fillMaxWidth() - .padding(start = 8.dp, end = 8.dp) - ) { - Text( - text = selectedApp.selectedApp.appName, - fontSize = 24.sp, - color = MD3.colorScheme.onPrimaryContainer - ) - if (selectedApp.selectedApp.hushType != null) { - if (selectedApp.selectedApp.hushType == HushType.DURATION - && System.currentTimeMillis() >= selectedApp.selectedApp.timeUpdated + selectedApp.selectedApp.durationInMinutes!! * 60000 - ) { + if (selectedApp.selectedApp.hushType != null) { + if (selectedApp.selectedApp.hushType == HushType.DURATION + && System.currentTimeMillis() >= selectedApp.selectedApp.timeUpdated + selectedApp.selectedApp.durationInMinutes!! * 60000 + ) { + CustomChip( + title = "Expired", + color = Color.Red, + fontColor = Color.White + ) + } else { + selectedApp.selectedApp.hushType?.let { CustomChip( - title = "Expired", - color = Color.Red, - fontColor = Color.White + title = it.label, ) - } else { - selectedApp.selectedApp.hushType?.let { - CustomChip( - title = it.label, - ) - } } } } - } - val buttonModifier = Modifier.padding(end = 4.dp) - AnimatedVisibility(showInitConfig) { - ShowInitConfig(onConfigDone, onCancelClick) - } + } + val buttonModifier = Modifier.padding(end = 4.dp) - AnimatedVisibility(showOptions) { - ShowOptions(buttonModifier, onRemoveClick, onEditClick, selectedApp) - } + AnimatedVisibility(showInitConfig) { + ShowInitConfig(selectedApp.selectedApp, onConfigDone, onCancelClick) } - } - @OptIn(ExperimentalMaterial3Api::class) - @Composable - fun ShowInitConfig( - onConfigDone: (type: HushType, startEndTime: StartEndTime, duration: Long, daysList: List, logNotification: Boolean) -> Unit, - onCancelClick: () -> Unit + AnimatedVisibility(showOptions) { + ShowOptions(buttonModifier, onRemoveClick, onEditClick, selectedApp) + } + } +} + +@OptIn(ExperimentalMaterial3Api::class) +@Composable +fun ShowInitConfig( + app: SelectedApp, + onConfigDone: (AppConfig) -> Unit, + onCancelClick: () -> Unit +) { + Column( + modifier = Modifier + .padding(start = 8.dp, end = 8.dp) + .wrapContentWidth() ) { - Column( - modifier = Modifier - .padding(start = 8.dp, end = 8.dp) - .wrapContentWidth() - ) { - var showTimePickerStart by remember { - mutableStateOf(false) - } + var showTimePickerStart by remember { + mutableStateOf(false) + } - var showTimePickerEnd by remember { - mutableStateOf(false) - } + var showTimePickerEnd by remember { + mutableStateOf(false) + } - var logNotificationCb by remember { - mutableStateOf(true) - } - val startEndTimePair by remember { - mutableStateOf(StartEndTime("00:00", "23:59")) - } - var selectedDays by remember { mutableStateOf(List(7) { null }) } + var logNotificationCb by remember { + mutableStateOf(true) + } + val startEndTimePair by remember { + mutableStateOf(StartEndTime("00:00", "23:59")) + } + var selectedDays by remember { mutableStateOf(List(7) { null }) } - var selectedDuration: Long = 0 - var husType: HushType by remember { - mutableStateOf(HushType.ALWAYS) - } + var selectedDuration: Long = 0 + var husType: HushType by remember { + mutableStateOf(HushType.ALWAYS) + } - ShowChipRow { - husType = it - }; + ShowChipRow { + husType = it + }; - AnimatedVisibility(visible = husType == HushType.ALWAYS) { - // default - } + AnimatedVisibility(visible = husType == HushType.ALWAYS) { + // default + } - AnimatedVisibility(visible = husType == HushType.DAYS) { - Column( - modifier = Modifier - .wrapContentWidth() - .wrapContentHeight(unbounded = true) + AnimatedVisibility(visible = husType == HushType.DAYS) { + Column( + modifier = Modifier + .wrapContentWidth() + .wrapContentHeight(unbounded = true) + .padding(top = 8.dp, bottom = 8.dp) + ) { + + Row( + Modifier + .fillMaxWidth() .padding(top = 8.dp, bottom = 8.dp) ) { + FilledTonalIconToggleButton( + checked = !selectedDays[0].isNullOrEmpty(), + colors = IconButtonDefaults.filledIconToggleButtonColors( + containerColor = MD3.colorScheme.surfaceVariant, + checkedContainerColor = MD3.colorScheme.tertiary + ), + onCheckedChange = { + selectedDays = selectedDays.toMutableList() + .apply { set(0, if (it) "SAT" else null) } + }) { + ShowDaysText(!selectedDays[0].isNullOrEmpty(), "SAT") + } + FilledTonalIconToggleButton( + checked = !selectedDays[1].isNullOrEmpty(), + colors = IconButtonDefaults.filledIconToggleButtonColors( + containerColor = MD3.colorScheme.surfaceVariant, + checkedContainerColor = MD3.colorScheme.tertiary + ), + onCheckedChange = { + selectedDays = selectedDays.toMutableList() + .apply { set(1, if (it) "SUN" else null) } + }) { + ShowDaysText(!selectedDays[1].isNullOrEmpty(), "SUN") + } + FilledTonalIconToggleButton( + checked = !selectedDays[2].isNullOrEmpty(), + colors = IconButtonDefaults.filledIconToggleButtonColors( + containerColor = MD3.colorScheme.surfaceVariant, + checkedContainerColor = MD3.colorScheme.tertiary + ), + onCheckedChange = { + selectedDays = selectedDays.toMutableList() + .apply { set(2, if (it) "MON" else null) } + }) { + ShowDaysText(!selectedDays[2].isNullOrEmpty(), "MON") + } + FilledTonalIconToggleButton( + checked = !selectedDays[3].isNullOrEmpty(), + colors = IconButtonDefaults.filledIconToggleButtonColors( + containerColor = MD3.colorScheme.surfaceVariant, + checkedContainerColor = MD3.colorScheme.tertiary + ), + onCheckedChange = { + selectedDays = selectedDays.toMutableList() + .apply { set(3, if (it) "TUE" else null) } + }) { + ShowDaysText(!selectedDays[3].isNullOrEmpty(), "TUE") + } + FilledTonalIconToggleButton( + checked = !selectedDays[4].isNullOrEmpty(), + colors = IconButtonDefaults.filledIconToggleButtonColors( + containerColor = MD3.colorScheme.surfaceVariant, + checkedContainerColor = MD3.colorScheme.tertiary + ), + onCheckedChange = { + selectedDays = selectedDays.toMutableList() + .apply { set(4, if (it) "WED" else null) } + }) { + ShowDaysText(!selectedDays[4].isNullOrEmpty(), "WED") + } + FilledTonalIconToggleButton( + checked = !selectedDays[5].isNullOrEmpty(), + colors = IconButtonDefaults.filledIconToggleButtonColors( + containerColor = MD3.colorScheme.surfaceVariant, + checkedContainerColor = MD3.colorScheme.tertiary + ), + onCheckedChange = { + selectedDays = selectedDays.toMutableList() + .apply { set(5, if (it) "THU" else null) } + } + ) { + ShowDaysText(!selectedDays[5].isNullOrEmpty(), "THU") + } + FilledTonalIconToggleButton( + checked = !selectedDays[6].isNullOrEmpty(), + onCheckedChange = { + selectedDays = selectedDays.toMutableList() + .apply { set(6, if (it) "FRI" else null) } + }, + colors = IconButtonDefaults.filledIconToggleButtonColors( + containerColor = MD3.colorScheme.surfaceVariant, + checkedContainerColor = MD3.colorScheme.tertiary + ) + ) { + ShowDaysText(!selectedDays[6].isNullOrEmpty(), "FRI") + } + } + Column(Modifier.padding(start = 8.dp, end = 8.dp)) { + Text( + modifier = Modifier.padding(top = 8.dp, bottom = 4.dp), + text = "Start Time", + color = MD3.colorScheme.onPrimaryContainer + ) Row( - Modifier + verticalAlignment = Alignment.CenterVertically, + modifier = Modifier .fillMaxWidth() - .padding(top = 8.dp, bottom = 8.dp) - ) { - FilledTonalIconToggleButton( - checked = !selectedDays[0].isNullOrEmpty(), - colors = IconButtonDefaults.filledIconToggleButtonColors( - containerColor = MD3.colorScheme.surfaceVariant, - checkedContainerColor = MD3.colorScheme.tertiary - ), - onCheckedChange = { - selectedDays = selectedDays.toMutableList() - .apply { set(0, if (it) "SAT" else null) } - }) { - ShowDaysText(!selectedDays[0].isNullOrEmpty(), "SAT") - } - FilledTonalIconToggleButton( - checked = !selectedDays[1].isNullOrEmpty(), - colors = IconButtonDefaults.filledIconToggleButtonColors( - containerColor = MD3.colorScheme.surfaceVariant, - checkedContainerColor = MD3.colorScheme.tertiary - ), - onCheckedChange = { - selectedDays = selectedDays.toMutableList() - .apply { set(1, if (it) "SUN" else null) } - }) { - ShowDaysText(!selectedDays[1].isNullOrEmpty(), "SUN") - } - FilledTonalIconToggleButton( - checked = !selectedDays[2].isNullOrEmpty(), - colors = IconButtonDefaults.filledIconToggleButtonColors( - containerColor = MD3.colorScheme.surfaceVariant, - checkedContainerColor = MD3.colorScheme.tertiary - ), - onCheckedChange = { - selectedDays = selectedDays.toMutableList() - .apply { set(2, if (it) "MON" else null) } - }) { - ShowDaysText(!selectedDays[2].isNullOrEmpty(), "MON") - } - FilledTonalIconToggleButton( - checked = !selectedDays[3].isNullOrEmpty(), - colors = IconButtonDefaults.filledIconToggleButtonColors( - containerColor = MD3.colorScheme.surfaceVariant, - checkedContainerColor = MD3.colorScheme.tertiary - ), - onCheckedChange = { - selectedDays = selectedDays.toMutableList() - .apply { set(3, if (it) "TUE" else null) } - }) { - ShowDaysText(!selectedDays[3].isNullOrEmpty(), "TUE") - } - FilledTonalIconToggleButton( - checked = !selectedDays[4].isNullOrEmpty(), - colors = IconButtonDefaults.filledIconToggleButtonColors( - containerColor = MD3.colorScheme.surfaceVariant, - checkedContainerColor = MD3.colorScheme.tertiary - ), - onCheckedChange = { - selectedDays = selectedDays.toMutableList() - .apply { set(4, if (it) "WED" else null) } - }) { - ShowDaysText(!selectedDays[4].isNullOrEmpty(), "WED") - } - FilledTonalIconToggleButton( - checked = !selectedDays[5].isNullOrEmpty(), - colors = IconButtonDefaults.filledIconToggleButtonColors( - containerColor = MD3.colorScheme.surfaceVariant, - checkedContainerColor = MD3.colorScheme.tertiary - ), - onCheckedChange = { - selectedDays = selectedDays.toMutableList() - .apply { set(5, if (it) "THU" else null) } + .clickable { + showTimePickerStart = true } - ) { - ShowDaysText(!selectedDays[5].isNullOrEmpty(), "THU") - } - FilledTonalIconToggleButton( - checked = !selectedDays[6].isNullOrEmpty(), - onCheckedChange = { - selectedDays = selectedDays.toMutableList() - .apply { set(6, if (it) "FRI" else null) } - }, - colors = IconButtonDefaults.filledIconToggleButtonColors( - containerColor = MD3.colorScheme.surfaceVariant, - checkedContainerColor = MD3.colorScheme.tertiary - ) - ) { - ShowDaysText(!selectedDays[6].isNullOrEmpty(), "FRI") - } - } - - Column(Modifier.padding(start = 8.dp, end = 8.dp)) { + ) { + Icon( + Icons.Outlined.Edit, + contentDescription = "Edit", + tint = MD3.colorScheme.onPrimaryContainer, + modifier = Modifier + .size(20.dp) + ) Text( - modifier = Modifier.padding(top = 8.dp, bottom = 4.dp), - text = "Start Time", - color = MD3.colorScheme.onPrimaryContainer + text = get12HrsFrom24Hrs(startEndTimePair.startTime), + fontSize = 24.sp, + fontWeight = FontWeight.Medium, + color = MD3.colorScheme.onPrimaryContainer, + modifier = Modifier.padding(start = 24.dp) + ) + } + Text( + modifier = Modifier.padding(top = 8.dp, bottom = 4.dp), + text = "End Time", + color = MD3.colorScheme.onPrimaryContainer + ) + Row( + verticalAlignment = Alignment.CenterVertically, + modifier = Modifier + .fillMaxWidth() + .clickable { + showTimePickerEnd = true + } + ) { + Icon( + Icons.Outlined.Edit, + contentDescription = "Edit", + tint = MD3.colorScheme.onPrimaryContainer, + modifier = Modifier.size(20.dp) ) - Row( - verticalAlignment = Alignment.CenterVertically, - modifier = Modifier - .fillMaxWidth() - .clickable { - showTimePickerStart = true - } - ) { - Icon( - Icons.Outlined.Edit, - contentDescription = "Edit", - tint = MD3.colorScheme.onPrimaryContainer, - modifier = Modifier - .size(20.dp) - ) - Text( - text = get12HrsFrom24Hrs(startEndTimePair.startTime), - fontSize = 24.sp, - fontWeight = FontWeight.Medium, - color = MD3.colorScheme.onPrimaryContainer, - modifier = Modifier.padding(start = 24.dp) - ) - } Text( - modifier = Modifier.padding(top = 8.dp, bottom = 4.dp), - text = "End Time", - color = MD3.colorScheme.onPrimaryContainer + text = get12HrsFrom24Hrs(startEndTimePair.endTime), + fontSize = 24.sp, + fontWeight = FontWeight.Medium, + color = MD3.colorScheme.onPrimaryContainer, + modifier = Modifier.padding(start = 24.dp) ) - Row( - verticalAlignment = Alignment.CenterVertically, - modifier = Modifier - .fillMaxWidth() - .clickable { - showTimePickerEnd = true - } - ) { - Icon( - Icons.Outlined.Edit, - contentDescription = "Edit", - tint = MD3.colorScheme.onPrimaryContainer, - modifier = Modifier.size(20.dp) - ) - Text( - text = get12HrsFrom24Hrs(startEndTimePair.endTime), - fontSize = 24.sp, - fontWeight = FontWeight.Medium, - color = MD3.colorScheme.onPrimaryContainer, - modifier = Modifier.padding(start = 24.dp) - ) - } } } } + } - AnimatedVisibility(visible = husType == HushType.DURATION) { - DurationSelector { - selectedDuration = it - } + AnimatedVisibility(visible = husType == HushType.DURATION) { + DurationSelector { + selectedDuration = it } + } - Row(modifier = Modifier.padding(8.dp)) { - CompositionLocalProvider(LocalMinimumInteractiveComponentEnforcement provides false) { - Checkbox( - checked = logNotificationCb, - onCheckedChange = { - logNotificationCb = !logNotificationCb + Row(modifier = Modifier.padding(8.dp)) { + CompositionLocalProvider(LocalMinimumInteractiveComponentEnforcement provides false) { + Checkbox( + checked = logNotificationCb, + onCheckedChange = { + logNotificationCb = !logNotificationCb - if (it) Constants.showNIY() - } - ) - } - Text( - text = "Log Notifications", - color = Color(androidx.compose.material3.MaterialTheme.colorScheme.onPrimaryContainer.toArgb()), - modifier = - Modifier - .align(Alignment.CenterVertically) - .padding(start = 8.dp) + if (it) Constants.showNIY() + } ) } + Text( + text = "Log Notifications", + color = Color(androidx.compose.material3.MaterialTheme.colorScheme.onPrimaryContainer.toArgb()), + modifier = + Modifier + .align(Alignment.CenterVertically) + .padding(start = 8.dp) + ) + } - if (showTimePickerStart) { - ShowTimePicker( - Pair( - startEndTimePair.startTime.split(":")[0].toInt(), - startEndTimePair.startTime.split(":")[1].toInt() - ), - "Pick a start time", - { - Timber.d(it) - startEndTimePair.startTime = it - showTimePickerStart = false - }, { - showTimePickerStart = false - }) - } - if (showTimePickerEnd) { - ShowTimePicker( - Pair( - startEndTimePair.endTime.split(":")[0].toInt(), - startEndTimePair.endTime.split(":")[1].toInt() - ), - "Pick an end time", - { - Timber.d(it) - startEndTimePair.endTime = it - showTimePickerEnd = false - }, { - showTimePickerEnd = false - }) - } - - AddCancelButtonBar(onAddClick = { - onConfigDone.invoke( - husType, startEndTimePair, selectedDuration, selectedDays, logNotificationCb - ) - }, onCancelClick = { - onCancelClick.invoke() - }) + if (showTimePickerStart) { + ShowTimePicker( + Pair( + startEndTimePair.startTime.split(":")[0].toInt(), + startEndTimePair.startTime.split(":")[1].toInt() + ), + "Pick a start time", + { + Timber.d(it) + startEndTimePair.startTime = it + showTimePickerStart = false + }, { + showTimePickerStart = false + }) + } + if (showTimePickerEnd) { + ShowTimePicker( + Pair( + startEndTimePair.endTime.split(":")[0].toInt(), + startEndTimePair.endTime.split(":")[1].toInt() + ), + "Pick an end time", + { + Timber.d(it) + startEndTimePair.endTime = it + showTimePickerEnd = false + }, { + showTimePickerEnd = false + }) } + AddCancelButtonBar(onAddClick = { + onConfigDone.invoke( + AppConfig( + app, + husType, + startEndTimePair, + selectedDuration, + selectedDays, + logNotificationCb + ) + ) + }, onCancelClick = { + onCancelClick.invoke() + }) } - @Composable - fun ShowOptions( - @SuppressLint("ModifierParameter") buttonModifier: Modifier, - onRemoveClick: (SelectedApp) -> Unit = {}, - onEditClick: (SelectedApp) -> Unit, - selectedApp: SelectedAppForList +} + +@Composable +fun ShowOptions( + @SuppressLint("ModifierParameter") buttonModifier: Modifier, + onRemoveClick: (SelectedApp) -> Unit = {}, + onEditClick: (SelectedApp) -> Unit, + selectedApp: SelectedAppForList +) { + Row( + modifier = Modifier + .background( + color = MD3.colorScheme.secondaryContainer, + RoundedCornerShape(bottomStart = 12.dp, bottomEnd = 12.dp) + ) + .fillMaxWidth() ) { - Row( - modifier = Modifier - .background( - color = MD3.colorScheme.secondaryContainer, - RoundedCornerShape(bottomStart = 12.dp, bottomEnd = 12.dp) - ) - .fillMaxWidth() - ) { - TextButton( - modifier = buttonModifier, - onClick = { Constants.showNIY() }) { - Text("Notification History", color = MD3.colorScheme.onSecondaryContainer) - } + TextButton( + modifier = buttonModifier, + onClick = { Constants.showNIY() }) { + Text("Notification History", color = MD3.colorScheme.onSecondaryContainer) + } - TextButton( - modifier = buttonModifier, - onClick = { onEditClick.invoke(selectedApp.selectedApp) }) { - Text("Edit", color = MD3.colorScheme.onSecondaryContainer) - } + TextButton( + modifier = buttonModifier, + onClick = { onEditClick.invoke(selectedApp.selectedApp) }) { + Text("Edit", color = MD3.colorScheme.onSecondaryContainer) + } - TextButton( - modifier = buttonModifier, - onClick = { onRemoveClick.invoke(selectedApp.selectedApp) }) { - Text("Remove", color = MD3.colorScheme.onSecondaryContainer) - } + TextButton( + modifier = buttonModifier, + onClick = { onRemoveClick.invoke(selectedApp.selectedApp) }) { + Text("Remove", color = MD3.colorScheme.onSecondaryContainer) } } +} - @Composable - fun DurationSelector(getDuration: (Long) -> Unit = {}) { - var duration by remember { mutableStateOf(0) } - Row( - modifier = Modifier - .background( - colorResource(id = R.color.whiteBG), RoundedCornerShape(12.dp) - ) - .height(48.dp) - .fillMaxWidth(), - horizontalArrangement = Arrangement.Center, - verticalAlignment = Alignment.CenterVertically - ) { - IconButton( - onClick = { - if (duration > 0) { - duration -= 10 - if (duration >= 60) { - duration -= 20 - } - } - getDuration.invoke(duration.toLong()) - }, modifier = Modifier - .padding(end = 16.dp) - .align(Alignment.CenterVertically) - ) { - Icon( - painterResource(id = R.drawable.twotone_remove_circle_24), - contentDescription = "Decrease duration by 10 minutes" - ) - } - - val hours = duration / 60 - val minutes = duration % 60 - Text( - text = if (hours > 0) { - "${hours}h ${minutes}min" - } else { - "${duration} min" - }, - modifier = Modifier - .padding(start = 16.dp, end = 16.dp) - .align(Alignment.CenterVertically) +@Composable +fun DurationSelector(getDuration: (Long) -> Unit = {}) { + var duration by remember { mutableStateOf(0) } + Row( + modifier = Modifier + .background( + colorResource(id = R.color.whiteBG), RoundedCornerShape(12.dp) ) - IconButton( - onClick = { - duration += 10 + .height(48.dp) + .fillMaxWidth(), + horizontalArrangement = Arrangement.Center, + verticalAlignment = Alignment.CenterVertically + ) { + IconButton( + onClick = { + if (duration > 0) { + duration -= 10 if (duration >= 60) { - duration += 30 + duration -= 20 } - getDuration.invoke(duration.toLong()) - }, modifier = Modifier - .padding(start = 16.dp) - .align(Alignment.CenterVertically) - ) { - Icon( - painterResource(id = R.drawable.twotone_add_circle_24), - contentDescription = "Increase duration by 10 minutes" - ) - } + } + getDuration.invoke(duration.toLong()) + }, modifier = Modifier + .padding(end = 16.dp) + .align(Alignment.CenterVertically) + ) { + Icon( + painterResource(id = R.drawable.twotone_remove_circle_24), + contentDescription = "Decrease duration by 10 minutes" + ) } - } - - @Composable - fun CustomChip( - title: String, - color: Color = MD3.colorScheme.tertiary, - fontColor: Color = MD3.colorScheme.onTertiary - ) { - Box( + val hours = duration / 60 + val minutes = duration % 60 + Text( + text = if (hours > 0) { + "${hours}h ${minutes}min" + } else { + "${duration} min" + }, modifier = Modifier - .padding(top = 4.dp, bottom = 4.dp) - .background( - color = color, - RoundedCornerShape(10.dp) - ) + .padding(start = 16.dp, end = 16.dp) + .align(Alignment.CenterVertically) + ) + IconButton( + onClick = { + duration += 10 + if (duration >= 60) { + duration += 30 + } + getDuration.invoke(duration.toLong()) + }, modifier = Modifier + .padding(start = 16.dp) + .align(Alignment.CenterVertically) ) { - Text( - text = title, - modifier = Modifier.padding( - top = 4.dp, bottom = 4.dp, start = 6.dp, end = 6.dp - ), - color = fontColor, - fontSize = 12.sp, + Icon( + painterResource(id = R.drawable.twotone_add_circle_24), + contentDescription = "Increase duration by 10 minutes" ) } - } - - @Composable - fun ShowDaysText(selected: Boolean, title: String) { - if (selected) { - Text( - text = title, - fontSize = 12.sp, - fontWeight = FontWeight.Bold, - color = MD3.colorScheme.onTertiary - ) - } else { - Text( - text = title, - color = MD3.colorScheme.onSurfaceVariant, - fontSize = 12.sp +} + + +@Composable +fun CustomChip( + title: String, + color: Color = MD3.colorScheme.tertiary, + fontColor: Color = MD3.colorScheme.onTertiary +) { + Box( + modifier = Modifier + .padding(top = 4.dp, bottom = 4.dp) + .background( + color = color, + RoundedCornerShape(10.dp) ) - } + ) { + Text( + text = title, + modifier = Modifier.padding( + top = 4.dp, bottom = 4.dp, start = 6.dp, end = 6.dp + ), + color = fontColor, + fontSize = 12.sp, + ) } - @OptIn(ExperimentalMaterial3Api::class) - @Composable - fun ShowChipRow(onHushTypeSelected: (HushType) -> Unit = {}) { - - val selectedChipIndex = remember { mutableStateOf(HushType.ALWAYS) } - - Row(modifier = Modifier.fillMaxWidth()) { - ShowTypeSelectorChip( - type = HushType.ALWAYS, - selectedChipIndex = selectedChipIndex, - onHushTypeSelected = onHushTypeSelected - ) - ShowTypeSelectorChip( - type = HushType.DURATION, - selectedChipIndex = selectedChipIndex, - onHushTypeSelected = onHushTypeSelected - ) - ShowTypeSelectorChip( - type = HushType.DAYS, - selectedChipIndex = selectedChipIndex, - onHushTypeSelected = onHushTypeSelected - ) - - } +} + +@Composable +fun ShowDaysText(selected: Boolean, title: String) { + if (selected) { + Text( + text = title, + fontSize = 12.sp, + fontWeight = FontWeight.Bold, + color = MD3.colorScheme.onTertiary + ) + } else { + Text( + text = title, + color = MD3.colorScheme.onSurfaceVariant, + fontSize = 12.sp + ) } +} + +@OptIn(ExperimentalMaterial3Api::class) +@Composable +fun ShowChipRow(onHushTypeSelected: (HushType) -> Unit = {}) { + + val selectedChipIndex = remember { mutableStateOf(HushType.ALWAYS) } + + Row(modifier = Modifier.fillMaxWidth()) { + ShowTypeSelectorChip( + type = HushType.ALWAYS, + selectedChipIndex = selectedChipIndex, + onHushTypeSelected = onHushTypeSelected + ) + ShowTypeSelectorChip( + type = HushType.DURATION, + selectedChipIndex = selectedChipIndex, + onHushTypeSelected = onHushTypeSelected + ) + ShowTypeSelectorChip( + type = HushType.DAYS, + selectedChipIndex = selectedChipIndex, + onHushTypeSelected = onHushTypeSelected + ) - @OptIn(ExperimentalMaterial3Api::class) - @Composable - fun ShowTypeSelectorChip( - type: HushType, - selectedChipIndex: MutableState, - onHushTypeSelected: (HushType) -> Unit - ) { - - FilterChip( - selected = selectedChipIndex.value == type, - onClick = { - selectedChipIndex.value = type - onHushTypeSelected.invoke(type) - }, - colors = FilterChipDefaults.filterChipColors( - selectedContainerColor = MD3.colorScheme.tertiary, - containerColor = MD3.colorScheme.surfaceVariant, - - ), - label = { - Text( - text = type.label, - color = if (selectedChipIndex.value == type) MD3.colorScheme.onTertiary else MD3.colorScheme.onSurfaceVariant - ) - }, - modifier = Modifier.padding(start = 4.dp), leadingIcon = { - Box( - Modifier.animateContentSize(keyframes { - durationMillis = 100 - }) - ) { - if (selectedChipIndex.value == type) { - Icon( - imageVector = Icons.Default.Done, - contentDescription = null, - tint = MD3.colorScheme.onTertiary, - modifier = Modifier.size(FilterChipDefaults.IconSize) - ) - } + } +} + +@OptIn(ExperimentalMaterial3Api::class) +@Composable +fun ShowTypeSelectorChip( + type: HushType, + selectedChipIndex: MutableState, + onHushTypeSelected: (HushType) -> Unit +) { + + FilterChip( + selected = selectedChipIndex.value == type, + onClick = { + selectedChipIndex.value = type + onHushTypeSelected.invoke(type) + }, + colors = FilterChipDefaults.filterChipColors( + selectedContainerColor = MD3.colorScheme.tertiary, + containerColor = MD3.colorScheme.surfaceVariant, + + ), + label = { + Text( + text = type.label, + color = if (selectedChipIndex.value == type) MD3.colorScheme.onTertiary else MD3.colorScheme.onSurfaceVariant + ) + }, + modifier = Modifier.padding(start = 4.dp), leadingIcon = { + Box( + Modifier.animateContentSize(keyframes { + durationMillis = 100 + }) + ) { + if (selectedChipIndex.value == type) { + Icon( + imageVector = Icons.Default.Done, + contentDescription = null, + tint = MD3.colorScheme.onTertiary, + modifier = Modifier.size(FilterChipDefaults.IconSize) + ) } + } - }) - } + }) +} - private fun get12HrsFrom24Hrs(inputTime: String): String { - val timeFormat = SimpleDateFormat("hh:mm", Locale.getDefault()) - val time = timeFormat.parse(inputTime) - val outputFormat = SimpleDateFormat("hh:mm a", Locale.getDefault()) - return outputFormat.format(time) +private fun get12HrsFrom24Hrs(inputTime: String): String { + val timeFormat = SimpleDateFormat("hh:mm", Locale.getDefault()) + val time = timeFormat.parse(inputTime) + val outputFormat = SimpleDateFormat("hh:mm a", Locale.getDefault()) + return outputFormat.format(time) + +} - } +data class StartEndTime(var startTime: String, var endTime: String) - data class StartEndTime(var startTime: String, var endTime: String) -} \ No newline at end of file +@Immutable +data class AppConfig( + val selectedApp: SelectedApp, + val type: HushType, + val startEndTime: StartEndTime, + val duration: Long, + val daysList: List, + val logNotification: Boolean +) \ No newline at end of file diff --git a/app/src/main/java/dev/souravdas/hush/nav/NavGraph.kt b/app/src/main/java/dev/souravdas/hush/nav/NavGraph.kt index 71cb2dd..e6c7d1c 100644 --- a/app/src/main/java/dev/souravdas/hush/nav/NavGraph.kt +++ b/app/src/main/java/dev/souravdas/hush/nav/NavGraph.kt @@ -4,7 +4,7 @@ import androidx.compose.runtime.Composable import androidx.navigation.NavHostController import androidx.navigation.compose.NavHost import androidx.navigation.compose.composable -import dev.souravdas.hush.compose.main.MainScreen +import dev.souravdas.hush.compose.main.MainActivityScreen /** * Created by Sourav @@ -24,7 +24,7 @@ fun NavGraph( composable( route = Screens.MainScreen.route, ) { - MainScreen().MainActivityScreen( + MainActivityScreen( onNotificationPermissionGet = onNotificationPermissionGet, checkNotificationPermission = checkNotificationPermission ) diff --git a/app/src/main/java/dev/souravdas/hush/others/UIEvents.kt b/app/src/main/java/dev/souravdas/hush/others/UIEvents.kt new file mode 100644 index 0000000..51a0dbb --- /dev/null +++ b/app/src/main/java/dev/souravdas/hush/others/UIEvents.kt @@ -0,0 +1,10 @@ +package dev.souravdas.hush.others + +/** + * Created by Sourav + * On 3/21/2023 4:01 PM + * For Hush! + */ +sealed class UIEvents{ + data class NotificationPermission(val isAvailable: Boolean): UIEvents() +} From 207fdc20b0855a334a666ab54f5eed26063fd869 Mon Sep 17 00:00:00 2001 From: Sourav Das Date: Tue, 21 Mar 2023 18:20:52 +0600 Subject: [PATCH 07/16] reduced recomposition --- .../souravdas/hush/compose/main/MainScreen.kt | 22 ++++++++++--------- 1 file changed, 12 insertions(+), 10 deletions(-) diff --git a/app/src/main/java/dev/souravdas/hush/compose/main/MainScreen.kt b/app/src/main/java/dev/souravdas/hush/compose/main/MainScreen.kt index 2c591d6..1c65cb8 100644 --- a/app/src/main/java/dev/souravdas/hush/compose/main/MainScreen.kt +++ b/app/src/main/java/dev/souravdas/hush/compose/main/MainScreen.kt @@ -66,6 +66,7 @@ fun MainActivityScreen( onNotificationPermissionGet: () -> Unit ) { viewModel.getInstalledApps() + viewModel.getSelectedApp() val scope = rememberCoroutineScope() val scaffoldState = rememberBottomSheetScaffoldState() val list = viewModel.appListSF.collectAsState() @@ -147,6 +148,11 @@ fun MainActivityScreen( viewModel.removeApp(app) } } + val addConfigLambda = remember<(AppConfig) -> Unit> { + { app -> + viewModel.addConfigInSelectedApp(app) + } + } if (showNotificationPermissionAlertDialog) ShowAlertDialog { @@ -211,12 +217,9 @@ fun MainActivityScreen( }) { app -> SelectedAppItem( selectedApp = app, - onRemoveClick = viewModel::removeApp, - onEditClick = viewModel::updateComplete, - onConfigDone = viewModel::addConfigInSelectedApp, - onCancelClick = { - viewModel.removeApp(app.selectedApp) - } + onRemoveClick = removeAppLambda, + onEditClick = editAppLambda, + onConfigDone = addConfigLambda ) } } @@ -229,7 +232,6 @@ fun SelectedAppItem( onRemoveClick: (SelectedApp) -> Unit = {}, onEditClick: (SelectedApp) -> Unit, onConfigDone: (AppConfig) -> Unit, - onCancelClick: () -> Unit ) { var showOptions by remember { mutableStateOf(false) @@ -303,7 +305,7 @@ fun SelectedAppItem( val buttonModifier = Modifier.padding(end = 4.dp) AnimatedVisibility(showInitConfig) { - ShowInitConfig(selectedApp.selectedApp, onConfigDone, onCancelClick) + ShowInitConfig(selectedApp.selectedApp, onConfigDone, onRemoveClick) } AnimatedVisibility(showOptions) { @@ -317,7 +319,7 @@ fun SelectedAppItem( fun ShowInitConfig( app: SelectedApp, onConfigDone: (AppConfig) -> Unit, - onCancelClick: () -> Unit + onRemoveClick: (SelectedApp) -> Unit ) { Column( modifier = Modifier @@ -584,7 +586,7 @@ fun ShowInitConfig( ) ) }, onCancelClick = { - onCancelClick.invoke() + onRemoveClick.invoke(app) }) } From 8101948649c7885420a3789ec21e5ed45a87b9b6 Mon Sep 17 00:00:00 2001 From: Sourav Das Date: Tue, 21 Mar 2023 20:05:50 +0600 Subject: [PATCH 08/16] log screen yay! --- .../souravdas/hush/activities/MainActivity.kt | 30 +++--- .../java/dev/souravdas/hush/arch/AppLogDao.kt | 5 + .../souravdas/hush/arch/AppLogRepository.kt | 4 + .../dev/souravdas/hush/arch/MainActivityVM.kt | 14 ++- .../dev/souravdas/hush/compose/LogScreen.kt | 53 ++++++++++ .../souravdas/hush/compose/main/MainScreen.kt | 96 +++++++++++++++++-- .../java/dev/souravdas/hush/nav/NavGraph.kt | 13 +++ .../java/dev/souravdas/hush/nav/Screens.kt | 2 +- 8 files changed, 196 insertions(+), 21 deletions(-) create mode 100644 app/src/main/java/dev/souravdas/hush/compose/LogScreen.kt diff --git a/app/src/main/java/dev/souravdas/hush/activities/MainActivity.kt b/app/src/main/java/dev/souravdas/hush/activities/MainActivity.kt index b862645..aa00f00 100644 --- a/app/src/main/java/dev/souravdas/hush/activities/MainActivity.kt +++ b/app/src/main/java/dev/souravdas/hush/activities/MainActivity.kt @@ -20,9 +20,11 @@ import dagger.hilt.android.AndroidEntryPoint import dev.sourav.emptycompose.ui.theme.HushTheme import dev.souravdas.hush.arch.MainActivityVM import dev.souravdas.hush.nav.NavGraph +import dev.souravdas.hush.nav.Screens import dev.souravdas.hush.others.Utils import dev.souravdas.hush.services.KeepAliveService import kotlinx.coroutines.launch +import timber.log.Timber import javax.inject.Inject @AndroidEntryPoint @@ -88,23 +90,25 @@ class MainActivity : ComponentActivity() { return enabledPackages.contains(packageName) } + @Deprecated("Deprecated in Java") override fun onBackPressed() { - if (doubleBackToExitPressedOnce) { - viewModel.removeIncompleteApp() - finishAffinity() - return - } + if (navController.currentDestination!!.route == Screens.MainScreen.route){ + if (doubleBackToExitPressedOnce) { + viewModel.removeIncompleteApp() + finishAffinity() + return + } - this.doubleBackToExitPressedOnce = true - Toast.makeText(this, "Please click BACK again to exit", Toast.LENGTH_SHORT).show() + this.doubleBackToExitPressedOnce = true + Toast.makeText(this, "Please click BACK again to exit", Toast.LENGTH_SHORT).show() - Handler(Looper.getMainLooper()).postDelayed(Runnable { - doubleBackToExitPressedOnce = false - }, 2000) + Handler(Looper.getMainLooper()).postDelayed(Runnable { + doubleBackToExitPressedOnce = false + }, 2000) + }else{ + super.onBackPressed() + } } - override fun onDestroy() { - super.onDestroy() - } } diff --git a/app/src/main/java/dev/souravdas/hush/arch/AppLogDao.kt b/app/src/main/java/dev/souravdas/hush/arch/AppLogDao.kt index 82059be..0532f6e 100644 --- a/app/src/main/java/dev/souravdas/hush/arch/AppLogDao.kt +++ b/app/src/main/java/dev/souravdas/hush/arch/AppLogDao.kt @@ -4,6 +4,8 @@ import androidx.room.Dao import androidx.room.Insert import androidx.room.Query import dev.souravdas.hush.models.AppLog +import dev.souravdas.hush.models.SelectedApp +import kotlinx.coroutines.flow.Flow /** * Created by Sourav @@ -18,4 +20,7 @@ interface AppLogDao { @Query("DELETE FROM app_log WHERE selected_app_id= :selectedAppID") suspend fun deleteAllByForeignKey(selectedAppID: Int) + + @Query("SELECT * FROM app_log WHERE selected_app_id= :selectedAppID") + fun getAllByForeignKey(selectedAppID: Int): Flow> } \ No newline at end of file diff --git a/app/src/main/java/dev/souravdas/hush/arch/AppLogRepository.kt b/app/src/main/java/dev/souravdas/hush/arch/AppLogRepository.kt index 8275522..58d4d2e 100644 --- a/app/src/main/java/dev/souravdas/hush/arch/AppLogRepository.kt +++ b/app/src/main/java/dev/souravdas/hush/arch/AppLogRepository.kt @@ -1,6 +1,8 @@ package dev.souravdas.hush.arch import dev.souravdas.hush.models.AppLog +import dev.souravdas.hush.models.SelectedApp +import kotlinx.coroutines.flow.Flow import javax.inject.Inject /** @@ -17,4 +19,6 @@ class AppLogRepository @Inject constructor(val appLogDao: AppLogDao) { suspend fun deleteAllBySelectedAppId(selectedAppId:Int){ appLogDao.deleteAllByForeignKey(selectedAppId) } + + fun getAllBySelectedAppID(selectedAppId: Int): Flow> = appLogDao.getAllByForeignKey(selectedAppId) } \ No newline at end of file diff --git a/app/src/main/java/dev/souravdas/hush/arch/MainActivityVM.kt b/app/src/main/java/dev/souravdas/hush/arch/MainActivityVM.kt index 0dbe723..0e17751 100644 --- a/app/src/main/java/dev/souravdas/hush/arch/MainActivityVM.kt +++ b/app/src/main/java/dev/souravdas/hush/arch/MainActivityVM.kt @@ -9,6 +9,7 @@ import dev.souravdas.hush.HushApp import dev.souravdas.hush.base.BaseViewModel import dev.souravdas.hush.compose.main.AppConfig import dev.souravdas.hush.compose.main.StartEndTime +import dev.souravdas.hush.models.AppLog import dev.souravdas.hush.models.InstalledPackageInfo import dev.souravdas.hush.models.SelectedApp import dev.souravdas.hush.models.SelectedAppForList @@ -34,9 +35,12 @@ class MainActivityVM @Inject constructor( private val _selectedAppsSF = MutableStateFlow>(emptyList()) val selectedAppsSF = _selectedAppsSF.asStateFlow() + private val _appLog = MutableStateFlow>(emptyList()) + val appLog = _appLog.asStateFlow() + companion object { const val APP_LIST = "APP_LIST" - const val SELECTED_APP = "SELECTED_APP" + const val LOG = "LOG" } fun addOrUpdateSelectedApp(selectedApp: SelectedApp) { @@ -51,6 +55,14 @@ class MainActivityVM @Inject constructor( } } + fun getLog(id: Int){ + viewModelScope.launch { + appLogRepository.getAllBySelectedAppID(id).collect{ + _appLog.value = it + } + } + } + fun getSelectedApp() { viewModelScope.launch { selectAppRepository.getSelectedAppsWithFlow().map { apps -> diff --git a/app/src/main/java/dev/souravdas/hush/compose/LogScreen.kt b/app/src/main/java/dev/souravdas/hush/compose/LogScreen.kt new file mode 100644 index 0000000..d95895c --- /dev/null +++ b/app/src/main/java/dev/souravdas/hush/compose/LogScreen.kt @@ -0,0 +1,53 @@ +package dev.souravdas.hush.compose + +import androidx.compose.foundation.layout.* +import androidx.compose.foundation.lazy.LazyColumn +import androidx.compose.foundation.lazy.items +import androidx.compose.material3.Card +import androidx.compose.material3.CardDefaults +import androidx.compose.material3.CardElevation +import androidx.compose.material3.Text +import androidx.compose.runtime.Composable +import androidx.compose.runtime.collectAsState +import androidx.compose.runtime.getValue +import androidx.compose.ui.Modifier +import androidx.compose.ui.unit.dp +import androidx.hilt.navigation.compose.hiltViewModel +import dev.souravdas.hush.arch.MainActivityVM +import dev.souravdas.hush.models.AppLog + +/** + * Created by Sourav + * On 3/21/2023 6:45 PM + * For Hush! + */ + +@Composable +fun AppLogList( + app_id: Long?, + viewModel: MainActivityVM = hiltViewModel() +) { + viewModel.getLog(app_id!!.toInt()) + + val logs by viewModel.appLog.collectAsState(emptyList()) + + Box(modifier = Modifier.fillMaxSize()) { + LazyColumn(modifier = Modifier.fillMaxSize()) { + items(logs) { log -> + Card( + elevation = CardDefaults.cardElevation(4.dp), + modifier = Modifier + .fillMaxWidth() + .padding(16.dp) + ) { + Column(Modifier.padding(16.dp)) { + Text(text = "Title: ${log.title ?: ""}") + Text(text = "Body: ${log.body ?: ""}") + Text(text = "Time Created: ${log.timeCreated}") + } + } + } + } + } + +} \ No newline at end of file diff --git a/app/src/main/java/dev/souravdas/hush/compose/main/MainScreen.kt b/app/src/main/java/dev/souravdas/hush/compose/main/MainScreen.kt index 1c65cb8..e8197c3 100644 --- a/app/src/main/java/dev/souravdas/hush/compose/main/MainScreen.kt +++ b/app/src/main/java/dev/souravdas/hush/compose/main/MainScreen.kt @@ -18,30 +18,38 @@ import androidx.compose.material.SwitchDefaults import androidx.compose.material.icons.Icons import androidx.compose.material.icons.filled.Done import androidx.compose.material.icons.outlined.Edit +import androidx.compose.material.icons.outlined.Lock +import androidx.compose.material.icons.outlined.MoreVert +import androidx.compose.material.icons.outlined.Search import androidx.compose.material3.* import androidx.compose.material3.Checkbox import androidx.compose.material3.Icon import androidx.compose.material3.Text import androidx.compose.material3.TextButton import androidx.compose.material3.TopAppBar +import androidx.compose.material3.DropdownMenu import androidx.compose.runtime.* import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.draw.clip import androidx.compose.ui.graphics.Color import androidx.compose.ui.graphics.toArgb +import androidx.compose.ui.graphics.vector.ImageVector import androidx.compose.ui.res.colorResource import androidx.compose.ui.res.painterResource import androidx.compose.ui.res.stringResource import androidx.compose.ui.text.font.FontWeight +import androidx.compose.ui.unit.DpOffset import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.sp import androidx.hilt.navigation.compose.hiltViewModel +import androidx.navigation.NavController import com.google.accompanist.drawablepainter.rememberDrawablePainter import dev.souravdas.hush.R import dev.souravdas.hush.arch.MainActivityVM import dev.souravdas.hush.models.SelectedApp import dev.souravdas.hush.models.SelectedAppForList +import dev.souravdas.hush.nav.Screens import dev.souravdas.hush.others.Constants import dev.souravdas.hush.others.HushType import kotlinx.coroutines.launch @@ -61,6 +69,7 @@ import androidx.compose.material3.MaterialTheme as MD3 ) @Composable fun MainActivityScreen( + navController: NavController, viewModel: MainActivityVM = hiltViewModel(), checkNotificationPermission: () -> Boolean, onNotificationPermissionGet: () -> Unit @@ -71,6 +80,10 @@ fun MainActivityScreen( val scaffoldState = rememberBottomSheetScaffoldState() val list = viewModel.appListSF.collectAsState() + var dropDownMenuExpanded by remember { + mutableStateOf(false) + } + BottomSheetScaffold( backgroundColor = MD3.colorScheme.background, scaffoldState = scaffoldState, @@ -84,8 +97,61 @@ fun MainActivityScreen( fontWeight = FontWeight.Medium, color = MD3.colorScheme.onBackground ) - } - ) + }, + actions = { + // search icon +// TopAppBarActionButton( +// imageVector = Icons.Outlined.Search, +// description = "Search" +// ) { +// +// } +// +// // lock icon +// TopAppBarActionButton( +// imageVector = Icons.Outlined.Lock, +// description = "Lock" +// ) { +// +// } + + // options icon (vertical dots) + TopAppBarActionButton( + imageVector = Icons.Outlined.MoreVert, + description = "Options" + ) { + // show the drop down menu + dropDownMenuExpanded = true + } + + // drop down menu + DropdownMenu( + expanded = dropDownMenuExpanded, + onDismissRequest = { + dropDownMenuExpanded = false + }, + // play around with these values + // to position the menu properly + offset = DpOffset(x = 10.dp, y = (-60).dp) + ) { + // this is a column scope + // items are added vertically + + DropdownMenuItem(onClick = { + + dropDownMenuExpanded = false + }) { + Text("Settings") + } + + DropdownMenuItem(onClick = { + + dropDownMenuExpanded = false + }) { + Text("About") + } + } + }) }, sheetContent = { InstalledAppList(items = list.value) { item -> @@ -219,19 +285,36 @@ fun MainActivityScreen( selectedApp = app, onRemoveClick = removeAppLambda, onEditClick = editAppLambda, - onConfigDone = addConfigLambda + onConfigDone = addConfigLambda, + onNotificationLogClick = { + navController.navigate(route = "log_screen/" + app.selectedApp.id.toLong()) + } ) } } } } +@Composable +fun TopAppBarActionButton( + imageVector: ImageVector, + description: String, + onClick: () -> Unit +) { + IconButton(onClick = { + onClick() + }) { + Icon(imageVector = imageVector, contentDescription = description) + } +} + @Composable fun SelectedAppItem( selectedApp: SelectedAppForList, onRemoveClick: (SelectedApp) -> Unit = {}, onEditClick: (SelectedApp) -> Unit, onConfigDone: (AppConfig) -> Unit, + onNotificationLogClick: (SelectedApp) -> Unit ) { var showOptions by remember { mutableStateOf(false) @@ -309,7 +392,7 @@ fun SelectedAppItem( } AnimatedVisibility(showOptions) { - ShowOptions(buttonModifier, onRemoveClick, onEditClick, selectedApp) + ShowOptions(buttonModifier, onRemoveClick, onEditClick, selectedApp, onNotificationLogClick) } } } @@ -597,7 +680,8 @@ fun ShowOptions( @SuppressLint("ModifierParameter") buttonModifier: Modifier, onRemoveClick: (SelectedApp) -> Unit = {}, onEditClick: (SelectedApp) -> Unit, - selectedApp: SelectedAppForList + selectedApp: SelectedAppForList, + onNotificationLogClick: (SelectedApp) -> Unit = {} ) { Row( modifier = Modifier @@ -609,7 +693,7 @@ fun ShowOptions( ) { TextButton( modifier = buttonModifier, - onClick = { Constants.showNIY() }) { + onClick = { onNotificationLogClick.invoke(selectedApp.selectedApp) }) { Text("Notification History", color = MD3.colorScheme.onSecondaryContainer) } diff --git a/app/src/main/java/dev/souravdas/hush/nav/NavGraph.kt b/app/src/main/java/dev/souravdas/hush/nav/NavGraph.kt index e6c7d1c..1c1c846 100644 --- a/app/src/main/java/dev/souravdas/hush/nav/NavGraph.kt +++ b/app/src/main/java/dev/souravdas/hush/nav/NavGraph.kt @@ -2,8 +2,11 @@ package dev.souravdas.hush.nav import androidx.compose.runtime.Composable import androidx.navigation.NavHostController +import androidx.navigation.NavType import androidx.navigation.compose.NavHost import androidx.navigation.compose.composable +import androidx.navigation.navArgument +import dev.souravdas.hush.compose.AppLogList import dev.souravdas.hush.compose.main.MainActivityScreen /** @@ -25,9 +28,19 @@ fun NavGraph( route = Screens.MainScreen.route, ) { MainActivityScreen( + navController, onNotificationPermissionGet = onNotificationPermissionGet, checkNotificationPermission = checkNotificationPermission ) } + + composable( + route = Screens.LogScreen.route, + arguments = listOf(navArgument("app_id"){ + type = NavType.LongType + }) + ) { + AppLogList(it.arguments?.getLong("app_id")) + } } } \ No newline at end of file diff --git a/app/src/main/java/dev/souravdas/hush/nav/Screens.kt b/app/src/main/java/dev/souravdas/hush/nav/Screens.kt index fcb6f7e..c29a802 100644 --- a/app/src/main/java/dev/souravdas/hush/nav/Screens.kt +++ b/app/src/main/java/dev/souravdas/hush/nav/Screens.kt @@ -7,5 +7,5 @@ package dev.souravdas.hush.nav */ sealed class Screens(val route: String){ object MainScreen: Screens(route = "main_screen") - object LogScreen: Screens(route = "log_screen") + object LogScreen: Screens(route = "log_screen/{app_id}") } From a784d589fe8d8c4eb05eae8345ab1d5f708c3c8a Mon Sep 17 00:00:00 2001 From: Sourav Das Date: Tue, 21 Mar 2023 20:29:18 +0600 Subject: [PATCH 09/16] UX update --- .../dev/souravdas/hush/compose/LogScreen.kt | 68 +++++++++++++++---- .../souravdas/hush/compose/main/MainScreen.kt | 2 +- .../java/dev/souravdas/hush/nav/NavGraph.kt | 13 ++-- .../java/dev/souravdas/hush/nav/Screens.kt | 3 +- .../java/dev/souravdas/hush/others/Utils.kt | 6 ++ 5 files changed, 71 insertions(+), 21 deletions(-) diff --git a/app/src/main/java/dev/souravdas/hush/compose/LogScreen.kt b/app/src/main/java/dev/souravdas/hush/compose/LogScreen.kt index d95895c..c614b51 100644 --- a/app/src/main/java/dev/souravdas/hush/compose/LogScreen.kt +++ b/app/src/main/java/dev/souravdas/hush/compose/LogScreen.kt @@ -1,20 +1,24 @@ package dev.souravdas.hush.compose +import androidx.compose.foundation.Image +import androidx.compose.foundation.background +import androidx.compose.foundation.clickable import androidx.compose.foundation.layout.* import androidx.compose.foundation.lazy.LazyColumn import androidx.compose.foundation.lazy.items -import androidx.compose.material3.Card -import androidx.compose.material3.CardDefaults -import androidx.compose.material3.CardElevation -import androidx.compose.material3.Text +import androidx.compose.material.icons.Icons +import androidx.compose.material.icons.outlined.ArrowBack +import androidx.compose.material3.* import androidx.compose.runtime.Composable import androidx.compose.runtime.collectAsState import androidx.compose.runtime.getValue import androidx.compose.ui.Modifier import androidx.compose.ui.unit.dp import androidx.hilt.navigation.compose.hiltViewModel +import androidx.navigation.NavController import dev.souravdas.hush.arch.MainActivityVM import dev.souravdas.hush.models.AppLog +import dev.souravdas.hush.others.Utils /** * Created by Sourav @@ -22,32 +26,66 @@ import dev.souravdas.hush.models.AppLog * For Hush! */ +@OptIn(ExperimentalMaterial3Api::class, ExperimentalLayoutApi::class) @Composable fun AppLogList( app_id: Long?, + appName: String?, + navController: NavController, viewModel: MainActivityVM = hiltViewModel() ) { viewModel.getLog(app_id!!.toInt()) val logs by viewModel.appLog.collectAsState(emptyList()) - Box(modifier = Modifier.fillMaxSize()) { - LazyColumn(modifier = Modifier.fillMaxSize()) { - items(logs) { log -> - Card( - elevation = CardDefaults.cardElevation(4.dp), + Scaffold(topBar = { + TopAppBar( + modifier = Modifier.padding(horizontal = 16.dp), + title = { Text(text = appName!!) }, + navigationIcon = { + Icon( + Icons.Outlined.ArrowBack, + tint = MaterialTheme.colorScheme.onBackground, + contentDescription = "BACK", + modifier = Modifier.clickable { + navController.popBackStack() + } + ) + } + ) + }) { + val modifier = Modifier.consumeWindowInsets(it) + Box( + modifier = modifier + .fillMaxSize() + .background(MaterialTheme.colorScheme.background) + ) { + Row() { + + LazyColumn( modifier = Modifier - .fillMaxWidth() - .padding(16.dp) + .fillMaxSize() ) { - Column(Modifier.padding(16.dp)) { - Text(text = "Title: ${log.title ?: ""}") - Text(text = "Body: ${log.body ?: ""}") - Text(text = "Time Created: ${log.timeCreated}") + items(logs) { log -> + Card( + elevation = CardDefaults.cardElevation(4.dp), + modifier = Modifier + .fillMaxWidth() + .padding(horizontal = 16.dp, vertical = 8.dp) + ) { + Column(Modifier.padding(16.dp)) { + Text(text = "Title: ${log.title ?: ""}") + Text(text = "Body: ${log.body ?: ""}") + System.currentTimeMillis() + Text(text = "Time: " + Utils().getStringDateFromMillis(log.timeCreated)) + } + } } } } + } } + } \ No newline at end of file diff --git a/app/src/main/java/dev/souravdas/hush/compose/main/MainScreen.kt b/app/src/main/java/dev/souravdas/hush/compose/main/MainScreen.kt index e8197c3..57cbec1 100644 --- a/app/src/main/java/dev/souravdas/hush/compose/main/MainScreen.kt +++ b/app/src/main/java/dev/souravdas/hush/compose/main/MainScreen.kt @@ -287,7 +287,7 @@ fun MainActivityScreen( onEditClick = editAppLambda, onConfigDone = addConfigLambda, onNotificationLogClick = { - navController.navigate(route = "log_screen/" + app.selectedApp.id.toLong()) + navController.navigate(route = "log_screen/${app.selectedApp.id.toLong()}/${app.selectedApp.appName}") } ) } diff --git a/app/src/main/java/dev/souravdas/hush/nav/NavGraph.kt b/app/src/main/java/dev/souravdas/hush/nav/NavGraph.kt index 1c1c846..8b3d1af 100644 --- a/app/src/main/java/dev/souravdas/hush/nav/NavGraph.kt +++ b/app/src/main/java/dev/souravdas/hush/nav/NavGraph.kt @@ -36,11 +36,16 @@ fun NavGraph( composable( route = Screens.LogScreen.route, - arguments = listOf(navArgument("app_id"){ - type = NavType.LongType - }) + arguments = listOf( + navArgument("app_id") { + type = NavType.LongType + }, + navArgument("app_name"){ + type = NavType.StringType + } + ) ) { - AppLogList(it.arguments?.getLong("app_id")) + AppLogList(it.arguments?.getLong("app_id"), it.arguments?.getString("app_name"), navController) } } } \ No newline at end of file diff --git a/app/src/main/java/dev/souravdas/hush/nav/Screens.kt b/app/src/main/java/dev/souravdas/hush/nav/Screens.kt index c29a802..394e1c3 100644 --- a/app/src/main/java/dev/souravdas/hush/nav/Screens.kt +++ b/app/src/main/java/dev/souravdas/hush/nav/Screens.kt @@ -7,5 +7,6 @@ package dev.souravdas.hush.nav */ sealed class Screens(val route: String){ object MainScreen: Screens(route = "main_screen") - object LogScreen: Screens(route = "log_screen/{app_id}") + object LogScreen: Screens(route = "log_screen/{app_id}/{app_name}") + } diff --git a/app/src/main/java/dev/souravdas/hush/others/Utils.kt b/app/src/main/java/dev/souravdas/hush/others/Utils.kt index 2426bac..40600ed 100644 --- a/app/src/main/java/dev/souravdas/hush/others/Utils.kt +++ b/app/src/main/java/dev/souravdas/hush/others/Utils.kt @@ -60,4 +60,10 @@ class Utils { } return if (sb.toString().isEmpty()) "" else sb.toString().substring(0, sb.length-1) } + + fun getStringDateFromMillis(millis: Long): String{ + val date = Date(millis) + val sdf = SimpleDateFormat("dd-MM-yy hh:mm a", Locale.UK) + return sdf.format(date) + } } \ No newline at end of file From 7871668a7d01e896287a35f3d5ea98ff51547dbd Mon Sep 17 00:00:00 2001 From: Sourav Das Date: Tue, 21 Mar 2023 21:07:03 +0600 Subject: [PATCH 10/16] Fixed padding issue --- .../dev/souravdas/hush/compose/LogScreen.kt | 89 +++++++++++-------- .../souravdas/hush/compose/main/MainScreen.kt | 17 ++-- 2 files changed, 61 insertions(+), 45 deletions(-) diff --git a/app/src/main/java/dev/souravdas/hush/compose/LogScreen.kt b/app/src/main/java/dev/souravdas/hush/compose/LogScreen.kt index c614b51..4a635d1 100644 --- a/app/src/main/java/dev/souravdas/hush/compose/LogScreen.kt +++ b/app/src/main/java/dev/souravdas/hush/compose/LogScreen.kt @@ -8,12 +8,14 @@ import androidx.compose.foundation.lazy.LazyColumn import androidx.compose.foundation.lazy.items import androidx.compose.material.icons.Icons import androidx.compose.material.icons.outlined.ArrowBack +import androidx.compose.material.icons.outlined.Delete import androidx.compose.material3.* import androidx.compose.runtime.Composable import androidx.compose.runtime.collectAsState import androidx.compose.runtime.getValue import androidx.compose.ui.Modifier import androidx.compose.ui.unit.dp +import androidx.compose.ui.unit.sp import androidx.hilt.navigation.compose.hiltViewModel import androidx.navigation.NavController import dev.souravdas.hush.arch.MainActivityVM @@ -38,47 +40,62 @@ fun AppLogList( val logs by viewModel.appLog.collectAsState(emptyList()) - Scaffold(topBar = { - TopAppBar( - modifier = Modifier.padding(horizontal = 16.dp), - title = { Text(text = appName!!) }, - navigationIcon = { - Icon( - Icons.Outlined.ArrowBack, - tint = MaterialTheme.colorScheme.onBackground, - contentDescription = "BACK", - modifier = Modifier.clickable { - navController.popBackStack() - } - ) + Scaffold( + topBar = { + TopAppBar( + modifier = Modifier.padding(horizontal = 16.dp), + title = { Text(text = appName!!) }, + navigationIcon = { + Icon( + Icons.Outlined.ArrowBack, + tint = MaterialTheme.colorScheme.onBackground, + contentDescription = "BACK", + modifier = Modifier.clickable { + navController.popBackStack() + } + ) + } + ) + }, + floatingActionButton = { + FloatingActionButton( + onClick = {}, + containerColor = MaterialTheme.colorScheme.secondary, + contentColor = MaterialTheme.colorScheme.onSecondary, + ) { + Icon(Icons.Outlined.Delete, contentDescription = "NUKE") } - ) - }) { - val modifier = Modifier.consumeWindowInsets(it) + } + ) { Box( - modifier = modifier - .fillMaxSize() + modifier = Modifier.padding(it) + .fillMaxHeight() .background(MaterialTheme.colorScheme.background) ) { - Row() { - LazyColumn( - modifier = Modifier - .fillMaxSize() - ) { - items(logs) { log -> - Card( - elevation = CardDefaults.cardElevation(4.dp), - modifier = Modifier - .fillMaxWidth() - .padding(horizontal = 16.dp, vertical = 8.dp) - ) { - Column(Modifier.padding(16.dp)) { - Text(text = "Title: ${log.title ?: ""}") - Text(text = "Body: ${log.body ?: ""}") - System.currentTimeMillis() - Text(text = "Time: " + Utils().getStringDateFromMillis(log.timeCreated)) - } + Box(Modifier.padding(16.dp)) { + Text( + text = "Muted Notifications", + fontSize = 16.sp, + color = MaterialTheme.colorScheme.onBackground + ) + } + + LazyColumn( + modifier = Modifier + ) { + items(logs) { log -> + Card( + elevation = CardDefaults.cardElevation(4.dp), + modifier = Modifier + .fillMaxWidth() + .padding(horizontal = 16.dp, vertical = 8.dp) + ) { + Column(Modifier.padding(16.dp)) { + Text(text = "Title: ${log.title ?: ""}") + Text(text = "Body: ${log.body ?: ""}") + System.currentTimeMillis() + Text(text = "Time: " + Utils().getStringDateFromMillis(log.timeCreated)) } } } diff --git a/app/src/main/java/dev/souravdas/hush/compose/main/MainScreen.kt b/app/src/main/java/dev/souravdas/hush/compose/main/MainScreen.kt index 57cbec1..fc92731 100644 --- a/app/src/main/java/dev/souravdas/hush/compose/main/MainScreen.kt +++ b/app/src/main/java/dev/souravdas/hush/compose/main/MainScreen.kt @@ -264,20 +264,19 @@ fun MainActivityScreen( ) } + Box(Modifier.padding(16.dp)) { + Text( + text = "Ongoing Hush!", + fontSize = 16.sp, + color = MD3.colorScheme.onBackground + ) + } + LazyColumn( modifier = modifier .padding(8.dp) .fillMaxSize() ) { - item { - Box(Modifier.padding(10.dp)) { - Text( - text = "Ongoing Hush!", - fontSize = 16.sp, - color = MD3.colorScheme.onBackground - ) - } - } items(selectedList, key = { it.selectedApp.timeUpdated }) { app -> From 31d22fc7378684913e5ce2a6bca05c6499e374f7 Mon Sep 17 00:00:00 2001 From: Sourav Das Date: Wed, 22 Mar 2023 19:57:53 +0600 Subject: [PATCH 11/16] settings screen [not functional yet lol] --- app/build.gradle | 4 +- .../dev/souravdas/hush/arch/MainActivityVM.kt | 20 +++- .../dev/souravdas/hush/compose/Settings.kt | 110 ++++++++++++++++++ .../souravdas/hush/compose/main/MainScreen.kt | 4 +- .../dev/souravdas/hush/models/HushConfig.kt | 21 ++++ .../java/dev/souravdas/hush/nav/NavGraph.kt | 8 ++ .../java/dev/souravdas/hush/nav/Screens.kt | 1 + .../dev/souravdas/hush/others/Constants.kt | 3 + 8 files changed, 163 insertions(+), 8 deletions(-) create mode 100644 app/src/main/java/dev/souravdas/hush/compose/Settings.kt create mode 100644 app/src/main/java/dev/souravdas/hush/models/HushConfig.kt diff --git a/app/build.gradle b/app/build.gradle index 1be076e..ff46b68 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -113,8 +113,8 @@ dependencies { implementation 'androidx.navigation:navigation-fragment-ktx:2.5.3' implementation "androidx.activity:activity-ktx:1.6.1" - implementation "androidx.lifecycle:lifecycle-viewmodel-compose:2.6.0-rc01" - implementation "androidx.lifecycle:lifecycle-livedata-ktx:2.5.1" + implementation "androidx.lifecycle:lifecycle-viewmodel-compose:2.6.0" + implementation "androidx.lifecycle:lifecycle-livedata-ktx:2.6.0" def nav_version = "2.5.3" diff --git a/app/src/main/java/dev/souravdas/hush/arch/MainActivityVM.kt b/app/src/main/java/dev/souravdas/hush/arch/MainActivityVM.kt index 0e17751..b45c2b4 100644 --- a/app/src/main/java/dev/souravdas/hush/arch/MainActivityVM.kt +++ b/app/src/main/java/dev/souravdas/hush/arch/MainActivityVM.kt @@ -9,10 +9,7 @@ import dev.souravdas.hush.HushApp import dev.souravdas.hush.base.BaseViewModel import dev.souravdas.hush.compose.main.AppConfig import dev.souravdas.hush.compose.main.StartEndTime -import dev.souravdas.hush.models.AppLog -import dev.souravdas.hush.models.InstalledPackageInfo -import dev.souravdas.hush.models.SelectedApp -import dev.souravdas.hush.models.SelectedAppForList +import dev.souravdas.hush.models.* import dev.souravdas.hush.others.Constants import dev.souravdas.hush.others.HushType import dev.souravdas.hush.others.Utils @@ -38,6 +35,9 @@ class MainActivityVM @Inject constructor( private val _appLog = MutableStateFlow>(emptyList()) val appLog = _appLog.asStateFlow() + private val _hushConfig = MutableSharedFlow() + val hushConfig = _hushConfig.asSharedFlow() + companion object { const val APP_LIST = "APP_LIST" const val LOG = "LOG" @@ -182,6 +182,18 @@ class MainActivityVM @Inject constructor( } } + fun getHushConfig(){ + viewModelScope.launch { + _hushConfig.tryEmit( + HushConfig( + dataStoreManager.getBooleanValue(Constants.DS_DND), + dataStoreManager.getBooleanValue(Constants.DS_DELETE_EXPIRE), + dataStoreManager.getBooleanValue(Constants.DS_NOTIFY_MUTE) + ) + ) + } + } + fun updateComplete(app: SelectedApp){ executedSuspendedCodeBlock { val selectedAppFromDB = selectAppRepository.getSelectedApp(app.packageName) diff --git a/app/src/main/java/dev/souravdas/hush/compose/Settings.kt b/app/src/main/java/dev/souravdas/hush/compose/Settings.kt new file mode 100644 index 0000000..7fc9f2a --- /dev/null +++ b/app/src/main/java/dev/souravdas/hush/compose/Settings.kt @@ -0,0 +1,110 @@ +package dev.souravdas.hush.compose + +/** + * Created by Sourav + * On 3/22/2023 2:03 PM + * For Hush! + */ +import androidx.compose.foundation.clickable +import androidx.compose.foundation.layout.* +import androidx.compose.material.icons.Icons +import androidx.compose.material.icons.outlined.ArrowBack +import androidx.compose.material3.* +import androidx.compose.runtime.* +import androidx.compose.ui.Alignment +import androidx.compose.ui.Modifier +import androidx.compose.ui.text.style.TextOverflow +import androidx.compose.ui.unit.dp +import androidx.hilt.navigation.compose.hiltViewModel +import androidx.lifecycle.ViewModel +import androidx.navigation.NavHostController +import dev.souravdas.hush.arch.MainActivityVM +import dev.souravdas.hush.models.HushConfig +import kotlinx.coroutines.flow.collect + +@OptIn(ExperimentalMaterial3Api::class) +@Composable +fun SettingsPage(viewModel: MainActivityVM = hiltViewModel(), navController: NavHostController) { + val hushConfig by viewModel.hushConfig.collectAsState(initial = HushConfig()) + + var notificationsEnabled by remember { mutableStateOf(true) } + var darkModeEnabled by remember { mutableStateOf(false) } + var locationTrackingEnabled by remember { mutableStateOf(true) } + var automaticUpdatesEnabled by remember { mutableStateOf(true) } + var languageSelectionEnabled by remember { mutableStateOf(false) } + + Scaffold( + topBar = { + TopAppBar( + modifier = Modifier.padding(horizontal = 16.dp), + title = { Text(text = "Settings") }, + navigationIcon = { + androidx.compose.material3.Icon( + Icons.Outlined.ArrowBack, + tint = MaterialTheme.colorScheme.onBackground, + contentDescription = "BACK", + modifier = Modifier.clickable { + navController.popBackStack() + } + ) + } + ) + } + ) { + Column( + modifier = Modifier + .padding(it) + .fillMaxWidth() + ) { + ToggleRow( + label = "Enable DND while muting notifications", + checked = hushConfig.isDnd, + onCheckedChange = { notificationsEnabled = it } + ) + ToggleRow( + label = "Automatically remove expired mutes", + checked = hushConfig.isAutoDeleteExpired, + onCheckedChange = { darkModeEnabled = it } + ) + ToggleRow( + label = "Notify if there's too many notification being muted", + checked = hushConfig.isAutoDeleteExpired, + onCheckedChange = { locationTrackingEnabled = it } + ) +// ToggleRow( +// label = { Text(text = "Automatic Updates") }, +// checked = automaticUpdatesEnabled, +// onCheckedChange = { automaticUpdatesEnabled = it } +// ) +// ToggleRow( +// label = { Text(text = "Language Selection") }, +// checked = languageSelectionEnabled, +// onCheckedChange = { languageSelectionEnabled = it } +// ) + } + } +} + +@Composable +fun ToggleRow(label: String, checked: Boolean, onCheckedChange: (Boolean) -> Unit) { + var enabled by remember { + mutableStateOf(true) + } + Row( + horizontalArrangement = Arrangement.SpaceBetween, + verticalAlignment = Alignment.CenterVertically, + modifier = Modifier + .fillMaxWidth() + .padding(8.dp) + ) { + Text(text = label, overflow = TextOverflow.Ellipsis, modifier = Modifier.fillMaxWidth(0.8f)) + Checkbox( + checked = enabled, + onCheckedChange = { + onCheckedChange.invoke(it) + enabled = !enabled + }, + modifier = Modifier.padding(horizontal = 4.dp) + ) + } +} diff --git a/app/src/main/java/dev/souravdas/hush/compose/main/MainScreen.kt b/app/src/main/java/dev/souravdas/hush/compose/main/MainScreen.kt index fc92731..5ce260e 100644 --- a/app/src/main/java/dev/souravdas/hush/compose/main/MainScreen.kt +++ b/app/src/main/java/dev/souravdas/hush/compose/main/MainScreen.kt @@ -138,14 +138,14 @@ fun MainActivityScreen( // items are added vertically DropdownMenuItem(onClick = { - + navController.navigate(route = Screens.SettingsScreen.route) dropDownMenuExpanded = false }) { Text("Settings") } DropdownMenuItem(onClick = { - + navController.navigate(route = Screens.SettingsScreen.route) dropDownMenuExpanded = false }) { Text("About") diff --git a/app/src/main/java/dev/souravdas/hush/models/HushConfig.kt b/app/src/main/java/dev/souravdas/hush/models/HushConfig.kt new file mode 100644 index 0000000..2a6a4c3 --- /dev/null +++ b/app/src/main/java/dev/souravdas/hush/models/HushConfig.kt @@ -0,0 +1,21 @@ +package dev.souravdas.hush.models + +/** + * Created by Sourav + * On 3/22/2023 3:02 PM + * For Hush! + */ +class HushConfig { + var isDnd: Boolean = false + var isAutoDeleteExpired: Boolean = false + var isNotificationReminder: Boolean = true + + constructor(isDnd: Boolean, isAutoDeleteExpired: Boolean, isNotificationReminder: Boolean) { + this.isDnd = isDnd + this.isAutoDeleteExpired = isAutoDeleteExpired + this.isNotificationReminder = isNotificationReminder + } + + constructor() + +} \ No newline at end of file diff --git a/app/src/main/java/dev/souravdas/hush/nav/NavGraph.kt b/app/src/main/java/dev/souravdas/hush/nav/NavGraph.kt index 8b3d1af..9ddd669 100644 --- a/app/src/main/java/dev/souravdas/hush/nav/NavGraph.kt +++ b/app/src/main/java/dev/souravdas/hush/nav/NavGraph.kt @@ -1,5 +1,6 @@ package dev.souravdas.hush.nav +import android.transition.Scene import androidx.compose.runtime.Composable import androidx.navigation.NavHostController import androidx.navigation.NavType @@ -7,6 +8,7 @@ import androidx.navigation.compose.NavHost import androidx.navigation.compose.composable import androidx.navigation.navArgument import dev.souravdas.hush.compose.AppLogList +import dev.souravdas.hush.compose.SettingsPage import dev.souravdas.hush.compose.main.MainActivityScreen /** @@ -47,5 +49,11 @@ fun NavGraph( ) { AppLogList(it.arguments?.getLong("app_id"), it.arguments?.getString("app_name"), navController) } + + composable( + route = Screens.SettingsScreen.route + ){ + SettingsPage(navController = navController) + } } } \ No newline at end of file diff --git a/app/src/main/java/dev/souravdas/hush/nav/Screens.kt b/app/src/main/java/dev/souravdas/hush/nav/Screens.kt index 394e1c3..0cee048 100644 --- a/app/src/main/java/dev/souravdas/hush/nav/Screens.kt +++ b/app/src/main/java/dev/souravdas/hush/nav/Screens.kt @@ -8,5 +8,6 @@ package dev.souravdas.hush.nav sealed class Screens(val route: String){ object MainScreen: Screens(route = "main_screen") object LogScreen: Screens(route = "log_screen/{app_id}/{app_name}") + object SettingsScreen: Screens(route = "settings_screen") } diff --git a/app/src/main/java/dev/souravdas/hush/others/Constants.kt b/app/src/main/java/dev/souravdas/hush/others/Constants.kt index 6431710..488b47c 100644 --- a/app/src/main/java/dev/souravdas/hush/others/Constants.kt +++ b/app/src/main/java/dev/souravdas/hush/others/Constants.kt @@ -10,6 +10,9 @@ import dev.souravdas.hush.HushApp */ object Constants { const val DS_HUSH_STATUS = "hush_status" + const val DS_DND = "dnd" + const val DS_DELETE_EXPIRE = "delete_expire" + const val DS_NOTIFY_MUTE = "notify_mute" fun showNIY (){ Toast.makeText( From 56854cc07f376d3611b43a129fe992dabd23c04f Mon Sep 17 00:00:00 2001 From: Sourav Das Date: Thu, 23 Mar 2023 20:28:24 +0600 Subject: [PATCH 12/16] added about screen and preferences --- app/build.gradle | 3 + app/src/main/AndroidManifest.xml | 3 + .../dev/souravdas/hush/arch/MainActivityVM.kt | 6 + .../dev/souravdas/hush/arch/SelectAppCache.kt | 13 +- .../java/dev/souravdas/hush/compose/About.kt | 141 ++++++++++++++++++ .../dev/souravdas/hush/compose/Settings.kt | 43 ++++-- .../souravdas/hush/compose/main/MainScreen.kt | 8 +- .../java/dev/souravdas/hush/nav/NavGraph.kt | 7 + .../java/dev/souravdas/hush/nav/Screens.kt | 1 + .../souravdas/hush/services/HushService.kt | 18 ++- 10 files changed, 225 insertions(+), 18 deletions(-) create mode 100644 app/src/main/java/dev/souravdas/hush/compose/About.kt diff --git a/app/build.gradle b/app/build.gradle index ff46b68..70d03ea 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -121,6 +121,9 @@ dependencies { implementation "androidx.navigation:navigation-compose:$nav_version" implementation("androidx.hilt:hilt-navigation-compose:1.0.0") + + implementation "com.github.bumptech.glide:compose:1.0.0-alpha.1" + androidTestImplementation 'androidx.test.ext:junit:1.1.5' androidTestImplementation 'androidx.test.espresso:espresso-core:3.5.1' androidTestImplementation platform('androidx.compose:compose-bom:2023.01.00') diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index daddf5e..61ca997 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -2,6 +2,9 @@ + + + diff --git a/app/src/main/java/dev/souravdas/hush/arch/MainActivityVM.kt b/app/src/main/java/dev/souravdas/hush/arch/MainActivityVM.kt index b45c2b4..8b4406e 100644 --- a/app/src/main/java/dev/souravdas/hush/arch/MainActivityVM.kt +++ b/app/src/main/java/dev/souravdas/hush/arch/MainActivityVM.kt @@ -63,6 +63,12 @@ class MainActivityVM @Inject constructor( } } + fun changeBooleanDS(key: String ,boolean: Boolean){ + viewModelScope.launch { + dataStoreManager.writeBooleanData(key,boolean) + } + } + fun getSelectedApp() { viewModelScope.launch { selectAppRepository.getSelectedAppsWithFlow().map { apps -> diff --git a/app/src/main/java/dev/souravdas/hush/arch/SelectAppCache.kt b/app/src/main/java/dev/souravdas/hush/arch/SelectAppCache.kt index 3fda51d..a4cd6c7 100644 --- a/app/src/main/java/dev/souravdas/hush/arch/SelectAppCache.kt +++ b/app/src/main/java/dev/souravdas/hush/arch/SelectAppCache.kt @@ -1,7 +1,10 @@ package dev.souravdas.hush.arch +import dev.sourav.base.datastore.DataStoreManager import dev.souravdas.hush.models.AppLog +import dev.souravdas.hush.models.HushConfig import dev.souravdas.hush.models.SelectedApp +import dev.souravdas.hush.others.Constants import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.combine import javax.inject.Inject @@ -13,14 +16,22 @@ import javax.inject.Singleton * For Hush! */ @Singleton -class SelectAppCache @Inject constructor(private val repository: SelectAppRepository, private val logRepository: AppLogRepository) { +class SelectAppCache @Inject constructor(private val repository: SelectAppRepository, private val logRepository: AppLogRepository, dataStoreManager: DataStoreManager) { private val selectedAppsFlow = repository.getSelectedAppsWithFlow() private val databaseUpdatesFlow = repository.getDBUpdatesWithFlow() + private val dsIsDnd = dataStoreManager.getBooleanValueAsFlow(Constants.DS_DND) + private val dsIsRemoveExpired = dataStoreManager.getBooleanValueAsFlow(Constants.DS_DELETE_EXPIRE) + private val dsIsNotifyMute = dataStoreManager.getBooleanValueAsFlow(Constants.DS_NOTIFY_MUTE) + fun getSelectedApps(): Flow> = combine(selectedAppsFlow, databaseUpdatesFlow) { selectedApps, _ -> selectedApps } + fun getConfig()= combine(dsIsDnd, dsIsRemoveExpired,dsIsNotifyMute) {a,b,c -> + HushConfig(a,b,c) + } + suspend fun logNotification(appLog: AppLog){ logRepository.insertLog(appLog) } diff --git a/app/src/main/java/dev/souravdas/hush/compose/About.kt b/app/src/main/java/dev/souravdas/hush/compose/About.kt new file mode 100644 index 0000000..2fb026b --- /dev/null +++ b/app/src/main/java/dev/souravdas/hush/compose/About.kt @@ -0,0 +1,141 @@ +package dev.souravdas.hush.compose + +import androidx.compose.foundation.background +import androidx.compose.foundation.clickable +import androidx.compose.foundation.layout.* +import androidx.compose.foundation.shape.CircleShape +import androidx.compose.foundation.shape.RoundedCornerShape +import androidx.compose.material.icons.Icons +import androidx.compose.material.icons.outlined.ArrowBack +import androidx.compose.material3.* +import androidx.compose.runtime.Composable +import androidx.compose.ui.Alignment +import androidx.compose.ui.Modifier +import androidx.compose.ui.draw.clip +import androidx.compose.ui.graphics.Color +import androidx.compose.ui.layout.ContentScale +import androidx.compose.ui.res.stringResource +import androidx.compose.ui.text.font.FontWeight +import androidx.compose.ui.tooling.preview.Preview +import androidx.compose.ui.unit.dp +import androidx.navigation.NavController +import com.bumptech.glide.integration.compose.ExperimentalGlideComposeApi +import com.bumptech.glide.integration.compose.GlideImage +import dagger.Provides +import dev.souravdas.hush.BuildConfig +import dev.souravdas.hush.R + +/** + * Created by Sourav + * On 3/23/2023 7:16 PM + * For Hush! + */ + +@OptIn(ExperimentalMaterial3Api::class, ExperimentalGlideComposeApi::class) +@Composable +fun AboutScreen(navController: NavController) { + Scaffold( + topBar = { + TopAppBar( + modifier = Modifier.padding(horizontal = 16.dp), + title = { Text(text = "About") }, + navigationIcon = { + Icon( + Icons.Outlined.ArrowBack, + tint = MaterialTheme.colorScheme.onBackground, + contentDescription = "BACK", + modifier = Modifier.clickable { + navController.popBackStack() + } + ) + } + ) + } + ) { + Row( + horizontalArrangement = Arrangement.Center, + verticalAlignment = Alignment.CenterVertically, + modifier = Modifier + .fillMaxSize() + .padding(it) + ) { + Column( + modifier = Modifier + .fillMaxWidth(0.8f) + .background( + MaterialTheme.colorScheme.primaryContainer, + RoundedCornerShape(12.dp) + ) + .padding(24.dp) + ) { + Text( + text = stringResource(id = R.string.app_name), + style = MaterialTheme.typography.displayMedium, + color = MaterialTheme.colorScheme.onPrimaryContainer, + modifier = Modifier.padding(bottom = 2.dp) + ) + + Text( + text = "Version: " + BuildConfig.VERSION_NAME, + style = MaterialTheme.typography.titleMedium, + color = MaterialTheme.colorScheme.onPrimaryContainer, + modifier = Modifier.padding(bottom = 16.dp) + ) + Text( + text = "Developer", + style = MaterialTheme.typography.titleLarge, + fontWeight = FontWeight.Bold, + color = MaterialTheme.colorScheme.onPrimaryContainer, + modifier = Modifier.padding(bottom = 8.dp) + ) + Row( + verticalAlignment = Alignment.CenterVertically, + modifier = Modifier.fillMaxWidth().padding(bottom = 16.dp) + ) { + GlideImage( + model = "https://github.com/Esarve.png", + contentDescription = "devimg", + modifier = Modifier + .width(64.dp) + .height(64.dp) + .clip(CircleShape) + ) + Text( + text = "Sourav Das\nhttps://souravdas.dev", + style = MaterialTheme.typography.bodyMedium, + color = MaterialTheme.colorScheme.onPrimaryContainer, + modifier = Modifier.padding(start = 16.dp) + ) + } + + Text( + text = "Designer", + style = MaterialTheme.typography.titleLarge, + fontWeight = FontWeight.Bold, + color = MaterialTheme.colorScheme.onPrimaryContainer, + modifier = Modifier.padding(bottom = 8.dp) + ) + Row( + verticalAlignment = Alignment.CenterVertically, + modifier = Modifier.fillMaxWidth().padding(bottom = 16.dp) + ) { + GlideImage( + model = "https://lh3.googleusercontent.com/_DAIFu6wp6wZJBWDR4KVQ6cV4DE3Ov2h9Vvn-3RztW6xJxuGo_sg2gdkZ2dFZTLzANuZ_Bu4EMIKXSIGZAHoYOzqxzY7tisGgq5WpiRNh9kqzh_0WSQZZrGo1d2Vsj2m=w1280", + contentDescription = "devimg", + modifier = Modifier + .width(64.dp) + .height(64.dp) + .clip(CircleShape) + ) + Text( + text = "Raisul Haque\nhttps://www.raishaq.com/", + style = MaterialTheme.typography.bodyMedium, + color = MaterialTheme.colorScheme.onPrimaryContainer, + modifier = Modifier.padding(start = 16.dp) + ) + } + } + } + + } +} \ No newline at end of file diff --git a/app/src/main/java/dev/souravdas/hush/compose/Settings.kt b/app/src/main/java/dev/souravdas/hush/compose/Settings.kt index 7fc9f2a..e1fec54 100644 --- a/app/src/main/java/dev/souravdas/hush/compose/Settings.kt +++ b/app/src/main/java/dev/souravdas/hush/compose/Settings.kt @@ -20,6 +20,7 @@ import androidx.lifecycle.ViewModel import androidx.navigation.NavHostController import dev.souravdas.hush.arch.MainActivityVM import dev.souravdas.hush.models.HushConfig +import dev.souravdas.hush.others.Constants import kotlinx.coroutines.flow.collect @OptIn(ExperimentalMaterial3Api::class) @@ -27,11 +28,29 @@ import kotlinx.coroutines.flow.collect fun SettingsPage(viewModel: MainActivityVM = hiltViewModel(), navController: NavHostController) { val hushConfig by viewModel.hushConfig.collectAsState(initial = HushConfig()) - var notificationsEnabled by remember { mutableStateOf(true) } - var darkModeEnabled by remember { mutableStateOf(false) } - var locationTrackingEnabled by remember { mutableStateOf(true) } - var automaticUpdatesEnabled by remember { mutableStateOf(true) } - var languageSelectionEnabled by remember { mutableStateOf(false) } + val isDnd by remember { mutableStateOf(hushConfig.isDnd) } + val isRemovedExpired by remember { mutableStateOf(hushConfig.isAutoDeleteExpired) } + val isNotify by remember { mutableStateOf(hushConfig.isNotificationReminder) } + + val onDndCheckChangeLambda = remember<(Boolean) -> Unit> { + { + viewModel.changeBooleanDS(Constants.DS_DND, it) + } + } + + val onRemovedExpiredChangeLambda = remember<(Boolean) -> Unit> { + { + viewModel.changeBooleanDS(Constants.DS_DELETE_EXPIRE, it) + } + } + + val onNotifyChangeLambda = remember<(Boolean) -> Unit> { + { + viewModel.changeBooleanDS(Constants.DS_NOTIFY_MUTE, it) + } + } + + Scaffold( topBar = { @@ -39,7 +58,7 @@ fun SettingsPage(viewModel: MainActivityVM = hiltViewModel(), navController: Nav modifier = Modifier.padding(horizontal = 16.dp), title = { Text(text = "Settings") }, navigationIcon = { - androidx.compose.material3.Icon( + Icon( Icons.Outlined.ArrowBack, tint = MaterialTheme.colorScheme.onBackground, contentDescription = "BACK", @@ -58,18 +77,18 @@ fun SettingsPage(viewModel: MainActivityVM = hiltViewModel(), navController: Nav ) { ToggleRow( label = "Enable DND while muting notifications", - checked = hushConfig.isDnd, - onCheckedChange = { notificationsEnabled = it } + checked = isDnd, + onCheckedChange = onDndCheckChangeLambda ) ToggleRow( label = "Automatically remove expired mutes", - checked = hushConfig.isAutoDeleteExpired, - onCheckedChange = { darkModeEnabled = it } + checked = isRemovedExpired, + onCheckedChange = onRemovedExpiredChangeLambda ) ToggleRow( label = "Notify if there's too many notification being muted", - checked = hushConfig.isAutoDeleteExpired, - onCheckedChange = { locationTrackingEnabled = it } + checked = isNotify, + onCheckedChange = onNotifyChangeLambda ) // ToggleRow( // label = { Text(text = "Automatic Updates") }, diff --git a/app/src/main/java/dev/souravdas/hush/compose/main/MainScreen.kt b/app/src/main/java/dev/souravdas/hush/compose/main/MainScreen.kt index 5ce260e..32be09f 100644 --- a/app/src/main/java/dev/souravdas/hush/compose/main/MainScreen.kt +++ b/app/src/main/java/dev/souravdas/hush/compose/main/MainScreen.kt @@ -10,6 +10,7 @@ import androidx.compose.foundation.clickable import androidx.compose.foundation.layout.* import androidx.compose.foundation.lazy.LazyColumn import androidx.compose.foundation.lazy.items +import androidx.compose.foundation.lazy.rememberLazyListState import androidx.compose.foundation.shape.CircleShape import androidx.compose.foundation.shape.RoundedCornerShape import androidx.compose.material.* @@ -145,7 +146,7 @@ fun MainActivityScreen( } DropdownMenuItem(onClick = { - navController.navigate(route = Screens.SettingsScreen.route) + navController.navigate(route = Screens.AboutScreen.route) dropDownMenuExpanded = false }) { Text("About") @@ -191,6 +192,7 @@ fun MainActivityScreen( Timber.d(selectedList.size.toString()) val modifier = Modifier.consumeWindowInsets(mo) val hushStatus = viewModel.getHushStatusAsFlow().collectAsState(initial = false) + val listState = rememberLazyListState() var showNotificationPermissionAlertDialog by remember { mutableStateOf(!checkNotificationPermission.invoke()) } @@ -207,6 +209,9 @@ fun MainActivityScreen( val editAppLambda = remember<(SelectedApp) -> Unit> { { app -> viewModel.updateComplete(app) + scope.launch { + listState.scrollToItem(index = 1) + } } } val removeAppLambda = remember<(SelectedApp) -> Unit> { @@ -273,6 +278,7 @@ fun MainActivityScreen( } LazyColumn( + state = listState, modifier = modifier .padding(8.dp) .fillMaxSize() diff --git a/app/src/main/java/dev/souravdas/hush/nav/NavGraph.kt b/app/src/main/java/dev/souravdas/hush/nav/NavGraph.kt index 9ddd669..0c7ca9b 100644 --- a/app/src/main/java/dev/souravdas/hush/nav/NavGraph.kt +++ b/app/src/main/java/dev/souravdas/hush/nav/NavGraph.kt @@ -7,6 +7,7 @@ import androidx.navigation.NavType import androidx.navigation.compose.NavHost import androidx.navigation.compose.composable import androidx.navigation.navArgument +import dev.souravdas.hush.compose.AboutScreen import dev.souravdas.hush.compose.AppLogList import dev.souravdas.hush.compose.SettingsPage import dev.souravdas.hush.compose.main.MainActivityScreen @@ -55,5 +56,11 @@ fun NavGraph( ){ SettingsPage(navController = navController) } + + composable( + route = Screens.AboutScreen.route + ){ + AboutScreen(navController) + } } } \ No newline at end of file diff --git a/app/src/main/java/dev/souravdas/hush/nav/Screens.kt b/app/src/main/java/dev/souravdas/hush/nav/Screens.kt index 0cee048..3bae3bb 100644 --- a/app/src/main/java/dev/souravdas/hush/nav/Screens.kt +++ b/app/src/main/java/dev/souravdas/hush/nav/Screens.kt @@ -9,5 +9,6 @@ sealed class Screens(val route: String){ object MainScreen: Screens(route = "main_screen") object LogScreen: Screens(route = "log_screen/{app_id}/{app_name}") object SettingsScreen: Screens(route = "settings_screen") + object AboutScreen: Screens(route = "about_screen") } diff --git a/app/src/main/java/dev/souravdas/hush/services/HushService.kt b/app/src/main/java/dev/souravdas/hush/services/HushService.kt index 5946f68..4a18760 100644 --- a/app/src/main/java/dev/souravdas/hush/services/HushService.kt +++ b/app/src/main/java/dev/souravdas/hush/services/HushService.kt @@ -4,6 +4,8 @@ import android.app.Notification import android.app.NotificationManager import android.content.Context import android.os.Build +import android.os.Build.VERSION +import android.os.Build.VERSION_CODES import android.os.Handler import android.os.Looper import android.service.notification.NotificationListenerService @@ -14,6 +16,7 @@ import dev.sourav.base.datastore.DataStoreManager import dev.souravdas.hush.HushApp import dev.souravdas.hush.arch.SelectAppCache import dev.souravdas.hush.models.AppLog +import dev.souravdas.hush.models.HushConfig import dev.souravdas.hush.models.SelectedApp import dev.souravdas.hush.others.Constants import dev.souravdas.hush.others.HushType @@ -21,6 +24,7 @@ import dev.souravdas.hush.others.Utils import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.SupervisorJob +import kotlinx.coroutines.flow.collect import kotlinx.coroutines.flow.firstOrNull import kotlinx.coroutines.launch import org.threeten.bp.LocalTime @@ -53,6 +57,7 @@ class HushService : NotificationListenerService() { @Inject lateinit var dataStoreManager: DataStoreManager private var selectedApps: List = emptyList() + private var hushConfig: HushConfig = HushConfig() override fun onCreate() { super.onCreate() @@ -61,6 +66,10 @@ class HushService : NotificationListenerService() { Timber.tag(TAG).i("Received app onCreate list $it") selectedApps = it } + + selectAppCache.getConfig().collect{ + hushConfig = it + } } } @@ -85,7 +94,6 @@ class HushService : NotificationListenerService() { app = it it.packageName == notification.packageName }) { - enableDndModeFor4Seconds() Timber.tag(TAG).i("App found on List. Cancelling notification") when (app!!.hushType) { @@ -121,6 +129,8 @@ class HushService : NotificationListenerService() { } private fun cancelAndLog(statusBarNotification: StatusBarNotification, app: SelectedApp) { + if (VERSION.SDK_INT >= VERSION_CODES.M) + enableDndModeFor4Seconds() val tmp = statusBarNotification cancelNotification(statusBarNotification.key) logNotification(tmp, app) @@ -140,11 +150,11 @@ class HushService : NotificationListenerService() { } } - @RequiresApi(Build.VERSION_CODES.M) - fun enableDndModeFor4Seconds() { + @RequiresApi(VERSION_CODES.M) + private fun enableDndModeFor4Seconds() { val notificationManager = HushApp.context.getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager - if (notificationManager.isNotificationPolicyAccessGranted && !isMute) { + if (!hushConfig.isDnd && notificationManager.isNotificationPolicyAccessGranted && !isMute) { val oldInterruptionFilter = notificationManager.currentInterruptionFilter notificationManager.setInterruptionFilter(NotificationManager.INTERRUPTION_FILTER_PRIORITY) isMute = true From f5081ef08985241ffb26057d8abf73832b5fb794 Mon Sep 17 00:00:00 2001 From: Sourav Das Date: Thu, 23 Mar 2023 23:12:48 +0600 Subject: [PATCH 13/16] fixed settings --- .../dev/souravdas/hush/arch/MainActivityVM.kt | 34 +++++++----- .../java/dev/souravdas/hush/compose/About.kt | 43 +++++++++++---- .../dev/souravdas/hush/compose/Settings.kt | 49 +++++++----------- app/src/main/res/drawable/roach.webp | Bin 0 -> 10660 bytes 4 files changed, 75 insertions(+), 51 deletions(-) create mode 100644 app/src/main/res/drawable/roach.webp diff --git a/app/src/main/java/dev/souravdas/hush/arch/MainActivityVM.kt b/app/src/main/java/dev/souravdas/hush/arch/MainActivityVM.kt index 8b4406e..6f68362 100644 --- a/app/src/main/java/dev/souravdas/hush/arch/MainActivityVM.kt +++ b/app/src/main/java/dev/souravdas/hush/arch/MainActivityVM.kt @@ -35,8 +35,16 @@ class MainActivityVM @Inject constructor( private val _appLog = MutableStateFlow>(emptyList()) val appLog = _appLog.asStateFlow() - private val _hushConfig = MutableSharedFlow() - val hushConfig = _hushConfig.asSharedFlow() + private val _dsIsDnd = dataStoreManager.getBooleanValueAsFlow(Constants.DS_DND) + private val _dsIsRemoveExpired = dataStoreManager.getBooleanValueAsFlow(Constants.DS_DELETE_EXPIRE) + private val _dsIsNotifyMute = dataStoreManager.getBooleanValueAsFlow(Constants.DS_NOTIFY_MUTE) + + val hushConfig : Flow = combine(_dsIsDnd, _dsIsRemoveExpired,_dsIsNotifyMute) {a,b,c -> + HushConfig(a,b,c) + } + + suspend fun getBoolean(key:String):Boolean = dataStoreManager.getBooleanValue(key) + companion object { const val APP_LIST = "APP_LIST" @@ -188,17 +196,17 @@ class MainActivityVM @Inject constructor( } } - fun getHushConfig(){ - viewModelScope.launch { - _hushConfig.tryEmit( - HushConfig( - dataStoreManager.getBooleanValue(Constants.DS_DND), - dataStoreManager.getBooleanValue(Constants.DS_DELETE_EXPIRE), - dataStoreManager.getBooleanValue(Constants.DS_NOTIFY_MUTE) - ) - ) - } - } +// fun getHushConfig(){ +// viewModelScope.launch { +// _hushConfig.tryEmit( +// HushConfig( +// dataStoreManager.getBooleanValue(Constants.DS_DND), +// dataStoreManager.getBooleanValue(Constants.DS_DELETE_EXPIRE), +// dataStoreManager.getBooleanValue(Constants.DS_NOTIFY_MUTE) +// ) +// ) +// } +// } fun updateComplete(app: SelectedApp){ executedSuspendedCodeBlock { diff --git a/app/src/main/java/dev/souravdas/hush/compose/About.kt b/app/src/main/java/dev/souravdas/hush/compose/About.kt index 2fb026b..adb1dbf 100644 --- a/app/src/main/java/dev/souravdas/hush/compose/About.kt +++ b/app/src/main/java/dev/souravdas/hush/compose/About.kt @@ -1,5 +1,9 @@ package dev.souravdas.hush.compose +import android.app.Activity +import android.content.Intent +import android.net.Uri +import androidx.compose.foundation.Image import androidx.compose.foundation.background import androidx.compose.foundation.clickable import androidx.compose.foundation.layout.* @@ -12,19 +16,19 @@ import androidx.compose.runtime.Composable import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.draw.clip -import androidx.compose.ui.graphics.Color -import androidx.compose.ui.layout.ContentScale +import androidx.compose.ui.platform.LocalContext +import androidx.compose.ui.res.painterResource import androidx.compose.ui.res.stringResource import androidx.compose.ui.text.font.FontWeight -import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.unit.dp +import androidx.core.content.ContextCompat.startActivity import androidx.navigation.NavController import com.bumptech.glide.integration.compose.ExperimentalGlideComposeApi import com.bumptech.glide.integration.compose.GlideImage -import dagger.Provides import dev.souravdas.hush.BuildConfig import dev.souravdas.hush.R + /** * Created by Sourav * On 3/23/2023 7:16 PM @@ -59,6 +63,7 @@ fun AboutScreen(navController: NavController) { .fillMaxSize() .padding(it) ) { + val activity = (LocalContext.current as Activity) Column( modifier = Modifier .fillMaxWidth(0.8f) @@ -90,7 +95,9 @@ fun AboutScreen(navController: NavController) { ) Row( verticalAlignment = Alignment.CenterVertically, - modifier = Modifier.fillMaxWidth().padding(bottom = 16.dp) + modifier = Modifier + .fillMaxWidth() + .padding(bottom = 16.dp) ) { GlideImage( model = "https://github.com/Esarve.png", @@ -99,6 +106,14 @@ fun AboutScreen(navController: NavController) { .width(64.dp) .height(64.dp) .clip(CircleShape) + .clickable { + activity.startActivity( + Intent( + Intent.ACTION_VIEW, + Uri.parse("https://souravdas.dev") + ) + ) + } ) Text( text = "Sourav Das\nhttps://souravdas.dev", @@ -117,11 +132,21 @@ fun AboutScreen(navController: NavController) { ) Row( verticalAlignment = Alignment.CenterVertically, - modifier = Modifier.fillMaxWidth().padding(bottom = 16.dp) + modifier = Modifier + .fillMaxWidth() + .padding(bottom = 16.dp) + .clickable { + activity.startActivity( + Intent( + Intent.ACTION_VIEW, + Uri.parse("https://www.raishaq.com/") + ) + ) + } ) { - GlideImage( - model = "https://lh3.googleusercontent.com/_DAIFu6wp6wZJBWDR4KVQ6cV4DE3Ov2h9Vvn-3RztW6xJxuGo_sg2gdkZ2dFZTLzANuZ_Bu4EMIKXSIGZAHoYOzqxzY7tisGgq5WpiRNh9kqzh_0WSQZZrGo1d2Vsj2m=w1280", - contentDescription = "devimg", + Image( + painterResource(id = R.drawable.roach), + contentDescription = "roachimg", modifier = Modifier .width(64.dp) .height(64.dp) diff --git a/app/src/main/java/dev/souravdas/hush/compose/Settings.kt b/app/src/main/java/dev/souravdas/hush/compose/Settings.kt index e1fec54..60e386f 100644 --- a/app/src/main/java/dev/souravdas/hush/compose/Settings.kt +++ b/app/src/main/java/dev/souravdas/hush/compose/Settings.kt @@ -5,8 +5,10 @@ package dev.souravdas.hush.compose * On 3/22/2023 2:03 PM * For Hush! */ +import androidx.compose.foundation.background import androidx.compose.foundation.clickable import androidx.compose.foundation.layout.* +import androidx.compose.foundation.shape.RoundedCornerShape import androidx.compose.material.icons.Icons import androidx.compose.material.icons.outlined.ArrowBack import androidx.compose.material3.* @@ -16,42 +18,45 @@ import androidx.compose.ui.Modifier import androidx.compose.ui.text.style.TextOverflow import androidx.compose.ui.unit.dp import androidx.hilt.navigation.compose.hiltViewModel -import androidx.lifecycle.ViewModel import androidx.navigation.NavHostController import dev.souravdas.hush.arch.MainActivityVM -import dev.souravdas.hush.models.HushConfig import dev.souravdas.hush.others.Constants -import kotlinx.coroutines.flow.collect @OptIn(ExperimentalMaterial3Api::class) @Composable fun SettingsPage(viewModel: MainActivityVM = hiltViewModel(), navController: NavHostController) { - val hushConfig by viewModel.hushConfig.collectAsState(initial = HushConfig()) + var isDnd by remember { mutableStateOf(false) } + var isRemovedExpired by remember { mutableStateOf(false) } + var isNotify by remember { mutableStateOf(false) } - val isDnd by remember { mutableStateOf(hushConfig.isDnd) } - val isRemovedExpired by remember { mutableStateOf(hushConfig.isAutoDeleteExpired) } - val isNotify by remember { mutableStateOf(hushConfig.isNotificationReminder) } + LaunchedEffect(Unit){ + isDnd = viewModel.getBoolean(Constants.DS_DND) + isRemovedExpired = viewModel.getBoolean(Constants.DS_DELETE_EXPIRE) + isNotify = viewModel.getBoolean(Constants.DS_NOTIFY_MUTE) + } val onDndCheckChangeLambda = remember<(Boolean) -> Unit> { { viewModel.changeBooleanDS(Constants.DS_DND, it) + isDnd = !isDnd } } val onRemovedExpiredChangeLambda = remember<(Boolean) -> Unit> { { viewModel.changeBooleanDS(Constants.DS_DELETE_EXPIRE, it) + isRemovedExpired = !isRemovedExpired } } val onNotifyChangeLambda = remember<(Boolean) -> Unit> { { viewModel.changeBooleanDS(Constants.DS_NOTIFY_MUTE, it) + isNotify = !isNotify } } - Scaffold( topBar = { TopAppBar( @@ -72,8 +77,8 @@ fun SettingsPage(viewModel: MainActivityVM = hiltViewModel(), navController: Nav ) { Column( modifier = Modifier - .padding(it) .fillMaxWidth() + .padding(it) ) { ToggleRow( label = "Enable DND while muting notifications", @@ -90,39 +95,25 @@ fun SettingsPage(viewModel: MainActivityVM = hiltViewModel(), navController: Nav checked = isNotify, onCheckedChange = onNotifyChangeLambda ) -// ToggleRow( -// label = { Text(text = "Automatic Updates") }, -// checked = automaticUpdatesEnabled, -// onCheckedChange = { automaticUpdatesEnabled = it } -// ) -// ToggleRow( -// label = { Text(text = "Language Selection") }, -// checked = languageSelectionEnabled, -// onCheckedChange = { languageSelectionEnabled = it } -// ) } } } @Composable -fun ToggleRow(label: String, checked: Boolean, onCheckedChange: (Boolean) -> Unit) { - var enabled by remember { - mutableStateOf(true) - } +fun ToggleRow(label: String, checked: Boolean, onCheckedChange: (Boolean) -> Unit) { + Row( horizontalArrangement = Arrangement.SpaceBetween, verticalAlignment = Alignment.CenterVertically, modifier = Modifier .fillMaxWidth() - .padding(8.dp) + .padding(horizontal = 16.dp, vertical = 8.dp) + ) { Text(text = label, overflow = TextOverflow.Ellipsis, modifier = Modifier.fillMaxWidth(0.8f)) Checkbox( - checked = enabled, - onCheckedChange = { - onCheckedChange.invoke(it) - enabled = !enabled - }, + checked = checked, + onCheckedChange = onCheckedChange, modifier = Modifier.padding(horizontal = 4.dp) ) } diff --git a/app/src/main/res/drawable/roach.webp b/app/src/main/res/drawable/roach.webp new file mode 100644 index 0000000000000000000000000000000000000000..5a845e2099de37d4f3d8d64b0c17039806d1a7fb GIT binary patch literal 10660 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 CFh+y` literal 0 HcmV?d00001 From 5ca08fa2131fa9d89db1cfadbaaf9745b1410e5f Mon Sep 17 00:00:00 2001 From: Sourav Das Date: Thu, 23 Mar 2023 23:31:11 +0600 Subject: [PATCH 14/16] should fix missing 1st notification --- app/src/main/java/dev/souravdas/hush/services/HushService.kt | 2 ++ 1 file changed, 2 insertions(+) diff --git a/app/src/main/java/dev/souravdas/hush/services/HushService.kt b/app/src/main/java/dev/souravdas/hush/services/HushService.kt index 4a18760..ea540be 100644 --- a/app/src/main/java/dev/souravdas/hush/services/HushService.kt +++ b/app/src/main/java/dev/souravdas/hush/services/HushService.kt @@ -67,6 +67,8 @@ class HushService : NotificationListenerService() { selectedApps = it } + isServiceRunning = dataStoreManager.getBooleanValue(Constants.DS_HUSH_STATUS) + selectAppCache.getConfig().collect{ hushConfig = it } From 16be084755af87d2daaba3255bf722e92582f67b Mon Sep 17 00:00:00 2001 From: Sourav Das Date: Thu, 23 Mar 2023 23:46:56 +0600 Subject: [PATCH 15/16] Bumped version code --- app/build.gradle | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/app/build.gradle b/app/build.gradle index 70d03ea..4fa27b3 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -13,8 +13,8 @@ android { applicationId "dev.souravdas.hush" minSdk 22 targetSdk 33 - versionCode 1 - versionName "0.1-alpha" + versionCode 2 + versionName "0.2-alpha" testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" vectorDrawables { @@ -90,7 +90,7 @@ dependencies { implementation 'androidx.compose.ui:ui-graphics' implementation 'androidx.compose.ui:ui-tooling-preview' implementation 'androidx.compose.material3:material3:1.1.0-alpha07' - implementation 'androidx.lifecycle:lifecycle-runtime-ktx:2.5.1' + implementation 'androidx.lifecycle:lifecycle-runtime-ktx:2.6.0' implementation 'androidx.activity:activity-compose:1.6.1' implementation 'androidx.compose.material:material:1.3.1' testImplementation 'junit:junit:4.13.2' From 9df20caab764d2623a7e63e0c08105ecd3986059 Mon Sep 17 00:00:00 2001 From: Sourav Das Date: Fri, 24 Mar 2023 11:11:30 +0600 Subject: [PATCH 16/16] Enabled/Disabled DND --- app/src/main/java/dev/souravdas/hush/services/HushService.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/src/main/java/dev/souravdas/hush/services/HushService.kt b/app/src/main/java/dev/souravdas/hush/services/HushService.kt index ea540be..134175a 100644 --- a/app/src/main/java/dev/souravdas/hush/services/HushService.kt +++ b/app/src/main/java/dev/souravdas/hush/services/HushService.kt @@ -131,7 +131,7 @@ class HushService : NotificationListenerService() { } private fun cancelAndLog(statusBarNotification: StatusBarNotification, app: SelectedApp) { - if (VERSION.SDK_INT >= VERSION_CODES.M) + if (VERSION.SDK_INT >= VERSION_CODES.M && hushConfig.isDnd) enableDndModeFor4Seconds() val tmp = statusBarNotification cancelNotification(statusBarNotification.key)