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

[feat] #174 market update alert #177

Open
wants to merge 9 commits into
base: develop
Choose a base branch
from
Open
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
2 changes: 2 additions & 0 deletions .github/workflows/android-pull-request-ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -26,10 +26,12 @@ jobs:
env:
BASE_URL: ${{ secrets.BASE_URL }}
KAKAO_NATIVE_KEY: ${{ secrets.KAKAO_NATIVE_KEY }}
AMPLITUDE_KEY: ${{ secrets.AMPLITUDE_KEY }}
run: |
echo base.url=\"$BASE_URL\" >> ./local.properties
echo kakao.native.key=\"$KAKAO_NATIVE_KEY\" >> ./local.properties
echo kakaoNativeKey=$KAKAO_NATIVE_KEY >> ./local.properties
echo amplitude.key=\"$AMPLITUDE_KEY\" >> ./local.properties

- name: Create Google Services JSON File
env:
Expand Down
1 change: 1 addition & 0 deletions app/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -58,4 +58,5 @@ dependencies {
testImplementation(libs.junit)
androidTestImplementation(libs.androidx.test.ext.junit)
androidTestImplementation(libs.espresso.core)
implementation(libs.amplitude.analytics)
}
1 change: 1 addition & 0 deletions app/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
<uses-permission
android:name="android.permission.POST_NOTIFICATIONS"
android:minSdkVersion="33" />
<uses-permission android:name="android.permission.READ_PHONE_STATE" />

<application
android:name=".LinkMindApp"
Expand Down
14 changes: 9 additions & 5 deletions app/src/main/java/org/sopt/linkmind/LinkMindApp.kt
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
package org.sopt.linkmind

import android.app.Application
import android.util.Log
import androidx.appcompat.app.AppCompatDelegate
import com.amplitude.android.Amplitude
import com.amplitude.android.Configuration
import com.kakao.sdk.common.KakaoSdk
import com.kakao.sdk.common.util.Utility
import dagger.hilt.android.HiltAndroidApp
import org.sopt.linkmind.BuildConfig.KAKAO_NATIVE_KEY
import timber.log.Timber
Expand All @@ -16,9 +16,13 @@ class LinkMindApp : Application() {
setTimber()
setDarkMode()
setKakaoSdk()

var keyHash = Utility.getKeyHash(this)
Log.e("ํ‚คํ•ด์‹œ", keyHash)
val amplitude = Amplitude(
Configuration(
apiKey = BuildConfig.AMPLITUDE_KEY,
context = applicationContext,
),
)
amplitude.track("Sign Up")
}

