Skip to content

Commit

Permalink
Merge pull request #11 from AndroidStudy-bmsk/feat/9-scrap
Browse files Browse the repository at this point in the history
[#9] 스크랩 기능을 추가
  • Loading branch information
YiBeomSeok authored Jul 3, 2024
2 parents a728345 + 9403f7b commit 4f3cb80
Show file tree
Hide file tree
Showing 78 changed files with 1,750 additions and 413 deletions.
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,14 @@
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

@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,55 @@
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

0 comments on commit 4f3cb80

Please sign in to comment.