From 0a77b27e720bd66989a93eff8954827db2b755e5 Mon Sep 17 00:00:00 2001 From: Richter3766 <97567615+Richter3766@users.noreply.github.com> Date: Tue, 25 Feb 2025 10:25:58 +0900 Subject: [PATCH 1/5] =?UTF-8?q?feat:=20=EB=A9=94=EC=9D=B8=20=ED=99=94?= =?UTF-8?q?=EB=A9=B4=20UI=20=EA=B0=9C=EC=84=A0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 아이콘 크기 조정 텍스트 크기 조정 아이콘 텍스트 간 간격 조정 --- .../presentation/ui/component/AppIconView.kt | 6 +- .../ui/component/NotificationAppListView.kt | 55 +++++++++++++++++-- .../presentation/ui/component/TopAppBar.kt | 34 ++++++++++++ .../presentation/ui/screen/MainScreen.kt | 11 +++- 4 files changed, 96 insertions(+), 10 deletions(-) create mode 100644 app/src/main/java/com/example/notimanager/presentation/ui/component/TopAppBar.kt diff --git a/app/src/main/java/com/example/notimanager/presentation/ui/component/AppIconView.kt b/app/src/main/java/com/example/notimanager/presentation/ui/component/AppIconView.kt index 7b9feb5..03594bd 100644 --- a/app/src/main/java/com/example/notimanager/presentation/ui/component/AppIconView.kt +++ b/app/src/main/java/com/example/notimanager/presentation/ui/component/AppIconView.kt @@ -14,14 +14,14 @@ fun AppIconView(appIcon: Bitmap?) { Image( bitmap = appIcon.asImageBitmap(), contentDescription = null, - modifier = Modifier.size(100.dp) + modifier = Modifier.size(50.dp) ) } else{ Image( - bitmap = Bitmap.createBitmap(100, 100, Bitmap.Config.ARGB_8888).asImageBitmap(), + bitmap = Bitmap.createBitmap(100, 10, Bitmap.Config.ARGB_8888).asImageBitmap(), contentDescription = null, - modifier = Modifier.size(100.dp) + modifier = Modifier.size(50.dp) ) } } \ No newline at end of file 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 6917ec0..4c37f74 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 @@ -2,20 +2,29 @@ package com.example.notimanager.presentation.ui.component import androidx.compose.foundation.clickable 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.fillMaxWidth import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.layout.width import androidx.compose.foundation.lazy.LazyColumn import androidx.compose.foundation.lazy.items import androidx.compose.foundation.text.BasicText import androidx.compose.material3.CircularProgressIndicator import androidx.compose.material3.MaterialTheme +import androidx.compose.material3.Text import androidx.compose.runtime.Composable import androidx.compose.runtime.getValue import androidx.compose.runtime.livedata.observeAsState import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier +import androidx.compose.ui.graphics.Color +import androidx.compose.ui.text.font.FontWeight +import androidx.compose.ui.text.style.TextOverflow +import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.unit.dp +import androidx.compose.ui.unit.max import androidx.hilt.navigation.compose.hiltViewModel import androidx.navigation.NavController import com.example.notimanager.common.objects.DateFormatter.formatTimestamp @@ -24,10 +33,13 @@ import com.example.notimanager.presentation.stateholder.state.NotificationAppSta import com.example.notimanager.presentation.stateholder.viewmodel.NotificationAppViewModel @Composable -fun NotificationAppListView(navController: NavController, viewModel: NotificationAppViewModel = hiltViewModel()) { +fun NotificationAppListView(navController: NavController, innerPadding: PaddingValues,viewModel: NotificationAppViewModel = hiltViewModel()) { val notificationAppState by viewModel.notificationAppState.observeAsState(NotificationAppState()) - Column { + Column( + Modifier.padding(innerPadding) + + ) { if (notificationAppState.isLoading) { CircularProgressIndicator(modifier = Modifier.padding(16.dp)) } else if (notificationAppState.error != null) { @@ -57,11 +69,42 @@ fun NotificationAppItemView(notification: NotificationApp, onClick: () -> Unit) verticalAlignment = Alignment.CenterVertically ) { AppIconView(notification.appIcon) + Spacer(modifier = Modifier.width(8.dp)) Column { - BasicText(text = notification.appName, style = MaterialTheme.typography.headlineMedium) - BasicText(text = notification.title, style = MaterialTheme.typography.bodyLarge) - BasicText(text = notification.content, style = MaterialTheme.typography.bodyMedium) - BasicText(text = formatTimestamp(notification.timestamp), style = MaterialTheme.typography.bodyMedium) + Text( + text = notification.appName, + style = MaterialTheme.typography.titleMedium.copy(fontWeight = FontWeight.Bold)) + Text( + text = notification.title, + style = MaterialTheme.typography.bodySmall.copy(fontWeight = FontWeight.Bold) + + ) + Text( + text = notification.content, + style = MaterialTheme.typography.bodySmall, + maxLines = 1, + overflow = TextOverflow.Ellipsis + ) + Text( + text = formatTimestamp(notification.timestamp), + style = MaterialTheme.typography.labelSmall, + color = Color.LightGray + ) } } +} + +@Composable +@Preview +fun PreviewNotificationAppItemView(){ + MaterialTheme{ + NotificationAppItemView( + notification = NotificationApp( + appName = "appName", + title = "title", + content = "content", + timestamp = 1234567890, + appIcon = null + ), onClick = {}) + } } \ No newline at end of file diff --git a/app/src/main/java/com/example/notimanager/presentation/ui/component/TopAppBar.kt b/app/src/main/java/com/example/notimanager/presentation/ui/component/TopAppBar.kt new file mode 100644 index 0000000..caae609 --- /dev/null +++ b/app/src/main/java/com/example/notimanager/presentation/ui/component/TopAppBar.kt @@ -0,0 +1,34 @@ +package com.example.notimanager.presentation.ui.component + +import androidx.compose.material.icons.Icons +import androidx.compose.material.icons.filled.MoreVert +import androidx.compose.material3.ExperimentalMaterial3Api +import androidx.compose.material3.Icon +import androidx.compose.material3.IconButton +import androidx.compose.material3.MaterialTheme +import androidx.compose.material3.Text +import androidx.compose.material3.TopAppBar +import androidx.compose.runtime.Composable +import androidx.compose.ui.tooling.preview.Preview + +@OptIn(ExperimentalMaterial3Api::class) +@Composable +fun MainTopAppBar(){ + TopAppBar( + title = { + Text(text = "Notification Manager") + }, + actions = { + IconButton(onClick = { /* TODO: 클릭 이벤트 처리 */ }) { + Icon(Icons.Filled.MoreVert, contentDescription = "더 보기") + } + }) +} + +@Preview(backgroundColor = 1) +@Composable +fun PreviewMainTopAppBar(){ + MaterialTheme{ + MainTopAppBar() + } +} \ No newline at end of file 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 2560a97..00f9c4c 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,12 +1,21 @@ package com.example.notimanager.presentation.ui.screen +import androidx.compose.material3.Scaffold import androidx.compose.runtime.Composable import androidx.navigation.NavController +import com.example.notimanager.presentation.ui.component.MainTopAppBar import com.example.notimanager.presentation.ui.component.NotificationAppListView import com.example.notimanager.presentation.ui.component.PermissionCheck @Composable fun MainScreen(navController: NavController){ + Scaffold( + topBar = { + MainTopAppBar() + } + ) { innerPadding -> + NotificationAppListView(navController, innerPadding) + } PermissionCheck() - NotificationAppListView(navController) + } \ No newline at end of file From f81bbbc09b1682e2f4d82fc26b9dbd14add0422c Mon Sep 17 00:00:00 2001 From: Richter3766 <97567615+Richter3766@users.noreply.github.com> Date: Tue, 25 Feb 2025 10:35:12 +0900 Subject: [PATCH 2/5] =?UTF-8?q?feat:=20=EC=95=B1=20=EC=A0=9C=EB=AA=A9=20?= =?UTF-8?q?=EB=A6=AC=EC=8A=A4=ED=8A=B8=20=ED=99=94=EB=A9=B4=20UI?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 메인화면과 같은 리스트 아이템 뷰 topbar 추가 --- .../ui/component/NotificationTitleListView.kt | 34 +++++++++++++++---- .../presentation/ui/component/TopAppBar.kt | 25 ++++++++++++++ .../presentation/ui/screen/TitleScreen.kt | 12 +++++-- 3 files changed, 62 insertions(+), 9 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 206c562..0209477 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 @@ -2,19 +2,25 @@ package com.example.notimanager.presentation.ui.component import androidx.compose.foundation.clickable 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.fillMaxWidth import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.layout.width import androidx.compose.foundation.lazy.LazyColumn import androidx.compose.foundation.lazy.items -import androidx.compose.foundation.text.BasicText import androidx.compose.material3.CircularProgressIndicator import androidx.compose.material3.MaterialTheme +import androidx.compose.material3.Text import androidx.compose.runtime.Composable import androidx.compose.runtime.getValue import androidx.compose.runtime.livedata.observeAsState import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier +import androidx.compose.ui.graphics.Color +import androidx.compose.ui.text.font.FontWeight +import androidx.compose.ui.text.style.TextOverflow import androidx.compose.ui.unit.dp import androidx.navigation.NavController import com.example.notimanager.common.objects.DateFormatter.formatTimestamp @@ -23,10 +29,12 @@ import com.example.notimanager.presentation.stateholder.state.NotificationTitleS import com.example.notimanager.presentation.stateholder.viewmodel.NotificationTitleViewModel @Composable -fun NotificationTitleListView(navController: NavController, viewModel: NotificationTitleViewModel) { +fun NotificationTitleListView(navController: NavController, innerPadding: PaddingValues,viewModel: NotificationTitleViewModel) { val notificationTitleState by viewModel.notificationTitleState.observeAsState(NotificationTitleState()) - Column { + Column ( + Modifier.padding(innerPadding) + ){ if (notificationTitleState.isLoading) { CircularProgressIndicator(modifier = Modifier.padding(16.dp)) } else if (notificationTitleState.error != null) { @@ -55,10 +63,24 @@ fun NotificationTitleItemView(notification: NotificationTitle, onClick: () -> Un verticalAlignment = Alignment.CenterVertically ) { AppIconView(notification.notificationIcon) + Spacer(modifier = Modifier.width(8.dp)) Column { - BasicText(text = notification.title, style = MaterialTheme.typography.bodyLarge) - BasicText(text = notification.content, style = MaterialTheme.typography.bodyMedium) - BasicText(text = formatTimestamp(notification.timestamp), style = MaterialTheme.typography.bodyMedium) + Text( + text = notification.title, + style = MaterialTheme.typography.bodySmall.copy(fontWeight = FontWeight.Bold) + + ) + Text( + text = notification.content, + style = MaterialTheme.typography.bodySmall, + maxLines = 1, + overflow = TextOverflow.Ellipsis + ) + Text( + text = formatTimestamp(notification.timestamp), + style = MaterialTheme.typography.labelSmall, + color = Color.LightGray + ) } } } \ No newline at end of file diff --git a/app/src/main/java/com/example/notimanager/presentation/ui/component/TopAppBar.kt b/app/src/main/java/com/example/notimanager/presentation/ui/component/TopAppBar.kt index caae609..b6c18f9 100644 --- a/app/src/main/java/com/example/notimanager/presentation/ui/component/TopAppBar.kt +++ b/app/src/main/java/com/example/notimanager/presentation/ui/component/TopAppBar.kt @@ -1,6 +1,7 @@ package com.example.notimanager.presentation.ui.component import androidx.compose.material.icons.Icons +import androidx.compose.material.icons.automirrored.filled.ArrowBack import androidx.compose.material.icons.filled.MoreVert import androidx.compose.material3.ExperimentalMaterial3Api import androidx.compose.material3.Icon @@ -9,6 +10,7 @@ import androidx.compose.material3.MaterialTheme import androidx.compose.material3.Text import androidx.compose.material3.TopAppBar import androidx.compose.runtime.Composable +import androidx.compose.ui.text.style.TextOverflow import androidx.compose.ui.tooling.preview.Preview @OptIn(ExperimentalMaterial3Api::class) @@ -25,6 +27,29 @@ fun MainTopAppBar(){ }) } +@OptIn(ExperimentalMaterial3Api::class) +@Composable +fun TitleTopAppBar(title: String, onBackClick: () -> Unit){ + TopAppBar( + title = { + Text( + text = title, + maxLines = 1, + overflow = TextOverflow.Ellipsis + ) + }, + navigationIcon = { + IconButton(onClick = onBackClick) { + Icon(Icons.AutoMirrored.Filled.ArrowBack, contentDescription = "뒤로 가기") + } + }, + actions = { + IconButton(onClick = { /* TODO: 클릭 이벤트 처리 */ }) { + Icon(Icons.Filled.MoreVert, contentDescription = "더 보기") + } + }) +} + @Preview(backgroundColor = 1) @Composable fun PreviewMainTopAppBar(){ 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 b6ebde3..7b3a93c 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,11 +1,13 @@ package com.example.notimanager.presentation.ui.screen +import androidx.compose.material3.Scaffold import androidx.compose.runtime.Composable import androidx.compose.runtime.LaunchedEffect import androidx.hilt.navigation.compose.hiltViewModel import androidx.navigation.NavController import com.example.notimanager.presentation.stateholder.viewmodel.NotificationTitleViewModel import com.example.notimanager.presentation.ui.component.NotificationTitleListView +import com.example.notimanager.presentation.ui.component.TitleTopAppBar @Composable fun TitleScreen(navController: NavController, appName: String = "", title:String = ""){ @@ -14,7 +16,11 @@ fun TitleScreen(navController: NavController, appName: String = "", title:String LaunchedEffect(appName, title) { viewModel.setArgs(appName, title) } - - NotificationTitleListView(navController, viewModel) - + Scaffold( + topBar = { + TitleTopAppBar(title = title, onBackClick = { navController.popBackStack() }) + } + ) { innerPadding -> + NotificationTitleListView(navController, innerPadding, viewModel) + } } \ No newline at end of file From c4d4aae6c259309d60275fc83dbf0087aff36f7a Mon Sep 17 00:00:00 2001 From: Richter3766 <97567615+Richter3766@users.noreply.github.com> Date: Tue, 25 Feb 2025 10:40:16 +0900 Subject: [PATCH 3/5] =?UTF-8?q?feat:=20=EC=95=8C=EB=A6=BC=20=EB=A6=AC?= =?UTF-8?q?=EC=8A=A4=ED=8A=B8=20UI?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 뒤로 가기 구현으로 위해, navController를 인자로 넘겨줌. --- .../ui/component/NotificationListView.kt | 7 ++++-- .../presentation/ui/component/TopAppBar.kt | 23 +++++++++++++++++++ .../presentation/ui/navigation/AppNavHost.kt | 2 +- .../ui/screen/NotificationScreen.kt | 15 ++++++++---- 4 files changed, 40 insertions(+), 7 deletions(-) diff --git a/app/src/main/java/com/example/notimanager/presentation/ui/component/NotificationListView.kt b/app/src/main/java/com/example/notimanager/presentation/ui/component/NotificationListView.kt index 6a225d9..d18aa0d 100644 --- a/app/src/main/java/com/example/notimanager/presentation/ui/component/NotificationListView.kt +++ b/app/src/main/java/com/example/notimanager/presentation/ui/component/NotificationListView.kt @@ -2,6 +2,7 @@ package com.example.notimanager.presentation.ui.component import androidx.compose.foundation.clickable import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.PaddingValues import androidx.compose.foundation.layout.Row import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.padding @@ -23,10 +24,12 @@ import com.example.notimanager.presentation.stateholder.state.NotificationState import com.example.notimanager.presentation.stateholder.viewmodel.NotificationViewModel @Composable -fun NotificationListView(viewModel: NotificationViewModel) { +fun NotificationListView(innerPadding: PaddingValues, viewModel: NotificationViewModel) { val notificationState by viewModel.notificationState.observeAsState(NotificationState()) val context = LocalContext.current - Column { + Column( + Modifier.padding(innerPadding) + ) { if (notificationState.isLoading) { CircularProgressIndicator(modifier = Modifier.padding(16.dp)) } else if (notificationState.error != null) { diff --git a/app/src/main/java/com/example/notimanager/presentation/ui/component/TopAppBar.kt b/app/src/main/java/com/example/notimanager/presentation/ui/component/TopAppBar.kt index b6c18f9..7aba4bc 100644 --- a/app/src/main/java/com/example/notimanager/presentation/ui/component/TopAppBar.kt +++ b/app/src/main/java/com/example/notimanager/presentation/ui/component/TopAppBar.kt @@ -50,6 +50,29 @@ fun TitleTopAppBar(title: String, onBackClick: () -> Unit){ }) } +@OptIn(ExperimentalMaterial3Api::class) +@Composable +fun NotificationTopAppBar(title: String, onBackClick: () -> Unit){ + TopAppBar( + title = { + Text( + text = title, + maxLines = 1, + overflow = TextOverflow.Ellipsis + ) + }, + navigationIcon = { + IconButton(onClick = onBackClick) { + Icon(Icons.AutoMirrored.Filled.ArrowBack, contentDescription = "뒤로 가기") + } + }, + actions = { + IconButton(onClick = { /* TODO: 클릭 이벤트 처리 */ }) { + Icon(Icons.Filled.MoreVert, contentDescription = "더 보기") + } + }) +} + @Preview(backgroundColor = 1) @Composable fun PreviewMainTopAppBar(){ diff --git a/app/src/main/java/com/example/notimanager/presentation/ui/navigation/AppNavHost.kt b/app/src/main/java/com/example/notimanager/presentation/ui/navigation/AppNavHost.kt index c997157..83e56d7 100644 --- a/app/src/main/java/com/example/notimanager/presentation/ui/navigation/AppNavHost.kt +++ b/app/src/main/java/com/example/notimanager/presentation/ui/navigation/AppNavHost.kt @@ -25,7 +25,7 @@ fun AppNavHost(navController: NavHostController) { composable("notificationScreen/{appName}/{title}") { backStackEntry -> val appName = backStackEntry.arguments?.getString("appName") val title = backStackEntry.arguments?.getString("title") - NotificationScreen(appName!!, title!!) + NotificationScreen(navController, appName!!, title!!) } } } \ No newline at end of file diff --git a/app/src/main/java/com/example/notimanager/presentation/ui/screen/NotificationScreen.kt b/app/src/main/java/com/example/notimanager/presentation/ui/screen/NotificationScreen.kt index 60d6847..3777763 100644 --- a/app/src/main/java/com/example/notimanager/presentation/ui/screen/NotificationScreen.kt +++ b/app/src/main/java/com/example/notimanager/presentation/ui/screen/NotificationScreen.kt @@ -1,19 +1,26 @@ package com.example.notimanager.presentation.ui.screen +import androidx.compose.material3.Scaffold import androidx.compose.runtime.Composable import androidx.compose.runtime.LaunchedEffect import androidx.hilt.navigation.compose.hiltViewModel +import androidx.navigation.NavController import com.example.notimanager.presentation.stateholder.viewmodel.NotificationViewModel import com.example.notimanager.presentation.ui.component.NotificationListView +import com.example.notimanager.presentation.ui.component.NotificationTopAppBar @Composable -fun NotificationScreen(appName: String = "", title:String = ""){ +fun NotificationScreen(navController: NavController, appName: String = "", title:String = ""){ val viewModel: NotificationViewModel = hiltViewModel() LaunchedEffect(appName, title) { viewModel.setArgs(appName, title) } - - NotificationListView(viewModel) - + Scaffold( + topBar = { + NotificationTopAppBar(title = title, onBackClick = { navController.popBackStack() }) + } + ) { innerPadding -> + NotificationListView(innerPadding, viewModel) + } } \ No newline at end of file From a08f7c5b699ba63be88e0943a3a10353d0bb98b3 Mon Sep 17 00:00:00 2001 From: Richter3766 <97567615+Richter3766@users.noreply.github.com> Date: Tue, 25 Feb 2025 10:41:24 +0900 Subject: [PATCH 4/5] =?UTF-8?q?feat:=20=EB=82=A0=EC=A7=9C=20=ED=91=9C?= =?UTF-8?q?=EC=8B=9C=20=ED=95=A8=EC=88=98=20=EA=B0=9C=EC=84=A0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 상대 시간, 절대 시간을 선택해 리턴하는 함수. 추후 SharedPreference를 통해 사용자가 원하는 포맷을 볼 수 있게 할 것. --- .../common/objects/DateFormatter.kt | 22 +++++++++++++++---- 1 file changed, 18 insertions(+), 4 deletions(-) diff --git a/app/src/main/java/com/example/notimanager/common/objects/DateFormatter.kt b/app/src/main/java/com/example/notimanager/common/objects/DateFormatter.kt index 1d95083..bafc1d9 100644 --- a/app/src/main/java/com/example/notimanager/common/objects/DateFormatter.kt +++ b/app/src/main/java/com/example/notimanager/common/objects/DateFormatter.kt @@ -5,13 +5,27 @@ import android.graphics.drawable.Drawable import android.icu.text.SimpleDateFormat import java.util.Date import java.util.Locale +import java.util.concurrent.TimeUnit object DateFormatter { - fun formatTimestamp(timestamp: Long): String { - val date = Date(timestamp) + fun formatTimestamp(timestamp: Long, format: String = "relative"): String { + return if (format == "relative") { + val currentTime = System.currentTimeMillis() + val timeDifference = currentTime - timestamp - val formatter = SimpleDateFormat("yyyy-MM-dd HH:mm:ss", Locale.getDefault()) - return formatter.format(date) + return when { + timeDifference < TimeUnit.SECONDS.toMillis(1) -> "방금" + timeDifference < TimeUnit.MINUTES.toMillis(1) -> "${timeDifference / 1000}초 전" + timeDifference < TimeUnit.HOURS.toMillis(1) -> "${timeDifference / TimeUnit.MINUTES.toMillis(1)}분 전" + timeDifference < TimeUnit.DAYS.toMillis(1) -> "${timeDifference / TimeUnit.HOURS.toMillis(1)}시간 전" + timeDifference < TimeUnit.DAYS.toMillis(7) -> "${timeDifference / TimeUnit.DAYS.toMillis(1)}일 전" + timeDifference < TimeUnit.DAYS.toMillis(30) -> "${timeDifference / TimeUnit.DAYS.toMillis(7)}주 전" + timeDifference < TimeUnit.DAYS.toMillis(365) -> "${timeDifference / TimeUnit.DAYS.toMillis(30)}달 전" + else -> "${timeDifference / TimeUnit.DAYS.toMillis(365)}년 전" + } + } else { + SimpleDateFormat("HH:mm dd.MM.yyyy", Locale.getDefault()).format(Date(timestamp)) + } } fun Drawable.toBitmap(): Bitmap { From c9c3fa6a4b3ded1564c9fa8326904cc3b1d59fe8 Mon Sep 17 00:00:00 2001 From: Richter3766 <97567615+Richter3766@users.noreply.github.com> Date: Tue, 25 Feb 2025 10:44:10 +0900 Subject: [PATCH 5/5] =?UTF-8?q?refactor:=20intent=20=EC=A7=81=EB=A0=AC?= =?UTF-8?q?=ED=99=94=20=ED=95=A8=EC=88=98=20=EC=9D=B4=EB=A6=84=20=EB=B3=80?= =?UTF-8?q?=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit PendingIntent가 아니라 Intent를 직렬화하므로 기능에 맞게 이름을 수정 불필요한 테스트 삭제. --- .../data/service/NotiListenerServiceTest.kt | 10 ++-- .../data/utils/PendingintentHelperTest.kt | 47 ------------------- .../notimanager/data/dto/NotificationDto.kt | 4 +- .../data/service/NotiListenerService.kt | 4 +- ...PendingIntentHelper.kt => IntentHelper.kt} | 8 ++-- 5 files changed, 12 insertions(+), 61 deletions(-) delete mode 100644 app/src/androidTest/java/com/example/notimanager/data/utils/PendingintentHelperTest.kt rename app/src/main/java/com/example/notimanager/data/utils/{PendingIntentHelper.kt => IntentHelper.kt} (75%) 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 99119d9..75d912b 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 @@ -15,7 +15,7 @@ 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.data.utils.NameGetter -import com.example.notimanager.data.utils.PendingIntentHelper +import com.example.notimanager.data.utils.IntentHelper import io.mockk.coEvery import io.mockk.coVerify import io.mockk.every @@ -41,13 +41,13 @@ class NotiListenerServiceTest { notiListenerService = NotiListenerService() notiListenerService.notificationRepository = notificationRepository mockkObject(NameGetter) - mockkObject(PendingIntentHelper) + mockkObject(IntentHelper) } @After fun tearDown() { unmockkObject(NameGetter) - unmockkObject(PendingIntentHelper) + unmockkObject(IntentHelper) } @Test @@ -85,7 +85,7 @@ class NotiListenerServiceTest { // Mock the PendingIntentHelper val intentArray = "MockedByteArray".toByteArray() - every { PendingIntentHelper.savePendingIntent(mockPendingIntent) } returns intentArray + every { IntentHelper.saveIntent(mockPendingIntent) } returns intentArray val expectedNotificationModel = NotificationModel( appName = "Test App", @@ -123,6 +123,6 @@ class NotiListenerServiceTest { coVerify { notificationRepository.insertAppIcon(appIconModel) } // Verify that PendingIntentHelper was called - verify { PendingIntentHelper.savePendingIntent(mockPendingIntent) } + verify { IntentHelper.saveIntent(mockPendingIntent) } } } \ No newline at end of file diff --git a/app/src/androidTest/java/com/example/notimanager/data/utils/PendingintentHelperTest.kt b/app/src/androidTest/java/com/example/notimanager/data/utils/PendingintentHelperTest.kt deleted file mode 100644 index e3ced31..0000000 --- a/app/src/androidTest/java/com/example/notimanager/data/utils/PendingintentHelperTest.kt +++ /dev/null @@ -1,47 +0,0 @@ -package com.example.notimanager.data.utils - -import android.app.PendingIntent -import android.content.Intent -import androidx.test.ext.junit.runners.AndroidJUnit4 -import androidx.test.platform.app.InstrumentationRegistry -import com.example.notimanager.presentation.ui.activity.MainActivity -import org.junit.Assert -import org.junit.Test -import org.junit.runner.RunWith - -@RunWith(AndroidJUnit4::class) -class PendingIntentHelperTest { - - @Test - fun testSaveAndRetrievePendingIntent() { - // 1. Create a Real PendingIntent - val context = InstrumentationRegistry.getInstrumentation().targetContext - val intent = Intent(context, MainActivity::class.java) - val originalPendingIntent = PendingIntent.getActivity( - context, - 0, - intent, - PendingIntent.FLAG_UPDATE_CURRENT or PendingIntent.FLAG_IMMUTABLE - ) - - // 2. Serialize - val byteArray = PendingIntentHelper.savePendingIntent(originalPendingIntent) - ?: throw AssertionError("Serialization failed: byteArray is null") - - // Check if serialization was successful - - // 3. Deserialize - val retrievedPendingIntent = PendingIntentHelper.retrievePendingIntent(byteArray) - ?: throw AssertionError("Deserialization failed: retrievedPendingIntent is null") - - // 4. Compare - // Check if deserialization was successful - - // Check if the retrieved PendingIntent is equal to the original one - Assert.assertEquals(originalPendingIntent.creatorPackage, retrievedPendingIntent.creatorPackage) - Assert.assertEquals(originalPendingIntent.isActivity, retrievedPendingIntent.isActivity) - Assert.assertEquals(originalPendingIntent.isBroadcast, retrievedPendingIntent.isBroadcast) - Assert.assertEquals(originalPendingIntent.isForegroundService, retrievedPendingIntent.isForegroundService) - Assert.assertEquals(originalPendingIntent.isService, retrievedPendingIntent.isService) - } -} \ No newline at end of file diff --git a/app/src/main/java/com/example/notimanager/data/dto/NotificationDto.kt b/app/src/main/java/com/example/notimanager/data/dto/NotificationDto.kt index 3164872..e802e84 100644 --- a/app/src/main/java/com/example/notimanager/data/dto/NotificationDto.kt +++ b/app/src/main/java/com/example/notimanager/data/dto/NotificationDto.kt @@ -1,7 +1,7 @@ package com.example.notimanager.data.dto import android.graphics.BitmapFactory -import com.example.notimanager.data.utils.PendingIntentHelper.retrievePendingIntent +import com.example.notimanager.data.utils.IntentHelper.retrieveIntent import com.example.notimanager.domain.model.Notification data class NotificationDto( @@ -17,7 +17,7 @@ data class NotificationDto( title = this.title, content = this.content, timestamp = this.timestamp, - intent = retrievePendingIntent(intentArray), + intent = retrieveIntent(intentArray), intentActive = this.intentActive, notificationIcon = BitmapFactory.decodeByteArray(iconBytes, 0, iconBytes.size) ) diff --git a/app/src/main/java/com/example/notimanager/data/service/NotiListenerService.kt b/app/src/main/java/com/example/notimanager/data/service/NotiListenerService.kt index c92e583..af4504c 100644 --- a/app/src/main/java/com/example/notimanager/data/service/NotiListenerService.kt +++ b/app/src/main/java/com/example/notimanager/data/service/NotiListenerService.kt @@ -10,7 +10,7 @@ import com.example.notimanager.data.model.NotificationModel import com.example.notimanager.data.repository.NotificationRepositoryInterface import com.example.notimanager.data.utils.AppIconGetter.convertByteArray import com.example.notimanager.data.utils.NameGetter -import com.example.notimanager.data.utils.PendingIntentHelper +import com.example.notimanager.data.utils.IntentHelper import dagger.hilt.android.AndroidEntryPoint import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.Dispatchers @@ -68,7 +68,7 @@ class NotiListenerService: NotificationListenerService() { notificationPackage: String?, ){ val intent = packageManager.getLaunchIntentForPackage(notificationPackage ?: "") - val intentArray = intent.let { pi -> PendingIntentHelper.savePendingIntent(pi!!) } + val intentArray = intent?.let { IntentHelper.saveIntent(it) } val notificationMetaModel = NotificationMetaModel( notificationId = id, diff --git a/app/src/main/java/com/example/notimanager/data/utils/PendingIntentHelper.kt b/app/src/main/java/com/example/notimanager/data/utils/IntentHelper.kt similarity index 75% rename from app/src/main/java/com/example/notimanager/data/utils/PendingIntentHelper.kt rename to app/src/main/java/com/example/notimanager/data/utils/IntentHelper.kt index 6c682c0..c97c833 100644 --- a/app/src/main/java/com/example/notimanager/data/utils/PendingIntentHelper.kt +++ b/app/src/main/java/com/example/notimanager/data/utils/IntentHelper.kt @@ -2,10 +2,9 @@ package com.example.notimanager.data.utils import android.content.Intent import android.os.Parcel -import android.util.Log -object PendingIntentHelper { - fun savePendingIntent(pendingIntent: Intent): ByteArray? { +object IntentHelper { + fun saveIntent(pendingIntent: Intent): ByteArray? { return try { val parcel = Parcel.obtain() @@ -14,12 +13,11 @@ object PendingIntentHelper { parcel.recycle() bytes } catch (e: Exception) { - Log.e(e.message, e.stackTraceToString()) null } } - fun retrievePendingIntent(byteArray: ByteArray): Intent? { + fun retrieveIntent(byteArray: ByteArray): Intent? { return try { val parcel = Parcel.obtain() parcel.unmarshall(byteArray, 0, byteArray.size)