diff --git a/app/build.gradle b/app/build.gradle index cbc4f60c6..e22dc8981 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -14,14 +14,14 @@ properties.load(project.rootProject.file('local.properties').newDataInputStream( def kakao_native_app_key = properties.get('KAKAO_NATIVE_APP_KEY_NO_QUEOTS') android { - compileSdk 31 + compileSdk 33 defaultConfig { applicationId "org.sopt.havit" minSdk 23 - targetSdk 31 - versionCode 108 - versionName "1.0.8" + targetSdk 33 + versionCode 110 + versionName "1.0.10" testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" buildConfigField("String", "HAVIT_BASE_URL_DEV", properties["HAVIT_BASE_URL_DEV"]) buildConfigField("String", "HAVIT_BASE_URL_PROD", properties["HAVIT_BASE_URL_PROD"]) @@ -80,7 +80,7 @@ android { dependencies { implementation 'androidx.core:core-ktx:1.7.0' - implementation 'androidx.appcompat:appcompat:1.4.0' + implementation 'androidx.appcompat:appcompat:1.6.1' implementation 'com.google.android.material:material:1.4.0' implementation 'androidx.constraintlayout:constraintlayout:2.1.2' implementation 'androidx.legacy:legacy-support-v4:1.0.0' @@ -100,7 +100,6 @@ dependencies { //kakao implementation "com.kakao.sdk:v2-user:2.11.0" // 카카오 로그인 - implementation 'com.kakao.sdk:usermgmt:1.27.0' // 카카오 로그인 버튼 만들 때 사용 // Retrofit implementation 'com.squareup.retrofit2:converter-gson:2.9.0' diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index 00258316f..692aaca8a 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -3,6 +3,7 @@ package="org.sopt.havit"> + diff --git a/app/src/main/java/org/sopt/havit/FirebaseTokenManager.kt b/app/src/main/java/org/sopt/havit/FirebaseTokenManager.kt index 98a33a3a1..81a012893 100644 --- a/app/src/main/java/org/sopt/havit/FirebaseTokenManager.kt +++ b/app/src/main/java/org/sopt/havit/FirebaseTokenManager.kt @@ -5,21 +5,18 @@ import android.util.Log import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.launch -import org.sopt.havit.data.RetrofitObject +import org.sopt.havit.data.api.HavitApi import org.sopt.havit.data.remote.FcmTokenParams -import org.sopt.havit.domain.repository.AuthRepository import javax.inject.Inject class FirebaseTokenManager @Inject constructor( - authRepository: AuthRepository, + private val havitApi: HavitApi ) { - private val accessToken = authRepository.getAccessToken() fun sendRegistrationToServer(fcmToken: String) { CoroutineScope(Dispatchers.IO).launch { kotlin.runCatching { - RetrofitObject.provideHavitApi(accessToken) - .refreshFcmToken(FcmTokenParams(fcmToken)) + havitApi.refreshFcmToken(FcmTokenParams(fcmToken)) }.onSuccess { Log.d(ContentValues.TAG, "onNewToken: success") }.onFailure { diff --git a/app/src/main/java/org/sopt/havit/data/RetrofitObject.kt b/app/src/main/java/org/sopt/havit/data/RetrofitObject.kt deleted file mode 100644 index 06372bc22..000000000 --- a/app/src/main/java/org/sopt/havit/data/RetrofitObject.kt +++ /dev/null @@ -1,44 +0,0 @@ -package org.sopt.havit.data - -import okhttp3.Interceptor -import okhttp3.OkHttpClient -import okhttp3.logging.HttpLoggingInterceptor -import org.sopt.havit.BuildConfig.* -import org.sopt.havit.data.api.HavitApi -import retrofit2.Retrofit -import retrofit2.converter.gson.GsonConverterFactory -import java.util.concurrent.TimeUnit - -object RetrofitObject { - - private fun getRetrofitBuild(jwt: String) = Retrofit.Builder() - .baseUrl(if (IS_DEV) HAVIT_BASE_URL_DEV else HAVIT_BASE_URL_PROD) - .client(getOkhttpClient(jwt)) - .addConverterFactory(GsonConverterFactory.create()) - .build() - - private fun getOkhttpClient(jwt: String) = OkHttpClient.Builder().apply { - readTimeout(20, TimeUnit.SECONDS) - connectTimeout(20, TimeUnit.SECONDS) - writeTimeout(5, TimeUnit.SECONDS) - addInterceptor(getTokenInterceptor(jwt)) - - if (DEBUG) { - addInterceptor(getLoggingInterceptor()) - } - }.build() - - private fun getTokenInterceptor(jwt: String) = Interceptor { - val request = it.request() - .newBuilder() - .addHeader("x-auth-token", jwt) - .build() - - return@Interceptor it.proceed(request) - } - - private fun getLoggingInterceptor(): HttpLoggingInterceptor = - HttpLoggingInterceptor().apply { level = HttpLoggingInterceptor.Level.BODY } - - fun provideHavitApi(jwt: String): HavitApi = getRetrofitBuild(jwt).create(HavitApi::class.java) -} diff --git a/app/src/main/java/org/sopt/havit/data/local/HavitAuthLocalPreferences.kt b/app/src/main/java/org/sopt/havit/data/local/HavitAuthLocalPreferences.kt index 73c4d8cb1..f4ead0ea7 100644 --- a/app/src/main/java/org/sopt/havit/data/local/HavitAuthLocalPreferences.kt +++ b/app/src/main/java/org/sopt/havit/data/local/HavitAuthLocalPreferences.kt @@ -11,6 +11,7 @@ class HavitAuthLocalPreferences @Inject constructor( ) { companion object { private const val ACCESS_TOKEN = "ACCESS_TOKEN" + private const val REFRESH_TOKEN = "REFRESH_TOKEN" private const val KAKAO_TOKEN = "KAKAO_TOKEN" private const val USER_EMAIL = "USER_EMAIL" private const val USER_AGE = "USER_AGE" @@ -24,6 +25,8 @@ class HavitAuthLocalPreferences @Inject constructor( fun setXAuthToken(token: String) = prefs.edit().putString(ACCESS_TOKEN, token).apply() fun getXAuthToken(): String = prefs.getString(ACCESS_TOKEN, "").toString() + fun setRefreshToken(token: String) = prefs.edit().putString(REFRESH_TOKEN, token).apply() + fun getRefreshToken(): String = prefs.getString(REFRESH_TOKEN, "").toString() fun setKakaoToken(token: String) = prefs.edit().putString(KAKAO_TOKEN, token).apply() diff --git a/app/src/main/java/org/sopt/havit/data/repository/AuthRepositoryImpl.kt b/app/src/main/java/org/sopt/havit/data/repository/AuthRepositoryImpl.kt index 64150a2d0..661ef08df 100644 --- a/app/src/main/java/org/sopt/havit/data/repository/AuthRepositoryImpl.kt +++ b/app/src/main/java/org/sopt/havit/data/repository/AuthRepositoryImpl.kt @@ -23,6 +23,10 @@ class AuthRepositoryImpl @Inject constructor( authLocalDataSource.saveAccessToken(accessToken) } + override fun saveRefreshToken(refreshToken: String) { + authLocalDataSource.saveRefreshToken(refreshToken) + } + override fun saveKakaoToken(kakaoToken: String) { authLocalDataSource.saveKakaoToken(kakaoToken) } diff --git a/app/src/main/java/org/sopt/havit/data/repository/ContentsRepositoryImpl.kt b/app/src/main/java/org/sopt/havit/data/repository/ContentsRepositoryImpl.kt index 91d1b5e29..6686331be 100644 --- a/app/src/main/java/org/sopt/havit/data/repository/ContentsRepositoryImpl.kt +++ b/app/src/main/java/org/sopt/havit/data/repository/ContentsRepositoryImpl.kt @@ -1,24 +1,20 @@ package org.sopt.havit.data.repository -import org.sopt.havit.data.RetrofitObject +import org.sopt.havit.data.api.HavitApi import org.sopt.havit.data.remote.BasicResponse import org.sopt.havit.data.remote.ContentsHavitRequest import org.sopt.havit.data.remote.ContentsHavitResponse import org.sopt.havit.data.source.remote.contents.ContentsRemoteDataSource import org.sopt.havit.domain.entity.Contents import org.sopt.havit.domain.repository.ContentsRepository -import org.sopt.havit.util.HavitSharedPreference import javax.inject.Inject class ContentsRepositoryImpl @Inject constructor( private val contentsRemoteDataSource: ContentsRemoteDataSource, - preference: HavitSharedPreference + private val havitApi: HavitApi ) : ContentsRepository { - - private val pref = preference.getXAuthToken() - override suspend fun isSeen(contentsId: Int): ContentsHavitResponse { - return RetrofitObject.provideHavitApi(pref).isHavit(ContentsHavitRequest(contentsId)) + return havitApi.isHavit(ContentsHavitRequest(contentsId)) } override suspend fun getContentsByCategory( diff --git a/app/src/main/java/org/sopt/havit/data/repository/MyPageRepositoryImpl.kt b/app/src/main/java/org/sopt/havit/data/repository/MyPageRepositoryImpl.kt index 5c3d7ae1e..4c5ed20b0 100644 --- a/app/src/main/java/org/sopt/havit/data/repository/MyPageRepositoryImpl.kt +++ b/app/src/main/java/org/sopt/havit/data/repository/MyPageRepositoryImpl.kt @@ -1,14 +1,14 @@ package org.sopt.havit.data.repository -import org.sopt.havit.data.RetrofitObject +import org.sopt.havit.data.api.HavitApi import org.sopt.havit.data.remote.UserResponse -import org.sopt.havit.data.source.local.AuthLocalDataSource import org.sopt.havit.domain.repository.MyPageRepository import javax.inject.Inject -class MyPageRepositoryImpl @Inject constructor(private val authLocalDataSource: AuthLocalDataSource) : - MyPageRepository { +class MyPageRepositoryImpl @Inject constructor( + private val havitApi: HavitApi +) : MyPageRepository { override suspend fun getUserInfo(): UserResponse { - return RetrofitObject.provideHavitApi(authLocalDataSource.getAccessToken()).getUserData() + return havitApi.getUserData() } } diff --git a/app/src/main/java/org/sopt/havit/data/source/local/AuthLocalDataSource.kt b/app/src/main/java/org/sopt/havit/data/source/local/AuthLocalDataSource.kt index 91ed4bfac..a747b24a1 100644 --- a/app/src/main/java/org/sopt/havit/data/source/local/AuthLocalDataSource.kt +++ b/app/src/main/java/org/sopt/havit/data/source/local/AuthLocalDataSource.kt @@ -3,6 +3,8 @@ package org.sopt.havit.data.source.local interface AuthLocalDataSource { fun saveAccessToken(token: String) fun getAccessToken(): String + fun saveRefreshToken(token: String) + fun getRefreshToken(): String fun saveKakaoToken(kakaoToken: String) fun getKakaoToken(): String fun getUserAge():Int diff --git a/app/src/main/java/org/sopt/havit/data/source/local/AuthLocalDataSourceImpl.kt b/app/src/main/java/org/sopt/havit/data/source/local/AuthLocalDataSourceImpl.kt index 37eaa3b94..79554a411 100644 --- a/app/src/main/java/org/sopt/havit/data/source/local/AuthLocalDataSourceImpl.kt +++ b/app/src/main/java/org/sopt/havit/data/source/local/AuthLocalDataSourceImpl.kt @@ -13,6 +13,14 @@ class AuthLocalDataSourceImpl @Inject constructor(private val havitLocalPreferen return havitLocalPreferences.getXAuthToken() } + override fun saveRefreshToken(token: String) { + havitLocalPreferences.setRefreshToken(token) + } + + override fun getRefreshToken(): String { + return havitLocalPreferences.getRefreshToken() + } + override fun saveKakaoToken(kakaoToken: String) = havitLocalPreferences.setKakaoToken(kakaoToken) diff --git a/app/src/main/java/org/sopt/havit/di/RepositoryModule.kt b/app/src/main/java/org/sopt/havit/di/RepositoryModule.kt index 8c8218fa9..ac1b1284d 100644 --- a/app/src/main/java/org/sopt/havit/di/RepositoryModule.kt +++ b/app/src/main/java/org/sopt/havit/di/RepositoryModule.kt @@ -4,6 +4,7 @@ import dagger.Module import dagger.Provides import dagger.hilt.InstallIn import dagger.hilt.components.SingletonComponent +import org.sopt.havit.data.api.HavitApi import org.sopt.havit.data.mapper.ContentsMapper import org.sopt.havit.data.repository.* import org.sopt.havit.data.source.local.AuthLocalDataSourceImpl @@ -12,7 +13,6 @@ import org.sopt.havit.data.source.remote.SearchRemoteDataSourceImpl import org.sopt.havit.data.source.remote.category.CategoryRemoteDataSourceImpl import org.sopt.havit.data.source.remote.contents.ContentsRemoteDataSourceImpl import org.sopt.havit.domain.repository.* -import org.sopt.havit.util.HavitSharedPreference import javax.inject.Singleton @Module @@ -29,16 +29,16 @@ object RepositoryModule { @Provides @Singleton fun provideMyPageRepository( - authLocalDataSourceImpl: AuthLocalDataSourceImpl - ): MyPageRepository = MyPageRepositoryImpl(authLocalDataSourceImpl) + havitApi: HavitApi + ): MyPageRepository = MyPageRepositoryImpl(havitApi) @Provides @Singleton fun provideContentsRepository( contentsRemoteDataSourceImpl: ContentsRemoteDataSourceImpl, - havitSharedPreference: HavitSharedPreference + havitApi: HavitApi ): ContentsRepository = - ContentsRepositoryImpl(contentsRemoteDataSourceImpl, havitSharedPreference) + ContentsRepositoryImpl(contentsRemoteDataSourceImpl, havitApi) @Provides @Singleton diff --git a/app/src/main/java/org/sopt/havit/di/RetrofitModule.kt b/app/src/main/java/org/sopt/havit/di/RetrofitModule.kt index d1cf3e886..2ed9bca94 100644 --- a/app/src/main/java/org/sopt/havit/di/RetrofitModule.kt +++ b/app/src/main/java/org/sopt/havit/di/RetrofitModule.kt @@ -1,16 +1,20 @@ package org.sopt.havit.di +import android.content.Context +import android.content.Intent import com.google.gson.Gson import com.google.gson.GsonBuilder import dagger.Module import dagger.Provides import dagger.hilt.InstallIn +import dagger.hilt.android.qualifiers.ApplicationContext import dagger.hilt.components.SingletonComponent import okhttp3.Interceptor import okhttp3.OkHttpClient import okhttp3.logging.HttpLoggingInterceptor -import org.sopt.havit.BuildConfig.* +import org.sopt.havit.BuildConfig import org.sopt.havit.data.source.local.AuthLocalDataSourceImpl +import org.sopt.havit.ui.sign.SplashWithSignActivity import retrofit2.Retrofit import retrofit2.converter.gson.GsonConverterFactory import javax.inject.Singleton @@ -21,35 +25,44 @@ object RetrofitModule { @Provides @Singleton - fun provideInterceptor(authLocalDataSourceImpl: AuthLocalDataSourceImpl) = - Interceptor { chain -> - with(chain) { - proceed( - request() - .newBuilder() - .addHeader( - "x-auth-token", - authLocalDataSourceImpl.getAccessToken() - ) - .build() - ) + fun provideAuthInterceptor( + @ApplicationContext context: Context, + authLocalDataSourceImpl: AuthLocalDataSourceImpl + ): Interceptor { + return Interceptor { chain -> + val originalRequest = chain.request() + val newRequest = originalRequest.newBuilder() + .header("x-auth-token", authLocalDataSourceImpl.getAccessToken()) + .build() + val response = chain.proceed(newRequest) + if (response.code() == 401) { + handle401Error(context, authLocalDataSourceImpl) } + response } + } + + private fun handle401Error(context: Context, authLocalDataSourceImpl: AuthLocalDataSourceImpl) { + authLocalDataSourceImpl.removeHavitAuthToken() + authLocalDataSourceImpl.saveAccessToken(authLocalDataSourceImpl.getRefreshToken()) + val intent = Intent(context, SplashWithSignActivity::class.java) + intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_CLEAR_TASK) + context.startActivity(intent) + } @Provides @Singleton - fun provideOkHttpClient( - interceptor: Interceptor - ): OkHttpClient { - return OkHttpClient.Builder().apply { - addInterceptor(interceptor) + fun provideOkHttpClient(interceptor: Interceptor): OkHttpClient { + val httpClientBuilder = OkHttpClient.Builder() + .addInterceptor(interceptor) - if (DEBUG) { - addInterceptor(HttpLoggingInterceptor().apply { - level = HttpLoggingInterceptor.Level.BODY - }) - } - }.build() + if (BuildConfig.DEBUG) { + httpClientBuilder.addInterceptor(HttpLoggingInterceptor().apply { + level = HttpLoggingInterceptor.Level.BODY + }) + } + + return httpClientBuilder.build() } @Provides @@ -58,11 +71,8 @@ object RetrofitModule { @Provides @Singleton - fun provideRetrofit( - client: OkHttpClient, - gson: Gson - ): Retrofit = Retrofit.Builder() - .baseUrl(if (IS_DEV) HAVIT_BASE_URL_DEV else HAVIT_BASE_URL_PROD) + fun provideRetrofit(client: OkHttpClient, gson: Gson): Retrofit = Retrofit.Builder() + .baseUrl(if (BuildConfig.IS_DEV) BuildConfig.HAVIT_BASE_URL_DEV else BuildConfig.HAVIT_BASE_URL_PROD) .client(client) .addConverterFactory(GsonConverterFactory.create(gson)) .build() diff --git a/app/src/main/java/org/sopt/havit/domain/repository/AuthRepository.kt b/app/src/main/java/org/sopt/havit/domain/repository/AuthRepository.kt index c25f1f526..c53406602 100644 --- a/app/src/main/java/org/sopt/havit/domain/repository/AuthRepository.kt +++ b/app/src/main/java/org/sopt/havit/domain/repository/AuthRepository.kt @@ -8,6 +8,7 @@ interface AuthRepository { fun getFcmToken(getFcmToken: (String) -> Unit) fun saveAccessToken(accessToken: String) + fun saveRefreshToken(refreshToken: String) fun saveKakaoToken(kakaoToken: String) diff --git a/app/src/main/java/org/sopt/havit/ui/category/CategoryContentModifyActivity.kt b/app/src/main/java/org/sopt/havit/ui/category/CategoryContentModifyActivity.kt index b72861149..6a1e86745 100644 --- a/app/src/main/java/org/sopt/havit/ui/category/CategoryContentModifyActivity.kt +++ b/app/src/main/java/org/sopt/havit/ui/category/CategoryContentModifyActivity.kt @@ -6,6 +6,7 @@ import android.os.Bundle import android.view.MotionEvent import android.view.inputmethod.InputMethodManager import android.widget.EditText +import androidx.activity.OnBackPressedCallback import androidx.activity.viewModels import androidx.core.widget.addTextChangedListener import dagger.hilt.android.AndroidEntryPoint @@ -33,8 +34,15 @@ class CategoryContentModifyActivity : private lateinit var iconAdapter: IconAdapter private lateinit var categoryTitleList: ArrayList + private val callback = object : OnBackPressedCallback(true) { + override fun handleOnBackPressed() { + setBackPressedAction() + } + } + override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) + this.onBackPressedDispatcher.addCallback(this, callback) setContentView(binding.root) initIconAdapter() @@ -48,10 +56,6 @@ class CategoryContentModifyActivity : observeModifyState() } - override fun onBackPressed() { - setBackPressedAction() - } - override fun dispatchTouchEvent(event: MotionEvent): Boolean { if (event.action == MotionEvent.ACTION_DOWN) { val v = currentFocus diff --git a/app/src/main/java/org/sopt/havit/ui/category/CategoryOrderModifyActivity.kt b/app/src/main/java/org/sopt/havit/ui/category/CategoryOrderModifyActivity.kt index a75575026..f0621747c 100644 --- a/app/src/main/java/org/sopt/havit/ui/category/CategoryOrderModifyActivity.kt +++ b/app/src/main/java/org/sopt/havit/ui/category/CategoryOrderModifyActivity.kt @@ -3,6 +3,7 @@ package org.sopt.havit.ui.category import android.content.Intent import android.os.Bundle import android.view.View +import androidx.activity.OnBackPressedCallback import androidx.activity.result.ActivityResultLauncher import androidx.activity.result.contract.ActivityResultContracts import androidx.activity.viewModels @@ -34,9 +35,16 @@ class CategoryOrderModifyActivity : private val originCategoryIdList = mutableListOf() lateinit var holder: RecyclerView.ViewHolder + private val callback = object : OnBackPressedCallback(true) { + override fun handleOnBackPressed() { + setBackPressedAction() + } + } + override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(binding.root) + this.onBackPressedDispatcher.addCallback(this, callback) initAdapter() setResult() @@ -48,10 +56,6 @@ class CategoryOrderModifyActivity : observeOrderModifyState() } - override fun onBackPressed() { - setBackPressedAction() - } - private fun setBackPressedAction() { val categoryIdList = mutableListOf() for (item in categoryOrderModifyAdapter.categoryList) { diff --git a/app/src/main/java/org/sopt/havit/ui/contents/more/BottomSheetMoreFragment.kt b/app/src/main/java/org/sopt/havit/ui/contents/more/BottomSheetMoreFragment.kt index e14f3f3d1..3c2a8a37f 100644 --- a/app/src/main/java/org/sopt/havit/ui/contents/more/BottomSheetMoreFragment.kt +++ b/app/src/main/java/org/sopt/havit/ui/contents/more/BottomSheetMoreFragment.kt @@ -5,6 +5,7 @@ import android.os.Bundle import android.view.LayoutInflater import android.view.View import android.view.ViewGroup +import androidx.activity.OnBackPressedCallback import androidx.fragment.app.Fragment import androidx.fragment.app.commit import androidx.fragment.app.replace @@ -30,11 +31,18 @@ class BottomSheetMoreFragment : BottomSheetDialogFragment() { var contents: ContentsMoreData? = null private lateinit var refreshDataOnBottomSheetDismiss: () -> Unit + private val onBackPressedCallback = object : OnBackPressedCallback(true) { + override fun handleOnBackPressed() { + if ((getCurrentFragmentOnMore() as? OnBackPressedHandler)?.onBackPressed() == false) + dismiss() + } + } + override fun onCreateDialog(savedInstanceState: Bundle?): Dialog { return object : BottomSheetDialog(requireContext()) { - override fun onBackPressed() { - if ((getCurrentFragmentOnMore() as? OnBackPressedHandler)?.onBackPressed() == true) return - dismiss() + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + onBackPressedDispatcher.addCallback(viewLifecycleOwner, onBackPressedCallback) } } } @@ -112,3 +120,4 @@ class BottomSheetMoreFragment : BottomSheetDialogFragment() { const val SET_ALARM = "SET_ALARM" } } + diff --git a/app/src/main/java/org/sopt/havit/ui/contents/more/edit_category/EditCategoryFromMoreViewModel.kt b/app/src/main/java/org/sopt/havit/ui/contents/more/edit_category/EditCategoryFromMoreViewModel.kt index 478f20c1d..16ce23735 100644 --- a/app/src/main/java/org/sopt/havit/ui/contents/more/edit_category/EditCategoryFromMoreViewModel.kt +++ b/app/src/main/java/org/sopt/havit/ui/contents/more/edit_category/EditCategoryFromMoreViewModel.kt @@ -5,7 +5,7 @@ import androidx.lifecycle.ViewModel import androidx.lifecycle.viewModelScope import dagger.hilt.android.lifecycle.HiltViewModel import kotlinx.coroutines.launch -import org.sopt.havit.data.RetrofitObject +import org.sopt.havit.data.api.HavitApi import org.sopt.havit.data.mapper.CategoryMapper import org.sopt.havit.data.remote.ContentsMoreData import org.sopt.havit.data.remote.ModifyContentCategoryParams @@ -17,7 +17,8 @@ import javax.inject.Inject @HiltViewModel class EditCategoryFromMoreViewModel @Inject constructor( authRepository: AuthRepository, - private val categoryMapper: CategoryMapper + private val categoryMapper: CategoryMapper, + private val havitApi: HavitApi ) : ViewModel() { private val token = authRepository.getAccessToken() private val contentsId = MutableLiveData() @@ -60,7 +61,7 @@ class EditCategoryFromMoreViewModel @Inject constructor( fun getCategoryListWithSelectedInfo() { viewModelScope.launch { kotlin.runCatching { - val response = RetrofitObject.provideHavitApi(token).getAllCategoryList( + val response = havitApi.getAllCategoryList( requireNotNull(contentsId.value) ) categoryList.value = response.data @@ -77,7 +78,7 @@ class EditCategoryFromMoreViewModel @Inject constructor( contentId = requireNotNull(contentsId.value), newCategoryIds = requireNotNull(newCategoryId.value) ) - RetrofitObject.provideHavitApi(token).modifyContentCategory(body) + havitApi.modifyContentCategory(body) }.onSuccess { userClicksOnButton(SUCCESS) }.onFailure { diff --git a/app/src/main/java/org/sopt/havit/ui/contents/more/edit_notification/EditNotificationFromMoreViewModel.kt b/app/src/main/java/org/sopt/havit/ui/contents/more/edit_notification/EditNotificationFromMoreViewModel.kt index 79c09788c..5a9663fce 100644 --- a/app/src/main/java/org/sopt/havit/ui/contents/more/edit_notification/EditNotificationFromMoreViewModel.kt +++ b/app/src/main/java/org/sopt/havit/ui/contents/more/edit_notification/EditNotificationFromMoreViewModel.kt @@ -6,19 +6,21 @@ import androidx.lifecycle.ViewModel import androidx.lifecycle.viewModelScope import dagger.hilt.android.lifecycle.HiltViewModel import kotlinx.coroutines.launch -import org.sopt.havit.data.RetrofitObject +import org.sopt.havit.data.api.HavitApi import org.sopt.havit.data.remote.ContentsMoreData import org.sopt.havit.data.remote.ModifyContentNotificationParams import org.sopt.havit.domain.repository.AuthRepository import org.sopt.havit.ui.share.notification.AfterTime import org.sopt.havit.util.CalenderUtil import org.sopt.havit.util.Event -import java.util.* +import java.util.Calendar +import java.util.Date import javax.inject.Inject @HiltViewModel class EditNotificationFromMoreViewModel @Inject constructor( - authRepository: AuthRepository + authRepository: AuthRepository, + private val havitApi: HavitApi ) : ViewModel() { /** token */ val token = authRepository.getAccessToken() @@ -95,7 +97,7 @@ class EditNotificationFromMoreViewModel @Inject constructor( fun deleteNotification() { viewModelScope.launch { kotlin.runCatching { - RetrofitObject.provideHavitApi(token).deleteContentNotification( + havitApi.deleteContentNotification( requireNotNull(contentId.value) ) }.onSuccess { @@ -112,7 +114,7 @@ class EditNotificationFromMoreViewModel @Inject constructor( viewModelScope.launch { val time = tempNotificationTime.value?.substring(0, 16)?.replace(".", "-") kotlin.runCatching { - RetrofitObject.provideHavitApi(token).modifyContentNotification( + havitApi.modifyContentNotification( requireNotNull(contentId.value), ModifyContentNotificationParams(requireNotNull(time)) ) diff --git a/app/src/main/java/org/sopt/havit/ui/contents/more/edit_title/EditTitleFromMoreViewModel.kt b/app/src/main/java/org/sopt/havit/ui/contents/more/edit_title/EditTitleFromMoreViewModel.kt index 37708e487..ebedf0bed 100644 --- a/app/src/main/java/org/sopt/havit/ui/contents/more/edit_title/EditTitleFromMoreViewModel.kt +++ b/app/src/main/java/org/sopt/havit/ui/contents/more/edit_title/EditTitleFromMoreViewModel.kt @@ -5,7 +5,7 @@ import androidx.lifecycle.ViewModel import androidx.lifecycle.viewModelScope import dagger.hilt.android.lifecycle.HiltViewModel import kotlinx.coroutines.launch -import org.sopt.havit.data.RetrofitObject +import org.sopt.havit.data.api.HavitApi import org.sopt.havit.data.remote.ContentsMoreData import org.sopt.havit.data.remote.ModifyTitleParams import org.sopt.havit.domain.repository.AuthRepository @@ -14,7 +14,8 @@ import javax.inject.Inject @HiltViewModel class EditTitleFromMoreViewModel @Inject constructor( - authRepository: AuthRepository + authRepository: AuthRepository, + private val havitApi: HavitApi ) : ViewModel() { val token = authRepository.getAccessToken() var contentsId = MutableLiveData() @@ -34,7 +35,7 @@ class EditTitleFromMoreViewModel @Inject constructor( fun patchNewTitle() { viewModelScope.launch { kotlin.runCatching { - RetrofitObject.provideHavitApi(token).modifyContentTitle( + havitApi.modifyContentTitle( requireNotNull(contentsId.value), ModifyTitleParams(requireNotNull(currTitle.value)) ) diff --git a/app/src/main/java/org/sopt/havit/ui/contents_simple/ContentsSimpleViewModel.kt b/app/src/main/java/org/sopt/havit/ui/contents_simple/ContentsSimpleViewModel.kt index 82ab1bc05..ed28e8ccc 100644 --- a/app/src/main/java/org/sopt/havit/ui/contents_simple/ContentsSimpleViewModel.kt +++ b/app/src/main/java/org/sopt/havit/ui/contents_simple/ContentsSimpleViewModel.kt @@ -7,20 +7,17 @@ import androidx.lifecycle.viewModelScope import dagger.hilt.android.lifecycle.HiltViewModel import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.launch -import org.sopt.havit.data.RetrofitObject +import org.sopt.havit.data.api.HavitApi import org.sopt.havit.data.remote.ContentsHavitRequest import org.sopt.havit.data.remote.ContentsSimpleResponse import org.sopt.havit.domain.entity.NetworkState -import org.sopt.havit.util.HavitSharedPreference import javax.inject.Inject @HiltViewModel class ContentsSimpleViewModel @Inject constructor( - preference: HavitSharedPreference + private val havitApi: HavitApi ) : ViewModel() { - private val token = preference.getXAuthToken() - private val _contentsList = MutableLiveData>() val contentsList: LiveData> = _contentsList @@ -40,13 +37,10 @@ class ContentsSimpleViewModel @Inject constructor( try { if (contentsType == "unseen") { val response = - RetrofitObject.provideHavitApi(token) - .getContentsUnseen() + havitApi.getContentsUnseen() _contentsList.postValue(response.data) } else { - val response = - RetrofitObject.provideHavitApi(token) - .getContentsRecent() + val response = havitApi.getContentsRecent() _contentsList.postValue(response.data) } _loadState.postValue(NetworkState.SUCCESS) @@ -73,9 +67,7 @@ class ContentsSimpleViewModel @Inject constructor( fun setIsSeen(contentsId: Int) { viewModelScope.launch { try { - val response = - RetrofitObject.provideHavitApi(token) - .isHavit(ContentsHavitRequest(contentsId)) + val response = havitApi.isHavit(ContentsHavitRequest(contentsId)) _isHavit.postValue(response.data.isSeen) _loadState.postValue(NetworkState.SUCCESS) } catch (e: Exception) { @@ -97,9 +89,7 @@ class ContentsSimpleViewModel @Inject constructor( fun deleteContents(contentsId: Int) { viewModelScope.launch(Dispatchers.IO) { try { - val response = - RetrofitObject.provideHavitApi(token) - .deleteContents(contentsId) + havitApi.deleteContents(contentsId) _loadState.postValue(NetworkState.SUCCESS) } catch (e: Exception) { _loadState.postValue(NetworkState.FAIL) diff --git a/app/src/main/java/org/sopt/havit/ui/home/HomeViewModel.kt b/app/src/main/java/org/sopt/havit/ui/home/HomeViewModel.kt index fbfadaa45..e4b98980d 100644 --- a/app/src/main/java/org/sopt/havit/ui/home/HomeViewModel.kt +++ b/app/src/main/java/org/sopt/havit/ui/home/HomeViewModel.kt @@ -8,7 +8,7 @@ import androidx.lifecycle.viewModelScope import dagger.hilt.android.lifecycle.HiltViewModel import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.launch -import org.sopt.havit.data.RetrofitObject +import org.sopt.havit.data.api.HavitApi import org.sopt.havit.data.remote.ContentsSimpleResponse import org.sopt.havit.data.remote.NotificationResponse import org.sopt.havit.data.remote.RecommendationResponse @@ -16,14 +16,12 @@ import org.sopt.havit.data.remote.UserResponse import org.sopt.havit.domain.entity.Category import org.sopt.havit.domain.entity.NetworkState import org.sopt.havit.ui.notification.NotificationActivity -import org.sopt.havit.util.HavitSharedPreference import javax.inject.Inject @HiltViewModel class HomeViewModel @Inject constructor( - preference: HavitSharedPreference + private val havitApi: HavitApi ) : ViewModel() { - private val token = preference.getXAuthToken() // 로딩 상태를 나타내는 변수 private val _loadState = MutableLiveData(NetworkState.LOADING) @@ -46,9 +44,7 @@ class HomeViewModel @Inject constructor( fun requestContentsTaken() { viewModelScope.launch(Dispatchers.IO) { try { - val response = - RetrofitObject.provideHavitApi(token) - .getContentsRecent() + val response = havitApi.getContentsRecent() _contentsList.postValue(response.data) _contentsLoadState.postValue(NetworkState.SUCCESS) checkLoadState() @@ -64,9 +60,7 @@ class HomeViewModel @Inject constructor( fun requestCategoryTaken() { viewModelScope.launch(Dispatchers.IO) { try { - val response = - RetrofitObject.provideHavitApi(token) - .getAllCategories() + val response = havitApi.getAllCategories() checkLoadState() _categoryData.postValue(response.data ?: emptyList()) _categoryLoadState.postValue(NetworkState.SUCCESS) @@ -116,9 +110,7 @@ class HomeViewModel @Inject constructor( fun requestRecommendTaken() { viewModelScope.launch(Dispatchers.IO) { try { - val response = - RetrofitObject.provideHavitApi(token) - .getRecommendation() + val response = havitApi.getRecommendation() checkLoadState() _recommendList.postValue(response.data) _recommendLoadState.postValue(NetworkState.SUCCESS) @@ -135,8 +127,7 @@ class HomeViewModel @Inject constructor( fun requestNotificationTaken() { viewModelScope.launch(Dispatchers.IO) { try { - val response = RetrofitObject.provideHavitApi(token) - .getNotification(NotificationActivity.before) + val response = havitApi.getNotification(NotificationActivity.before) checkLoadState() _notificationList.postValue(response.data) _notificationLoadState.postValue(NetworkState.SUCCESS) @@ -153,9 +144,7 @@ class HomeViewModel @Inject constructor( fun requestUserDataTaken() { viewModelScope.launch(Dispatchers.IO) { try { - val response = - RetrofitObject.provideHavitApi(token) - .getUserData() + val response = havitApi.getUserData() _userData.postValue(response.data) _userLoadState.postValue(NetworkState.SUCCESS) setReachRate(response.data) // 목표 달성률 계산 diff --git a/app/src/main/java/org/sopt/havit/ui/notification/NotificationViewModel.kt b/app/src/main/java/org/sopt/havit/ui/notification/NotificationViewModel.kt index c757e4376..d650928b8 100644 --- a/app/src/main/java/org/sopt/havit/ui/notification/NotificationViewModel.kt +++ b/app/src/main/java/org/sopt/havit/ui/notification/NotificationViewModel.kt @@ -7,17 +7,15 @@ import androidx.lifecycle.viewModelScope import dagger.hilt.android.lifecycle.HiltViewModel import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.launch -import org.sopt.havit.data.RetrofitObject +import org.sopt.havit.data.api.HavitApi import org.sopt.havit.data.remote.ContentsHavitRequest import org.sopt.havit.data.remote.NotificationResponse.NotificationData -import org.sopt.havit.util.HavitSharedPreference import javax.inject.Inject @HiltViewModel class NotificationViewModel @Inject constructor( - preference: HavitSharedPreference + private val havitApi: HavitApi ) : ViewModel() { - private val token = preference.getXAuthToken() private val _contentsList = MutableLiveData>() val contentsList: LiveData> = _contentsList @@ -28,9 +26,7 @@ class NotificationViewModel @Inject constructor( viewModelScope.launch(Dispatchers.IO) { try { _contentLoadState.postValue(true) - val response = - RetrofitObject.provideHavitApi(token) - .getNotification(option) + val response = havitApi.getNotification(option) _contentsList.postValue(response.data) _contentLoadState.postValue(false) } catch (e: Exception) { @@ -43,9 +39,7 @@ class NotificationViewModel @Inject constructor( fun setIsSeen(contentsId: Int) { viewModelScope.launch { try { - val response = - RetrofitObject.provideHavitApi(token) - .isHavit(ContentsHavitRequest(contentsId)) + val response = havitApi.isHavit(ContentsHavitRequest(contentsId)) _isSeen.postValue(response.data.isSeen) } catch (e: Exception) { } @@ -60,9 +54,7 @@ class NotificationViewModel @Inject constructor( fun deleteContents(contentsId: Int) { viewModelScope.launch(Dispatchers.IO) { try { - val response = - RetrofitObject.provideHavitApi(token) - .deleteContents(contentsId) + havitApi.deleteContents(contentsId) } catch (e: Exception) { } } diff --git a/app/src/main/java/org/sopt/havit/ui/onboarding/OnboardingActivity.kt b/app/src/main/java/org/sopt/havit/ui/onboarding/OnboardingActivity.kt index 005ab5d92..0201eaba8 100644 --- a/app/src/main/java/org/sopt/havit/ui/onboarding/OnboardingActivity.kt +++ b/app/src/main/java/org/sopt/havit/ui/onboarding/OnboardingActivity.kt @@ -34,7 +34,7 @@ class OnboardingActivity : } private fun setIndicator() { - binding.indicatorOnboarding.setViewPager2(binding.vpOnboarding) + binding.indicatorOnboarding.attachTo(binding.vpOnboarding) } private fun checkLastOnboardingPage() { @@ -67,10 +67,6 @@ class OnboardingActivity : finish() } - override fun onBackPressed() { - // super.onBackPressed() // 건너뛰기, 가입하기 버튼을 눌러야만 - } - companion object { const val ONBOARDING_PAGE_NUM = 5 } diff --git a/app/src/main/java/org/sopt/havit/ui/setting/SettingPersonalDataActivity.kt b/app/src/main/java/org/sopt/havit/ui/setting/SettingPersonalDataActivity.kt index 115663636..73bac7e20 100644 --- a/app/src/main/java/org/sopt/havit/ui/setting/SettingPersonalDataActivity.kt +++ b/app/src/main/java/org/sopt/havit/ui/setting/SettingPersonalDataActivity.kt @@ -9,6 +9,6 @@ class SettingPersonalDataActivity : BaseBindingActivity(R.layout.activity_setting_personal_data) { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) - binding.ivBack.setOnClickListener { super.onBackPressed() } + binding.ivBack.setOnClickListener { this.finish() } } } diff --git a/app/src/main/java/org/sopt/havit/ui/setting/SettingPolicyActivity.kt b/app/src/main/java/org/sopt/havit/ui/setting/SettingPolicyActivity.kt index 59da77060..dba7a0bba 100644 --- a/app/src/main/java/org/sopt/havit/ui/setting/SettingPolicyActivity.kt +++ b/app/src/main/java/org/sopt/havit/ui/setting/SettingPolicyActivity.kt @@ -9,6 +9,6 @@ class SettingPolicyActivity : BaseBindingActivity(R.layout.activity_setting_policy) { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) - binding.ivBack.setOnClickListener { super.onBackPressed() } + binding.ivBack.setOnClickListener { finish() } } } diff --git a/app/src/main/java/org/sopt/havit/ui/setting/viewmodel/SettingViewModel.kt b/app/src/main/java/org/sopt/havit/ui/setting/viewmodel/SettingViewModel.kt index 5033a57a7..866ef5d54 100644 --- a/app/src/main/java/org/sopt/havit/ui/setting/viewmodel/SettingViewModel.kt +++ b/app/src/main/java/org/sopt/havit/ui/setting/viewmodel/SettingViewModel.kt @@ -12,7 +12,7 @@ import com.google.android.play.core.install.model.UpdateAvailability import dagger.hilt.android.lifecycle.HiltViewModel import kotlinx.coroutines.launch import org.sopt.havit.BuildConfig -import org.sopt.havit.data.RetrofitObject +import org.sopt.havit.data.api.HavitApi import org.sopt.havit.data.remote.NewNicknameRequest import org.sopt.havit.data.remote.UserResponse import org.sopt.havit.domain.entity.Notice @@ -23,7 +23,8 @@ import javax.inject.Inject @HiltViewModel class SettingViewModel @Inject constructor( private val authRepository: AuthRepository, - application: Application + application: Application, + private val havitApi: HavitApi ) : AndroidViewModel(application) { private val token = authRepository.getAccessToken() private val _user = MutableLiveData() @@ -56,8 +57,7 @@ class SettingViewModel @Inject constructor( fun requestUserInfo() { viewModelScope.launch { try { - val response = RetrofitObject.provideHavitApi(token) - .getUserData() + val response = havitApi.getUserData() _user.postValue(response.data) } catch (e: Exception) { } @@ -84,9 +84,7 @@ class SettingViewModel @Inject constructor( kotlin.runCatching { val newNickname = nickname.value?.trim() ?: throw IllegalArgumentException("nickname cannot be null") - RetrofitObject.provideHavitApi(token).modifyUserNickname( - NewNicknameRequest(newNickname) - ) + havitApi.modifyUserNickname(NewNicknameRequest(newNickname)) }.onSuccess { Log.d(TAG, "requestNewNickname: success") }.onFailure { @@ -109,7 +107,7 @@ class SettingViewModel @Inject constructor( fun unregister() { viewModelScope.launch { try { - RetrofitObject.provideHavitApi(token).deleteUser() + havitApi.deleteUser() } catch (e: Exception) { Log.d("SETTING", "error : $e") } @@ -122,7 +120,7 @@ class SettingViewModel @Inject constructor( fun getNoticeList() { viewModelScope.launch { kotlin.runCatching { - RetrofitObject.provideHavitApi(token).getNoticeList().data + havitApi.getNoticeList().data }.onSuccess { _noticeList.value = it }.onFailure { diff --git a/app/src/main/java/org/sopt/havit/ui/share/AddCategoryViewModel.kt b/app/src/main/java/org/sopt/havit/ui/share/AddCategoryViewModel.kt index 152ee1c30..b3f1abcab 100644 --- a/app/src/main/java/org/sopt/havit/ui/share/AddCategoryViewModel.kt +++ b/app/src/main/java/org/sopt/havit/ui/share/AddCategoryViewModel.kt @@ -6,7 +6,7 @@ import androidx.lifecycle.ViewModel import androidx.lifecycle.viewModelScope import dagger.hilt.android.lifecycle.HiltViewModel import kotlinx.coroutines.launch -import org.sopt.havit.data.RetrofitObject +import org.sopt.havit.data.api.HavitApi import org.sopt.havit.data.remote.CategoryAddRequest import org.sopt.havit.domain.model.NetworkStatus import org.sopt.havit.domain.repository.AuthRepository @@ -15,6 +15,7 @@ import javax.inject.Inject @HiltViewModel class AddCategoryViewModel @Inject constructor( authRepository: AuthRepository, + private val havitApi: HavitApi ) : ViewModel() { /** token */ @@ -30,7 +31,7 @@ class AddCategoryViewModel @Inject constructor( fun getExistingCategoryList() { viewModelScope.launch { kotlin.runCatching { - RetrofitObject.provideHavitApi(token).getAllCategories().data ?: emptyList() + havitApi.getAllCategories().data ?: emptyList() }.onSuccess { categoryList -> val tmp: MutableList = mutableListOf() for (element in categoryList) tmp.add(element.title) @@ -102,8 +103,7 @@ class AddCategoryViewModel @Inject constructor( val title = categoryTitle.value ?: throw IllegalStateException("title") val imageId = selectedIconPosition.value?.plus(1) ?: throw IllegalStateException("position") - RetrofitObject.provideHavitApi(token) - .addCategory(CategoryAddRequest(title, imageId)) + havitApi.addCategory(CategoryAddRequest(title, imageId)) }.onSuccess { _addCategoryViewState.value = NetworkStatus.Success() clearIconPosition() diff --git a/app/src/main/java/org/sopt/havit/ui/share/BottomSheetShareFragment.kt b/app/src/main/java/org/sopt/havit/ui/share/BottomSheetShareFragment.kt index 5915fce9f..f6d81e8f7 100644 --- a/app/src/main/java/org/sopt/havit/ui/share/BottomSheetShareFragment.kt +++ b/app/src/main/java/org/sopt/havit/ui/share/BottomSheetShareFragment.kt @@ -5,6 +5,7 @@ import android.os.Bundle import android.view.LayoutInflater import android.view.View import android.view.ViewGroup +import androidx.activity.OnBackPressedCallback import androidx.navigation.NavGraph.Companion.findStartDestination import androidx.navigation.findNavController import com.google.android.material.bottomsheet.BottomSheetBehavior @@ -21,6 +22,15 @@ class BottomSheetShareFragment : BottomSheetDialogFragment() { private var _binding: FragmentBottomSheetShareBinding? = null private val binding get() = _binding!! + private val onBackPressedCallback = object : OnBackPressedCallback(true) { + override fun handleOnBackPressed() { + if ((getTopmostFragmentOrNull() as? OnBackPressedHandler)?.onBackPressed() == true) return + val navController = binding.fcvShare.findNavController() + if (navController.graph.findStartDestination() == navController.currentDestination) dismiss() + else navController.popBackStack() + } + } + override fun onCreateView( inflater: LayoutInflater, container: ViewGroup?, @@ -48,11 +58,9 @@ class BottomSheetShareFragment : BottomSheetDialogFragment() { // 안드로이드 자체 뒤로가기 눌렀을 때 BackPressed 감지 override fun onCreateDialog(savedInstanceState: Bundle?): Dialog { return object : BottomSheetDialog(requireContext(), R.style.AppBottomSheetDialogTheme) { - override fun onBackPressed() { - if ((getTopmostFragmentOrNull() as? OnBackPressedHandler)?.onBackPressed() == true) return - val navController = binding.fcvShare.findNavController() - if (navController.graph.findStartDestination() == navController.currentDestination) super.onBackPressed() - else navController.popBackStack() + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + onBackPressedDispatcher.addCallback(viewLifecycleOwner, onBackPressedCallback) } } } diff --git a/app/src/main/java/org/sopt/havit/ui/share/ShareViewModel.kt b/app/src/main/java/org/sopt/havit/ui/share/ShareViewModel.kt index 746dd4699..7267840f6 100644 --- a/app/src/main/java/org/sopt/havit/ui/share/ShareViewModel.kt +++ b/app/src/main/java/org/sopt/havit/ui/share/ShareViewModel.kt @@ -10,7 +10,7 @@ import kotlinx.coroutines.launch import org.jsoup.Jsoup import org.jsoup.nodes.Document import org.sopt.havit.BuildConfig -import org.sopt.havit.data.RetrofitObject +import org.sopt.havit.data.api.HavitApi import org.sopt.havit.data.mapper.CategoryMapper import org.sopt.havit.data.remote.ContentsSummeryData import org.sopt.havit.data.remote.CreateContentsRequest @@ -20,7 +20,6 @@ import org.sopt.havit.domain.repository.AuthRepository import org.sopt.havit.ui.share.notification.AfterTime import org.sopt.havit.util.CalenderUtil import org.sopt.havit.util.HavitAuthUtil -import org.sopt.havit.util.HavitSharedPreference import java.util.Calendar import java.util.Date import java.util.regex.Pattern @@ -30,7 +29,7 @@ import javax.inject.Inject class ShareViewModel @Inject constructor( private val authRepository: AuthRepository, private val categoryMapper: CategoryMapper, - private val preference: HavitSharedPreference + private val havitApi: HavitApi ) : ViewModel() { /** token */ fun getAccessToken() = authRepository.getAccessToken() @@ -69,7 +68,7 @@ class ShareViewModel @Inject constructor( viewModelScope.launch { kotlin.runCatching { _categoryViewState.value = NetworkStatus.Loading() - RetrofitObject.provideHavitApi(getAccessToken()).getCategoryList().data + havitApi.getCategoryList().data }.onSuccess { _categoryList.value = it.toMutableList() _categoryNum.value = it.size @@ -237,8 +236,7 @@ class ShareViewModel @Inject constructor( viewModelScope.launch { kotlin.runCatching { val createContentsRequest = getCreateContentsRequest() - RetrofitObject.provideHavitApi(preference.getXAuthToken()) - .createContents(createContentsRequest) + havitApi.createContents(createContentsRequest) }.onSuccess { _saveContentsViewState.value = NetworkStatus.Success() }.onFailure { diff --git a/app/src/main/java/org/sopt/havit/ui/sign/SignUpViewModel.kt b/app/src/main/java/org/sopt/havit/ui/sign/SignUpViewModel.kt index 25035c9e1..77b6c146b 100644 --- a/app/src/main/java/org/sopt/havit/ui/sign/SignUpViewModel.kt +++ b/app/src/main/java/org/sopt/havit/ui/sign/SignUpViewModel.kt @@ -71,6 +71,7 @@ class SignUpViewModel @Inject constructor( }.onSuccess { if (it.success) { authRepository.saveAccessToken(requireNotNull(it.data.accessToken)) + authRepository.saveRefreshToken(requireNotNull(it.data.refreshToken)) _accessToken.postValue(it.data.accessToken) isServerNetwork.postValue(NetworkState.SUCCESS) } diff --git a/app/src/main/java/org/sopt/havit/ui/sign/SplashWithSignActivity.kt b/app/src/main/java/org/sopt/havit/ui/sign/SplashWithSignActivity.kt index e47a805ad..14c12a951 100644 --- a/app/src/main/java/org/sopt/havit/ui/sign/SplashWithSignActivity.kt +++ b/app/src/main/java/org/sopt/havit/ui/sign/SplashWithSignActivity.kt @@ -1,14 +1,21 @@ package org.sopt.havit.ui.sign +import android.Manifest import android.app.Activity import android.content.Intent import android.content.pm.ActivityInfo +import android.content.pm.PackageManager +import android.net.Uri import android.os.Build import android.os.Bundle +import android.provider.Settings import android.view.animation.Animation import android.view.animation.AnimationUtils +import androidx.activity.OnBackPressedCallback import androidx.activity.result.contract.ActivityResultContracts import androidx.activity.viewModels +import androidx.core.app.ActivityCompat +import androidx.core.content.ContextCompat import dagger.hilt.android.AndroidEntryPoint import org.sopt.havit.MainActivity import org.sopt.havit.R @@ -38,6 +45,8 @@ class SplashWithSignActivity : private val signInViewModel: SignInViewModel by viewModels() private var isFromShare by Delegates.notNull() + private val REQUEST_PERMISSION_CODE = 0 + private val alphaLogoAnim by lazy { AnimationUtils.loadAnimation(this, R.anim.alpha_15_to_5_20000).apply { fillAfter = true @@ -52,9 +61,18 @@ class SplashWithSignActivity : } } + private val callback = object : OnBackPressedCallback(true) { + override fun handleOnBackPressed() { + finish() + } + } + override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(binding.root) + + this.onBackPressedDispatcher.addCallback(this, callback) + requestedOrientation = ActivityInfo.SCREEN_ORIENTATION_PORTRAIT binding.main = signInViewModel initFcmToken() @@ -107,7 +125,7 @@ class SplashWithSignActivity : override fun onAnimationRepeat(p0: Animation?) {} override fun onAnimationEnd(p0: Animation?) { - setAutoLogin() + checkAlarmPermission() } }) } else { @@ -163,6 +181,46 @@ class SplashWithSignActivity : ) } + private fun checkAlarmPermission() { + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU && PackageManager.PERMISSION_DENIED == ContextCompat.checkSelfPermission( + this, + Manifest.permission.POST_NOTIFICATIONS + ) + ) { + ActivityCompat.requestPermissions( + this, + arrayOf(Manifest.permission.POST_NOTIFICATIONS), + REQUEST_PERMISSION_CODE + ) + + } else { + setAutoLogin() + } + } + + override fun onRequestPermissionsResult( + requestCode: Int, + permissions: Array, + grantResults: IntArray + ) { + super.onRequestPermissionsResult(requestCode, permissions, grantResults) + when (requestCode) { + REQUEST_PERMISSION_CODE -> { + if (grantResults.isNotEmpty() && grantResults[0] == PackageManager.PERMISSION_GRANTED) { + startOnBoardingActivity() //권한 설정 완료 + } else { + //권한 설정 취소 + val intent: Intent = + Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS).setData( + Uri.parse("package:" + this.packageName) + ) + startActivity(intent) + this.finish() + } + } + } + } + private fun isAlreadyUserObserver() { signInViewModel.isAlreadyUser.observe( this, @@ -185,9 +243,4 @@ class SplashWithSignActivity : super.setRequestedOrientation(requestedOrientation) } } - - override fun onBackPressed() { - super.onBackPressed() - finish() - } } diff --git a/app/src/main/java/org/sopt/havit/ui/web/WebActivity.kt b/app/src/main/java/org/sopt/havit/ui/web/WebActivity.kt index 0f61cc59d..d14f0a3f6 100644 --- a/app/src/main/java/org/sopt/havit/ui/web/WebActivity.kt +++ b/app/src/main/java/org/sopt/havit/ui/web/WebActivity.kt @@ -7,6 +7,7 @@ import android.view.View.GONE import android.view.animation.AnimationUtils import android.webkit.* import android.widget.Toast +import androidx.activity.OnBackPressedCallback import androidx.activity.viewModels import com.bumptech.glide.Glide import dagger.hilt.android.AndroidEntryPoint @@ -28,9 +29,18 @@ class WebActivity : BaseBindingActivity(R.layout.activity_we private var startTime: Int = 0 private var endTime: Int = 0 + private val callback = object : OnBackPressedCallback(true) { + override fun handleOnBackPressed() { + setBackPressedAction() + } + } + override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(binding.root) + + this.onBackPressedDispatcher.addCallback(this, callback) + binding.vm = webViewModel startTime = SystemClock.elapsedRealtime().toInt() initIsHavit() @@ -152,11 +162,9 @@ class WebActivity : BaseBindingActivity(R.layout.activity_we GoogleAnalyticsUtil.logScreenDurationTimeEvent(CONTENT_SCREEN_TIME, endTime - startTime) } - override fun onBackPressed() { - super.onBackPressed() + private fun setBackPressedAction() { super.finish() setWebViewDurationTimeLogging() GoogleAnalyticsUtil.logClickEvent(CLICK_GO_BACK) } - } diff --git a/app/src/main/java/org/sopt/havit/util/HavitSharedPreference.kt b/app/src/main/java/org/sopt/havit/util/HavitSharedPreference.kt index ea620d6ed..23d867dfa 100644 --- a/app/src/main/java/org/sopt/havit/util/HavitSharedPreference.kt +++ b/app/src/main/java/org/sopt/havit/util/HavitSharedPreference.kt @@ -8,16 +8,16 @@ import javax.inject.Inject class HavitSharedPreference @Inject constructor(@ApplicationContext private val context: Context) { companion object { - private const val X_AUTH_TOKEN_1 = "TOKEN" // 정아 + private const val X_AUTH_TOKEN = "ACCESS_TOKEN" private const val FIRST_USER = "FIRST_USER" } fun setXAuthToken(xAuthToken: String) { val prefs: SharedPreferences = - context.getSharedPreferences(X_AUTH_TOKEN_1, Context.MODE_PRIVATE) + context.getSharedPreferences(X_AUTH_TOKEN, Context.MODE_PRIVATE) val editor: SharedPreferences.Editor = prefs.edit() editor.putString( - X_AUTH_TOKEN_1, + X_AUTH_TOKEN, xAuthToken ) editor.apply() @@ -25,13 +25,13 @@ class HavitSharedPreference @Inject constructor(@ApplicationContext private val fun getXAuthToken(): String { val prefs: SharedPreferences = - context.getSharedPreferences(X_AUTH_TOKEN_1, Context.MODE_PRIVATE) - return prefs.getString(X_AUTH_TOKEN_1, "").toString() + context.getSharedPreferences(X_AUTH_TOKEN, Context.MODE_PRIVATE) + return prefs.getString(X_AUTH_TOKEN, "").toString() } fun clearXAuthToken() { val prefs: SharedPreferences = - context.getSharedPreferences(X_AUTH_TOKEN_1, Context.MODE_PRIVATE) + context.getSharedPreferences(X_AUTH_TOKEN, Context.MODE_PRIVATE) prefs.edit().clear().apply() } diff --git a/build.gradle b/build.gradle index b0512d090..4581dbf87 100644 --- a/build.gradle +++ b/build.gradle @@ -5,7 +5,7 @@ buildscript { mavenCentral() } dependencies { - classpath "com.android.tools.build:gradle:7.0.4" + classpath 'com.android.tools.build:gradle:7.3.0' classpath 'org.jetbrains.kotlin:kotlin-gradle-plugin:1.7.10' classpath "androidx.navigation:navigation-safe-args-gradle-plugin:2.4.2" classpath 'com.google.gms:google-services:4.3.15' @@ -18,4 +18,4 @@ buildscript { task clean(type: Delete) { delete rootProject.buildDir -} \ No newline at end of file +} diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index faf676bd4..42e2f3e11 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,6 +1,6 @@ #Tue Jan 11 16:57:39 KST 2022 distributionBase=GRADLE_USER_HOME -distributionUrl=https\://services.gradle.org/distributions/gradle-7.0.2-bin.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-7.4-bin.zip distributionPath=wrapper/dists zipStorePath=wrapper/dists zipStoreBase=GRADLE_USER_HOME