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

πŸ”€ :: (#184) 1.2.0 μΆœμ‹œ #185

Merged
merged 29 commits into from
Sep 5, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
29 commits
Select commit Hold shift + click to select a range
2389f93
:recycle: :: interceptor 둜직 μˆ˜μ •
ImGaram Sep 1, 2023
1a1da5c
:sparkles: :: format pattern λ³€κ²½
ImGaram Sep 2, 2023
bb3d116
:fire: :: accountIdx 제거
ImGaram Sep 2, 2023
dec961d
:recycle: :: splash 둜직 μˆ˜μ •
ImGaram Sep 2, 2023
01dca1d
:recycle: :: view model ν•¨μˆ˜ ν˜•μ‹ λ³€κ²½
ImGaram Sep 2, 2023
2af6267
:recycle: :: splashμ—μ„œ profile data κ°€μ Έμ™€μ„œ μ΄μš©ν•˜λŠ” 둜직 μΆ”κ°€
ImGaram Sep 2, 2023
152c5a2
Merge pull request #177 from team-haribo/feature/176_splash_fix
ImGaram Sep 3, 2023
917e1fe
:heavy_plus_sign: :: firebase 라이브러리 μΆ”κ°€
ImGaram Sep 3, 2023
5baef88
:sparkles: :: goms notification message service 생성
ImGaram Sep 3, 2023
873110b
:sparkles: :: firebase message service μΆ”κ°€
ImGaram Sep 3, 2023
fb0d469
:sparkles: :: notification api service 생성
ImGaram Sep 3, 2023
857699a
:sparkles: :: notification api data source 생성
ImGaram Sep 3, 2023
0561b9c
:sparkles: :: notification api repository 생성
ImGaram Sep 3, 2023
b70d776
:sparkles: :: notification api use case 생성
ImGaram Sep 3, 2023
003a4d9
:sparkles: :: notification api view model 생성
ImGaram Sep 3, 2023
3dd028b
:sparkles: :: module에 notification api μΆ”κ°€
ImGaram Sep 3, 2023
c1b036b
:sparkles: :: notification μ΄ˆκΈ°ν™” 둜직 생성
ImGaram Sep 3, 2023
0f2b884
Merge pull request #179 from team-haribo/feature/178_push_notification
ImGaram Sep 3, 2023
e9b27fc
:fire: :: toast μ‚­μ œ
ImGaram Sep 4, 2023
a53dcaf
:recycle: :: interceptor 쑰건 url, parsePattern μˆ˜μ •
ImGaram Sep 4, 2023
dee312b
:sparkles: :: notification permission μΆ”κ°€
ImGaram Sep 4, 2023
02dd166
:arrow_up: :: firebase 버전 μ—…κ·Έλ ˆμ΄λ“œ
ImGaram Sep 4, 2023
ddc54f0
:sparkles: :: notification κΆŒν•œ μš”μ²­ κ΅¬ν˜„
ImGaram Sep 4, 2023
55199bd
:recycle: :: camera κΆŒν•œ denied λ˜μ—ˆμ„ λ•Œ text λ³€κ²½
ImGaram Sep 4, 2023
825c0d7
Merge pull request #181 from team-haribo/feature/180_notification_per…
ImGaram Sep 4, 2023
c3fc625
:heavy_plus_sign: :: in app updates dependency μΆ”κ°€
ImGaram Sep 4, 2023
aa3a9e3
:sparkles: :: μ•± μ—…λ°μ΄νŠΈ ν™”λ©΄ λ„μš°λŠ” κΈ°λŠ₯ κ΅¬ν˜„
ImGaram Sep 4, 2023
9307cd2
Merge pull request #183 from team-haribo/feature/182_in_app_update
ImGaram Sep 4, 2023
35308c0
:rocket: :: 1.2.0 μΆœμ‹œ
ImGaram Sep 5, 2023
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: 1 addition & 1 deletion .idea/compiler.xml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion .idea/gradle.xml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

6 changes: 4 additions & 2 deletions buildSrc/src/main/java/Dependency.kt
Original file line number Diff line number Diff line change
Expand Up @@ -65,8 +65,10 @@ object Dependency {

object Google {
const val MATERIAL = "com.google.android.material:material:${Versions.Material}"
const val FIREBASE_BOM = "com.google.firebase:firebase-bom:${Versions.FIREBASE_BOM}"
const val FIREBASE_ANALYTICS = "com.google.firebase:firebase-analytics-ktx"
const val FIREBASE_BOM = "com.google.firebase:firebase-bom:${Versions.FirebaseBom}"
const val FIREBASE_ANALYTICS = "com.google.firebase:firebase-analytics-ktx:${Versions.FirebaseAnalytics}"
const val FIREBASE_MESSAGING = "com.google.firebase:firebase-messaging-ktx:${Versions.FirebaseMessaging}"
const val IN_APP_UPDATE = "com.google.android.play:core-ktx:${Versions.InAppUpdate}"
}

object Test {
Expand Down
6 changes: 5 additions & 1 deletion buildSrc/src/main/java/Versions.kt
Original file line number Diff line number Diff line change
Expand Up @@ -44,5 +44,9 @@ object Versions {
const val Lifecycle = "2.3.1"
const val LifecycleRuntime = "2.5.1"

const val FIREBASE_BOM = "32.0.0"
const val FirebaseBom = "32.2.3"
const val FirebaseAnalytics = "21.3.0"
const val FirebaseMessaging = "23.2.1"

const val InAppUpdate = "1.8.1"
}
12 changes: 12 additions & 0 deletions data/src/main/java/com/goms/data/api/NotificationApi.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
package com.goms.data.api

import retrofit2.Response
import retrofit2.http.POST
import retrofit2.http.Path

interface NotificationApi {
@POST("notification/token/{deviceToken}")
suspend fun setNotification(
@Path("deviceToken") deviceToken: String
): Response<Unit>
}
Original file line number Diff line number Diff line change
Expand Up @@ -21,38 +21,21 @@ class LoginInterceptor @Inject constructor(
override fun intercept(chain: Interceptor.Chain): Response {
val request = chain.request()

// 토큰 κ°±μ‹  μš”μ²­μΈμ§€, 둜그인 μš”μ²­μΈμ§€ 확인해 λ”°λ‘œ λ¦¬ν„΄ν•œλ‹€.
if ("/api/v1/auth" == request.url.encodedPath && "PATCH" == request.method)
return chain.proceed(request)
if ("/api/v1/auth/signin" == request.url.encodedPath && "POST" == request.method)
return chain.proceed(request)

val currentTime = LocalDateTime.now()
val parsePattern = DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH-mm-ss")
val parsePattern = DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm:ss")
val accessTokenExp = authTokenDataSource.getAccessTokenExp()
val refreshTokenExp = authTokenDataSource.getRefreshTokenExp()
val accessTokenExpireDate = LocalDateTime.parse(accessTokenExp, parsePattern)
val refreshTokenExpireDate = LocalDateTime.parse(refreshTokenExp, parsePattern)

if (currentTime.isAfter(refreshTokenExpireDate)) throw NeedLoginException()
if (currentTime.isAfter(accessTokenExpireDate)) {
val currentRefreshToken = authTokenDataSource.getRefreshToken()
val refreshRequest = chain.request().newBuilder()
.url(BuildConfig.BASE_URL+"auth")
.addHeader("refreshToken", "Bearer $currentRefreshToken")
.patch("".toRequestBody(null))
.build()
val refreshResponse = chain.proceed(refreshRequest)
if (refreshResponse.isSuccessful) {
val jsonParser = JsonParser()
val token = jsonParser.parse(refreshResponse.body?.string()) as JsonObject
authTokenDataSource.setToken(
accessToken = token["accessToken"].toString().deleteDot(),
refreshToken = token["refreshToken"].toString().deleteDot(),
accessTokenExp = token["accessTokenExp"].toString().deleteDot(),
refreshTokenExp = token["refreshTokenExp"].toString().deleteDot()
)
} else throw NeedLoginException()
tokenRefresh(chain)
}

// 이 뢀뢄이 κΈ°μ‘΄ μš”μ²­μ— token headerλ₯Ό λΆ™μ—¬ return ν•˜λŠ” κ³³
Expand All @@ -64,6 +47,26 @@ class LoginInterceptor @Inject constructor(
)
}

private fun tokenRefresh(chain: Interceptor.Chain) {
val currentRefreshToken = authTokenDataSource.getRefreshToken()
val refreshRequest = chain.request().newBuilder()
.url(BuildConfig.BASE_URL+"auth")
.addHeader("refreshToken", "Bearer $currentRefreshToken")
.patch("".toRequestBody(null))
.build()
val refreshResponse = chain.proceed(refreshRequest)
if (refreshResponse.isSuccessful) {
val jsonParser = JsonParser()
val token = jsonParser.parse(refreshResponse.body?.string()) as JsonObject
authTokenDataSource.setToken(
accessToken = token["accessToken"].toString().deleteDot(),
refreshToken = token["refreshToken"].toString().deleteDot(),
accessTokenExp = token["accessTokenExp"].toString().deleteDot(),
refreshTokenExp = token["refreshTokenExp"].toString().deleteDot()
)
} else throw NeedLoginException()
}

private fun String.deleteDot(): String {
return this.substring(1, this.length-1)
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
package com.goms.data.datasource.notification

import kotlinx.coroutines.flow.Flow
import retrofit2.Response

interface NotificationDataSource {
suspend fun setNotification(deviceToken: String): Flow<Response<Unit>>
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
package com.goms.data.datasource.notification

import com.goms.data.api.NotificationApi
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.flow
import retrofit2.Response
import javax.inject.Inject

class NotificationDataSourceImpl @Inject constructor(
private val notificationApi: NotificationApi
): NotificationDataSource {
override suspend fun setNotification(deviceToken: String): Flow<Response<Unit>> {
return flow {
emit(notificationApi.setNotification(deviceToken))
}
}
}
1 change: 0 additions & 1 deletion data/src/main/java/com/goms/data/mapper/ProfileMapper.kt
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@ import com.goms.domain.data.profile.ProfileResponseData
object ProfileMapper {
fun profileResponseToData(profileResponse: ProfileResponse): ProfileResponseData {
return ProfileResponseData(
accountIdx = profileResponse.accountIdx,
name = profileResponse.name,
studentNum = StudentInfoMapper.studentInfoToData(profileResponse.studentNum),
authority = profileResponse.authority,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,8 @@ package com.goms.data.model.profile

import com.goms.data.model.util.StudentInfo
import com.google.gson.annotations.SerializedName
import java.util.UUID

data class ProfileResponse(
@SerializedName("accountIdx") val accountIdx: UUID,
@SerializedName("name") val name: String,
@SerializedName("studentNum") val studentNum: StudentInfo,
@SerializedName("authority") val authority: String,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ class AuthRepositoryImpl @Inject constructor(
val currentTime = LocalDateTime.now()
val accessTokenExp = authTokenDataSource.getAccessTokenExp()
val refreshTokenExp = authTokenDataSource.getRefreshTokenExp()
val parsePattern = DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH-mm-ss")
val parsePattern = DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm:ss")
val refreshExpireDate = LocalDateTime.parse(refreshTokenExp, parsePattern)
val accessExpireDate = LocalDateTime.parse(accessTokenExp, parsePattern)

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
package com.goms.data.repository

import com.goms.data.datasource.notification.NotificationDataSource
import com.goms.domain.repository.NotificationRepository
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.flow
import retrofit2.Response
import javax.inject.Inject

class NotificationRepositoryImpl @Inject constructor(
private val notificationDataSource: NotificationDataSource
): NotificationRepository {
override suspend fun setNotification(deviceToken: String): Flow<Response<Unit>> {
return flow {
notificationDataSource.setNotification(deviceToken).collect {
emit(it)
}
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,8 @@ package com.goms.domain.data.profile

import com.goms.domain.data.util.StudentInfoData
import java.io.Serializable
import java.util.UUID

data class ProfileResponseData(
val accountIdx: UUID,
val name: String,
val studentNum: StudentInfoData,
val authority: String,
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
package com.goms.domain.repository

import kotlinx.coroutines.flow.Flow
import retrofit2.Response

interface NotificationRepository {
suspend fun setNotification(deviceToken: String): Flow<Response<Unit>>
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
package com.goms.domain.usecase.notification

import com.goms.domain.repository.NotificationRepository
import kotlinx.coroutines.flow.Flow
import retrofit2.Response
import javax.inject.Inject

class SetNotificationUseCase @Inject constructor(
private val notificationRepository: NotificationRepository
) {
suspend operator fun invoke(deviceToken: String): Flow<Response<Unit>> {
return notificationRepository.setNotification(deviceToken)
}
}
9 changes: 7 additions & 2 deletions presentation/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,8 @@ android {
applicationId = "com.goms.presentation"
minSdk = 26
targetSdk = 33
versionCode = 7
versionName = "1.1.1"
versionCode = 8
versionName = "1.2.0"

testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"

Expand Down Expand Up @@ -88,6 +88,9 @@ dependencies {
implementation(Dependency.Retrofit.OKHTTP)
implementation(Dependency.Retrofit.OKHTTP_LOGGING_INTERCEPTOR)

// in app update
implementation(Dependency.Google.IN_APP_UPDATE)

// compose
implementation(Dependency.Compose.ACTIVITY_COMPOSE)
implementation(Dependency.Compose.COMPOSE)
Expand Down Expand Up @@ -118,6 +121,8 @@ dependencies {
implementation(Dependency.AndroidX.SWIPE_REFRESH_LAYOUT)
implementation(Dependency.Libraries.SWIPE_REFRESH)

// firebase
implementation(platform(Dependency.Google.FIREBASE_BOM))
implementation(Dependency.Google.FIREBASE_ANALYTICS)
implementation(Dependency.Google.FIREBASE_MESSAGING)
}
10 changes: 9 additions & 1 deletion presentation/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@

<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.POST_NOTIFICATIONS"/>

<uses-feature
android:name="android.hardware.camera"
Expand Down Expand Up @@ -53,6 +54,13 @@
android:name=".view.main.MainActivity"
android:screenOrientation="portrait"
android:exported="true" />
</application>

<service
android:name=".utils.notification.GomsNotification"
android:exported="false">
<intent-filter>
<action android:name="com.google.firebase.MESSAGING_EVENT" />
</intent-filter>
</service>
</application>
</manifest>
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@ import com.goms.data.datasource.auth.AuthDataSource
import com.goms.data.datasource.auth.AuthDataSourceImpl
import com.goms.data.datasource.late.LateDataSource
import com.goms.data.datasource.late.LateDataSourceImpl
import com.goms.data.datasource.notification.NotificationDataSource
import com.goms.data.datasource.notification.NotificationDataSourceImpl
import com.goms.data.datasource.outing.OutingDataSource
import com.goms.data.datasource.outing.OutingDataSourceImpl
import com.goms.data.datasource.profile.ProfileDataSource
Expand Down Expand Up @@ -50,4 +52,9 @@ abstract class DataSourceModule {
abstract fun bindCouncilDataSource(
councilDataSourceImpl: CouncilDataSourceImpl
): CouncilDataSource

@Binds
abstract fun bindNotificationDataSource(
notificationDataSourceImpl: NotificationDataSourceImpl
): NotificationDataSource
}
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
package com.goms.presentation.di.module

import android.util.Log
import com.goms.data.api.AuthApi
import com.goms.data.api.CouncilApi
import com.goms.data.api.LateApi
import com.goms.data.api.NotificationApi
import com.goms.data.api.OutingApi
import com.goms.data.api.ProfileApi
import com.goms.data.api.interceptor.LoginInterceptor
Expand All @@ -13,6 +15,7 @@ import dagger.Provides
import dagger.hilt.InstallIn
import dagger.hilt.components.SingletonComponent
import okhttp3.OkHttpClient
import okhttp3.logging.HttpLoggingInterceptor
import retrofit2.Retrofit
import retrofit2.converter.gson.GsonConverterFactory
import java.util.concurrent.TimeUnit
Expand All @@ -24,16 +27,25 @@ object NetWorkModule {
@Provides
@Singleton
fun provideOkhttpClient(
httpLoggingInterceptor: HttpLoggingInterceptor,
loginInterceptor: LoginInterceptor
): OkHttpClient {
return OkHttpClient.Builder()
.addInterceptor(loginInterceptor)
.addInterceptor(httpLoggingInterceptor)
.connectTimeout(30, TimeUnit.SECONDS)
.readTimeout(30, TimeUnit.SECONDS)
.writeTimeout(30, TimeUnit.SECONDS)
.build()
}

@Provides
@Singleton
fun provideHttpLoggingInterceptor(): HttpLoggingInterceptor {
return HttpLoggingInterceptor { message -> Log.v("HTTP", message) }
.setLevel(HttpLoggingInterceptor.Level.BODY)
}

@Provides
@Singleton
fun provideGsonConverterFactory(): GsonConverterFactory {
Expand Down Expand Up @@ -86,4 +98,10 @@ object NetWorkModule {
fun provideCouncilService(retrofit: Retrofit): CouncilApi {
return retrofit.create(CouncilApi::class.java)
}

@Provides
@Singleton
fun provideNotificationApi(retrofit: Retrofit): NotificationApi {
return retrofit.create(NotificationApi::class.java)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,13 @@ package com.goms.presentation.di.module
import com.goms.data.repository.AuthRepositoryImpl
import com.goms.data.repository.CouncilRepositoryImpl
import com.goms.data.repository.LateRepositoryImpl
import com.goms.data.repository.NotificationRepositoryImpl
import com.goms.data.repository.OutingRepositoryImpl
import com.goms.data.repository.ProfileRepositoryImpl
import com.goms.domain.repository.AuthRepository
import com.goms.domain.repository.CouncilRepository
import com.goms.domain.repository.LateRepository
import com.goms.domain.repository.NotificationRepository
import com.goms.domain.repository.OutingRepository
import com.goms.domain.repository.ProfileRepository
import dagger.Binds
Expand Down Expand Up @@ -42,4 +44,9 @@ abstract class RepositoryModule {
abstract fun bindCouncilRepository(
councilRepositoryImpl: CouncilRepositoryImpl
): CouncilRepository

@Binds
abstract fun bindNotificationRepository(
notificationRepositoryImpl: NotificationRepositoryImpl
): NotificationRepository
}
Loading
Loading