From 7472cd3f87f18f3f5de3c76393f0378a50210de2 Mon Sep 17 00:00:00 2001 From: Richter3766 <97567615+Richter3766@users.noreply.github.com> Date: Thu, 27 Feb 2025 19:42:02 +0900 Subject: [PATCH 1/6] =?UTF-8?q?refactor:=20NotiListenerService=20=EB=8F=84?= =?UTF-8?q?=EB=A9=94=EC=9D=B8=EC=9C=BC=EB=A1=9C=20=EC=9D=B4=EB=8F=99?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 해당 서비스는 도메인에 위치하는 것이 맞는 듯함. 인터페이스 선언이 domain에 있고, 서비스는 인터페이스만 있으면 됨. --- .../data/service/NotiListenerServiceTest.kt | 10 +++++----- app/src/main/AndroidManifest.xml | 2 +- .../data/repository/NotificationRepository.kt | 1 + .../com/example/notimanager/di/RepositoryModule.kt | 2 +- .../repository/NotificationRepositoryInterface.kt | 2 +- .../{data => domain}/service/NotiListenerService.kt | 5 ++--- 6 files changed, 11 insertions(+), 11 deletions(-) rename app/src/main/java/com/example/notimanager/{data => domain}/repository/NotificationRepositoryInterface.kt (92%) rename app/src/main/java/com/example/notimanager/{data => domain}/service/NotiListenerService.kt (96%) diff --git a/app/src/androidTest/java/com/example/notimanager/data/service/NotiListenerServiceTest.kt b/app/src/androidTest/java/com/example/notimanager/data/service/NotiListenerServiceTest.kt index 75d912b..6c837c9 100644 --- a/app/src/androidTest/java/com/example/notimanager/data/service/NotiListenerServiceTest.kt +++ b/app/src/androidTest/java/com/example/notimanager/data/service/NotiListenerServiceTest.kt @@ -13,7 +13,7 @@ import com.example.notimanager.data.model.NotificationMetaModel import com.example.notimanager.presentation.ui.activity.MainActivity import com.example.notimanager.data.model.NotificationModel import com.example.notimanager.data.repository.NotificationRepository -import com.example.notimanager.data.service.NotiListenerService +import com.example.notimanager.domain.service.NotiListenerService import com.example.notimanager.data.utils.NameGetter import com.example.notimanager.data.utils.IntentHelper import io.mockk.coEvery @@ -85,7 +85,7 @@ class NotiListenerServiceTest { // Mock the PendingIntentHelper val intentArray = "MockedByteArray".toByteArray() - every { IntentHelper.saveIntent(mockPendingIntent) } returns intentArray + every { IntentHelper.saveIntent(realIntent) } returns intentArray val expectedNotificationModel = NotificationModel( appName = "Test App", @@ -103,12 +103,12 @@ class NotiListenerServiceTest { coEvery { notificationRepository.insertNotificationMeta(notificationMetaModel) } returns 1L val notificationIconModel = NotificationIconModel( notificationId = 1L, - iconBytes = uri + iconBytes = "".toByteArray() ) coEvery { notificationRepository.insertNotificationIcon(notificationIconModel) } returns 1L val appIconModel = AppIconModel( - iconBytes = "com.example.test", + iconBytes = "".toByteArray(), notiAppName = "Test App" ) coEvery { notificationRepository.insertAppIcon(appIconModel) } returns 1L @@ -123,6 +123,6 @@ class NotiListenerServiceTest { coVerify { notificationRepository.insertAppIcon(appIconModel) } // Verify that PendingIntentHelper was called - verify { IntentHelper.saveIntent(mockPendingIntent) } + verify { IntentHelper.saveIntent(realIntent) } } } \ No newline at end of file diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index a2383bc..0ba43a3 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -25,7 +25,7 @@ diff --git a/app/src/main/java/com/example/notimanager/data/repository/NotificationRepository.kt b/app/src/main/java/com/example/notimanager/data/repository/NotificationRepository.kt index 8f7ecba..01e37b0 100644 --- a/app/src/main/java/com/example/notimanager/data/repository/NotificationRepository.kt +++ b/app/src/main/java/com/example/notimanager/data/repository/NotificationRepository.kt @@ -8,6 +8,7 @@ import com.example.notimanager.data.source.local.dao.AppIconDao import com.example.notimanager.data.source.local.dao.NotificationDao import com.example.notimanager.data.source.local.dao.NotificationIconDao import com.example.notimanager.data.source.local.dao.NotificationMetaDao +import com.example.notimanager.domain.repository.NotificationRepositoryInterface class NotificationRepository( private val notificationDao: NotificationDao, diff --git a/app/src/main/java/com/example/notimanager/di/RepositoryModule.kt b/app/src/main/java/com/example/notimanager/di/RepositoryModule.kt index bba488e..c2855aa 100644 --- a/app/src/main/java/com/example/notimanager/di/RepositoryModule.kt +++ b/app/src/main/java/com/example/notimanager/di/RepositoryModule.kt @@ -5,7 +5,7 @@ import com.example.notimanager.data.repository.NotificationAppRepository import com.example.notimanager.data.repository.NotificationPermissionRepository import com.example.notimanager.data.repository.NotificationRepository import com.example.notimanager.data.repository.NotificationDomainRepository -import com.example.notimanager.data.repository.NotificationRepositoryInterface +import com.example.notimanager.domain.repository.NotificationRepositoryInterface import com.example.notimanager.data.repository.NotificationTitleRepository import com.example.notimanager.data.source.local.dao.AppIconDao import com.example.notimanager.data.source.local.dao.NotificationDao diff --git a/app/src/main/java/com/example/notimanager/data/repository/NotificationRepositoryInterface.kt b/app/src/main/java/com/example/notimanager/domain/repository/NotificationRepositoryInterface.kt similarity index 92% rename from app/src/main/java/com/example/notimanager/data/repository/NotificationRepositoryInterface.kt rename to app/src/main/java/com/example/notimanager/domain/repository/NotificationRepositoryInterface.kt index 6983167..93133bb 100644 --- a/app/src/main/java/com/example/notimanager/data/repository/NotificationRepositoryInterface.kt +++ b/app/src/main/java/com/example/notimanager/domain/repository/NotificationRepositoryInterface.kt @@ -1,4 +1,4 @@ -package com.example.notimanager.data.repository +package com.example.notimanager.domain.repository import com.example.notimanager.data.model.AppIconModel import com.example.notimanager.data.model.NotificationIconModel diff --git a/app/src/main/java/com/example/notimanager/data/service/NotiListenerService.kt b/app/src/main/java/com/example/notimanager/domain/service/NotiListenerService.kt similarity index 96% rename from app/src/main/java/com/example/notimanager/data/service/NotiListenerService.kt rename to app/src/main/java/com/example/notimanager/domain/service/NotiListenerService.kt index df49b25..76e9653 100644 --- a/app/src/main/java/com/example/notimanager/data/service/NotiListenerService.kt +++ b/app/src/main/java/com/example/notimanager/domain/service/NotiListenerService.kt @@ -1,14 +1,13 @@ -package com.example.notimanager.data.service +package com.example.notimanager.domain.service import android.graphics.drawable.Icon import android.service.notification.NotificationListenerService import android.service.notification.StatusBarNotification -import android.util.Log import com.example.notimanager.data.model.AppIconModel import com.example.notimanager.data.model.NotificationIconModel import com.example.notimanager.data.model.NotificationMetaModel import com.example.notimanager.data.model.NotificationModel -import com.example.notimanager.data.repository.NotificationRepositoryInterface +import com.example.notimanager.domain.repository.NotificationRepositoryInterface import com.example.notimanager.data.utils.AppIconGetter.convertByteArray import com.example.notimanager.data.utils.AppIconGetter.convertByteArrayWithColor import com.example.notimanager.data.utils.NameGetter From 79e3dec3ae32ea983acb8d5d3d38f6b0f9a076a0 Mon Sep 17 00:00:00 2001 From: Richter3766 <97567615+Richter3766@users.noreply.github.com> Date: Fri, 28 Feb 2025 14:23:57 +0900 Subject: [PATCH 2/6] =?UTF-8?q?feat:=20=EB=A9=94=EC=9D=B8=20=ED=99=94?= =?UTF-8?q?=EB=A9=B4=20PullToRefresh=20=EC=A0=81=EC=9A=A9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../ui/component/NotificationAppListView.kt | 90 ++++++++++--------- .../presentation/ui/screen/MainScreen.kt | 42 ++++++++- 2 files changed, 90 insertions(+), 42 deletions(-) diff --git a/app/src/main/java/com/example/notimanager/presentation/ui/component/NotificationAppListView.kt b/app/src/main/java/com/example/notimanager/presentation/ui/component/NotificationAppListView.kt index 1f16ac3..55813e9 100644 --- a/app/src/main/java/com/example/notimanager/presentation/ui/component/NotificationAppListView.kt +++ b/app/src/main/java/com/example/notimanager/presentation/ui/component/NotificationAppListView.kt @@ -5,6 +5,7 @@ import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.PaddingValues import androidx.compose.foundation.layout.Row import androidx.compose.foundation.layout.Spacer +import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.width @@ -19,6 +20,7 @@ import androidx.compose.material3.IconButton import androidx.compose.material3.MaterialTheme import androidx.compose.material3.Text import androidx.compose.runtime.Composable +import androidx.compose.runtime.LaunchedEffect import androidx.compose.runtime.getValue import androidx.compose.runtime.livedata.observeAsState import androidx.compose.runtime.mutableStateOf @@ -43,52 +45,59 @@ import com.example.notimanager.presentation.stateholder.viewmodel.NotificationAp @Composable fun NotificationAppListView( navController: NavController, - innerPadding: PaddingValues, - viewModel: NotificationAppViewModel = hiltViewModel(), - priorityViewModel: NotificationAppPriorityViewModel = hiltViewModel() + viewModel: NotificationAppViewModel, + priorityViewModel: NotificationAppPriorityViewModel ) { val notificationAppState by viewModel.notificationAppState.observeAsState(NotificationAppState()) val priorityState by priorityViewModel.notificationAppPriorityState.observeAsState((NotificationAppPriorityState())) + var currentNotiPriority by remember { mutableStateOf(priorityState.notificationAppList) } + var currentNoti by remember { mutableStateOf(notificationAppState.notificationAppList) } - Column( - Modifier.padding(innerPadding) - ) { - if (notificationAppState.isLoading || priorityState.isLoading) { - CircularProgressIndicator(modifier = Modifier.padding(16.dp)) - } else if (notificationAppState.error != null) { + LaunchedEffect(priorityState.notificationAppList) { + if (!priorityState.isLoading) { + currentNotiPriority = priorityState.notificationAppList + } + } - } else { - LazyColumn { - items(priorityState.notificationAppList) { notification -> - NotificationAppItemView( - notification = notification, - onClick = { - navController - .navigate("titleScreen/${notification.appName}/${notification.title}" - ) - }, - viewModel = viewModel, - priorityViewModel = priorityViewModel - ) - } + LaunchedEffect(notificationAppState.notificationAppList) { + if (!notificationAppState.isLoading) { + currentNoti = notificationAppState.notificationAppList + } + } - item { - HorizontalDivider() - } + LazyColumn( + Modifier.fillMaxSize() + ) { + items(currentNotiPriority) { notification -> + NotificationAppItemView( + notification = notification, + onClick = { + navController + .navigate( + "titleScreen/${notification.appName}/${notification.title}" + ) + }, + viewModel = viewModel, + priorityViewModel = priorityViewModel + ) + } - items(notificationAppState.notificationAppList) { notification -> - NotificationAppItemView( - notification = notification, - onClick = { - navController - .navigate("titleScreen/${notification.appName}/${notification.title}" - ) - }, - viewModel = viewModel, - priorityViewModel = priorityViewModel - ) - } - } + item { + HorizontalDivider() + } + + items(currentNoti) { notification -> + NotificationAppItemView( + notification = notification, + onClick = { + navController + .navigate( + "titleScreen/${notification.appName}/${notification.title}" + ) + }, + viewModel = viewModel, + priorityViewModel = priorityViewModel + ) } } } @@ -157,7 +166,7 @@ fun NotificationAppItemView( priorityViewModel.removeAppPriority(notification.appName){ viewModel.loadNotificationApps() } - + showModal = false }) } else{ @@ -165,6 +174,7 @@ fun NotificationAppItemView( viewModel.setAppPriority(notification.appName, priorityViewModel.getLength()){ priorityViewModel.loadNotificationAppPriority() } + showModal = false }) } ClickableTextView(text = "삭제", onClick = {}) diff --git a/app/src/main/java/com/example/notimanager/presentation/ui/screen/MainScreen.kt b/app/src/main/java/com/example/notimanager/presentation/ui/screen/MainScreen.kt index f6cf750..ad6307e 100644 --- a/app/src/main/java/com/example/notimanager/presentation/ui/screen/MainScreen.kt +++ b/app/src/main/java/com/example/notimanager/presentation/ui/screen/MainScreen.kt @@ -1,18 +1,40 @@ package com.example.notimanager.presentation.ui.screen +import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.foundation.layout.padding +import androidx.compose.material3.ExperimentalMaterial3Api import androidx.compose.material3.HorizontalDivider import androidx.compose.material3.Scaffold +import androidx.compose.material3.pulltorefresh.PullToRefreshBox import androidx.compose.runtime.Composable +import androidx.compose.runtime.getValue +import androidx.compose.runtime.mutableStateOf +import androidx.compose.runtime.remember +import androidx.compose.runtime.rememberCoroutineScope +import androidx.compose.runtime.setValue import androidx.compose.ui.Modifier import androidx.compose.ui.unit.dp +import androidx.hilt.navigation.compose.hiltViewModel import androidx.navigation.NavController +import com.example.notimanager.presentation.stateholder.viewmodel.NotificationAppPriorityViewModel +import com.example.notimanager.presentation.stateholder.viewmodel.NotificationAppViewModel import com.example.notimanager.presentation.ui.component.MainTopAppBar import com.example.notimanager.presentation.ui.component.NotificationAppListView import com.example.notimanager.presentation.ui.component.PermissionCheck +import kotlinx.coroutines.delay +import kotlinx.coroutines.launch +@OptIn(ExperimentalMaterial3Api::class) @Composable -fun MainScreen(navController: NavController){ +fun MainScreen( + navController: NavController, +) { + // TODO: Shared Prefernence로 알림 들어오는 지 체크하는 로직 추가하기 + val viewModel: NotificationAppViewModel = hiltViewModel() + val priorityViewModel: NotificationAppPriorityViewModel = hiltViewModel() + var isRefreshing by remember { mutableStateOf(false) } + val coroutineScope = rememberCoroutineScope() + Scaffold( topBar = { MainTopAppBar() @@ -22,7 +44,23 @@ fun MainScreen(navController: NavController){ modifier = Modifier.padding(innerPadding), thickness = 0.2.dp ) - NotificationAppListView(navController, innerPadding) + PullToRefreshBox( + isRefreshing = isRefreshing, + onRefresh = { + isRefreshing = true + viewModel.loadNotificationApps() + priorityViewModel.loadNotificationAppPriority() + coroutineScope.launch { + delay(2000) + isRefreshing = false + } + }, + modifier = Modifier + .padding(innerPadding) + .fillMaxSize() + ) { + NotificationAppListView(navController, viewModel, priorityViewModel) + } } PermissionCheck() From 860a0d4362c62ba13718988100cd0fbce8f169ae Mon Sep 17 00:00:00 2001 From: Richter3766 <97567615+Richter3766@users.noreply.github.com> Date: Fri, 28 Feb 2025 14:24:06 +0900 Subject: [PATCH 3/6] =?UTF-8?q?feat:=20=EC=A0=9C=EB=AA=A9=20=ED=99=94?= =?UTF-8?q?=EB=A9=B4=20PullToRefresh=20=EC=A0=81=EC=9A=A9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../ui/component/NotificationTitleListView.kt | 62 +++++++++++-------- .../presentation/ui/screen/TitleScreen.kt | 31 +++++++++- 2 files changed, 65 insertions(+), 28 deletions(-) diff --git a/app/src/main/java/com/example/notimanager/presentation/ui/component/NotificationTitleListView.kt b/app/src/main/java/com/example/notimanager/presentation/ui/component/NotificationTitleListView.kt index cce4e19..899cd92 100644 --- a/app/src/main/java/com/example/notimanager/presentation/ui/component/NotificationTitleListView.kt +++ b/app/src/main/java/com/example/notimanager/presentation/ui/component/NotificationTitleListView.kt @@ -5,6 +5,7 @@ import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.PaddingValues import androidx.compose.foundation.layout.Row import androidx.compose.foundation.layout.Spacer +import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.width @@ -19,6 +20,7 @@ import androidx.compose.material3.IconButton import androidx.compose.material3.MaterialTheme import androidx.compose.material3.Text import androidx.compose.runtime.Composable +import androidx.compose.runtime.LaunchedEffect import androidx.compose.runtime.getValue import androidx.compose.runtime.livedata.observeAsState import androidx.compose.runtime.mutableStateOf @@ -41,7 +43,6 @@ import com.example.notimanager.presentation.stateholder.viewmodel.NotificationTi @Composable fun NotificationTitleListView( navController: NavController, - innerPadding: PaddingValues, viewModel: NotificationTitleViewModel, priorityViewModel: NotificationTitlePriorityViewModel ) { @@ -51,35 +52,42 @@ fun NotificationTitleListView( val priorityState by priorityViewModel.notificationTitlePriorityState.observeAsState( NotificationTitlePriorityState() ) - Column ( - Modifier.padding(innerPadding) - ){ - if (notificationTitleState.isLoading || priorityState.isLoading) { - CircularProgressIndicator(modifier = Modifier.padding(16.dp)) - } else if (notificationTitleState.error != null) { + var currentNotiPriority by remember { mutableStateOf(priorityState.notificationTitleList) } + var currentNoti by remember { mutableStateOf(notificationTitleState.notificationTitleList) } - } else { - LazyColumn { - items(priorityState.notificationTitleList) { notification -> - NotificationTitleItemView(notification = notification, onClick = { - navController.navigate( - "notificationScreen/${viewModel.getAppName()}/${notification.title}" - ) - }, viewModel = viewModel, priorityViewModel = priorityViewModel) - } + LaunchedEffect(priorityState.notificationTitleList) { + if (!priorityState.isLoading) { + currentNotiPriority = priorityState.notificationTitleList + } + } - item { - HorizontalDivider() - } + LaunchedEffect(notificationTitleState.notificationTitleList) { + if (!notificationTitleState.isLoading) { + currentNoti = notificationTitleState.notificationTitleList + } + } - items(notificationTitleState.notificationTitleList) { notification -> - NotificationTitleItemView(notification = notification, onClick = { - navController.navigate( - "notificationScreen/${viewModel.getAppName()}/${notification.title}" - ) - }, viewModel = viewModel, priorityViewModel = priorityViewModel) - } - } + LazyColumn( + modifier = Modifier.fillMaxSize() + ) { + items(currentNotiPriority) { notification -> + NotificationTitleItemView(notification = notification, onClick = { + navController.navigate( + "notificationScreen/${viewModel.getAppName()}/${notification.title}" + ) + }, viewModel = viewModel, priorityViewModel = priorityViewModel) + } + + item { + HorizontalDivider() + } + + items(currentNoti) { notification -> + NotificationTitleItemView(notification = notification, onClick = { + navController.navigate( + "notificationScreen/${viewModel.getAppName()}/${notification.title}" + ) + }, viewModel = viewModel, priorityViewModel = priorityViewModel) } } } diff --git a/app/src/main/java/com/example/notimanager/presentation/ui/screen/TitleScreen.kt b/app/src/main/java/com/example/notimanager/presentation/ui/screen/TitleScreen.kt index 9d6091b..64f1e8d 100644 --- a/app/src/main/java/com/example/notimanager/presentation/ui/screen/TitleScreen.kt +++ b/app/src/main/java/com/example/notimanager/presentation/ui/screen/TitleScreen.kt @@ -1,10 +1,17 @@ package com.example.notimanager.presentation.ui.screen import androidx.compose.foundation.layout.padding +import androidx.compose.material3.ExperimentalMaterial3Api import androidx.compose.material3.HorizontalDivider import androidx.compose.material3.Scaffold +import androidx.compose.material3.pulltorefresh.PullToRefreshBox import androidx.compose.runtime.Composable import androidx.compose.runtime.LaunchedEffect +import androidx.compose.runtime.getValue +import androidx.compose.runtime.mutableStateOf +import androidx.compose.runtime.remember +import androidx.compose.runtime.rememberCoroutineScope +import androidx.compose.runtime.setValue import androidx.compose.ui.Modifier import androidx.compose.ui.unit.dp import androidx.hilt.navigation.compose.hiltViewModel @@ -13,12 +20,18 @@ import com.example.notimanager.presentation.stateholder.viewmodel.NotificationTi import com.example.notimanager.presentation.stateholder.viewmodel.NotificationTitleViewModel import com.example.notimanager.presentation.ui.component.NotificationTitleListView import com.example.notimanager.presentation.ui.component.TitleTopAppBar +import kotlinx.coroutines.delay +import kotlinx.coroutines.launch +@OptIn(ExperimentalMaterial3Api::class) @Composable fun TitleScreen(navController: NavController, appName: String = "", title:String = ""){ val viewModel: NotificationTitleViewModel = hiltViewModel() val priorityViewModel: NotificationTitlePriorityViewModel = hiltViewModel() + var isRefreshing by remember { mutableStateOf(false) } + val coroutineScope = rememberCoroutineScope() + LaunchedEffect(appName, title) { viewModel.setArgs(appName, title) priorityViewModel.setArgs(appName, title) @@ -32,6 +45,22 @@ fun TitleScreen(navController: NavController, appName: String = "", title:String modifier = Modifier.padding(innerPadding), thickness = 0.2.dp ) - NotificationTitleListView(navController, innerPadding, viewModel, priorityViewModel) + PullToRefreshBox( + isRefreshing = isRefreshing, + onRefresh = { + isRefreshing = true + viewModel.loadNotificationTitles() + priorityViewModel.loadNotificationTitles() + coroutineScope.launch { + delay(2000) + isRefreshing = false + } + }, + modifier = Modifier + .padding(innerPadding) + ) { + NotificationTitleListView(navController, viewModel, priorityViewModel) + } + } } \ No newline at end of file From 60fa620248ad59140234afed6cd764f3b2dca782 Mon Sep 17 00:00:00 2001 From: Richter3766 <97567615+Richter3766@users.noreply.github.com> Date: Fri, 28 Feb 2025 15:01:13 +0900 Subject: [PATCH 4/6] =?UTF-8?q?build:=20lifescyle=20=EC=9D=98=EC=A1=B4?= =?UTF-8?q?=EC=84=B1=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/build.gradle.kts | 1 + gradle/libs.versions.toml | 4 +++- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/app/build.gradle.kts b/app/build.gradle.kts index d5852a1..bcc8a7a 100644 --- a/app/build.gradle.kts +++ b/app/build.gradle.kts @@ -117,6 +117,7 @@ dependencies { implementation(libs.protolite.well.known.types) implementation(libs.androidx.navigation.compose) implementation(libs.coil.compose) + implementation(libs.androidx.lifecycle.runtime.compose) // 테스트 testImplementation(libs.junit) diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index aa93334..e3d1df0 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -1,5 +1,5 @@ [versions] -agp = "8.8.1" +agp = "8.8.2" byteBuddy = "1.17.1" byteBuddyAgent = "1.17.1" coilCompose = "3.1.0" @@ -22,6 +22,7 @@ junitVersion = "1.2.1" espressoCore = "3.6.1" kotlinStdlib = "2.0.21" kotlinxCoroutinesAndroid = "1.8.0" +lifecycleRuntimeCompose = "2.8.7" lifecycleRuntimeKtx = "2.8.7" activityCompose = "1.10.0" composeBom = "2025.02.00" @@ -40,6 +41,7 @@ runtimeLivedata = "1.7.8" androidx-core-ktx = { group = "androidx.core", name = "core-ktx", version.ref = "coreKtx" } androidx-datastore = { module = "androidx.datastore:datastore", version.ref = "datastore" } androidx-hilt-navigation-compose = { module = "androidx.hilt:hilt-navigation-compose", version.ref = "hiltNavigationCompose" } +androidx-lifecycle-runtime-compose = { module = "androidx.lifecycle:lifecycle-runtime-compose", version.ref = "lifecycleRuntimeCompose" } androidx-navigation-compose = { module = "androidx.navigation:navigation-compose", version.ref = "navigationCompose" } androidx-room-compiler = { module = "androidx.room:room-compiler", version.ref = "roomCompiler" } androidx-room-ktx = { module = "androidx.room:room-ktx" } From d69dd70aef0658895c273a71a67dc3d92f90432b Mon Sep 17 00:00:00 2001 From: Richter3766 <97567615+Richter3766@users.noreply.github.com> Date: Fri, 28 Feb 2025 15:02:34 +0900 Subject: [PATCH 5/6] =?UTF-8?q?feat:=20=EC=9E=90=EB=8F=99=20=EC=83=88?= =?UTF-8?q?=EB=A1=9C=EA=B3=A0=EC=B9=A8=20=EB=A1=9C=EC=A7=81=20=EC=B6=94?= =?UTF-8?q?=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 백그라운드 상태에서 포그라운드 상태로 넘어올 경우 데이터를 새로고침하여 보여주도록 함. Pull To Refresh 시 인디케이터를 짧게 보여줌. -> 성능 빠른 것처럼 보이게. --- .../presentation/ui/screen/MainScreen.kt | 31 ++++++++++++------- .../presentation/ui/screen/TitleScreen.kt | 15 +++++++-- 2 files changed, 32 insertions(+), 14 deletions(-) diff --git a/app/src/main/java/com/example/notimanager/presentation/ui/screen/MainScreen.kt b/app/src/main/java/com/example/notimanager/presentation/ui/screen/MainScreen.kt index ad6307e..166a1d0 100644 --- a/app/src/main/java/com/example/notimanager/presentation/ui/screen/MainScreen.kt +++ b/app/src/main/java/com/example/notimanager/presentation/ui/screen/MainScreen.kt @@ -15,6 +15,9 @@ import androidx.compose.runtime.setValue import androidx.compose.ui.Modifier import androidx.compose.ui.unit.dp import androidx.hilt.navigation.compose.hiltViewModel +import androidx.lifecycle.Lifecycle +import androidx.lifecycle.compose.LifecycleEventEffect +import androidx.lifecycle.compose.LifecycleResumeEffect import androidx.navigation.NavController import com.example.notimanager.presentation.stateholder.viewmodel.NotificationAppPriorityViewModel import com.example.notimanager.presentation.stateholder.viewmodel.NotificationAppViewModel @@ -29,12 +32,27 @@ import kotlinx.coroutines.launch fun MainScreen( navController: NavController, ) { - // TODO: Shared Prefernence로 알림 들어오는 지 체크하는 로직 추가하기 val viewModel: NotificationAppViewModel = hiltViewModel() val priorityViewModel: NotificationAppPriorityViewModel = hiltViewModel() + var isRefreshing by remember { mutableStateOf(false) } val coroutineScope = rememberCoroutineScope() + val onRefresh: () -> Unit = { + isRefreshing = true + viewModel.loadNotificationApps() + priorityViewModel.loadNotificationAppPriority() + coroutineScope.launch { + delay(500) + isRefreshing = false + } + } + + LifecycleEventEffect(Lifecycle.Event.ON_RESUME) { + viewModel.loadNotificationApps() + priorityViewModel.loadNotificationAppPriority() + } + Scaffold( topBar = { MainTopAppBar() @@ -46,15 +64,7 @@ fun MainScreen( ) PullToRefreshBox( isRefreshing = isRefreshing, - onRefresh = { - isRefreshing = true - viewModel.loadNotificationApps() - priorityViewModel.loadNotificationAppPriority() - coroutineScope.launch { - delay(2000) - isRefreshing = false - } - }, + onRefresh = onRefresh, modifier = Modifier .padding(innerPadding) .fillMaxSize() @@ -63,5 +73,4 @@ fun MainScreen( } } PermissionCheck() - } \ No newline at end of file diff --git a/app/src/main/java/com/example/notimanager/presentation/ui/screen/TitleScreen.kt b/app/src/main/java/com/example/notimanager/presentation/ui/screen/TitleScreen.kt index 64f1e8d..f666a5e 100644 --- a/app/src/main/java/com/example/notimanager/presentation/ui/screen/TitleScreen.kt +++ b/app/src/main/java/com/example/notimanager/presentation/ui/screen/TitleScreen.kt @@ -15,9 +15,12 @@ import androidx.compose.runtime.setValue import androidx.compose.ui.Modifier import androidx.compose.ui.unit.dp import androidx.hilt.navigation.compose.hiltViewModel +import androidx.lifecycle.Lifecycle +import androidx.lifecycle.compose.LifecycleEventEffect import androidx.navigation.NavController import com.example.notimanager.presentation.stateholder.viewmodel.NotificationTitlePriorityViewModel import com.example.notimanager.presentation.stateholder.viewmodel.NotificationTitleViewModel +import com.example.notimanager.presentation.ui.component.NotificationAppListView import com.example.notimanager.presentation.ui.component.NotificationTitleListView import com.example.notimanager.presentation.ui.component.TitleTopAppBar import kotlinx.coroutines.delay @@ -36,6 +39,12 @@ fun TitleScreen(navController: NavController, appName: String = "", title:String viewModel.setArgs(appName, title) priorityViewModel.setArgs(appName, title) } + + LifecycleEventEffect(Lifecycle.Event.ON_RESUME) { + viewModel.loadNotificationTitles() + priorityViewModel.loadNotificationTitles() + } + Scaffold( topBar = { TitleTopAppBar(title = title, onBackClick = { navController.popBackStack() }) @@ -45,6 +54,7 @@ fun TitleScreen(navController: NavController, appName: String = "", title:String modifier = Modifier.padding(innerPadding), thickness = 0.2.dp ) + PullToRefreshBox( isRefreshing = isRefreshing, onRefresh = { @@ -52,12 +62,11 @@ fun TitleScreen(navController: NavController, appName: String = "", title:String viewModel.loadNotificationTitles() priorityViewModel.loadNotificationTitles() coroutineScope.launch { - delay(2000) + delay(500) isRefreshing = false } }, - modifier = Modifier - .padding(innerPadding) + modifier = Modifier.padding(innerPadding) ) { NotificationTitleListView(navController, viewModel, priorityViewModel) } From 52c6c5262d28d7ed6c70e3fe0faeb04bff521c70 Mon Sep 17 00:00:00 2001 From: Richter3766 <97567615+Richter3766@users.noreply.github.com> Date: Fri, 28 Feb 2025 15:03:51 +0900 Subject: [PATCH 6/6] =?UTF-8?q?chore:=20=ED=83=80=EC=BC=93=20API=20?= =?UTF-8?q?=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 최신 API를 적극 활용할 수 있도록 target APi를 최신버전인 35로 설정 --- app/src/main/AndroidManifest.xml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index 0ba43a3..f7d40df 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -12,7 +12,8 @@ android:roundIcon="@mipmap/ic_launcher_round" android:supportsRtl="true" android:theme="@style/Theme.NotiManger" - tools:targetApi="31"> + android:enableOnBackInvokedCallback="true" + tools:targetApi="35">