Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[#9] 스크랩 기능을 추가한다 #10

Closed
wants to merge 22 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions .editorconfig
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
root = true

[*]

# ktlint specific settings for Compose
[*.kt]
ktlint_function_naming_ignore_when_annotated_with=Composable
7 changes: 7 additions & 0 deletions app/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ android {
compileSdk = Configuration.compileSdk

defaultConfig {
applicationId = Configuration.applicationId
minSdk = Configuration.minSdk
targetSdk = Configuration.targetSdk
versionCode = Configuration.versionCode
Expand Down Expand Up @@ -46,6 +47,12 @@ dependencies {
implementation(projects.core.commonUi)

implementation(projects.feature.main)
implementation(projects.feature.mainNavGraph)
implementation(projects.feature.scrap)
implementation(projects.feature.topic)
implementation(projects.feature.webview)

implementation(projects.core.repo.scrap.impl)

implementation(libs.androidx.appcompat)
}
1 change: 1 addition & 0 deletions app/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="org.bmsk.lifemash"
xmlns:tools="http://schemas.android.com/tools">

<uses-permission android:name="android.permission.INTERNET" />
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
import gradle.kotlin.dsl.accessors._285dcef16d8875fee0ec91e18e07daf9.implementation
import org.bmsk.lifemash.configureHiltAndroid
import org.bmsk.lifemash.configureKotestAndroid
import org.bmsk.lifemash.configureKotlinAndroid
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
import org.bmsk.lifemash.configureCoroutineAndroid
import org.bmsk.lifemash.configureHiltAndroid
import org.bmsk.lifemash.configureKotest
import org.bmsk.lifemash.configureKotlinAndroid

plugins {
id("com.android.library")
id("lifemash.verify.detekt")
}

configureKotlinAndroid()
configureKotest()
configureCoroutineAndroid()
Original file line number Diff line number Diff line change
Expand Up @@ -4,15 +4,15 @@ import org.gradle.api.Project
import org.gradle.kotlin.dsl.dependencies

internal fun Project.configureComposeAndroid() {
with(plugins) {
apply("org.jetbrains.kotlin.plugin.compose")
}

val libs = extensions.libs
androidExtension.apply {
buildFeatures {
compose = true
}
composeOptions {
kotlinCompilerExtensionVersion =
libs.findVersion("androidxComposeCompiler").get().toString()
}

dependencies {
val bom = libs.findLibrary("androidx-compose-bom").get()
Expand Down
13 changes: 8 additions & 5 deletions build-logic/src/main/kotlin/org/bmsk/lifemash/KotlinAndroid.kt
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import org.gradle.api.Project
import org.gradle.kotlin.dsl.dependencies
import org.gradle.kotlin.dsl.provideDelegate
import org.gradle.kotlin.dsl.withType
import org.jetbrains.kotlin.gradle.dsl.JvmTarget
import org.jetbrains.kotlin.gradle.tasks.KotlinCompile

/**
Expand Down Expand Up @@ -52,14 +53,16 @@ internal fun Project.configureKotlinAndroid() {

internal fun Project.configureKotlin() {
tasks.withType<KotlinCompile>().configureEach {
kotlinOptions {
jvmTarget = JavaVersion.VERSION_17.toString()
compilerOptions {
jvmTarget.set(JvmTarget.JVM_17)
// Treat all Kotlin warnings as errors (disabled by default)
// Override by setting warningsAsErrors=true in your ~/.gradle/gradle.properties
val warningsAsErrors: String? by project
allWarningsAsErrors = warningsAsErrors.toBoolean()
freeCompilerArgs = freeCompilerArgs + listOf(
"-opt-in=kotlin.RequiresOptIn",
allWarningsAsErrors.set(warningsAsErrors.toBoolean())
freeCompilerArgs.set(
freeCompilerArgs.get() + listOf(
"-opt-in=kotlin.RequiresOptIn",
)
)
}
}
Expand Down
2 changes: 2 additions & 0 deletions build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@ plugins {
alias(libs.plugins.kotlin.serialization) apply false
alias(libs.plugins.hilt) apply false
alias(libs.plugins.verify.detekt) apply false
alias(libs.plugins.ksp) apply false
alias(libs.plugins.compose.compiler) apply false
}

apply {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
package org.bmsk.buildsrc

object Configuration {
const val applicationId = "org.bmsk.lifemash_newsapp"
const val applicationId = "org.bmsk.lifemash"
const val compileSdk = 34
const val targetSdk = 34
const val minSdk = 28
Expand Down
Original file line number Diff line number Diff line change
@@ -1,14 +1,16 @@
package org.bmsk.lifemash.core.data

import org.bmsk.lifemash.core.model.DateParser
import org.bmsk.lifemash.core.model.NewsModel
import org.bmsk.lifemash.core.network.model.NewsItem
import java.util.Date

internal fun List<NewsItem>.asDomain(): List<NewsModel> {
return this.map {
NewsModel(
title = it.title ?: "",
link = it.link ?: "",
pubDate = it.pubDate?.let { date -> DateParser.parseDate(date) } ?: "",
pubDate = it.pubDate?.let(DateParser::parseDate) ?: Date(),
imageUrl = null,
)
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
package org.bmsk.lifemash.core.designsystem.effect

import androidx.compose.foundation.clickable
import androidx.compose.foundation.interaction.MutableInteractionSource
import androidx.compose.runtime.Composable
import androidx.compose.runtime.remember
import androidx.compose.ui.Modifier
import androidx.compose.ui.composed

@Composable
fun Modifier.noRippleClickable(onClick: () -> Unit): Modifier = this.clickable(
interactionSource = remember { MutableInteractionSource() },
indication = null,
onClick = onClick,
)

5 changes: 5 additions & 0 deletions core/model/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -6,3 +6,8 @@ java {
sourceCompatibility = JavaVersion.VERSION_17
targetCompatibility = JavaVersion.VERSION_17
}

dependencies {
// test
testImplementation(libs.junit)
}
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package org.bmsk.lifemash.core.data
package org.bmsk.lifemash.core.model

import java.text.SimpleDateFormat
import java.util.Date
Expand All @@ -7,14 +7,15 @@ import java.util.TimeZone

object DateParser {

fun parseDate(input: String): String {
fun parseDate(input: String): Date {
val parser = SimpleDateFormat("EEE, dd MMM yyyy HH:mm:ss z", Locale.ENGLISH)
val date = parser.parse(input) as Date
return parser.parse(input) as Date
}

fun formatDate(date: Date): String {
val formatter = SimpleDateFormat("yyyy-MM-dd HH:mm:ss", Locale.KOREAN).apply {
timeZone = TimeZone.getTimeZone("Asia/Seoul")
}

return formatter.format(date)
}
}
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
package org.bmsk.lifemash.core.model

import java.util.Date

data class NewsModel(
val title: String,
val link: String,
val pubDate: String,
val pubDate: Date,
val imageUrl: String? = null,
)
Original file line number Diff line number Diff line change
@@ -1,20 +1,17 @@
package org.bmsk.lifemash.core.data
package org.bmsk.lifemash.core.model

import org.junit.Assert.assertEquals
import org.junit.Test
import org.junit.jupiter.api.Assertions.assertEquals
import org.mockito.Mock

class DateParserTest {
@Mock
val dateParser = DateParser

@Test
@Throws(Exception::class)
fun testDateFormat() {
// 서버로부터 받은 GMT 시간 문자열
val input = "Tue, 20 Jun 2023 02:57:43 GMT"

val output = dateParser.parseDate(input)
val output = DateParser.formatDate(DateParser.parseDate(input))

// 기대하는 결과값
val expected = "2023-06-20 11:57:43"
Expand Down
1 change: 0 additions & 1 deletion core/network/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,6 @@ dependencies {
implementation(libs.moshi)

kapt(libs.tikxml.processor)
implementation(libs.tikxml.core)
implementation(libs.tikxml.annotation)
implementation(libs.tikxml.retrofit)
}
9 changes: 9 additions & 0 deletions core/repo/scrap/api/build.gradle.kts
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
plugins {
id("lifemash.kotlin.library")
id("kotlinx-serialization")
}

dependencies {
implementation(projects.core.model)
implementation(libs.kotlinx.serialization.json)
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
package org.bmsk.lifemash.core.repo.scrap.api

import org.bmsk.lifemash.core.model.NewsModel
import java.util.Date

interface ScrapNewsRepository {
fun addNewsToDB(newsModel: NewsModel)

fun getNewsFromDB(): List<NewsModel>

fun deleteNewsFromDB(newsModel: NewsModel)

fun deleteAllNewsFromDB()

fun updateNewsFromDB(newsModel: NewsModel)

fun updateAllNewsFromDB(newsModels: List<NewsModel>)

fun getNewsByTitle(title: String): NewsModel?

fun getNewsByLink(link: String): NewsModel?

fun getNewsByPubDate(pubDate: Date): NewsModel?

fun getNewsByImageUrl(imageUrl: String): NewsModel?

fun getNewsByContent(content: String): NewsModel?
}
19 changes: 19 additions & 0 deletions core/repo/scrap/impl/build.gradle.kts
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
plugins {
id("lifemash.android.library")
id("lifemash.android.hilt")
id("kotlinx-serialization")
alias(libs.plugins.ksp)
}

android {
namespace = "org.bmsk.lifemash.core.repo.scrap"
}

dependencies {
implementation(projects.core.repo.scrap.api)
implementation(projects.core.model)

implementation(libs.androidx.room.ktx)
implementation(libs.androidx.room.runtime)
ksp(libs.androidx.room.compiler)
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
package org.bmsk.lifemash.core.repo.scrap.impl

import androidx.room.TypeConverter
import java.util.Date

internal class DateConverter {
@TypeConverter
fun fromTimestamp(value: Long): Date = Date(value)

@TypeConverter
fun dateToTimestamp(date: Date): Long = date.time
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
package org.bmsk.lifemash.core.repo.scrap.impl

import org.bmsk.lifemash.core.model.NewsModel
import org.bmsk.lifemash.core.repo.scrap.impl.entity.NewsEntity

fun NewsModel.toEntity(): NewsEntity = NewsEntity(
title = this.title,
link = this.link,
pubDate = this.pubDate,
imageUrl = this.imageUrl,
)

fun NewsEntity.toModel(): NewsModel = NewsModel(
title = this.title,
link = this.link,
pubDate = this.pubDate,
imageUrl = this.imageUrl,
)
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
package org.bmsk.lifemash.core.repo.scrap.impl

import org.bmsk.lifemash.core.model.NewsModel
import org.bmsk.lifemash.core.repo.scrap.api.ScrapNewsRepository
import org.bmsk.lifemash.core.repo.scrap.impl.dao.ScrapNewsDao
import org.bmsk.lifemash.core.repo.scrap.impl.entity.NewsEntity
import java.util.Date
import javax.inject.Inject

internal class ScrapNewsRepositoryImpl @Inject constructor(
private val scrapNewsDao: ScrapNewsDao,
) : ScrapNewsRepository {

override fun addNewsToDB(newsModel: NewsModel) {
scrapNewsDao.insertNews(newsModel.toEntity())
}

override fun getNewsFromDB(): List<NewsModel> = scrapNewsDao.getAllNews().map(NewsEntity::toModel)

override fun deleteNewsFromDB(newsModel: NewsModel) {
scrapNewsDao.deleteNews(newsModel.toEntity())
}

override fun deleteAllNewsFromDB() {
TODO("Not yet implemented")
}

override fun updateNewsFromDB(newsModel: NewsModel) {
scrapNewsDao.updateNews(newsModel.toEntity())
}

override fun updateAllNewsFromDB(newsModels: List<NewsModel>) {
TODO("Not yet implemented")
}

override fun getNewsByTitle(title: String): NewsModel? {
TODO("Not yet implemented")
}

override fun getNewsByLink(link: String): NewsModel? = scrapNewsDao.getNewsByLink(link)?.toModel()

override fun getNewsByPubDate(pubDate: Date): NewsModel? {
TODO("Not yet implemented")
}

override fun getNewsByImageUrl(imageUrl: String): NewsModel? {
TODO("Not yet implemented")
}

override fun getNewsByContent(content: String): NewsModel? {
TODO("Not yet implemented")
}
}
Loading
Loading