From bad456f842b2cf6bff814c7d5a4c07e1e9e5abd8 Mon Sep 17 00:00:00 2001 From: Gracia Hotmauli <95269134+hotmauligracia@users.noreply.github.com> Date: Tue, 12 Aug 2025 02:23:39 +0700 Subject: [PATCH] store status, product fixed, file compression --- .idea/deviceManager.xml | 13 +++++ app/build.gradle.kts | 3 -- app/src/main/AndroidManifest.xml | 14 ++--- .../ui/profile/ProfileFragment.kt | 18 +++++-- .../profile/mystore/StoreSuspendedActivity.kt | 26 ++++++++++ .../product/DetailStoreProductActivity.kt | 25 ++++++--- .../alya/ecommerce_serang/utils/FileUtils.kt | 52 ++++++++++++++++++- .../utils/viewmodel/ProfileViewModel.kt | 8 +-- .../res/layout/activity_store_suspended.xml | 39 ++++++++++++++ gradle/libs.versions.toml | 2 +- gradle/wrapper/gradle-wrapper.properties | 2 +- 11 files changed, 173 insertions(+), 29 deletions(-) create mode 100644 .idea/deviceManager.xml create mode 100644 app/src/main/java/com/alya/ecommerce_serang/ui/profile/mystore/StoreSuspendedActivity.kt create mode 100644 app/src/main/res/layout/activity_store_suspended.xml diff --git a/.idea/deviceManager.xml b/.idea/deviceManager.xml new file mode 100644 index 0000000..91f9558 --- /dev/null +++ b/.idea/deviceManager.xml @@ -0,0 +1,13 @@ + + + + + + \ No newline at end of file diff --git a/app/build.gradle.kts b/app/build.gradle.kts index ce4e99b..c34c44b 100644 --- a/app/build.gradle.kts +++ b/app/build.gradle.kts @@ -124,7 +124,4 @@ dependencies { implementation(platform("com.google.firebase:firebase-bom:33.13.0")) implementation("com.google.firebase:firebase-analytics") implementation("com.google.firebase:firebase-messaging-ktx") - } - - diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index 4455d19..610dd43 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -29,6 +29,9 @@ android:theme="@style/Theme.Ecommerce_serang" android:usesCleartextTraffic="true" tools:targetApi="31"> + @@ -82,12 +85,11 @@ - - - - - - + + + + + store?.let { when (store.storeStatus) { + "process" -> startActivity(Intent(requireContext(), StoreOnReviewActivity::class.java)) "active" -> startActivity(Intent(requireContext(), MyStoreActivity::class.java)) - else -> startActivity(Intent(requireContext(), StoreOnReviewActivity::class.java)) + "inactive" -> startActivity(Intent(requireContext(), MyStoreActivity::class.java)) + "suspended" -> startActivity(Intent(requireContext(), StoreSuspendedActivity::class.java)) + else -> startActivity(Intent(requireContext(), RegisterStoreActivity::class.java)) } } ?: run { Toast.makeText(requireContext(), "Gagal memuat data toko", Toast.LENGTH_SHORT).show() @@ -132,6 +134,12 @@ class ProfileFragment : Fragment() { } } + private fun observeStoreStatus() { + viewModel.checkStore.observe(viewLifecycleOwner) { hasStore -> + binding.tvBukaToko.text = if (hasStore) "Toko Saya" else "Buka Toko" + } + } + private fun updateUI(user: UserProfile) = with(binding){ val fullImageUrl = when (val img = user.image) { is String -> { diff --git a/app/src/main/java/com/alya/ecommerce_serang/ui/profile/mystore/StoreSuspendedActivity.kt b/app/src/main/java/com/alya/ecommerce_serang/ui/profile/mystore/StoreSuspendedActivity.kt new file mode 100644 index 0000000..56a0c5c --- /dev/null +++ b/app/src/main/java/com/alya/ecommerce_serang/ui/profile/mystore/StoreSuspendedActivity.kt @@ -0,0 +1,26 @@ +package com.alya.ecommerce_serang.ui.profile.mystore + +import android.os.Bundle +import androidx.activity.enableEdgeToEdge +import androidx.appcompat.app.AppCompatActivity +import androidx.core.view.ViewCompat +import androidx.core.view.WindowInsetsCompat +import com.alya.ecommerce_serang.R +import com.alya.ecommerce_serang.databinding.ActivityStoreSuspendedBinding + +class StoreSuspendedActivity : AppCompatActivity() { + + private lateinit var binding: ActivityStoreSuspendedBinding + + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + binding = ActivityStoreSuspendedBinding.inflate(layoutInflater) + setContentView(binding.root) + + binding.header.headerTitle.text = "Toko Dinonaktifkan" + binding.header.headerLeftIcon.setOnClickListener { + onBackPressedDispatcher.onBackPressed() + finish() + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/alya/ecommerce_serang/ui/profile/mystore/product/DetailStoreProductActivity.kt b/app/src/main/java/com/alya/ecommerce_serang/ui/profile/mystore/product/DetailStoreProductActivity.kt index 9e0bca5..1ced252 100644 --- a/app/src/main/java/com/alya/ecommerce_serang/ui/profile/mystore/product/DetailStoreProductActivity.kt +++ b/app/src/main/java/com/alya/ecommerce_serang/ui/profile/mystore/product/DetailStoreProductActivity.kt @@ -27,6 +27,8 @@ import com.alya.ecommerce_serang.data.repository.ProductRepository import com.alya.ecommerce_serang.data.repository.Result import com.alya.ecommerce_serang.databinding.ActivityDetailStoreProductBinding import com.alya.ecommerce_serang.utils.BaseViewModelFactory +import com.alya.ecommerce_serang.utils.FileUtils.compressFile +import com.alya.ecommerce_serang.utils.ImageUtils.compressImage import com.alya.ecommerce_serang.utils.SessionManager import com.alya.ecommerce_serang.utils.viewmodel.ProductViewModel import com.bumptech.glide.Glide @@ -40,7 +42,7 @@ class DetailStoreProductActivity : AppCompatActivity() { private lateinit var binding: ActivityDetailStoreProductBinding private lateinit var sessionManager: SessionManager - private lateinit var categoryList: List + private var categoryList: List = emptyList() private var imageUri: Uri? = null private var sppirtUri: Uri? = null private var halalUri: Uri? = null @@ -60,7 +62,10 @@ class DetailStoreProductActivity : AppCompatActivity() { if (result.resultCode == Activity.RESULT_OK) { imageUri = result.data?.data imageUri?.let { - binding.ivPreviewFoto.setImageURI(it) + compressImage(this, it, "productimg").let { compressedImageFile -> + binding.ivPreviewFoto.setImageURI(Uri.fromFile(compressedImageFile)) + imageUri = Uri.fromFile(compressedImageFile) + } binding.switcherFotoProduk.showNext() hasImage = true } @@ -70,17 +75,21 @@ class DetailStoreProductActivity : AppCompatActivity() { private val sppirtLauncher = registerForActivityResult(ActivityResultContracts.GetContent()) { uri -> if (uri != null && isValidFile(uri)) { - sppirtUri = uri - binding.tvSppirtName.text = getFileName(uri) - binding.switcherSppirt.showNext() + compressFile(this, uri).let { compressedFile -> + sppirtUri = compressedFile?.toUri() + binding.tvSppirtName.text = getFileName(sppirtUri!!) + binding.switcherSppirt.showNext() + } } } private val halalLauncher = registerForActivityResult(ActivityResultContracts.GetContent()) { uri -> if (uri != null && isValidFile(uri)) { - halalUri = uri - binding.tvHalalName.text = getFileName(uri) - binding.switcherHalal.showNext() + compressFile(this, uri).let { compressedFile -> + halalUri = compressedFile?.toUri() + binding.tvHalalName.text = getFileName(halalUri!!) + binding.switcherHalal.showNext() + } } } diff --git a/app/src/main/java/com/alya/ecommerce_serang/utils/FileUtils.kt b/app/src/main/java/com/alya/ecommerce_serang/utils/FileUtils.kt index facbdfc..1194605 100644 --- a/app/src/main/java/com/alya/ecommerce_serang/utils/FileUtils.kt +++ b/app/src/main/java/com/alya/ecommerce_serang/utils/FileUtils.kt @@ -8,13 +8,46 @@ import okhttp3.MediaType.Companion.toMediaTypeOrNull import okhttp3.MultipartBody import okhttp3.RequestBody.Companion.asRequestBody import java.io.File +import java.io.FileInputStream import java.io.FileOutputStream +import java.util.zip.GZIPOutputStream object FileUtils { private const val TAG = "FileUtils" /** - * Creates a temporary file from a URI in the app's cache directory + * Compress a file to GZIP format to reduce its size to below 1MB + * @param context The context + * @param uri The URI of the file to compress + * @param maxSize The target size limit in bytes (1MB = 1048576 bytes) + * @return The compressed file, or null if compression failed + */ + fun compressFile(context: Context, uri: Uri, maxSize: Long = 1048576L): File? { + try { + // Create a temporary file for compressed content + val originalFile = createTempFileFromUri(context, uri, "compressed") + val compressedFile = File(context.cacheDir, "compressed_${System.currentTimeMillis()}.gz") + + // Compress the original file into the GZIP file + compressToGZIP(originalFile, compressedFile) + + // Check if the compressed file is larger than the allowed size + if (compressedFile.length() <= maxSize) { + Log.d(TAG, "Compression successful. Compressed file size: ${compressedFile.length()} bytes.") + return compressedFile + } else { + // If the file is still too large, you can handle it by reducing quality or adjusting compression logic + Log.e(TAG, "Compressed file exceeds the size limit. Size: ${compressedFile.length()} bytes.") + return null + } + } catch (e: Exception) { + Log.e(TAG, "Error during file compression: ${e.message}", e) + return null + } + } + + /** + * Creates a temporary file from the URI in the app's cache directory. */ fun createTempFileFromUri(context: Context, uri: Uri, prefix: String = "temp"): File? { try { @@ -41,6 +74,23 @@ object FileUtils { } } + /** + * Compress the input file into a GZIP file. + */ + private fun compressToGZIP(inputFile: File?, outputFile: File) { + FileInputStream(inputFile).use { inputStream -> + FileOutputStream(outputFile).use { fileOutputStream -> + GZIPOutputStream(fileOutputStream).use { gzipOutputStream -> + val buffer = ByteArray(1024) + var bytesRead: Int + while (inputStream.read(buffer).also { bytesRead = it } != -1) { + gzipOutputStream.write(buffer, 0, bytesRead) + } + } + } + } + } + /** * Gets the file extension from a URI using ContentResolver */ diff --git a/app/src/main/java/com/alya/ecommerce_serang/utils/viewmodel/ProfileViewModel.kt b/app/src/main/java/com/alya/ecommerce_serang/utils/viewmodel/ProfileViewModel.kt index e655986..6e56947 100644 --- a/app/src/main/java/com/alya/ecommerce_serang/utils/viewmodel/ProfileViewModel.kt +++ b/app/src/main/java/com/alya/ecommerce_serang/utils/viewmodel/ProfileViewModel.kt @@ -47,15 +47,15 @@ class ProfileViewModel(private val userRepository: UserRepository) : ViewModel() val response: HasStoreResponse = userRepository.checkStore() // Log and store success message - Log.d("RegisterViewModel", "OTP Response: ${response.hasStore}") - _checkStore.value = response.hasStore // Store the message for UI feedback + Log.d("ProfileViewModel", "Has store: ${response.hasStore}") + _checkStore.postValue(response.hasStore) // Store the message for UI feedback } catch (exception: Exception) { // Handle any errors and update state - _checkStore.value = false + _checkStore.postValue(false) // Log the error for debugging - Log.e("RegisterViewModel", "Error:", exception) + Log.e(":ProfileViewModel", "Error:", exception) } } } diff --git a/app/src/main/res/layout/activity_store_suspended.xml b/app/src/main/res/layout/activity_store_suspended.xml new file mode 100644 index 0000000..3ab2dbe --- /dev/null +++ b/app/src/main/res/layout/activity_store_suspended.xml @@ -0,0 +1,39 @@ + + + + + + + + + + + + + + \ No newline at end of file diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 7ee4510..e09c11f 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -1,5 +1,5 @@ [versions] -agp = "8.9.2" +agp = "8.12.0" glide = "4.16.0" gson = "2.11.0" hiltAndroid = "2.56.2" # Updated from 2.44 for better compatibility diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index 00bf192..7ba3b55 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,6 +1,6 @@ #Wed Oct 16 14:37:43 ICT 2024 distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-8.11.1-bin.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-8.13-bin.zip zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists