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

#273 [feat] 앱 버전이 맞지 않을 경우, 업데이트 화면 뜨게 하기 #274

Merged
Merged
Show file tree
Hide file tree
Changes from 10 commits
Commits
Show all changes
32 commits
Select commit Hold shift + click to select a range
1537930
#273[feat]force_update xml 추가 및 string 업데이트
Nov 2, 2023
3cbbb2c
#273[feat] Version, VersionResponse data class 추가
Nov 2, 2023
9b119ca
#273[feat] ForceUpdateActivity 추가 및 버튼 클릭시, 플레이 스토어 화면으로 넘어가게 코드 작성
Nov 2, 2023
4cb7c5f
#273[feat] ForceUpdateActivity 추가
Nov 2, 2023
74ab40a
#273[feat] ForceUpdate 서버 연결 파일 추가(DataSource, Repository, Repository…
Nov 2, 2023
73fe39b
#273[feat] ForceUpdate Repo 모듈에 추가
Nov 2, 2023
78256da
#273[feat] SplashActivity에 dataObserver로 서버 통신 성공 시, 현재 appName과 비교 후…
Nov 2, 2023
c570cba
#273[feat] ktlint 정렬
Nov 2, 2023
a3f5a7c
#273[feat] ktlint 정렬
Nov 2, 2023
555f79a
#273[feat] ktlint 정렬
Nov 2, 2023
bdebaf0
#273[chore] Version domain entity 불필요한 변수 삭제
stellar-halo Nov 3, 2023
2034dc5
#273[chore] forceUpdateActivity에서 intent private으로 변경
stellar-halo Nov 3, 2023
c030123
#273[fix] splash 화면 전에 업데이트 뷰로 이동하던 코드 수정
stellar-halo Nov 5, 2023
2e6744f
#273[chore] viewModel 서버 통신 변수명 수정(isVersionStatus -> isForceUpdateSt…
stellar-halo Nov 5, 2023
10c6fb5
#273[chore] 데이터 바인딩에 따른 안쓰는 string 아이템 삭제
stellar-halo Nov 5, 2023
f631c2d
#273[fix] ForceUpdateActivity에 VERSION 엔티티 넘기기
stellar-halo Nov 5, 2023
96f0c6c
#273[fix] VERSION 엔티티로 변경
stellar-halo Nov 5, 2023
9abb91a
#273[add] viewModel 생성, view와 데이터 바인딩 연결, intent로 값 받아오기
stellar-halo Nov 5, 2023
24baa99
#273[fix] Parcelable 추가
stellar-halo Nov 5, 2023
4be191c
#273[fix] forceUpdateViewModel과 연결
stellar-halo Nov 5, 2023
33130f8
#273[add] versionDetail, versionState 엔티티 추가
stellar-halo Nov 5, 2023
a1a3192
#273[fix] viewModel로 버전 비교 로직 이전
stellar-halo Nov 5, 2023
44b9eac
#273[fix] update state 엔티티 추가로 when으로 변경하여 분기 처리
stellar-halo Nov 5, 2023
f3a3b98
#273[fix] private 처리
stellar-halo Nov 5, 2023
cb2bccd
#273[fix] vm -> viewModel 약어 교체
stellar-halo Nov 5, 2023
b633534
#273[fix] listener 함수명 구체적으로 변경 및 뷰모델 캡슐화
stellar-halo Nov 5, 2023
d4ac96c
#273[fix] checkUpdateVersion 리턴값 수정
stellar-halo Nov 5, 2023
6baa58e
#273[fix] checkUpdateVersion 반대로 되어있던 리턴값 수정
stellar-halo Nov 5, 2023
4877767
#273[fix] 스토어 링크 object로 추출, 함수명 자세하게 수정
stellar-halo Nov 5, 2023
855c21e
#273[fix] MutableLiveData, LiveData로 변경 및 그에 따른 null 처리 추가.
stellar-halo Nov 5, 2023
04c2dcd
#273[fix] String으로 스토어 링크 추출
stellar-halo Nov 5, 2023
35bb9fd
#273[fix] 불필요한 변수 삭제 및 observer 수정
stellar-halo Nov 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
3 changes: 3 additions & 0 deletions app/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,9 @@
android:theme="@style/Theme.PeekabookAOS"
android:usesCleartextTraffic="true"
tools:targetApi="31">
<activity android:name=".presentation.forceUpdate.ForceUpdateActivity"
android:exported="false"
android:screenOrientation="portrait"/>
<activity
android:name=".presentation.profileModify.ProfileModifyActivity"
android:exported="false"
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
package com.sopt.peekabookaos.data.entity.response

