diff --git a/.idea/deploymentTargetDropDown.xml b/.idea/deploymentTargetDropDown.xml index 6c603685..cb33ae7f 100644 --- a/.idea/deploymentTargetDropDown.xml +++ b/.idea/deploymentTargetDropDown.xml @@ -12,6 +12,6 @@ - + \ No newline at end of file diff --git a/README.md b/README.md index 61e20ea6..a4af2034 100644 --- a/README.md +++ b/README.md @@ -1,19 +1,55 @@ -# Surveasy-app +# ✅ Surveasy 서베이지 +
-✅ 서베이지 패널용 안드로이드 어플 workspace 입니다. +## ⚙️ 주요 기능 +* 서베이지 웹에 올라오는 설문에 참여 +* 참여한 설문에 해당하는 리워드 지급 + +

+## 📚 기술 스택 ---- +| 분류 | 사용기술 | +| ------------- | ----------------------------------------- | +| 아키텍처 | MVVM, Clean Architecture | +| 네트워크 통신 | Retrofit, Okhttp | +| 이미지 처리 | Glide | +| 비동기 | Coroutine, Flow | +| jetpack | Navigation, Hilt, DataBinding, viewpager2 | +| 데이터 | Datastore | +| etc | Firebase | +

-### ⚙️ 주요 기능 -* 서베이지 웹에 올라오는 설문에 참여 -* 참여한 설문에 해당하는 리워드 지급 -* 다양한 주제의 poll에 참여 +## 📲 주요 기능 동작 화면 + +### 로그인 / 회원가입 +기존 회원 로그인 및 신규 회원 카카오 로그인| +|------| +|| + +
+ +### 설문 참여 +설문 상세 확인|설문 참여| +|------|---| +||| + +
-### 📱 설치 방법 +### 주요 화면 + +설문 리스트|정산 내역 확인| +|------|---| +||| + + + + +