private fun setTimber() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,11 @@ internal fun Project.configureKotlinAndroid(
"KAKAO_NATIVE_KEY",
gradleLocalProperties(rootDir).getProperty("kakao.native.key")
)
buildConfigField(
"String",
"AMPLITUDE_KEY",
gradleLocalProperties(rootDir).getProperty("amplitude.key")
)
manifestPlaceholders["KAKAO_NATIVE_KEY"] = gradleLocalProperties(rootDir).getProperty("kakaoNativeKey")
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,13 +38,28 @@ interface SecurityDataStore {
@SetValue(KEY_FCM_ALLOWED)
suspend fun setFcmAllowed(boolean: Boolean)

@GetValue(KEY_POPUP_VISIBILITY)
fun flowPopupVisibility(): Flow<Boolean>

@SetValue(KEY_POPUP_VISIBILITY)
suspend fun setPopupVisibility(boolean: Boolean)

@GetValue(KEY_MARKET_UPDATE)
fun flowMarketUpdate(): Flow<Boolean>

@SetValue(KEY_MARKET_UPDATE)
suspend fun setMarketUpdate(boolean: Boolean)

@ClearValues
suspend fun clearAll()

companion object {
const val KEY_ACCESSTOKEN = "key-accesstoken"
const val KEY_REFRESHTOKEN = "key-refreshtoken"
const val KEY_DEVICETOKEN = "key-devicetoken"
const val KEY_AUTOLOGIN = "key-autologin"
const val KEY_FCM_ALLOWED = "key-fcm-allowed"
const val KEY_POPUP_VISIBILITY = "key-popup-dialog"
const val KEY_MARKET_UPDATE = "key-market-update"
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle">
<solid android:color="@color/neutrals_white" />
<corners android:radius="2dp" />
</shape>
5 changes: 5 additions & 0 deletions core/designsystem/src/main/res/values/strings.xml
Original file line number Diff line number Diff line change
Expand Up @@ -155,6 +155,11 @@
<string name="home_user_clip">๋‹˜์˜ ํด๋ฆฝ</string>
<string name="home_this_week_link">์ด์ฃผ์˜ ๋งํฌ</string>
<string name="home_this_week_recommend">์ด์ฃผ์˜ ์ถ”์ฒœ ์‚ฌ์ดํŠธ</string>
<string name="home_survey_title">1๋ถ„ ์„ค๋ฌธ์กฐ์‚ฌ ์ฐธ์—ฌํ•˜๊ณ \n์Šคํƒ€๋ฒ…์Šค ๊ธฐํ”„ํ‹ฐ์ฝ˜ ๋ฐ›๊ธฐ</string>
<string name="home_survey_subtitle">ํ† ์Šคํ„ฐ ์‚ฌ์šฉ ํ”ผ๋“œ๋ฐฑ์„ ๋‚จ๊ฒจ์ฃผ์‹œ๋ฉด\n์ถ”์ฒจ์„ ํ†ตํ•ด ๊ธฐํ”„ํ‹ฐ์ฝ˜์„ ๋“œ๋ ค์š”!</string>
<string name="home_survey_button">์ฐธ์—ฌํ•˜๊ธฐ</string>
<string name="home_survey_skip"><u>์ผ์ฃผ์ผ๊ฐ„ ๋ณด์ง€ ์•Š๊ธฐ</u></string>


<!-- error -->
<string name="error_clip_length">ํด๋ฆฝ์˜ ์ด๋ฆ„์€ ์ตœ๋Œ€ 15์ž๊นŒ์ง€ ์ž…๋ ฅ ๊ฐ€๋Šฅํ•ด์š”</string>
Expand Down
9 changes: 9 additions & 0 deletions core/model/src/main/java/org/sopt/model/home/PopupInfo.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
package org.sopt.model.home

data class PopupInfo(
val popupId: Int,
val popupImage: String,
val popupActiveStartDate: String,
val popupActiveEndDate: String,
val popupLinkUrl: String,
)
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
package org.sopt.model.home

data class PopupInvisible(
val popupId: Int,
val popupHideUntil: String,
)
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
package org.sopt.remote.home.api

import org.sopt.network.model.response.base.BaseResponse
import org.sopt.remote.home.request.RequestPopupInvisibleDto
import org.sopt.remote.home.response.ResponsePopupInfoDto
import org.sopt.remote.home.response.ResponsePopupInvisibleDto
import retrofit2.http.Body
import retrofit2.http.GET
import retrofit2.http.PATCH

interface PopupService {
companion object {
const val API = "api"
const val V2 = "v2"
const val POPUP = "popup"
}

@PATCH("/$API/$V2/$POPUP")
suspend fun patchPopupInvisible(
@Body requestPopupInvisibleDto: RequestPopupInvisibleDto,
): BaseResponse<ResponsePopupInvisibleDto>

@GET("/$API/$V2/$POPUP")
suspend fun getPopupInfo(): BaseResponse<ResponsePopupInfoDto>
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
package org.sopt.remote.home.datasource

import org.sopt.home.datasource.RemotePopupDataSource
import org.sopt.model.home.PopupInfo
import org.sopt.model.home.PopupInvisible
import org.sopt.remote.home.api.PopupService
import org.sopt.remote.home.request.RequestPopupInvisibleDto
import org.sopt.remote.home.response.toCoreModel
import javax.inject.Inject

class RemotePopupDatasourceImpl @Inject constructor(
private val popupService: PopupService,
) : RemotePopupDataSource {
override suspend fun patchPopupInvisible(popupId: Long, hideDate: Long): PopupInvisible =
popupService.patchPopupInvisible(RequestPopupInvisibleDto(popupId, hideDate)).data!!.toCoreModel()

override suspend fun getPopupInfo(): List<PopupInfo> =
popupService.getPopupInfo().data!!.popupList.map { it.toCoreModel() }
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,9 @@ import dagger.Module
import dagger.hilt.InstallIn
import dagger.hilt.components.SingletonComponent
import org.sopt.home.datasource.RemoteHomeDataSource
import org.sopt.home.datasource.RemotePopupDataSource
import org.sopt.remote.home.datasource.RemoteHomeDataSourceImpl
import org.sopt.remote.home.datasource.RemotePopupDatasourceImpl
import javax.inject.Singleton

@Module
Expand All @@ -16,4 +18,10 @@ abstract class HomeDataSourceModule {
abstract fun bindRemoteHomeDatasource(
remoteHomeDataSourceImpl: RemoteHomeDataSourceImpl,
): RemoteHomeDataSource

@Singleton
@Binds
abstract fun bindRemotePopupDataSource(
remotePopupDataSourceImpl: RemotePopupDatasourceImpl,
): RemotePopupDataSource
}
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,10 @@ import dagger.hilt.InstallIn
import dagger.hilt.components.SingletonComponent
import org.sopt.network.di.AuthLinkMindRetrofit
import org.sopt.remote.home.api.HomeService
import org.sopt.remote.home.api.PopupService
import retrofit2.Retrofit
import javax.inject.Singleton

@Module
@InstallIn(SingletonComponent::class)
object HomeServiceModule {
Expand All @@ -16,4 +18,9 @@ object HomeServiceModule {
@Provides
fun provideHomeService(@AuthLinkMindRetrofit retrofit: Retrofit): HomeService =
retrofit.create(HomeService::class.java)

@Singleton
@Provides
fun providePopupService(@AuthLinkMindRetrofit retrofit: Retrofit): PopupService =
retrofit.create(PopupService::class.java)
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
package org.sopt.remote.home.request

import kotlinx.serialization.SerialName
import kotlinx.serialization.Serializable

@Serializable
data class RequestPopupInvisibleDto(
@SerialName("popupId")
val popupId: Long,
@SerialName("hideDate")
val hideDate: Long,
)
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
package org.sopt.remote.home.response

import kotlinx.serialization.SerialName
import kotlinx.serialization.Serializable
import org.sopt.model.home.PopupInfo

@Serializable
data class ResponsePopupInfoDto(
@SerialName("popupList")
val popupList: List<ResponsePopupInfo>,
)

@Serializable
data class ResponsePopupInfo(
@SerialName("id")
val id: Int,
@SerialName("image")
val image: String,
@SerialName("activeStartDate")
val activeStartDate: String,
@SerialName("activeEndDate")
val activeEndDate: String,
@SerialName("linkUrl")
val linkUrl: String,
)

internal fun ResponsePopupInfoDto.toCoreModel() = popupList.map {
it.toCoreModel()
}

internal fun ResponsePopupInfo.toCoreModel() = PopupInfo(
popupId = id,
popupImage = image,
popupActiveStartDate = activeStartDate,
popupActiveEndDate = activeEndDate,
popupLinkUrl = linkUrl,
)
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
package org.sopt.remote.home.response

import kotlinx.serialization.SerialName
import kotlinx.serialization.Serializable
import org.sopt.model.home.PopupInvisible

@Serializable
data class ResponsePopupInvisibleDto(
@SerialName("popupId")
val popupId: Int,
@SerialName("hideUntil")
val hideUntil: String,
)

internal fun ResponsePopupInvisibleDto.toCoreModel() = PopupInvisible(
popupId = popupId,
popupHideUntil = hideUntil,
)
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
package org.sopt.home.datasource

import org.sopt.model.home.PopupInfo
import org.sopt.model.home.PopupInvisible

interface RemotePopupDataSource {
suspend fun patchPopupInvisible(popupId: Long, hideDate: Long): PopupInvisible
suspend fun getPopupInfo(): List<PopupInfo>
}
8 changes: 8 additions & 0 deletions data/home/src/main/java/org/sopt/home/di/RepositoryModule.kt
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@ import dagger.hilt.InstallIn
import dagger.hilt.components.SingletonComponent
import org.sopt.home.repository.HomeRepoImpl
import org.sopt.home.repository.HomeRepository
import org.sopt.home.repository.PopupRepoImpl
import org.sopt.home.repository.PopupRepository
import javax.inject.Singleton

@Module
Expand All @@ -16,4 +18,10 @@ abstract class RepositoryModule {
abstract fun bindHomeRepository(
homeRepoImpl: HomeRepoImpl,
): HomeRepository

@Singleton
@Binds
abstract fun bindPopupRepository(
popupRepoImpl: PopupRepoImpl,
): PopupRepository
}
16 changes: 16 additions & 0 deletions data/home/src/main/java/org/sopt/home/repository/PopupRepoImpl.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
package org.sopt.home.repository

import org.sopt.home.datasource.RemotePopupDataSource
import org.sopt.model.home.PopupInfo
import org.sopt.model.home.PopupInvisible
import javax.inject.Inject

class PopupRepoImpl @Inject constructor(
private val remotePopupDataSource: RemotePopupDataSource,
) : PopupRepository {
override suspend fun patchPopupInvisible(popupId: Long, hideDate: Long): Result<PopupInvisible> =
runCatching { remotePopupDataSource.patchPopupInvisible(popupId, hideDate) }

override suspend fun getPopupInfo(): Result<List<PopupInfo>> =
runCatching { remotePopupDataSource.getPopupInfo() }
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
package org.sopt.home.repository

import org.sopt.model.home.PopupInfo
import org.sopt.model.home.PopupInvisible

interface PopupRepository {
suspend fun patchPopupInvisible(popupId: Long, hideDate: Long): Result<PopupInvisible>
suspend fun getPopupInfo(): Result<List<PopupInfo>>
}
11 changes: 11 additions & 0 deletions domain/home/src/main/java/org/sopt/home/usecase/GetPopupInfo.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
package org.sopt.home.usecase

import org.sopt.home.repository.PopupRepository
import org.sopt.model.home.PopupInfo
import javax.inject.Inject

class GetPopupInfo @Inject constructor(
private val popupRepository: PopupRepository,
) {
suspend operator fun invoke(): Result<List<PopupInfo>> = popupRepository.getPopupInfo()
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
package org.sopt.home.usecase

import org.sopt.home.repository.PopupRepository
import org.sopt.model.home.PopupInvisible
import javax.inject.Inject

class PatchPopupInvisible @Inject constructor(
private val popupRepository: PopupRepository,
) {
suspend operator fun invoke(popupId: Long, hideDate: Long): Result<PopupInvisible> =
popupRepository.patchPopupInvisible(popupId, hideDate)
}
2 changes: 2 additions & 0 deletions feature/home/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -18,4 +18,6 @@ dependencies {
implementation(libs.jsoup)
implementation(libs.orbit.core)
implementation(libs.orbit.viewmodel)
implementation(libs.google.play.core)
implementation(projects.core.datastore)
}
Loading
Loading