import com.sopt.peekabookaos.domain.entity.Version
import kotlinx.serialization.SerialName
import kotlinx.serialization.Serializable

@Serializable
data class VersionResponse(
val imageUrl: String,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

imageUrl이 현재 뷰에는 쓰이지 않는데 nullable 변수인지 서버한테 물어보면 좋을 것 같네요

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

꼼꼼한 핃백 감사합니다

val iosForceVersion: String,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

현재 우리는 iOSForceVersion이라는 변수가 필요하지 않습니다!
json에는 ignoreUnknownKey라는 키워드가 있는데 다음에 공부해서 리팩토링 해봅시다

val androidForceVersion: String,
@SerialName("text")
val versionText: String
) {
fun toVersion(): Version = Version(
imageUrl = this.imageUrl,
iosForceVersion = this.iosForceVersion,
androidForceVersion = this.androidForceVersion,
versionText = this.versionText
)
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
package com.sopt.peekabookaos.data.repository

import com.sopt.peekabookaos.data.source.remote.ForceUpdateDataSource
import com.sopt.peekabookaos.domain.entity.Version
import com.sopt.peekabookaos.domain.repository.ForceUpdateRepository
import javax.inject.Inject

class ForceUpdateRepositoryImpl @Inject constructor(
private val forceUpdateDataSource: ForceUpdateDataSource
) : ForceUpdateRepository {
override suspend fun getVersion(): Result<Version> =
kotlin.runCatching { forceUpdateDataSource.getVersion() }.map { response ->
requireNotNull(response.data).toVersion()
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
package com.sopt.peekabookaos.data.service

import com.sopt.peekabookaos.data.entity.BaseResponse
import com.sopt.peekabookaos.data.entity.response.VersionResponse
import retrofit2.http.GET

interface ForceUpdateService {
@GET("user/v1/version")
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

👍👍👍

suspend fun getVersion(): BaseResponse<VersionResponse>
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
package com.sopt.peekabookaos.data.source.remote

import com.sopt.peekabookaos.data.entity.BaseResponse
import com.sopt.peekabookaos.data.entity.response.VersionResponse
import com.sopt.peekabookaos.data.service.ForceUpdateService
import javax.inject.Inject

class ForceUpdateDataSource @Inject constructor(
private val forceUpdateService: ForceUpdateService
) {
suspend fun getVersion(): BaseResponse<VersionResponse> =
forceUpdateService.getVersion()
}
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import com.sopt.peekabookaos.data.repository.AuthRepositoryImpl
import com.sopt.peekabookaos.data.repository.BlockRepositoryImpl
import com.sopt.peekabookaos.data.repository.BookRepositoryImpl
import com.sopt.peekabookaos.data.repository.DetailRepositoryImpl
import com.sopt.peekabookaos.data.repository.ForceUpdateRepositoryImpl
import com.sopt.peekabookaos.data.repository.MyPageRepositoryImpl
import com.sopt.peekabookaos.data.repository.NaverRepositoryImpl
import com.sopt.peekabookaos.data.repository.NotificationRepositoryImpl
Expand All @@ -17,6 +18,7 @@ import com.sopt.peekabookaos.domain.repository.AuthRepository
import com.sopt.peekabookaos.domain.repository.BlockRepository
import com.sopt.peekabookaos.domain.repository.BookRepository
import com.sopt.peekabookaos.domain.repository.DetailRepository
import com.sopt.peekabookaos.domain.repository.ForceUpdateRepository
import com.sopt.peekabookaos.domain.repository.MyPageRepository
import com.sopt.peekabookaos.domain.repository.NaverRepository
import com.sopt.peekabookaos.domain.repository.NotificationRepository
Expand Down Expand Up @@ -112,4 +114,10 @@ abstract class RepositoryModule {
abstract fun bindToMyPageRepository(
myPageRepositoryImpl: MyPageRepositoryImpl
): MyPageRepository

@Binds
@Singleton
abstract fun bindToForceUpdateRepository(
forceUpdateRepositoryImpl: ForceUpdateRepositoryImpl
): ForceUpdateRepository
}
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import com.sopt.peekabookaos.data.service.AuthService
import com.sopt.peekabookaos.data.service.BlockService
import com.sopt.peekabookaos.data.service.BookService
import com.sopt.peekabookaos.data.service.DetailService
import com.sopt.peekabookaos.data.service.ForceUpdateService
import com.sopt.peekabookaos.data.service.MyPageService
import com.sopt.peekabookaos.data.service.NaverService
import com.sopt.peekabookaos.data.service.NotificationService
Expand All @@ -21,6 +22,7 @@ import dagger.Provides
import dagger.hilt.InstallIn
import dagger.hilt.components.SingletonComponent
import retrofit2.Retrofit
import retrofit2.create

@Module
@InstallIn(SingletonComponent::class)
Expand Down Expand Up @@ -76,4 +78,8 @@ object RetrofitServiceModule {
@Provides
fun providesReportService(@PeekaType retrofit: Retrofit): ReportService =
retrofit.create(ReportService::class.java)

@Provides
fun providesForceUpdateService(@PeekaType retrofit: Retrofit): ForceUpdateService =
retrofit.create(ForceUpdateService::class.java)
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
package com.sopt.peekabookaos.domain.entity

data class Version(
val imageUrl: String = "",
val iosForceVersion: String = "",
stellar-halo marked this conversation as resolved.
Show resolved Hide resolved
val androidForceVersion: String = "",
val versionText: String = ""
)
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
package com.sopt.peekabookaos.domain.repository

import com.sopt.peekabookaos.domain.entity.Version

interface ForceUpdateRepository {
suspend fun getVersion(): Result<Version>
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
package com.sopt.peekabookaos.domain.usecase

import com.sopt.peekabookaos.domain.repository.ForceUpdateRepository
import javax.inject.Inject

class GetVersionUseCase @Inject constructor(
private val forceUpdateRepository: ForceUpdateRepository
) {
suspend operator fun invoke() = forceUpdateRepository.getVersion()
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
package com.sopt.peekabookaos.presentation.forceUpdate

import android.content.Intent
import android.net.Uri
import android.os.Bundle
import com.sopt.peekabookaos.R
import com.sopt.peekabookaos.databinding.ActivityForceUpdateBinding
import com.sopt.peekabookaos.util.binding.BindingActivity

class ForceUpdateActivity :
BindingActivity<ActivityForceUpdateBinding>(R.layout.activity_force_update) {
lateinit var intentToPlayStore: Intent
stellar-halo marked this conversation as resolved.
Show resolved Hide resolved

override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
binding.btnForceUpdate.setOnClickListener {
intentToPlayStore = Intent(
Intent.ACTION_VIEW,
Uri.parse("https://play.google.com/store/apps/details?id=com.sopt.peekabookaos&hl=ko-KR")
)
startActivity(intentToPlayStore)
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,11 @@ import android.os.Bundle
import android.os.Handler
import android.os.Looper
import androidx.activity.viewModels
import com.sopt.peekabookaos.BuildConfig
import com.sopt.peekabookaos.R
import com.sopt.peekabookaos.databinding.ActivitySplashBinding
import com.sopt.peekabookaos.domain.entity.SplashState
import com.sopt.peekabookaos.presentation.forceUpdate.ForceUpdateActivity
import com.sopt.peekabookaos.presentation.main.MainActivity
import com.sopt.peekabookaos.presentation.onboarding.OnboardingActivity
import com.sopt.peekabookaos.util.binding.BindingActivity
Expand All @@ -18,11 +20,31 @@ import dagger.hilt.android.AndroidEntryPoint
@SuppressLint("CustomSplashScreen")
class SplashActivity : BindingActivity<ActivitySplashBinding>(R.layout.activity_splash) {
private val splashViewModel: SplashViewModel by viewModels()
private val appVersionName = BuildConfig.VERSION_NAME

override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
initDataObserver()
binding.lottieSplash.playAnimation()
Handler(Looper.getMainLooper()).postDelayed({ checkSplashState() }, DURATION)
splashViewModel.getVersion()
stellar-halo marked this conversation as resolved.
Show resolved Hide resolved
}

private fun initDataObserver() {
stellar-halo marked this conversation as resolved.
Show resolved Hide resolved
splashViewModel.isVersionStatus.observe(this) { success ->
if (success) {
checkVersionUpdate()
}
}
}

private fun checkVersionUpdate() {
val isPreviousVersion = appVersionName != splashViewModel.versionName.value
stellar-halo marked this conversation as resolved.
Show resolved Hide resolved
if (isPreviousVersion) {
startActivity(Intent(this, ForceUpdateActivity::class.java))
finish()
} else {
Handler(Looper.getMainLooper()).postDelayed({ checkSplashState() }, DURATION)
stellar-halo marked this conversation as resolved.
Show resolved Hide resolved
}
}

private fun checkSplashState() {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,14 +1,40 @@
package com.sopt.peekabookaos.presentation.splash

import androidx.lifecycle.LiveData
import androidx.lifecycle.MutableLiveData
import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
import com.sopt.peekabookaos.domain.entity.SplashState
import com.sopt.peekabookaos.domain.usecase.GetSplashStateUseCase
import com.sopt.peekabookaos.domain.usecase.GetVersionUseCase
import dagger.hilt.android.lifecycle.HiltViewModel
import kotlinx.coroutines.launch
import timber.log.Timber
import javax.inject.Inject

@HiltViewModel
class SplashViewModel @Inject constructor(
private val getSplashStateUseCase: GetSplashStateUseCase
private val getSplashStateUseCase: GetSplashStateUseCase,
private val getVersionUseCase: GetVersionUseCase
) : ViewModel() {
private val _versionName: MutableLiveData<String> = MutableLiveData()
val versionName: LiveData<String> = _versionName
private val _isVersionStatus = MutableLiveData(false)
val isVersionStatus: LiveData<Boolean> = _isVersionStatus
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

UiState라는 데이터클래스를 만들어서 변수를 하나에 관리하는 건 어떨까요?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

당장은 여기에서만 쓰이니 안만드는게 좋겠다고 생각했는데, 나중엔 다른 곳에서도 쓰일 수도 있겠네요..!

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

음 .. 개인적으론 코딩스타일인 것 같아서 다음에 uiState 공부하고 적용해보면 좋을 것 같아요

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

isVersionStatus보다는 isForceUpdate가 더 직관적인 것 같은데 어떻게 생각하시나요?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

서버 통신 변수명이니까 status가 들어가는 것이 좋아보여 isForceUpdateStatus로 변경했습니다


fun getSplashState(): SplashState = getSplashStateUseCase()

fun getVersion() {
viewModelScope.launch {
getVersionUseCase()
.onSuccess { response ->
_versionName.value = response.androidForceVersion
_isVersionStatus.value = true
}
.onFailure { throwable ->
_isVersionStatus.value = false
Timber.e("$throwable")
}
}
}
stellar-halo marked this conversation as resolved.
Show resolved Hide resolved
}
73 changes: 73 additions & 0 deletions app/src/main/res/layout/activity_force_update.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools">

<data>

</data>

<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@color/network_background"
tools:context=".presentation.splash.SplashActivity">

<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginHorizontal="40dp"
android:background="@color/peeka_beige"
android:elevation="20dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent">

<TextView
android:id="@+id/tv_force_update_title"
style="@style/NameBd"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="22dp"
android:gravity="center"
android:text="@string/force_update_title"
android:textColor="@color/peeka_red"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />

<TextView
android:id="@+id/tv_force_update_content"
style="@style/H2Md"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="5dp"
android:gravity="center"
android:text="@string/force_update_content"
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

데이터바인딩이 필요해보입니다

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

현재는 고정문구라하여 데바 안하겠습니다!

android:textColor="@color/peeka_red"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/tv_force_update_title" />

<androidx.appcompat.widget.AppCompatButton
android:id="@+id/btn_force_update"
style="@style/H1Bd"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginHorizontal="16dp"
android:layout_marginTop="15dp"
android:layout_marginBottom="16dp"
android:background="@color/peeka_red"
android:paddingVertical="10dp"
android:text="@string/force_update_button"
android:textColor="@color/peeka_white"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/tv_force_update_content" />

</androidx.constraintlayout.widget.ConstraintLayout>

</androidx.constraintlayout.widget.ConstraintLayout>
</layout>
5 changes: 5 additions & 0 deletions app/src/main/res/values/strings.xml
Original file line number Diff line number Diff line change
Expand Up @@ -206,4 +206,9 @@
<string name="profile_modify_intoduce_hint">한 줄 소개는 40자까지 쓸 수 있어요!</string>
<string name="blocked_user_empty">차단된 사용자가 없어요.</string>
<string name="profile_modify_timeStamp">yyyyMMdd_HHmmss</string>

<!-- Force Update -->
<string name="force_update_title">앗! 피카북이 달라졌어요</string>
<string name="force_update_content">어느 기능이 추가되었는지 알아볼까요?</string>
Copy link
Contributor

@2zerozu 2zerozu Nov 2, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

아마 이 내용을 서버에서 보내주기 때문에 string으로 저장하는 것이 아닌 서버통신에서 받아온 것을 사용하면 될 것 같네요

+) 기디한테 어느 부분이 가변한 문구인지 물어본 다음에 적용하는 게 좋을 것 같네요

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

넵!🫡

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

지금 전부 고정문구라네요!

<string name="force_update_button">업데이트 하러 가기</string>
</resources>
Loading