+ +## 📱 설치 방법 * play store 에 "서베이지" 검색 후 다운로드 * https://play.google.com/store/apps/details?id=com.surveasy.surveasy - diff --git a/app/.gitignore b/app/.gitignore index 42afabfd..ea5db48b 100644 --- a/app/.gitignore +++ b/app/.gitignore @@ -1 +1,168 @@ -/build \ No newline at end of file +/build + +### macOS ### +# General +.DS_Store +.AppleDouble +.LSOverride + +# Icon must end with two \r +Icon + + +# Thumbnails +._* + +# Files that might appear in the root of a volume +.DocumentRevisions-V100 +.fseventsd +.Spotlight-V100 +.TemporaryItems +.Trashes +.VolumeIcon.icns +.com.apple.timemachine.donotpresent + +# Directories potentially created on remote AFP share +.AppleDB +.AppleDesktop +Network Trash Folder +Temporary Items +.apdisk + +### macOS Patch ### +# iCloud generated files +*.icloud + +### AndroidStudio ### +# Covers files to be ignored for android development using Android Studio. + +# Built application files +*.apk +*.ap_ +*.aab + +# Files for the ART/Dalvik VM +*.dex + +# Java class files +*.class + +# Generated files +bin/ +gen/ +out/ + +# Gradle files +.gradle +.gradle/ +build/ + +# Signing files +.signing/ + +# Local configuration file (sdk path, etc) +local.properties + +# Proguard folder generated by Eclipse +proguard/ + +# Log Files +*.log + +# Android Studio +/*/build/ +/*/local.properties +/*/out +/*/*/build +/*/*/production +captures/ +.navigation/ +*.ipr +*~ +*.swp + +# Keystore files +*.jks +*.keystore + +# Google Services (e.g. APIs or Firebase) +# google-services.json + +# Android Patch +gen-external-apklibs + +# External native build folder generated in Android Studio 2.2 and later +.externalNativeBuild + +# NDK +obj/ + +# IntelliJ IDEA +*.iml +*.iws +/out/ + +# User-specific configurations +.idea/caches/ +.idea/libraries/ +.idea/shelf/ +.idea/workspace.xml +.idea/tasks.xml +.idea/.name +.idea/compiler.xml +.idea/copyright/profiles_settings.xml +.idea/encodings.xml +.idea/misc.xml +.idea/modules.xml +.idea/scopes/scope_settings.xml +.idea/dictionaries +.idea/vcs.xml +.idea/jsLibraryMappings.xml +.idea/datasources.xml +.idea/dataSources.ids +.idea/sqlDataSources.xml +.idea/dynamic.xml +.idea/uiDesigner.xml +.idea/assetWizardSettings.xml +.idea/gradle.xml +.idea/jarRepositories.xml +.idea/navEditor.xml + +# Legacy Eclipse project files +.classpath +.project +.cproject +.settings/ + +# Mobile Tools for Java (J2ME) +.mtj.tmp/ + +# Package Files # +*.war +*.ear + +# virtual machine crash logs (Reference: http://www.java.com/en/download/help/error_hotspot.xml) +hs_err_pid* + +## Plugin-specific files: + +# mpeltonen/sbt-idea plugin +.idea_modules/ + +# JIRA plugin +atlassian-ide-plugin.xml + +# Mongo Explorer plugin +.idea/mongoSettings.xml + +# Crashlytics plugin (for Android Studio and IntelliJ) +com_crashlytics_export_strings.xml +crashlytics.properties +crashlytics-build.properties +fabric.properties + +### AndroidStudio Patch ### + +!/gradle/wrapper/gradle-wrapper.jar + +# End of https://www.toptal.com/developers/gitignore/api/macos,androidstudio \ No newline at end of file diff --git a/app/build.gradle.kts b/app/build.gradle.kts index 8d91a763..fa437298 100644 --- a/app/build.gradle.kts +++ b/app/build.gradle.kts @@ -23,8 +23,8 @@ android { applicationId = "com.surveasy.surveasy" minSdk = 24 targetSdk = 34 - versionCode = 46 - versionName = "2.0.6" + versionCode = 60 + versionName = "2.1.5" testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner" @@ -105,10 +105,16 @@ dependencies { implementation("com.google.firebase:firebase-auth-ktx:22.1.2") implementation("com.google.firebase:firebase-analytics") implementation("com.google.firebase:firebase-storage-ktx") + implementation("com.google.firebase:firebase-config-ktx") + implementation("com.google.firebase:firebase-messaging-ktx") // indicator implementation("com.tbuonomo:dotsindicator:4.2") // kakao implementation("com.kakao.sdk:v2-user:2.11.2") + + //inapp update + implementation("com.google.android.play:app-update-ktx:2.1.0") + } \ No newline at end of file diff --git a/app/release/app-release.aab b/app/release/app-release.aab index df4bfc1a..9ba16e43 100644 Binary files a/app/release/app-release.aab and b/app/release/app-release.aab differ diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index e8181925..ea9711cd 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -6,6 +6,7 @@ + @@ -87,6 +88,14 @@ android:name=".presentation.intro.IntroActivity" android:exported="true" android:windowSoftInputMode="adjustPan" /> + + + + + + \ No newline at end of file diff --git a/app/src/main/java/com/surveasy/surveasy/app/MyFirebaseMessagingService.kt b/app/src/main/java/com/surveasy/surveasy/app/MyFirebaseMessagingService.kt new file mode 100644 index 00000000..92d7f10b --- /dev/null +++ b/app/src/main/java/com/surveasy/surveasy/app/MyFirebaseMessagingService.kt @@ -0,0 +1,17 @@ +package com.surveasy.surveasy.app + +import android.util.Log +import com.google.firebase.messaging.FirebaseMessagingService +import com.google.firebase.messaging.RemoteMessage + +class MyFirebaseMessagingService : FirebaseMessagingService() { + override fun onMessageReceived(message: RemoteMessage) { + super.onMessageReceived(message) + } + + override fun onNewToken(token: String) { + super.onNewToken(token) + Log.d("TAG", "onNewToken: $token") + } + +} \ No newline at end of file diff --git a/app/src/main/java/com/surveasy/surveasy/app/di/FirebaseModule.kt b/app/src/main/java/com/surveasy/surveasy/app/di/FirebaseModule.kt index 19d03d3b..847f715f 100644 --- a/app/src/main/java/com/surveasy/surveasy/app/di/FirebaseModule.kt +++ b/app/src/main/java/com/surveasy/surveasy/app/di/FirebaseModule.kt @@ -2,6 +2,7 @@ package com.surveasy.surveasy.app.di import com.google.firebase.Firebase import com.google.firebase.auth.FirebaseAuth +import com.google.firebase.messaging.FirebaseMessaging import dagger.Module import dagger.Provides import dagger.hilt.InstallIn @@ -20,4 +21,8 @@ object FirebaseModule { @Provides @Singleton fun provideFirebaseStorage(): Firebase = Firebase + + @Provides + @Singleton + fun provideFirebaseMessaging(): FirebaseMessaging = FirebaseMessaging.getInstance() } \ No newline at end of file diff --git a/app/src/main/java/com/surveasy/surveasy/app/di/NetworkModule.kt b/app/src/main/java/com/surveasy/surveasy/app/di/NetworkModule.kt index 972c6f8a..c53df842 100644 --- a/app/src/main/java/com/surveasy/surveasy/app/di/NetworkModule.kt +++ b/app/src/main/java/com/surveasy/surveasy/app/di/NetworkModule.kt @@ -1,9 +1,9 @@ package com.surveasy.surveasy.app.di import com.surveasy.surveasy.BuildConfig -import com.surveasy.surveasy.app.DataStoreManager import com.surveasy.surveasy.data.config.AccessTokenInterceptor import com.surveasy.surveasy.data.config.BearerInterceptor +import com.surveasy.surveasy.data.config.RetryInterceptor import dagger.Module import dagger.Provides import dagger.hilt.InstallIn @@ -23,12 +23,15 @@ object NetworkModule { fun provideOkHttpClient( httpLoggingInterceptor: HttpLoggingInterceptor, accessTokenInterceptor: AccessTokenInterceptor, - bearerInterceptor: BearerInterceptor + bearerInterceptor: BearerInterceptor, + retryInterceptor: RetryInterceptor, ): OkHttpClient { return OkHttpClient.Builder() .readTimeout(10000, TimeUnit.MILLISECONDS) .connectTimeout(10000, TimeUnit.MILLISECONDS) + .writeTimeout(10000, TimeUnit.MILLISECONDS) + .addInterceptor(retryInterceptor) .addInterceptor(httpLoggingInterceptor) .addNetworkInterceptor(accessTokenInterceptor) .addInterceptor(bearerInterceptor) @@ -43,10 +46,6 @@ object NetworkModule { } } - @Provides - fun provideAccessTokenInterceptor(dataStoreManager: DataStoreManager): AccessTokenInterceptor = - AccessTokenInterceptor(dataStoreManager) - @Provides fun provideRetrofit(okHttpClient: OkHttpClient): Retrofit { diff --git a/app/src/main/java/com/surveasy/surveasy/app/di/RepositoryModule.kt b/app/src/main/java/com/surveasy/surveasy/app/di/RepositoryModule.kt index c3f9c7eb..bf4e3eaf 100644 --- a/app/src/main/java/com/surveasy/surveasy/app/di/RepositoryModule.kt +++ b/app/src/main/java/com/surveasy/surveasy/app/di/RepositoryModule.kt @@ -2,6 +2,7 @@ package com.surveasy.surveasy.app.di import com.google.firebase.Firebase import com.google.firebase.auth.FirebaseAuth +import com.google.firebase.messaging.FirebaseMessaging import com.surveasy.surveasy.data.remote.SurveasyApi import com.surveasy.surveasy.data.repository.FirebaseRepositoryImpl import com.surveasy.surveasy.data.repository.PanelRepositoryImpl @@ -25,8 +26,12 @@ object RepositoryModule { @Singleton @Provides - fun provideFirebaseRepository(fbAuth: FirebaseAuth, fb: Firebase): FirebaseRepository = - FirebaseRepositoryImpl(fbAuth, fb) + fun provideFirebaseRepository( + fbAuth: FirebaseAuth, + fb: Firebase, + fcm: FirebaseMessaging + ): FirebaseRepository = + FirebaseRepositoryImpl(fbAuth, fb, fcm) @Singleton @Provides diff --git a/app/src/main/java/com/surveasy/surveasy/data/config/RetryInterceptor.kt b/app/src/main/java/com/surveasy/surveasy/data/config/RetryInterceptor.kt new file mode 100644 index 00000000..c53dde69 --- /dev/null +++ b/app/src/main/java/com/surveasy/surveasy/data/config/RetryInterceptor.kt @@ -0,0 +1,32 @@ +package com.surveasy.surveasy.data.config + +import okhttp3.Interceptor +import okhttp3.Response +import java.io.IOException +import javax.inject.Inject + +class RetryInterceptor @Inject constructor() : + Interceptor { + + @Throws(IOException::class) + override fun intercept(chain: Interceptor.Chain): Response { + + var retryCount = 0 + val request = chain.request() + var response = chain.proceed(request) + + while (response.code == RETRY_ERROR && retryCount < RETRY_MAX) { + retryCount++ + response.close() + response = chain.proceed(request) + } + + return response + + } + + companion object { + const val RETRY_ERROR = 400 + const val RETRY_MAX = 2 + } +} \ No newline at end of file diff --git a/app/src/main/java/com/surveasy/surveasy/data/model/response/HistoryResponse.kt b/app/src/main/java/com/surveasy/surveasy/data/model/response/HistoryResponse.kt index cb1c7ee4..0b1a49f4 100644 --- a/app/src/main/java/com/surveasy/surveasy/data/model/response/HistoryResponse.kt +++ b/app/src/main/java/com/surveasy/surveasy/data/model/response/HistoryResponse.kt @@ -30,6 +30,8 @@ data class HistorySurveyResponse( val imgUrl: String, val createdAt: String, val sentAt: String?, + val responseStatus: String?, + val surveyStatus: String?, ) : BaseDataModel { companion object : DomainMapper { override fun HistorySurveyResponse.toDomainModel(): HistorySurvey = HistorySurvey( @@ -38,7 +40,9 @@ data class HistorySurveyResponse( reward = reward, imgUrl = imgUrl, createdAt = createdAt, - sentAt = sentAt + sentAt = sentAt, + responseStatus = responseStatus, + surveyStatus = surveyStatus, ) } } \ No newline at end of file diff --git a/app/src/main/java/com/surveasy/surveasy/data/repository/FirebaseRepositoryImpl.kt b/app/src/main/java/com/surveasy/surveasy/data/repository/FirebaseRepositoryImpl.kt index f116b4f8..154af930 100644 --- a/app/src/main/java/com/surveasy/surveasy/data/repository/FirebaseRepositoryImpl.kt +++ b/app/src/main/java/com/surveasy/surveasy/data/repository/FirebaseRepositoryImpl.kt @@ -3,6 +3,9 @@ package com.surveasy.surveasy.data.repository import android.net.Uri import com.google.firebase.Firebase import com.google.firebase.auth.FirebaseAuth +import com.google.firebase.messaging.FirebaseMessaging +import com.google.firebase.remoteconfig.remoteConfig +import com.google.firebase.remoteconfig.remoteConfigSettings import com.google.firebase.storage.storage import com.surveasy.surveasy.domain.repository.FirebaseRepository import kotlinx.coroutines.tasks.await @@ -10,7 +13,8 @@ import javax.inject.Inject class FirebaseRepositoryImpl @Inject constructor( private val firebaseAuth: FirebaseAuth, - private val firebase: Firebase + private val firebase: Firebase, + private val firebaseMessaging: FirebaseMessaging ) : FirebaseRepository { override suspend fun getFbUid(email: String, pw: String): String { return try { @@ -46,4 +50,52 @@ class FirebaseRepositoryImpl @Inject constructor( } } + override suspend fun getFcmToken(): String { + return try { + val task = firebaseMessaging.token + task.await() + + if (task.isSuccessful) { + task.result.toString() + } else { + "" + } + } catch (e: Exception) { + "" + } + } + + override suspend fun checkVersion(version: String): Boolean { + + + return try { + + val remoteConfig = Firebase.remoteConfig + val configSettings = remoteConfigSettings { + minimumFetchIntervalInSeconds = 3600 + } + remoteConfig.setConfigSettingsAsync(configSettings) + + val defaultConfigMap = mapOf( + REMOTE_KEY to "0.0.0" + ) + remoteConfig.setDefaultsAsync(defaultConfigMap) + + val task = remoteConfig.fetchAndActivate() + task.await() + if (task.isSuccessful) { + val targetVersion = remoteConfig.getString(REMOTE_KEY) + targetVersion <= version + } else { + true + } + } catch (e: Exception) { + true + } + } + + companion object { + const val REMOTE_KEY = "version" + } + } \ No newline at end of file diff --git a/app/src/main/java/com/surveasy/surveasy/domain/model/History.kt b/app/src/main/java/com/surveasy/surveasy/domain/model/History.kt index 904caae4..8cd87c43 100644 --- a/app/src/main/java/com/surveasy/surveasy/domain/model/History.kt +++ b/app/src/main/java/com/surveasy/surveasy/domain/model/History.kt @@ -15,4 +15,6 @@ data class HistorySurvey( val imgUrl: String, val createdAt: String, val sentAt: String?, + val responseStatus: String?, + val surveyStatus: String?, ) : BaseDomainModel diff --git a/app/src/main/java/com/surveasy/surveasy/domain/repository/FirebaseRepository.kt b/app/src/main/java/com/surveasy/surveasy/domain/repository/FirebaseRepository.kt index 93c4cadb..ccec21ab 100644 --- a/app/src/main/java/com/surveasy/surveasy/domain/repository/FirebaseRepository.kt +++ b/app/src/main/java/com/surveasy/surveasy/domain/repository/FirebaseRepository.kt @@ -5,4 +5,8 @@ interface FirebaseRepository { suspend fun getFbUid(email: String, pw: String): String suspend fun loadImage(uri: String, id: Int, imgName: String): String + + suspend fun getFcmToken(): String + + suspend fun checkVersion(version: String): Boolean } \ No newline at end of file diff --git a/app/src/main/java/com/surveasy/surveasy/domain/usecase/CheckVersionUseCase.kt b/app/src/main/java/com/surveasy/surveasy/domain/usecase/CheckVersionUseCase.kt new file mode 100644 index 00000000..566289bc --- /dev/null +++ b/app/src/main/java/com/surveasy/surveasy/domain/usecase/CheckVersionUseCase.kt @@ -0,0 +1,9 @@ +package com.surveasy.surveasy.domain.usecase + +import com.surveasy.surveasy.domain.repository.FirebaseRepository +import javax.inject.Inject + +class CheckVersionUseCase @Inject constructor(private val repository: FirebaseRepository) { + suspend operator fun invoke(version: String): Boolean = + repository.checkVersion(version) +} \ No newline at end of file diff --git a/app/src/main/java/com/surveasy/surveasy/domain/usecase/GetFcmTokenUseCase.kt b/app/src/main/java/com/surveasy/surveasy/domain/usecase/GetFcmTokenUseCase.kt new file mode 100644 index 00000000..50944538 --- /dev/null +++ b/app/src/main/java/com/surveasy/surveasy/domain/usecase/GetFcmTokenUseCase.kt @@ -0,0 +1,10 @@ +package com.surveasy.surveasy.domain.usecase + +import com.surveasy.surveasy.domain.repository.FirebaseRepository +import javax.inject.Inject + +class GetFcmTokenUseCase @Inject constructor( + private val repository: FirebaseRepository +) { + suspend operator fun invoke(): String = repository.getFcmToken() +} \ No newline at end of file diff --git a/app/src/main/java/com/surveasy/surveasy/presentation/bindingadapters/TextBindingAdatper.kt b/app/src/main/java/com/surveasy/surveasy/presentation/bindingadapters/TextBindingAdatper.kt index 1b39a3d0..3ef78f0a 100644 --- a/app/src/main/java/com/surveasy/surveasy/presentation/bindingadapters/TextBindingAdatper.kt +++ b/app/src/main/java/com/surveasy/surveasy/presentation/bindingadapters/TextBindingAdatper.kt @@ -25,7 +25,7 @@ fun TextView.rewardTitle(reward: Int) { @BindingAdapter("englishTitle") fun TextView.englishTitle(english: Boolean) { - text = if (english) "영어 설문에 참여합니다." else "영어 설문에 참여하지 않습니다." + text = resources.getText(if (english) R.string.my_english_yes else R.string.my_english_no) } @BindingAdapter("respondedCnt", "totalCnt") @@ -38,9 +38,9 @@ fun TextView.getReward(reward: Int) { text = "${reward}원 받기" } -@BindingAdapter("sentDay") -fun TextView.sentDay(date: Int) { - text = "이번달 ${date}일 정산 예정이에요!" +@BindingAdapter("sentMonth", "sentDay") +fun TextView.sentDay(month: String, date: Int) { + text = "$month ${date}일 정산 예정이에요!" } @BindingAdapter("setHelperText") @@ -59,4 +59,15 @@ fun TextInputLayout.nameHelperText(state: InputState) { fun TextView.setDoneLabel(item: UiSurveyListData) { text = resources.getText(if (item.participated) R.string.list_participate else R.string.list_done) +} + +@BindingAdapter("historyBefore", "historyDone") +fun TextView.setHistoryAlertText(isBefore: Boolean, isDone: Boolean?) { + text = if (!isBefore) { + resources.getText(R.string.history_warn2_label) + } else if (isDone == true) { + resources.getText(R.string.history_warn2_label) + } else { + resources.getText(R.string.history_warn1_label) + } } \ No newline at end of file diff --git a/app/src/main/java/com/surveasy/surveasy/presentation/main/MainActivity.kt b/app/src/main/java/com/surveasy/surveasy/presentation/main/MainActivity.kt index dc11883e..a1e81e56 100644 --- a/app/src/main/java/com/surveasy/surveasy/presentation/main/MainActivity.kt +++ b/app/src/main/java/com/surveasy/surveasy/presentation/main/MainActivity.kt @@ -1,18 +1,25 @@ package com.surveasy.surveasy.presentation.main +import android.content.Intent +import android.net.Uri import androidx.activity.viewModels +import androidx.lifecycle.lifecycleScope import androidx.navigation.NavController import androidx.navigation.fragment.NavHostFragment import androidx.navigation.ui.setupWithNavController +import com.google.android.play.core.appupdate.AppUpdateManager +import com.google.android.play.core.appupdate.AppUpdateManagerFactory import com.surveasy.surveasy.R import com.surveasy.surveasy.databinding.ActivityMainBinding import com.surveasy.surveasy.presentation.base.BaseActivity import dagger.hilt.android.AndroidEntryPoint +import kotlinx.coroutines.launch @AndroidEntryPoint class MainActivity : BaseActivity(ActivityMainBinding::inflate) { private lateinit var navHostFragment: NavHostFragment private lateinit var navController: NavController + private lateinit var appUpdateManager: AppUpdateManager private val viewModel: MainViewModel by viewModels() override fun initData() = Unit @@ -22,6 +29,7 @@ class MainActivity : BaseActivity(ActivityMainBinding::infl viewModel.events.collect { when (it) { is MainEvents.FinishApp -> finish() + else -> Unit } } } @@ -32,6 +40,86 @@ class MainActivity : BaseActivity(ActivityMainBinding::infl supportFragmentManager.findFragmentById(R.id.nav_host_fragment) as NavHostFragment navController = navHostFragment.navController binding.bnvNavBar.setupWithNavController(navController) + val appVersion = packageManager.getPackageInfo(packageName, 0).versionName + lifecycleScope.launch { viewModel.checkVersion(appVersion) } + + appUpdateManager = AppUpdateManagerFactory.create(this) + } + + private fun goStore() { + val uri = "https://play.google.com/store/apps/details?id=com.surveasy.surveasy" + val intent = Intent(Intent.ACTION_VIEW, Uri.parse(uri)) + startActivity(intent) } +// private fun checkUpdate() { +// var appUpdateInfoTask = appUpdateManager.appUpdateInfo +// appUpdateInfoTask.addOnSuccessListener { appUpdateInfo -> +// +// // 업데이트 가능한 구버전 상태 +// if (appUpdateInfo.updateAvailability() == UpdateAvailability.UPDATE_AVAILABLE +// && appUpdateInfo.isUpdateTypeAllowed(AppUpdateType.IMMEDIATE) +// ) { +// // Request the update. +// appUpdateManager.startUpdateFlowForResult( +// appUpdateInfo, +// AppUpdateType.IMMEDIATE, +// this, +// REQUEST_CODE_UPDATE +// ) +// +// appUpdateManager.startUpdateFlowForResult( +// // Pass the intent that is returned by 'getAppUpdateInfo()'. +// appUpdateInfo, +// // an activity result launcher registered via registerForActivityResult +// activityResultLauncher, +// // Or pass 'AppUpdateType.FLEXIBLE' to newBuilder() for +// // flexible updates. +// AppUpdateOptions.newBuilder(AppUpdateType.IMMEDIATE).build()) +// +// } +// +// else { +// // 업데이트 필요 없는 최신 상태 +// } +// +// +// } +// } + +// // 업데이트 취소나 실패 콜백 +// override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) { +// super.onActivityResult(requestCode, resultCode, data) +// +// if (requestCode == REQUEST_CODE_UPDATE) { +// if (resultCode != RESULT_OK) { +// Log.e("MY_APP", "Update flow failed! Result code: $resultCode") +// +// } +// } +// } +// +// +// // 어플이 다시 불러와졌을 경우, 업데이트 이어서 계속 진행 +// override fun onResume() { +// super.onResume() +// +// appUpdateManager.appUpdateInfo.addOnSuccessListener { appUpdateInfo -> +// if (appUpdateInfo.updateAvailability() == UpdateAvailability.DEVELOPER_TRIGGERED_UPDATE_IN_PROGRESS) { +// // If an in-app update is already running, resume the update. +// appUpdateManager.startUpdateFlowForResult( +// appUpdateInfo, +// AppUpdateType.IMMEDIATE, +// this, +// REQUEST_CODE_UPDATE) +// +// } +// } +// +// } +// +// companion object { +// const val REQUEST_CODE_UPDATE = 9999 +// } + } \ No newline at end of file diff --git a/app/src/main/java/com/surveasy/surveasy/presentation/main/MainViewModel.kt b/app/src/main/java/com/surveasy/surveasy/presentation/main/MainViewModel.kt index c5aff54d..ec5bcac4 100644 --- a/app/src/main/java/com/surveasy/surveasy/presentation/main/MainViewModel.kt +++ b/app/src/main/java/com/surveasy/surveasy/presentation/main/MainViewModel.kt @@ -2,20 +2,39 @@ package com.surveasy.surveasy.presentation.main import androidx.lifecycle.ViewModel import androidx.lifecycle.viewModelScope +import com.surveasy.surveasy.domain.usecase.CheckVersionUseCase +import dagger.hilt.android.lifecycle.HiltViewModel +import kotlinx.coroutines.async import kotlinx.coroutines.flow.MutableSharedFlow import kotlinx.coroutines.flow.SharedFlow import kotlinx.coroutines.flow.asSharedFlow import kotlinx.coroutines.launch +import javax.inject.Inject -class MainViewModel : ViewModel() { +@HiltViewModel +class MainViewModel @Inject constructor( + private val checkVersionUseCase: CheckVersionUseCase +) : ViewModel() { private val _events = MutableSharedFlow() val events: SharedFlow = _events.asSharedFlow() + fun finishApp() = viewModelScope.launch { _events.emit(MainEvents.FinishApp) } + + suspend fun checkVersion(version: String) { + val isUpdated = viewModelScope.async { + checkVersionUseCase(version) + }.await() + + if (!isUpdated) { + _events.emit(MainEvents.UpdateDialog) + } + } } sealed class MainEvents { data object FinishApp : MainEvents() + data object UpdateDialog : MainEvents() } \ No newline at end of file diff --git a/app/src/main/java/com/surveasy/surveasy/presentation/main/home/HomeFragment.kt b/app/src/main/java/com/surveasy/surveasy/presentation/main/home/HomeFragment.kt index 9881b87e..c2a2127f 100644 --- a/app/src/main/java/com/surveasy/surveasy/presentation/main/home/HomeFragment.kt +++ b/app/src/main/java/com/surveasy/surveasy/presentation/main/home/HomeFragment.kt @@ -1,6 +1,9 @@ package com.surveasy.surveasy.presentation.main.home import android.content.Intent +import android.net.Uri +import android.text.SpannableString +import android.text.style.UnderlineSpan import androidx.activity.OnBackPressedCallback import androidx.fragment.app.activityViewModels import androidx.fragment.app.viewModels @@ -14,6 +17,7 @@ import com.surveasy.surveasy.presentation.main.home.notice.HomeNoticeActivity import com.surveasy.surveasy.presentation.main.survey.SurveyActivity import com.surveasy.surveasy.presentation.main.survey.fs.FsActivity import com.surveasy.surveasy.presentation.util.IntentId +import com.surveasy.surveasy.presentation.util.showTwoButtonDialog import dagger.hilt.android.AndroidEntryPoint @AndroidEntryPoint @@ -33,7 +37,10 @@ class HomeFragment : BaseFragment(R.layout.fragment_home) { vm = viewModel rvHomeList.adapter = adapter rvHomeList.animation = null + drawUnderLine() + tvAlertTitle.setOnClickListener { showAlertDialog() } finishApp() + // repeatOnStarted { viewModel.getFcmToken() } } override fun initEventObserver() { @@ -70,6 +77,30 @@ class HomeFragment : BaseFragment(R.layout.fragment_home) { startActivity(intent) } + private fun drawUnderLine() { + val ss = SpannableString(binding.tvAlertTitle.text.toString()) + ss.setSpan(UnderlineSpan(), 0, ss.length, 0) + binding.tvAlertTitle.text = ss + } + + private fun showAlertDialog() = with(resources) { + showTwoButtonDialog( + requireContext(), + getString(R.string.alert_title), + getString(R.string.alert_content), + getString(R.string.alert_yes), + getString(R.string.alert_no), + { goChatLink() }, + {} + ) + } + + private fun goChatLink() { + val uri = "https://open.kakao.com/o/g9K6Y3Qg" + val intent = Intent(Intent.ACTION_VIEW, Uri.parse(uri)) + startActivity(intent) + } + private fun finishApp() { var backPressTime = 0L requireActivity().onBackPressedDispatcher.addCallback(object : OnBackPressedCallback(true) { @@ -78,7 +109,7 @@ class HomeFragment : BaseFragment(R.layout.fragment_home) { parentViewModel.finishApp() } else { backPressTime = System.currentTimeMillis() - showToastMessage("뒤로가기 버튼을 한 번 더 누르면 종료됩니다.") + showToastMessage(resources.getString(R.string.back_alert)) } } }) diff --git a/app/src/main/java/com/surveasy/surveasy/presentation/main/home/HomeViewModel.kt b/app/src/main/java/com/surveasy/surveasy/presentation/main/home/HomeViewModel.kt index 60ecccce..e2c004e3 100644 --- a/app/src/main/java/com/surveasy/surveasy/presentation/main/home/HomeViewModel.kt +++ b/app/src/main/java/com/surveasy/surveasy/presentation/main/home/HomeViewModel.kt @@ -4,6 +4,7 @@ import androidx.lifecycle.ViewModel import androidx.lifecycle.viewModelScope import com.surveasy.surveasy.app.DataStoreManager import com.surveasy.surveasy.domain.base.BaseState +import com.surveasy.surveasy.domain.usecase.GetFcmTokenUseCase import com.surveasy.surveasy.domain.usecase.ListHomeSurveyUseCase import com.surveasy.surveasy.domain.usecase.QueryPanelInfoUseCase import com.surveasy.surveasy.presentation.main.home.mapper.toUiHomeListData @@ -30,6 +31,7 @@ class HomeViewModel @Inject constructor( private val queryPanelInfoUseCase: QueryPanelInfoUseCase, private val listHomeSurveyUseCase: ListHomeSurveyUseCase, private val dataStoreManager: DataStoreManager, + private val getFcmTokenUseCase: GetFcmTokenUseCase, ) : ViewModel() { private val _uiState = MutableStateFlow(HomeUiState()) val uiState: StateFlow = _uiState.asStateFlow() @@ -88,6 +90,14 @@ class HomeViewModel @Inject constructor( }.launchIn(viewModelScope) } +// suspend fun getFcmToken() { +// val fcmToken = viewModelScope.async { +// getFcmTokenUseCase() +// }.await() +// +// Log.d("TAG", "getFcmToken: $fcmToken") +// } + fun navigateToSurveyDetail(id: Int) { viewModelScope.launch { _events.emit(HomeEvents.ClickSurveyItem(id)) } } diff --git a/app/src/main/java/com/surveasy/surveasy/presentation/main/home/mapper/UiHomeListDataMapper.kt b/app/src/main/java/com/surveasy/surveasy/presentation/main/home/mapper/UiHomeListDataMapper.kt index 62bee117..a1191525 100644 --- a/app/src/main/java/com/surveasy/surveasy/presentation/main/home/mapper/UiHomeListDataMapper.kt +++ b/app/src/main/java/com/surveasy/surveasy/presentation/main/home/mapper/UiHomeListDataMapper.kt @@ -7,6 +7,6 @@ fun HomeSurveyInfo.toUiHomeListData(): UiHomeListData = UiHomeListData( id = id, title = title, reward = reward, - targetInput = targetInput ?: "모두", + targetInput = if(targetInput.isNullOrEmpty()) "모두" else targetInput, responseCount = responseCount, ) \ No newline at end of file diff --git a/app/src/main/java/com/surveasy/surveasy/presentation/main/list/ListFragment.kt b/app/src/main/java/com/surveasy/surveasy/presentation/main/list/ListFragment.kt index 94b4d918..22fa3bd1 100644 --- a/app/src/main/java/com/surveasy/surveasy/presentation/main/list/ListFragment.kt +++ b/app/src/main/java/com/surveasy/surveasy/presentation/main/list/ListFragment.kt @@ -79,7 +79,7 @@ class ListFragment : BaseFragment(R.layout.fragment_list) { parentViewModel.finishApp() } else { backPressTime = System.currentTimeMillis() - showToastMessage("뒤로가기 버튼을 한 번 더 누르면 종료됩니다.") + showToastMessage(resources.getString(R.string.back_alert)) } } }) diff --git a/app/src/main/java/com/surveasy/surveasy/presentation/main/list/mapper/UiSurveyListDataMapper.kt b/app/src/main/java/com/surveasy/surveasy/presentation/main/list/mapper/UiSurveyListDataMapper.kt index 4ae1603b..c2422178 100644 --- a/app/src/main/java/com/surveasy/surveasy/presentation/main/list/mapper/UiSurveyListDataMapper.kt +++ b/app/src/main/java/com/surveasy/surveasy/presentation/main/list/mapper/UiSurveyListDataMapper.kt @@ -9,9 +9,9 @@ fun SurveyInfo.toUiSurveyListData(): UiSurveyListData = UiSurveyListData( reward = reward, headCount = headCount, spendTime = spendTime, - targetInput = targetInput ?: "모두", + targetInput = if(targetInput.isNullOrEmpty()) "모두" else targetInput, status = status, - responseCount = responseCount, + responseCount = if(responseCount > headCount) headCount - 1 else responseCount, participated = participated, overdue = overdue ) \ No newline at end of file diff --git a/app/src/main/java/com/surveasy/surveasy/presentation/main/my/MyFragment.kt b/app/src/main/java/com/surveasy/surveasy/presentation/main/my/MyFragment.kt index 301588ef..038f7abc 100644 --- a/app/src/main/java/com/surveasy/surveasy/presentation/main/my/MyFragment.kt +++ b/app/src/main/java/com/surveasy/surveasy/presentation/main/my/MyFragment.kt @@ -74,7 +74,7 @@ class MyFragment : BaseFragment(R.layout.fragment_my) { parentViewModel.finishApp() } else { backPressTime = System.currentTimeMillis() - showToastMessage("뒤로가기 버튼을 한 번 더 누르면 종료됩니다.") + showToastMessage(resources.getString(R.string.back_alert)) } } }) diff --git a/app/src/main/java/com/surveasy/surveasy/presentation/main/my/contact/ContactActivity.kt b/app/src/main/java/com/surveasy/surveasy/presentation/main/my/contact/ContactActivity.kt index 36ee4bb7..05136fd0 100644 --- a/app/src/main/java/com/surveasy/surveasy/presentation/main/my/contact/ContactActivity.kt +++ b/app/src/main/java/com/surveasy/surveasy/presentation/main/my/contact/ContactActivity.kt @@ -21,7 +21,7 @@ class ContactActivity : BaseActivity(ActivityContactBind val clipData = ClipData.newPlainText("text", resources.getText(R.string.my_email)) clipboardManager.setPrimaryClip(clipData) - showToastMessage("이메일 주소가 복사되었습니다.") + showToastMessage(resources.getString(R.string.email_copy)) } ivBack.setOnClickListener { finish() } diff --git a/app/src/main/java/com/surveasy/surveasy/presentation/main/my/history/HistoryEditFragment.kt b/app/src/main/java/com/surveasy/surveasy/presentation/main/my/history/HistoryEditFragment.kt index 140c0895..4b109f02 100644 --- a/app/src/main/java/com/surveasy/surveasy/presentation/main/my/history/HistoryEditFragment.kt +++ b/app/src/main/java/com/surveasy/surveasy/presentation/main/my/history/HistoryEditFragment.kt @@ -58,15 +58,15 @@ class HistoryEditFragment : } } - private fun showDialogToGetPermission() { + private fun showDialogToGetPermission() = with(resources) { showTwoButtonDialog( requireContext(), - "권한이 필요합니다", - "설문 완료 인증 캡쳐본을 전송하기 위해서 접근 권한이 필요합니다.", - "설정으로 이동", - "나중에 하기", + getString(R.string.permission_title), + getString(R.string.permission_content), + getString(R.string.permission_yes), + getString(R.string.permission_no), { settingDialog() }, - { showToastMessage("권한을 허용하지 않을 경우, 설문 완료 캡쳐본 전송이 불가합니다.") } + { showToastMessage(getString(R.string.permission_alert)) } ) } diff --git a/app/src/main/java/com/surveasy/surveasy/presentation/main/my/history/HistoryViewModel.kt b/app/src/main/java/com/surveasy/surveasy/presentation/main/my/history/HistoryViewModel.kt index 1642fd08..18eab0e3 100644 --- a/app/src/main/java/com/surveasy/surveasy/presentation/main/my/history/HistoryViewModel.kt +++ b/app/src/main/java/com/surveasy/surveasy/presentation/main/my/history/HistoryViewModel.kt @@ -41,6 +41,7 @@ class HistoryViewModel @Inject constructor( private val queryAccountInfoUseCase: QueryAccountInfoUseCase, ) : ViewModel() { private val sid = MutableStateFlow(-1) + val monthInfo = MutableStateFlow("") val date = MutableStateFlow(0) private val _mainUiState = MutableStateFlow(HistoryUiState()) @@ -153,7 +154,8 @@ class HistoryViewModel @Inject constructor( reward = reward, imgUrl = imgUrl, createdAt = createdAt, - sentAt = sentAt + sentAt = sentAt, + surveyDone = surveyDone ) } } @@ -211,6 +213,9 @@ class HistoryViewModel @Inject constructor( 21 } ) + monthInfo.emit( + if (day > 21 || day <= 1) "다음 달" else "이번 달" + ) } } @@ -232,6 +237,7 @@ class HistoryViewModel @Inject constructor( const val AFTER = "after" const val FIRST_PAGE = 0 const val DEFAULT_SIZE = 10 + const val DONE = "DONE" } } @@ -267,4 +273,5 @@ data class HistoryDetailUiState( val imgUrl: String = "", val createdAt: String = "", val sentAt: String? = null, + val surveyDone: Boolean? = false ) \ No newline at end of file diff --git a/app/src/main/java/com/surveasy/surveasy/presentation/main/my/history/mapper/UiHistoryDataMapper.kt b/app/src/main/java/com/surveasy/surveasy/presentation/main/my/history/mapper/UiHistoryDataMapper.kt index 10cbd53e..89ccf425 100644 --- a/app/src/main/java/com/surveasy/surveasy/presentation/main/my/history/mapper/UiHistoryDataMapper.kt +++ b/app/src/main/java/com/surveasy/surveasy/presentation/main/my/history/mapper/UiHistoryDataMapper.kt @@ -23,5 +23,6 @@ fun HistorySurvey.toUiHistorySurveyData(): UiHistorySurveyData = UiHistorySurvey reward = reward, imgUrl = imgUrl, createdAt = createdAt, - sentAt = sentAt + sentAt = sentAt, + surveyDone = surveyStatus == "DONE" ) \ No newline at end of file diff --git a/app/src/main/java/com/surveasy/surveasy/presentation/main/my/history/model/UiHistoryData.kt b/app/src/main/java/com/surveasy/surveasy/presentation/main/my/history/model/UiHistoryData.kt index 8bc4dc67..fb472d25 100644 --- a/app/src/main/java/com/surveasy/surveasy/presentation/main/my/history/model/UiHistoryData.kt +++ b/app/src/main/java/com/surveasy/surveasy/presentation/main/my/history/model/UiHistoryData.kt @@ -19,4 +19,5 @@ data class UiHistorySurveyData( val imgUrl: String, val createdAt: String, val sentAt: String?, + val surveyDone: Boolean?, ) diff --git a/app/src/main/java/com/surveasy/surveasy/presentation/main/my/setting/SettingActivity.kt b/app/src/main/java/com/surveasy/surveasy/presentation/main/my/setting/SettingActivity.kt index 96a4ea04..209ca902 100644 --- a/app/src/main/java/com/surveasy/surveasy/presentation/main/my/setting/SettingActivity.kt +++ b/app/src/main/java/com/surveasy/surveasy/presentation/main/my/setting/SettingActivity.kt @@ -2,6 +2,7 @@ package com.surveasy.surveasy.presentation.main.my.setting import android.content.Intent import androidx.activity.viewModels +import com.surveasy.surveasy.R import com.surveasy.surveasy.databinding.ActivitySettingBinding import com.surveasy.surveasy.presentation.base.BaseActivity import com.surveasy.surveasy.presentation.intro.IntroActivity @@ -33,10 +34,10 @@ class SettingActivity : BaseActivity(ActivitySettingBind vLogout.setOnClickListener { showTwoButtonDialog( this@SettingActivity, - "로그아웃 하시겠습니까?", + resources.getString(R.string.logout_title), "", - "로그아웃", - "닫기", + resources.getString(R.string.logout_yes), + resources.getString(R.string.logout_no), { viewModel.logout() } ) {} } @@ -44,14 +45,15 @@ class SettingActivity : BaseActivity(ActivitySettingBind vWithdraw.setOnClickListener { showTwoButtonDialog( this@SettingActivity, - "정말 탈퇴 하시겠습니까?", - "회원 탈퇴 시 패널 정보가 모두 사라집니다.", - "탈퇴하기", - "닫기", + resources.getString(R.string.withdraw_title), + resources.getString(R.string.withdraw_content), + resources.getString(R.string.withdraw_yes), + resources.getString(R.string.logout_no), { viewModel.withdraw() } ) { } } ivBack.setOnClickListener { finish() } + tvVersionInfo.text = packageManager.getPackageInfo(packageName, 0).versionName.toString() } diff --git a/app/src/main/java/com/surveasy/surveasy/presentation/main/survey/SurveyProofFragment.kt b/app/src/main/java/com/surveasy/surveasy/presentation/main/survey/SurveyProofFragment.kt index 67dd5951..f0cb3f81 100644 --- a/app/src/main/java/com/surveasy/surveasy/presentation/main/survey/SurveyProofFragment.kt +++ b/app/src/main/java/com/surveasy/surveasy/presentation/main/survey/SurveyProofFragment.kt @@ -8,7 +8,6 @@ import android.net.Uri import android.os.Build import android.provider.MediaStore import android.provider.Settings -import androidx.activity.OnBackPressedCallback import androidx.activity.result.contract.ActivityResultContracts import androidx.core.content.ContextCompat import androidx.fragment.app.activityViewModels @@ -70,12 +69,12 @@ class SurveyProofFragment : private fun showDialogToGetPermission() { showTwoButtonDialog( requireContext(), - "권한이 필요합니다", - "설문 완료 인증 캡쳐본을 전송하기 위해서 접근 권한이 필요합니다.", - "설정으로 이동", - "나중에 하기", + getString(R.string.permission_title), + getString(R.string.permission_content), + getString(R.string.permission_yes), + getString(R.string.permission_no), { settingDialog() }, - { showToastMessage("권한을 허용하지 않을 경우, 설문 완료 캡쳐본 전송이 불가합니다.") } + { showToastMessage(getString(R.string.permission_alert)) } ) } diff --git a/app/src/main/java/com/surveasy/surveasy/presentation/main/survey/mapper/UiSurveyDetailDataMapper.kt b/app/src/main/java/com/surveasy/surveasy/presentation/main/survey/mapper/UiSurveyDetailDataMapper.kt index bf9c295a..ef526904 100644 --- a/app/src/main/java/com/surveasy/surveasy/presentation/main/survey/mapper/UiSurveyDetailDataMapper.kt +++ b/app/src/main/java/com/surveasy/surveasy/presentation/main/survey/mapper/UiSurveyDetailDataMapper.kt @@ -8,8 +8,8 @@ fun SurveyDetailInfo.toSurveyDetailData(): UiSurveyDetailData = UiSurveyDetailDa reward = reward, headCount = headCount, spendTime = spendTime, - responseCount = responseCount, - targetInput = targetInput ?: "모두", + responseCount = if(responseCount > headCount) headCount - 1 else responseCount, + targetInput = if(targetInput.isNullOrEmpty()) "모두" else targetInput, noticeToPanel = noticeToPanel ?: "성실한 참여 부탁드립니다.", surveyDescription = description, link = link, diff --git a/app/src/main/res/layout/activity_edit.xml b/app/src/main/res/layout/activity_edit.xml index be0a03a9..ea26a0de 100644 --- a/app/src/main/res/layout/activity_edit.xml +++ b/app/src/main/res/layout/activity_edit.xml @@ -83,7 +83,7 @@ - + android:background="@color/white"> - + - + - + - + - + + - - + - + - + - + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/activity_setting.xml b/app/src/main/res/layout/activity_setting.xml index c980c373..4f2344e5 100644 --- a/app/src/main/res/layout/activity_setting.xml +++ b/app/src/main/res/layout/activity_setting.xml @@ -101,7 +101,6 @@ android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginEnd="8dp" - android:text="1.0" android:textColor="@color/light_gray" app:layout_constraintBottom_toBottomOf="@id/tv_version" app:layout_constraintEnd_toEndOf="@id/guide_end" diff --git a/app/src/main/res/layout/fragment_history.xml b/app/src/main/res/layout/fragment_history.xml index 45fb9c07..0f5c75e5 100644 --- a/app/src/main/res/layout/fragment_history.xml +++ b/app/src/main/res/layout/fragment_history.xml @@ -52,19 +52,21 @@ android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginTop="24dp" + android:textSize="16sp" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toBottomOf="@id/tv_history_title" - app:sentDay="@{vm.date}" /> + app:sentDay="@{vm.date}" + app:sentMonth="@{vm.monthInfo}" /> @@ -97,7 +100,7 @@ - - @@ -152,7 +143,7 @@ android:layout_marginHorizontal="25sp" android:layout_marginTop="20dp" android:background="@drawable/register_button" - android:enabled="@{vm.mainUiState.isBefore}" + android:enabled="@{vm.mainUiState.isBefore && !vm.detailUiState.surveyDone}" android:onClick="@{() -> vm.navigateToEdit()}" android:text="@string/history_change_label" android:textColor="@color/white" diff --git a/app/src/main/res/layout/fragment_history_edit.xml b/app/src/main/res/layout/fragment_history_edit.xml index 2229c71a..6d7a2772 100644 --- a/app/src/main/res/layout/fragment_history_edit.xml +++ b/app/src/main/res/layout/fragment_history_edit.xml @@ -42,13 +42,17 @@ diff --git a/app/src/main/res/layout/fragment_home.xml b/app/src/main/res/layout/fragment_home.xml index b9a4a1ed..c9f47982 100644 --- a/app/src/main/res/layout/fragment_home.xml +++ b/app/src/main/res/layout/fragment_home.xml @@ -254,6 +254,29 @@ app:layout_constraintTop_toBottomOf="@id/cl_fs" app:list="@{vm.uiState.list}" /> + + + + + + app:layout_constraintTop_toBottomOf="@id/tv_alert_title" /> + app:layout_constraintTop_toBottomOf="@id/tv_alert_title" /> diff --git a/app/src/main/res/layout/fragment_survey.xml b/app/src/main/res/layout/fragment_survey.xml index 0dcb3b26..fd2ab71e 100644 --- a/app/src/main/res/layout/fragment_survey.xml +++ b/app/src/main/res/layout/fragment_survey.xml @@ -50,19 +50,22 @@ diff --git a/app/src/main/res/layout/fragment_survey_done.xml b/app/src/main/res/layout/fragment_survey_done.xml index 01fb72ae..cc6d369d 100644 --- a/app/src/main/res/layout/fragment_survey_done.xml +++ b/app/src/main/res/layout/fragment_survey_done.xml @@ -36,6 +36,7 @@ android:layout_marginTop="50dp" android:text="@string/survey_done_label" android:textColor="@color/main_green" + android:textSize="20dp" app:layout_constraintBottom_toTopOf="@id/btn_list" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintStart_toStartOf="parent" @@ -47,16 +48,16 @@ style="@style/TextMediumBold" android:layout_width="0dp" android:layout_height="wrap_content" + android:layout_marginTop="60dp" android:background="@drawable/register_button" android:onClick="@{() -> vm.navigateToList()}" android:paddingHorizontal="29dp" - app:getReward="@{vm.uiState.reward}" android:textColor="@color/white" - app:layout_constraintTop_toBottomOf="@id/tv_done" + app:getReward="@{vm.uiState.reward}" app:layout_constraintBottom_toBottomOf="parent" - android:layout_marginTop="60dp" - app:layout_constraintStart_toStartOf="@id/tv_done" app:layout_constraintEnd_toEndOf="@id/tv_done" + app:layout_constraintStart_toStartOf="@id/tv_done" + app:layout_constraintTop_toBottomOf="@id/tv_done" app:layout_constraintVertical_chainStyle="packed" /> diff --git a/app/src/main/res/layout/fragment_survey_proof.xml b/app/src/main/res/layout/fragment_survey_proof.xml index 24851d8b..57de7fee 100644 --- a/app/src/main/res/layout/fragment_survey_proof.xml +++ b/app/src/main/res/layout/fragment_survey_proof.xml @@ -57,13 +57,16 @@ diff --git a/app/src/main/res/layout/item_history.xml b/app/src/main/res/layout/item_history.xml index a61addd6..beb18d82 100644 --- a/app/src/main/res/layout/item_history.xml +++ b/app/src/main/res/layout/item_history.xml @@ -26,10 +26,14 @@ diff --git a/app/src/main/res/layout/item_list_done.xml b/app/src/main/res/layout/item_list_done.xml index 2b0b9fe2..c3d6f30c 100644 --- a/app/src/main/res/layout/item_list_done.xml +++ b/app/src/main/res/layout/item_list_done.xml @@ -47,10 +47,11 @@ @@ -87,6 +89,7 @@ android:layout_height="wrap_content" android:layout_marginStart="8dp" android:textColor="@color/light_gray" + android:textSize="13dp" app:layout_constraintBottom_toBottomOf="@id/tv_list_chip" app:layout_constraintStart_toEndOf="@id/tv_list_chip" app:layout_constraintTop_toTopOf="@id/tv_list_chip" @@ -101,6 +104,7 @@ android:layout_marginStart="4dp" android:text="참여 중" android:textColor="@color/light_gray" + android:textSize="13dp" app:layout_constraintBottom_toBottomOf="@id/tv_list_chip" app:layout_constraintStart_toEndOf="@id/tv_participate" app:layout_constraintTop_toTopOf="@id/tv_list_chip" /> diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 44ec9a5e..0221e3ad 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -422,7 +422,6 @@ 설문 참여 인증 방법 안내 부정 참여 경고 불성실 응답에 대한 패널티 안내 - 정말 떠나시는 건가요? 탈퇴 시 정산 예정 금액은 지급되지 않습니다. 서베이지를 떠나는 이유를 알려주세요.\n남겨주신 소중한 의견을 참고해 더 발전하겠습니다! Loading ... @@ -455,8 +454,8 @@ 정산 예정 정산 완료 설문 완료 화면 - ※사진 변경 시, 기존 제출 화면은 삭제됩니다. - ※마감된 설문의 제출 화면은 변경이 불가합니다. + ※사진 변경 시,\n기존 제출 화면은 삭제됩니다. + ※마감된 설문의 제출 화면은\n변경이 불가합니다. 설문 완료 화면 변경하기 사진 다시 선택하기 제출화면 변경하기 @@ -496,5 +495,25 @@ 마감 참여 완료 패널 기본 정보 입력이\n완료되었습니다. + 더 나은 서비스 제공을 위해 새로운 어플 버전이 출시되었습니다. 업데이트를 진행하지 않으면 서비스 이용이 제한될 수 있습니다. + 🔔 + 설문 알림을 받고 싶다면? + 설문 알림 안내 + 더 나은 서비스를 제공하기 위해 현재 설문 알림 기능을 개선하고 있습니다.\n\n새로운 알림 기능이 완성될 때까지 [오픈 채팅방]을 통해 설문 알림을 제공받으실 수 있습니다. + 참여하기 + 닫기 + 권한이 필요합니다 + 설문 완료 인증 캡쳐본을 전송하기 위해서 접근 권한이 필요합니다. + 설정으로 이동 + 나중에 하기 + 권한을 허용하지 않을 경우, 설문 완료 캡쳐본 전송이 불가합니다. + 로그아웃 하시겠습니까? + 로그아웃 + 닫기 + 정말 탈퇴 하시겠습니까? + 회원 탈퇴 시 패널 정보가 모두 사라집니다. + 탈퇴하기 + 뒤로가기 버튼을 한 번 더 누르면 종료됩니다. + 이메일 주소가 복사되었습니다. \ No newline at end of file diff --git a/app/src/main/res/values/text_style.xml b/app/src/main/res/values/text_style.xml index 8b80bca2..280c50b9 100644 --- a/app/src/main/res/values/text_style.xml +++ b/app/src/main/res/values/text_style.xml @@ -25,12 +25,24 @@ @color/black + + + + + +