diff --git a/app/build.gradle b/app/build.gradle index dd626dcb..0942b9c6 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -28,8 +28,8 @@ android { applicationId "com.hyeeyoung.wishboard" minSdkVersion 24 targetSdkVersion 33 - versionCode 22 - versionName "1.2.0" + versionCode 30 + versionName "1.2.1" testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" vectorDrawables { @@ -82,6 +82,7 @@ dependencies { implementation 'androidx.security:security-crypto-ktx:1.1.0-alpha04' implementation 'androidx.lifecycle:lifecycle-livedata-ktx:2.4.0' implementation 'androidx.lifecycle:lifecycle-viewmodel-ktx:2.4.0' + implementation 'androidx.lifecycle:lifecycle-runtime-ktx:2.3.1' implementation 'androidx.fragment:fragment-ktx:1.5.4' implementation 'androidx.preference:preference-ktx:1.2.0' implementation 'androidx.navigation:navigation-ui-ktx:2.4.0' @@ -91,12 +92,7 @@ dependencies { implementation 'io.coil-kt:coil:2.1.0' // jsoup - implementation 'org.jsoup:jsoup:1.14.1' - - // glide - implementation 'com.github.bumptech.glide:glide:4.12.0' - implementation 'androidx.lifecycle:lifecycle-runtime-ktx:2.3.1' - kapt 'com.github.bumptech.glide:compiler:4.12.0' + implementation 'org.jsoup:jsoup:1.14.1' // TODO delete // Network implementation platform('com.squareup.okhttp3:okhttp-bom:4.10.0') @@ -111,11 +107,6 @@ dependencies { kapt "com.google.dagger:hilt-compiler:$hilt_version" implementation "androidx.hilt:hilt-navigation-fragment:1.0.0" - // AWS S3 - implementation 'com.amplifyframework:aws-storage-s3:1.31.1' - implementation 'com.amplifyframework:aws-auth-cognito:1.31.1' - implementation 'com.amplifyframework:core-kotlin:0.15.1' - // Firebase FCM implementation 'com.google.firebase:firebase-messaging-ktx' implementation 'com.google.firebase:firebase-analytics-ktx' @@ -130,11 +121,15 @@ dependencies { implementation "com.airbnb.android:lottie:$lottie_version" // Calendar View - implementation 'joda-time:joda-time:2.10.14' + implementation 'joda-time:joda-time:2.10.14' // TODO delete // Timber implementation 'com.jakewharton.timber:timber:5.0.1' + // In App Update + implementation 'com.google.android.play:app-update:2.1.0' + implementation 'com.google.android.play:app-update-ktx:2.1.0' + // Compose def composeBom = platform('androidx.compose:compose-bom:2023.05.01') implementation composeBom @@ -144,15 +139,15 @@ dependencies { implementation 'androidx.compose.runtime:runtime-livedata' implementation 'androidx.lifecycle:lifecycle-viewmodel-compose' - implementation "androidx.compose.ui:ui" - implementation "androidx.compose.ui:ui-tooling-preview" + implementation 'androidx.compose.ui:ui' + implementation 'androidx.compose.ui:ui-tooling-preview' implementation 'androidx.compose.material3:material3' implementation 'androidx.constraintlayout:constraintlayout-compose:1.0.1' implementation 'io.coil-kt:coil-compose:2.4.0' - androidTestImplementation "androidx.compose.ui:ui-test-junit4" - debugImplementation "androidx.compose.ui:ui-tooling" - debugImplementation "androidx.compose.ui:ui-test-manifest" + androidTestImplementation 'androidx.compose.ui:ui-test-junit4' + debugImplementation 'androidx.compose.ui:ui-tooling' + debugImplementation 'androidx.compose.ui:ui-test-manifest' testImplementation 'junit:junit:4.12' androidTestImplementation 'androidx.test.ext:junit:1.1.3' diff --git a/app/src/main/java/com/hyeeyoung/wishboard/WishBoardApp.kt b/app/src/main/java/com/hyeeyoung/wishboard/WishBoardApp.kt index 16844714..45f594f0 100644 --- a/app/src/main/java/com/hyeeyoung/wishboard/WishBoardApp.kt +++ b/app/src/main/java/com/hyeeyoung/wishboard/WishBoardApp.kt @@ -2,10 +2,6 @@ package com.hyeeyoung.wishboard import android.app.Application import androidx.appcompat.app.AppCompatDelegate -import com.amplifyframework.AmplifyException -import com.amplifyframework.auth.cognito.AWSCognitoAuthPlugin -import com.amplifyframework.core.Amplify -import com.amplifyframework.storage.s3.AWSS3StoragePlugin import com.hyeeyoung.wishboard.util.WishBoardDebugTree import dagger.hilt.android.HiltAndroidApp import timber.log.Timber @@ -17,18 +13,6 @@ class WishBoardApp : Application() { AppCompatDelegate.setDefaultNightMode(AppCompatDelegate.MODE_NIGHT_NO) setUpTimber() - setUpAmplify() - } - - private fun setUpAmplify() { - try { - Amplify.addPlugin(AWSCognitoAuthPlugin()) - Amplify.addPlugin(AWSS3StoragePlugin()) - Amplify.configure(applicationContext) - Timber.d("Initialized Amplify") - } catch (error: AmplifyException) { - Timber.e("Could not initialize Amplify", error) - } } private fun setUpTimber() { diff --git a/app/src/main/java/com/hyeeyoung/wishboard/data/interceptor/AuthInterceptor.kt b/app/src/main/java/com/hyeeyoung/wishboard/data/interceptor/AuthInterceptor.kt index b98b6041..fa3eb1e2 100644 --- a/app/src/main/java/com/hyeeyoung/wishboard/data/interceptor/AuthInterceptor.kt +++ b/app/src/main/java/com/hyeeyoung/wishboard/data/interceptor/AuthInterceptor.kt @@ -20,7 +20,7 @@ import timber.log.Timber import javax.inject.Inject class AuthInterceptor @Inject constructor( - private val gson: Gson, + private val gson: Gson, // TODO json으로 변경 private val context: Application, private val localStorage: WishBoardPreference, ) : Interceptor { diff --git a/app/src/main/java/com/hyeeyoung/wishboard/data/services/AWSS3Service.kt b/app/src/main/java/com/hyeeyoung/wishboard/data/services/AWSS3Service.kt deleted file mode 100644 index 971baad7..00000000 --- a/app/src/main/java/com/hyeeyoung/wishboard/data/services/AWSS3Service.kt +++ /dev/null @@ -1,40 +0,0 @@ -package com.hyeeyoung.wishboard.data.services - -import com.amplifyframework.kotlin.core.Amplify -import com.amplifyframework.storage.StorageException -import timber.log.Timber -import java.io.File - -class AWSS3Service { - suspend fun uploadFile(fileName: String, file: File): Boolean { - val upload = Amplify.Storage.uploadFile(fileName, file) - return try { - val result = upload.result() - Timber.d("Successfully uploaded: ${result.key}") - true - } catch (error: StorageException) { - Timber.e("Upload failed", error) - false - } - } - - suspend fun getImageUrl(fileName: String): String? { - return try { - val url = Amplify.Storage.getUrl(fileName).url.toString() - Timber.d("Successfully generated: $url") - url - } catch (error: StorageException) { - Timber.e("URL generation failure", error) - null - } - } - - suspend fun removeImageUrl(fileName: String) { - try { - val result = Amplify.Storage.remove(fileName) - Timber.d("Successfully removed ${result.key}") - } catch (error: StorageException) { - Timber.e("Remove failure", error) - } - } -} \ No newline at end of file diff --git a/app/src/main/java/com/hyeeyoung/wishboard/presentation/calendar/screen/CalendarActivity.kt b/app/src/main/java/com/hyeeyoung/wishboard/presentation/calendar/screen/CalendarActivity.kt index 99a58a17..63851054 100644 --- a/app/src/main/java/com/hyeeyoung/wishboard/presentation/calendar/screen/CalendarActivity.kt +++ b/app/src/main/java/com/hyeeyoung/wishboard/presentation/calendar/screen/CalendarActivity.kt @@ -23,7 +23,7 @@ class CalendarActivity : ComponentActivity() { val notiList by viewModel.calendarNotiList.collectAsState() CalendarScreen( - notiList = notiList, + notiList = notiList ?: emptyList(), onClickBack = { finish() }, onClickNotiWithLink = { shopUrl -> startActivity(Intent(Intent.ACTION_VIEW, Uri.parse(shopUrl))) diff --git a/app/src/main/java/com/hyeeyoung/wishboard/presentation/calendar/screen/CalendarScreen.kt b/app/src/main/java/com/hyeeyoung/wishboard/presentation/calendar/screen/CalendarScreen.kt index 39fff2e6..a6f6ba03 100644 --- a/app/src/main/java/com/hyeeyoung/wishboard/presentation/calendar/screen/CalendarScreen.kt +++ b/app/src/main/java/com/hyeeyoung/wishboard/presentation/calendar/screen/CalendarScreen.kt @@ -1,11 +1,14 @@ package com.hyeeyoung.wishboard.presentation.calendar.screen import androidx.compose.foundation.ExperimentalFoundationApi +import androidx.compose.foundation.background import androidx.compose.foundation.layout.Column import androidx.compose.foundation.pager.rememberPagerState import androidx.compose.material3.Scaffold import androidx.compose.material3.SnackbarHostState import androidx.compose.runtime.* +import androidx.compose.ui.Modifier +import androidx.compose.ui.graphics.Color import androidx.compose.ui.res.stringResource import androidx.compose.ui.tooling.preview.Preview import com.hyeeyoung.wishboard.R @@ -26,11 +29,10 @@ private const val INITIAL_PAGE = PAGE_COUNT / 2 @OptIn(ExperimentalFoundationApi::class) @Composable fun CalendarScreen( - notiList: List?, + notiList: List, onClickBack: () -> Unit, onClickNotiWithLink: (String) -> Unit ) { - if (notiList == null) return WishboardTheme { var selectedDate by remember { mutableStateOf(LocalDate.now()) } var prevPage by remember { mutableStateOf(INITIAL_PAGE) } @@ -44,7 +46,7 @@ fun CalendarScreen( val snackbarMsgForNotiLink = stringResource(id = R.string.noti_item_url_snackbar_text) Scaffold(snackbarHost = { WishboardSnackbarHost(hostState = snackbarHostState) }) { - Column { + Column(modifier = Modifier.background(Color.White)) { CalendarHeader(selectedDate = selectedDate, onClickBack = onClickBack) CalendarTable( selectedDate = selectedDate, @@ -156,3 +158,13 @@ fun CalendarPreview() { onClickNotiWithLink = {} ) } + +@Preview(showBackground = true) +@Composable +fun EmmptyCalendarPreview() { + CalendarScreen( + notiList = emptyList(), + onClickBack = {}, + onClickNotiWithLink = {} + ) +} \ No newline at end of file diff --git a/app/src/main/java/com/hyeeyoung/wishboard/presentation/my/screens/MyProfileEditFragment.kt b/app/src/main/java/com/hyeeyoung/wishboard/presentation/my/screens/MyProfileEditFragment.kt index c05befd0..4d222695 100644 --- a/app/src/main/java/com/hyeeyoung/wishboard/presentation/my/screens/MyProfileEditFragment.kt +++ b/app/src/main/java/com/hyeeyoung/wishboard/presentation/my/screens/MyProfileEditFragment.kt @@ -3,7 +3,6 @@ package com.hyeeyoung.wishboard.presentation.my.screens import android.net.Uri import android.os.Bundle import android.view.View -import androidx.activity.result.contract.ActivityResultContracts import androidx.core.os.bundleOf import androidx.hilt.navigation.fragment.hiltNavGraphViewModels import androidx.navigation.fragment.findNavController @@ -14,8 +13,7 @@ import com.hyeeyoung.wishboard.presentation.my.MyViewModel import com.hyeeyoung.wishboard.presentation.wishitem.WishItemStatus import com.hyeeyoung.wishboard.util.BaseFragment import com.hyeeyoung.wishboard.util.UiState -import com.hyeeyoung.wishboard.util.extension.collectFlow -import com.hyeeyoung.wishboard.util.extension.showPhotoDialog +import com.hyeeyoung.wishboard.util.extension.* import com.hyeeyoung.wishboard.util.showKeyboard import dagger.hilt.android.AndroidEntryPoint @@ -25,23 +23,14 @@ class MyProfileEditFragment : private val viewModel: MyViewModel by hiltNavGraphViewModels(R.id.my_nav_graph) private var photoUri: Uri? = null - private val requestSelectPicture = - registerForActivityResult(ActivityResultContracts.PickVisualMedia()) { uri -> - if (uri != null) viewModel.setSelectedUserProfileImage(uri) - } - - private val requestCamera = - registerForActivityResult(ActivityResultContracts.RequestPermission()) { isGranted -> - if (isGranted) { - photoUri = viewModel.createCameraImageUri() - takePicture.launch(photoUri) - } - } - - private val takePicture = - registerForActivityResult(ActivityResultContracts.TakePicture()) { success -> - if (success && (photoUri != null)) viewModel.setSelectedUserProfileImage(photoUri!!) - } + private val requestSelectPicture = requestSelectPicture { uri -> viewModel.setSelectedUserProfileImage(uri) } + private val requestCamera = requestCamera { + photoUri = viewModel.createCameraImageUri() + takePicture.launch(photoUri) + } + private val takePicture = takePicture { + viewModel.setSelectedUserProfileImage(photoUri ?: return@takePicture) + } override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) diff --git a/app/src/main/java/com/hyeeyoung/wishboard/presentation/splash/SplashActivity.kt b/app/src/main/java/com/hyeeyoung/wishboard/presentation/splash/SplashActivity.kt index f2dae2b1..3ac171ba 100644 --- a/app/src/main/java/com/hyeeyoung/wishboard/presentation/splash/SplashActivity.kt +++ b/app/src/main/java/com/hyeeyoung/wishboard/presentation/splash/SplashActivity.kt @@ -3,13 +3,13 @@ package com.hyeeyoung.wishboard.presentation.splash import android.content.Intent import android.net.Uri import android.os.Bundle +import androidx.activity.viewModels import androidx.lifecycle.lifecycleScope import com.google.android.play.core.appupdate.AppUpdateManagerFactory import com.google.android.play.core.install.model.AppUpdateType import com.google.android.play.core.install.model.UpdateAvailability import com.hyeeyoung.wishboard.BuildConfig import com.hyeeyoung.wishboard.R -import com.hyeeyoung.wishboard.data.local.WishBoardPreference import com.hyeeyoung.wishboard.databinding.ActivitySplashBinding import com.hyeeyoung.wishboard.presentation.common.screens.TwoButtonDialogFragment import com.hyeeyoung.wishboard.presentation.common.types.DialogButtonReplyType @@ -17,34 +17,32 @@ import com.hyeeyoung.wishboard.presentation.main.MainActivity import com.hyeeyoung.wishboard.presentation.sign.screens.SignActivity import com.hyeeyoung.wishboard.util.BaseActivity import com.hyeeyoung.wishboard.util.DialogListener -import kotlinx.coroutines.Dispatchers -import kotlinx.coroutines.Job +import dagger.hilt.android.AndroidEntryPoint import kotlinx.coroutines.delay import kotlinx.coroutines.launch +@AndroidEntryPoint class SplashActivity : BaseActivity(R.layout.activity_splash) { - private var job: Job? = null + private val viewModel: SplashViewModel by viewModels() override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) - lifecycleScope.launch(Dispatchers.Main) { - job = launch { - delay(2000) - checkForNewVersionUpdate() - } + lifecycleScope.launch() { + delay(2000) + checkForNewVersionUpdate() } } private fun moveToNext() { - val isLogin = WishBoardPreference(this).isLogin + val isLogin = viewModel.isLogin() val nextScreen = if (isLogin) MainActivity::class.java else SignActivity::class.java startActivity(Intent(this@SplashActivity, nextScreen)) finish() } private fun checkForNewVersionUpdate() { - val appUpdateManager = AppUpdateManagerFactory.create(this) + val appUpdateManager = AppUpdateManagerFactory.create(this@SplashActivity) val appUpdateInfoTask = appUpdateManager.appUpdateInfo appUpdateInfoTask.addOnSuccessListener { appUpdateInfo -> @@ -53,6 +51,8 @@ class SplashActivity : BaseActivity(R.layout.activity_spl && appUpdateInfo.availableVersionCode() != BuildConfig.VERSION_CODE ) { showUpdateDialog() + } else { + moveToNext() } }.addOnFailureListener { moveToNext() @@ -83,9 +83,4 @@ class SplashActivity : BaseActivity(R.layout.activity_spl startActivity(it) } } - - override fun onPause() { - job?.cancel() - super.onPause() - } -} \ No newline at end of file +} diff --git a/app/src/main/java/com/hyeeyoung/wishboard/presentation/splash/SplashViewModel.kt b/app/src/main/java/com/hyeeyoung/wishboard/presentation/splash/SplashViewModel.kt new file mode 100644 index 00000000..62b3b76a --- /dev/null +++ b/app/src/main/java/com/hyeeyoung/wishboard/presentation/splash/SplashViewModel.kt @@ -0,0 +1,13 @@ +package com.hyeeyoung.wishboard.presentation.splash + +import androidx.lifecycle.ViewModel +import com.hyeeyoung.wishboard.data.local.WishBoardPreference +import dagger.hilt.android.lifecycle.HiltViewModel +import javax.inject.Inject + +@HiltViewModel +class SplashViewModel @Inject constructor( + private val localStorage: WishBoardPreference, +) : ViewModel() { + fun isLogin() = localStorage.isLogin +} diff --git a/app/src/main/java/com/hyeeyoung/wishboard/presentation/wishitem/screens/WishBasicFragment.kt b/app/src/main/java/com/hyeeyoung/wishboard/presentation/wishitem/screens/WishBasicFragment.kt index d4319f49..25bae0ea 100644 --- a/app/src/main/java/com/hyeeyoung/wishboard/presentation/wishitem/screens/WishBasicFragment.kt +++ b/app/src/main/java/com/hyeeyoung/wishboard/presentation/wishitem/screens/WishBasicFragment.kt @@ -3,7 +3,6 @@ package com.hyeeyoung.wishboard.presentation.wishitem.screens import android.net.Uri import android.os.Bundle import android.view.View -import androidx.activity.result.contract.ActivityResultContracts import androidx.core.os.bundleOf import androidx.hilt.navigation.fragment.hiltNavGraphViewModels import androidx.navigation.fragment.findNavController @@ -22,8 +21,7 @@ import com.hyeeyoung.wishboard.presentation.wishitem.WishItemStatus import com.hyeeyoung.wishboard.presentation.wishitem.viewmodels.WishItemRegistrationViewModel import com.hyeeyoung.wishboard.util.BaseFragment import com.hyeeyoung.wishboard.util.FolderListDialogListener -import com.hyeeyoung.wishboard.util.extension.getParcelableValue -import com.hyeeyoung.wishboard.util.extension.showPhotoDialog +import com.hyeeyoung.wishboard.util.extension.* import com.hyeeyoung.wishboard.util.setOnSingleClickListener import dagger.hilt.android.AndroidEntryPoint @@ -39,23 +37,14 @@ class WishBasicFragment : BaseFragment(R.layout.fragment_wi private val shopLinkInputDialog = ShopLinkInputBottomDialogFragment() private var photoUri: Uri? = null - private val requestSelectPicture = - registerForActivityResult(ActivityResultContracts.PickVisualMedia()) { uri -> - if (uri != null) selectAndLoadImage(uri) - } - - private val requestCamera = - registerForActivityResult(ActivityResultContracts.RequestPermission()) { isGranted -> - if (isGranted) { - photoUri = viewModel.createCameraImageUri() - takePicture.launch(photoUri) - } - } - - private val takePicture = - registerForActivityResult(ActivityResultContracts.TakePicture()) { success -> - if (success && (photoUri != null)) selectAndLoadImage(photoUri!!) - } + private val requestSelectPicture = requestSelectPicture { uri -> selectAndLoadImage(uri) } + private val requestCamera = requestCamera { + photoUri = viewModel.createCameraImageUri() + takePicture.launch(photoUri) + } + private val takePicture = takePicture { + selectAndLoadImage(photoUri ?: return@takePicture) + } override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) diff --git a/app/src/main/java/com/hyeeyoung/wishboard/util/Util.kt b/app/src/main/java/com/hyeeyoung/wishboard/util/Util.kt index 63c6087a..51ee1740 100644 --- a/app/src/main/java/com/hyeeyoung/wishboard/util/Util.kt +++ b/app/src/main/java/com/hyeeyoung/wishboard/util/Util.kt @@ -6,13 +6,7 @@ import android.graphics.Bitmap import android.graphics.BitmapFactory import android.view.View import android.view.inputmethod.InputMethodManager -import android.widget.ImageView -import androidx.lifecycle.LifecycleCoroutineScope -import com.bumptech.glide.Glide -import com.hyeeyoung.wishboard.R -import com.hyeeyoung.wishboard.data.services.AWSS3Service import kotlinx.coroutines.Dispatchers -import kotlinx.coroutines.launch import kotlinx.coroutines.withContext import timber.log.Timber import java.io.File @@ -57,20 +51,6 @@ fun getTimestamp(): String { return dateFormat.format(Date()) } -/** S3에서 다운로드 받은 이미지를 ImageView에 디스플레이 */ -fun loadProfileImage( // TODO need refactoring - lifecycleScope: LifecycleCoroutineScope, - imageUrl: String, - imageView: ImageView -) { - lifecycleScope.launch { - AWSS3Service().getImageUrl(imageUrl)?.let { imageUrl -> - Glide.with(imageView.context).load(imageUrl) - .placeholder(R.drawable.ic_background_user_profile).into(imageView) - } - } -} - fun getNotiDateServerFormat(date: String, hour: String, minute: String) = "$date $hour:$minute:00" // TODO DateFormatUtil.kt 로 이동 diff --git a/app/src/main/java/com/hyeeyoung/wishboard/util/extension/FragmentExt.kt b/app/src/main/java/com/hyeeyoung/wishboard/util/extension/FragmentExt.kt index 91d2b42f..56abe166 100644 --- a/app/src/main/java/com/hyeeyoung/wishboard/util/extension/FragmentExt.kt +++ b/app/src/main/java/com/hyeeyoung/wishboard/util/extension/FragmentExt.kt @@ -1,6 +1,7 @@ package com.hyeeyoung.wishboard.util.extension import android.Manifest +import android.net.Uri import androidx.activity.result.ActivityResultLauncher import androidx.activity.result.PickVisualMediaRequest import androidx.activity.result.contract.ActivityResultContracts @@ -35,4 +36,19 @@ fun Fragment.showPhotoDialog( } }) }.show(parentFragmentManager, "PhotoDialog") -} \ No newline at end of file +} + +fun Fragment.requestSelectPicture(block: (Uri) -> Unit) = + registerForActivityResult(ActivityResultContracts.PickVisualMedia()) { uri -> + block(uri ?: return@registerForActivityResult) + } + +fun Fragment.requestCamera(block: () -> Unit) = + registerForActivityResult(ActivityResultContracts.RequestPermission()) { isGranted -> + if (isGranted) block() + } + +fun Fragment.takePicture(block: () -> Unit) = + registerForActivityResult(ActivityResultContracts.TakePicture()) { success -> + if (success) block() + } diff --git a/app/src/main/res/layout/item_cart.xml b/app/src/main/res/layout/item_cart.xml index 25e5842d..af428cc7 100644 --- a/app/src/main/res/layout/item_cart.xml +++ b/app/src/main/res/layout/item_cart.xml @@ -45,8 +45,8 @@ +