update icon, chat, balance, and count order

This commit is contained in:
shaulascr
2025-06-25 17:19:44 +07:00
parent 25764c6b89
commit 0cbaecd0cd
29 changed files with 488 additions and 262 deletions

Binary file not shown.

After

Width:  |  Height:  |  Size: 27 KiB

View File

@ -5,6 +5,7 @@ import com.alya.ecommerce_serang.data.api.dto.Store
import com.alya.ecommerce_serang.data.api.response.auth.ListStoreTypeResponse
import com.alya.ecommerce_serang.data.api.response.customer.product.StoreResponse
import com.alya.ecommerce_serang.data.api.response.store.profile.StoreDataResponse
import com.alya.ecommerce_serang.data.api.response.store.sells.OrderListResponse
import com.alya.ecommerce_serang.data.api.retrofit.ApiService
import okhttp3.MultipartBody
import okhttp3.RequestBody
@ -71,4 +72,90 @@ class MyStoreRepository(private val apiService: ApiService) {
street, subdistrict, detail, postalCode, latitude, longitude, userPhone, storeType, storeimg
)
}
suspend fun getSellList(status: String): Result<OrderListResponse> {
return try {
Log.d("SellsRepository", "Add Evidence : $status")
val response = apiService.getSellList(status)
if (response.isSuccessful) {
val allListSell = response.body()
if (allListSell != null) {
Log.d("SellsRepository", "Add Evidence successfully: ${allListSell.message}")
Result.Success(allListSell)
} else {
Log.e("SellsRepository", "Response body was null")
Result.Error(Exception("Empty response from server"))
}
} else {
val errorBody = response.errorBody()?.string() ?: "Unknown error"
Log.e("SellsRepository", "Error Add Evidence : $errorBody")
Result.Error(Exception(errorBody))
}
} catch (e: Exception) {
Log.e("SellsRepository", "Exception Add Evidence ", e)
Result.Error(e)
}
}
suspend fun getBalance(): Result<com.alya.ecommerce_serang.data.api.response.store.StoreResponse> {
return try {
val response = apiService.getMyStoreData()
if (response.isSuccessful) {
val body = response.body()
?: return Result.Error(IllegalStateException("Response body is null"))
// Validate the balance field
val balanceRaw = body.store.balance
balanceRaw.toDoubleOrNull()
?: return Result.Error(NumberFormatException("Invalid balance format: $balanceRaw"))
Result.Success(body)
} else {
Result.Error(
Exception("Failed to load balance: ${response.code()} ${response.message()}")
)
}
} catch (e: Exception) {
Log.e("MyStoreRepository", "Error fetching balance", e)
Result.Error(e)
}
}
// private fun fetchBalance() {
// showLoading(true)
// lifecycleScope.launch {
// try {
// val response = ApiConfig.getApiService(sessionManager).getMyStoreData()
// if (response.isSuccessful && response.body() != null) {
// val storeData = response.body()!!
// val balance = storeData.store.balance
//
// // Format the balance
// try {
// val balanceValue = balance.toDouble()
// binding.tvBalance.text = String.format("Rp%,.0f", balanceValue)
// } catch (e: Exception) {
// binding.tvBalance.text = "Rp$balance"
// }
// } else {
// Toast.makeText(
// this@BalanceActivity,
// "Gagal memuat data saldo: ${response.message()}",
// Toast.LENGTH_SHORT
// ).show()
// }
// } catch (e: Exception) {
// Log.e(TAG, "Error fetching balance", e)
// Toast.makeText(
// this@BalanceActivity,
// "Error: ${e.message}",
// Toast.LENGTH_SHORT
// ).show()
// } finally {
// showLoading(false)
// }
// }
// }
}

View File

@ -63,6 +63,8 @@ class ChatActivity : AppCompatActivity() {
// For image attachment
private var tempImageUri: Uri? = null
private var imageAttach = false
// Typing indicator handler
private val typingHandler = android.os.Handler(android.os.Looper.getMainLooper())
private val stopTypingRunnable = Runnable {
@ -269,6 +271,7 @@ class ChatActivity : AppCompatActivity() {
}
// Options button
binding.btnOptions.visibility = View.GONE
binding.btnOptions.setOnClickListener {
showOptionsMenu()
}
@ -281,6 +284,7 @@ class ChatActivity : AppCompatActivity() {
// This will automatically handle product attachment if enabled
viewModel.sendMessage(message)
binding.editTextMessage.text.clear()
binding.layoutAttachImage.visibility = View.GONE
// Instantly scroll to show new message
binding.recyclerChat.postDelayed({
@ -291,24 +295,33 @@ class ChatActivity : AppCompatActivity() {
// Attachment button
binding.btnAttachment.setOnClickListener {
this.currentFocus?.let { view ->
val imm = getSystemService(Context.INPUT_METHOD_SERVICE) as? InputMethodManager
imm?.hideSoftInputFromWindow(view.windowToken, 0)
}
checkPermissionsAndShowImagePicker()
}
binding.btnCloseChat.setOnClickListener{
binding.layoutAttachImage.visibility = View.GONE
imageAttach = false
viewModel.clearSelectedImage()
}
// Product card click to enable/disable product attachment
binding.productContainer.setOnClickListener {
toggleProductAttachment()
}
}
private fun toggleProductAttachment() {
val currentState = viewModel.state.value
if (currentState?.hasProductAttachment == true) {
// Disable product attachment
viewModel.disableProductAttachment()
updateProductAttachmentUI(false)
Toast.makeText(this, "Product attachment disabled", Toast.LENGTH_SHORT).show()
} else {
// Enable product attachment
viewModel.enableProductAttachment()
updateProductAttachmentUI(true)
Toast.makeText(this, "Product will be attached to your next message", Toast.LENGTH_SHORT).show()
@ -405,7 +418,7 @@ class ChatActivity : AppCompatActivity() {
}
}
// Update product info
// layout attach product
if (!state.productName.isNullOrEmpty()) {
binding.tvProductName.text = state.productName
binding.tvProductPrice.text = state.productPrice
@ -440,15 +453,11 @@ class ChatActivity : AppCompatActivity() {
// Update attachment hint
if (state.hasAttachment) {
binding.editTextMessage.hint = getString(R.string.image_attached)
binding.layoutAttachImage.visibility = View.VISIBLE
} else {
binding.editTextMessage.hint = getString(R.string.write_message)
}
// Show typing indicator
binding.tvTypingIndicator.visibility =
if (state.isOtherUserTyping) View.VISIBLE else View.GONE
// Show error if any
state.error?.let { error ->
Toast.makeText(this@ChatActivity, error, Toast.LENGTH_SHORT).show()
@ -459,7 +468,7 @@ class ChatActivity : AppCompatActivity() {
private fun updateInputHint(state: ChatUiState) {
binding.editTextMessage.hint = when {
state.hasAttachment -> getString(R.string.image_attached)
state.hasAttachment -> getString(R.string.write_message)
state.hasProductAttachment -> "Type your message (product will be attached)"
else -> getString(R.string.write_message)
}
@ -504,6 +513,7 @@ class ChatActivity : AppCompatActivity() {
getString(R.string.cancel)
)
AlertDialog.Builder(this)
.setTitle(getString(R.string.options))
.setItems(options) { dialog, which ->
@ -578,7 +588,21 @@ class ChatActivity : AppCompatActivity() {
private fun handleSelectedImage(uri: Uri) {
try {
Log.d(TAG, "Processing selected image: $uri")
Log.d(TAG, "Processing selected image: ${uri.toString()}")
imageAttach = true
binding.layoutAttachImage.visibility = View.VISIBLE
val fullImageUrl = when (val img = uri.toString()) {
is String -> {
if (img.startsWith("/")) BASE_URL + img.substring(1) else img
}
else -> R.drawable.placeholder_image
}
Glide.with(this)
.load(fullImageUrl)
.placeholder(R.drawable.placeholder_image)
.into(binding.ivAttach)
Log.d(TAG, "Display attach image: $uri")
// Always use the copy-to-cache approach for reliability
contentResolver.openInputStream(uri)?.use { inputStream ->
@ -598,6 +622,7 @@ class ChatActivity : AppCompatActivity() {
Log.d(TAG, "Image processed successfully: ${outputFile.absolutePath}, size: ${outputFile.length()}")
viewModel.setSelectedImageFile(outputFile)
Toast.makeText(this, "Image selected", Toast.LENGTH_SHORT).show()
} else {
Log.e(TAG, "Failed to create image file")
@ -682,24 +707,3 @@ class ChatActivity : AppCompatActivity() {
}
}
}
//if implement typing status
// private fun handleConnectionState(state: ConnectionState) {
// when (state) {
// is ConnectionState.Connected -> {
// binding.tvConnectionStatus.visibility = View.GONE
// }
// is ConnectionState.Connecting -> {
// binding.tvConnectionStatus.visibility = View.VISIBLE
// binding.tvConnectionStatus.text = getString(R.string.connecting)
// }
// is ConnectionState.Disconnected -> {
// binding.tvConnectionStatus.visibility = View.VISIBLE
// binding.tvConnectionStatus.text = getString(R.string.disconnected_reconnecting)
// }
// is ConnectionState.Error -> {
// binding.tvConnectionStatus.visibility = View.VISIBLE
// binding.tvConnectionStatus.text = getString(R.string.connection_error, state.message)
// }
// }
// }

View File

@ -23,6 +23,28 @@ import java.util.Locale
import java.util.TimeZone
import javax.inject.Inject
/**
* ChatViewModel - Manages chat functionality for both buyers and store owners
*
* ARCHITECTURE OVERVIEW:
* - Handles real-time messaging via Socket.IO
* - Manages chat state using LiveData/MutableLiveData pattern
* - Supports multiple message types: TEXT, IMAGE, PRODUCT
* - Maintains separate flows for buyer and store owner chat
*
* KEY RESPONSIBILITIES:
* 1. Socket connection management and real-time message handling
* 2. Message sending/receiving with different attachment types
* 3. Chat history loading and message status updates
* 4. Product attachment functionality for commerce integration
* 5. User session management and authentication
*
* STATE MANAGEMENT PATTERN:
* - All UI state updates go through updateState() helper function
* - State updates are atomic and follow immutable pattern
* - Error states are cleared explicitly via clearError()
*/
@HiltViewModel
class ChatViewModel @Inject constructor(
private val chatRepository: ChatRepository,
@ -730,6 +752,19 @@ class ChatViewModel @Inject constructor(
Log.d(TAG, "Image attachment ${if (file != null) "selected: ${file.name}" else "cleared"}")
}
fun clearSelectedImage() {
Log.d(TAG, "Clearing selected image attachment")
selectedImageFile?.let { file ->
Log.d(TAG, "Clearing image file: ${file.name}")
}
selectedImageFile = null
updateState { it.copy(hasAttachment = false) }
Log.d(TAG, "Image attachment cleared successfully")
}
// convert form chatLine api to UI chat messages
private fun convertChatLineToUiMessage(chatLine: ChatLine): ChatUiMessage {
val formattedTime = formatTimestamp(chatLine.createdAt)

View File

@ -7,12 +7,14 @@ import android.widget.Toast
import androidx.activity.enableEdgeToEdge
import androidx.activity.viewModels
import androidx.appcompat.app.AppCompatActivity
import androidx.lifecycle.lifecycleScope
import com.alya.ecommerce_serang.BuildConfig.BASE_URL
import com.alya.ecommerce_serang.R
import com.alya.ecommerce_serang.data.api.dto.Store
import com.alya.ecommerce_serang.data.api.retrofit.ApiConfig
import com.alya.ecommerce_serang.data.api.retrofit.ApiService
import com.alya.ecommerce_serang.data.repository.MyStoreRepository
import com.alya.ecommerce_serang.data.repository.Result
import com.alya.ecommerce_serang.databinding.ActivityMyStoreBinding
import com.alya.ecommerce_serang.ui.profile.mystore.balance.BalanceActivity
import com.alya.ecommerce_serang.ui.profile.mystore.chat.ChatListStoreActivity
@ -24,6 +26,7 @@ import com.alya.ecommerce_serang.utils.BaseViewModelFactory
import com.alya.ecommerce_serang.utils.SessionManager
import com.alya.ecommerce_serang.utils.viewmodel.MyStoreViewModel
import com.bumptech.glide.Glide
import kotlinx.coroutines.launch
class MyStoreActivity : AppCompatActivity() {
private lateinit var binding: ActivityMyStoreBinding
@ -66,6 +69,9 @@ class MyStoreActivity : AppCompatActivity() {
}
setUpClickListeners()
getCountOrder()
viewModel.fetchBalance()
fetchBalance()
}
private fun myStoreProfileOverview(store: Store){
@ -147,6 +153,46 @@ class MyStoreActivity : AppCompatActivity() {
}
}
private fun getCountOrder(){
lifecycleScope.launch {
try {
val allCounts = viewModel.getAllStatusCounts()
val totalUnpaid = allCounts["unpaid"]
val totalPaid = allCounts["paid"]
val totalProcessed = allCounts["processed"]
Log.d("MyStoreActivity",
"Total orders: unpaid=$totalUnpaid, processed=$totalProcessed, paid=$totalPaid")
binding.tvNumPesananMasuk.text = totalUnpaid.toString()
binding.tvNumPembayaran.text = totalPaid.toString()
binding.tvNumPerluDikirim.text = totalProcessed.toString()
} catch (e:Exception){
Log.e("MyStoreActivity", "Error getting order counts: ${e.message}")
}
}
}
private fun fetchBalance(){
viewModel.balanceResult.observe(this){result ->
when (result) {
is com.alya.ecommerce_serang.data.repository.Result.Loading ->
null
// binding.progressBar.isVisible = true
is com.alya.ecommerce_serang.data.repository.Result.Success ->
viewModel.formattedBalance.observe(this) {
binding.tvBalance.text = it
}
is Result.Error -> {
// binding.progressBar.isVisible = false
Log.e(
"MyStoreActivity",
"Gagal memuat saldo: ${result.exception.localizedMessage}"
)
}
}
}
}
companion object {
private const val PROFILE_REQUEST_CODE = 100
}

View File

@ -408,6 +408,10 @@ class BalanceActivity : AppCompatActivity() {
}
}
private fun navigateTotalBalance(){
}
companion object {
private const val TOP_UP_REQUEST_CODE = 101
}

View File

@ -426,8 +426,8 @@ class ChatStoreActivity : AppCompatActivity() {
}
// Show typing indicator
binding.tvTypingIndicator.visibility =
if (state.isOtherUserTyping) View.VISIBLE else View.GONE
// binding.tvTypingIndicator.visibility =
// if (state.isOtherUserTyping) View.VISIBLE else View.GONE
// Show error if any
state.error?.let { error ->
@ -520,6 +520,19 @@ class ChatStoreActivity : AppCompatActivity() {
private fun handleSelectedImage(uri: Uri) {
try {
Log.d(TAG, "Processing selected image: $uri")
binding.layoutAttachImage.visibility = View.VISIBLE
val fullImageUrl = when (val img = uri.toString()) {
is String -> {
if (img.startsWith("/")) BASE_URL + img.substring(1) else img
}
else -> R.drawable.placeholder_image
}
Glide.with(this)
.load(fullImageUrl)
.placeholder(R.drawable.placeholder_image)
.into(binding.ivAttach)
Log.d(TAG, "Display attach image: $uri")
// Always use the copy-to-cache approach for reliability
contentResolver.openInputStream(uri)?.use { inputStream ->

View File

@ -9,6 +9,7 @@ import android.view.ViewGroup
import android.widget.Toast
import androidx.fragment.app.Fragment
import androidx.fragment.app.viewModels
import androidx.lifecycle.lifecycleScope
import androidx.recyclerview.widget.LinearLayoutManager
import com.alya.ecommerce_serang.data.api.response.store.sells.OrdersItem
import com.alya.ecommerce_serang.data.api.retrofit.ApiConfig
@ -16,12 +17,14 @@ import com.alya.ecommerce_serang.data.repository.Result
import com.alya.ecommerce_serang.data.repository.SellsRepository
import com.alya.ecommerce_serang.databinding.FragmentSellsListBinding
import com.alya.ecommerce_serang.ui.order.address.ViewState
import com.alya.ecommerce_serang.ui.profile.mystore.MyStoreActivity
import com.alya.ecommerce_serang.ui.profile.mystore.sells.payment.DetailPaymentActivity
import com.alya.ecommerce_serang.ui.profile.mystore.sells.shipment.DetailShipmentActivity
import com.alya.ecommerce_serang.utils.BaseViewModelFactory
import com.alya.ecommerce_serang.utils.SessionManager
import com.alya.ecommerce_serang.utils.viewmodel.SellsViewModel
import com.google.gson.Gson
import kotlinx.coroutines.launch
class SellsListFragment : Fragment() {
@ -84,6 +87,7 @@ class SellsListFragment : Fragment() {
observeSellsList()
observePaymentConfirmation()
loadSells()
// getAllOrderCountsAndNavigate()
}
private fun setupRecyclerView() {
@ -183,6 +187,30 @@ class SellsListFragment : Fragment() {
context.startActivity(intent)
}
private fun getAllOrderCountsAndNavigate() {
lifecycleScope.launch {
try {
// Show loading if needed
binding.progressBar.visibility = View.VISIBLE
val allCounts = viewModel.getAllStatusCounts()
binding.progressBar.visibility = View.GONE
val intent = Intent(requireContext(), MyStoreActivity::class.java)
intent.putExtra("total_unpaid", allCounts["unpaid"])
intent.putExtra("total_paid", allCounts["paid"])
intent.putExtra("total_processed", allCounts["processed"])
Log.d("SellsListFragment", "Total orders: unpaid=${allCounts["unpaid"]}, processed=${allCounts["processed"]}, Paid=${allCounts["paid"]}")
} catch (e: Exception) {
binding.progressBar.visibility = View.GONE
Log.e(TAG, "Error getting order counts: ${e.message}")
}
}
}
override fun onDestroyView() {
super.onDestroyView()
_binding = null

View File

@ -1,11 +1,14 @@
package com.alya.ecommerce_serang.utils.viewmodel
import android.util.Log
import androidx.lifecycle.LiveData
import androidx.lifecycle.MutableLiveData
import androidx.lifecycle.ViewModel
import androidx.lifecycle.map
import androidx.lifecycle.viewModelScope
import com.alya.ecommerce_serang.data.api.dto.Store
import com.alya.ecommerce_serang.data.api.response.auth.StoreTypesItem
import com.alya.ecommerce_serang.data.api.response.store.StoreResponse
import com.alya.ecommerce_serang.data.api.response.store.profile.StoreDataResponse
import com.alya.ecommerce_serang.data.repository.MyStoreRepository
import com.alya.ecommerce_serang.data.repository.Result
@ -13,6 +16,8 @@ import kotlinx.coroutines.launch
import okhttp3.MediaType.Companion.toMediaTypeOrNull
import okhttp3.MultipartBody
import okhttp3.RequestBody
import java.text.NumberFormat
import java.util.Locale
class MyStoreViewModel(private val repository: MyStoreRepository): ViewModel() {
private val _myStoreProfile = MutableLiveData<Store?>()
@ -30,6 +35,9 @@ class MyStoreViewModel(private val repository: MyStoreRepository): ViewModel() {
private val _errorMessage = MutableLiveData<String>()
val errorMessage : LiveData<String> = _errorMessage
private val _balanceResult = MutableLiveData<Result<StoreResponse>>()
val balanceResult: LiveData<Result<StoreResponse>> get() = _balanceResult
fun loadMyStore(){
viewModelScope.launch {
when (val result = repository.fetchMyStoreProfile()){
@ -100,6 +108,56 @@ class MyStoreViewModel(private val repository: MyStoreRepository): ViewModel() {
}
}
suspend fun getTotalOrdersByStatus(status: String): Int {
return try {
when (val result = repository.getSellList(status)) {
is Result.Success -> {
// Access the orders list from the response
result.data.orders.size ?: 0
}
is Result.Error -> {
Log.e("SellsViewModel", "Error getting orders count: ${result.exception.message}")
0
}
is Result.Loading -> 0
}
} catch (e: Exception) {
Log.e("SellsViewModel", "Exception getting orders count", e)
0
}
}
//count the order
suspend fun getAllStatusCounts(): Map<String, Int> {
val statuses = listOf( "unpaid", "paid", "processed")
val counts = mutableMapOf<String, Int>()
statuses.forEach { status ->
counts[status] = getTotalOrdersByStatus(status)
Log.d("SellsViewModel", "Status: $status, countOrder=${counts[status]}")
}
return counts
}
val formattedBalance: LiveData<String> = balanceResult.map { result ->
when (result) {
is Result.Success -> {
val raw = result.data.store.balance.toDouble()
NumberFormat.getCurrencyInstance(Locale("in", "ID")).format(raw)
}
else -> ""
}
}
/** Trigger the network call */
fun fetchBalance() {
viewModelScope.launch {
_balanceResult.value = Result.Loading
_balanceResult.value = repository.getBalance()
}
}
private fun String.toRequestBody(): RequestBody =
RequestBody.create("text/plain".toMediaTypeOrNull(), this)
}

View File

@ -146,6 +146,38 @@ class SellsViewModel(private val repository: SellsRepository) : ViewModel() {
Log.d(TAG, "========== getSellList method completed ==========")
}
//get total order each status
suspend fun getTotalOrdersByStatus(status: String): Int {
return try {
when (val result = repository.getSellList(status)) {
is Result.Success -> {
// Access the orders list from the response
result.data.orders.size ?: 0
}
is Result.Error -> {
Log.e("SellsViewModel", "Error getting orders count: ${result.exception.message}")
0
}
is Result.Loading -> 0
}
} catch (e: Exception) {
Log.e("SellsViewModel", "Exception getting orders count", e)
0
}
}
//count the order
suspend fun getAllStatusCounts(): Map<String, Int> {
val statuses = listOf( "unpaid", "paid", "processed")
val counts = mutableMapOf<String, Int>()
statuses.forEach { status ->
counts[status] = getTotalOrdersByStatus(status)
Log.d("SellsViewModel", "Status: $status, countOrder=${counts[status]}")
}
return counts
}
fun getSellDetails(orderId: Int) {
Log.d(TAG, "========== Starting getSellDetails ==========")

View File

@ -0,0 +1,9 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="14dp"
android:height="14dp"
android:viewportWidth="14"
android:viewportHeight="14">
<path
android:pathData="M7,8.4L2.1,13.3C1.917,13.483 1.683,13.575 1.4,13.575C1.117,13.575 0.883,13.483 0.7,13.3C0.517,13.116 0.425,12.883 0.425,12.6C0.425,12.316 0.517,12.083 0.7,11.9L5.6,7L0.7,2.1C0.517,1.916 0.425,1.683 0.425,1.4C0.425,1.116 0.517,0.883 0.7,0.7C0.883,0.516 1.117,0.425 1.4,0.425C1.683,0.425 1.917,0.516 2.1,0.7L7,5.6L11.9,0.7C12.083,0.516 12.317,0.425 12.6,0.425C12.883,0.425 13.117,0.516 13.3,0.7C13.483,0.883 13.575,1.116 13.575,1.4C13.575,1.683 13.483,1.916 13.3,2.1L8.4,7L13.3,11.9C13.483,12.083 13.575,12.316 13.575,12.6C13.575,12.883 13.483,13.116 13.3,13.3C13.117,13.483 12.883,13.575 12.6,13.575C12.317,13.575 12.083,13.483 11.9,13.3L7,8.4Z"
android:fillColor="#000000"/>
</vector>

View File

@ -1,170 +1,74 @@
<?xml version="1.0" encoding="utf-8"?>
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="108dp"
<vector
android:height="108dp"
android:width="108dp"
android:viewportHeight="108"
android:viewportWidth="108"
android:viewportHeight="108">
<path
android:fillColor="#3DDC84"
xmlns:android="http://schemas.android.com/apk/res/android">
<path android:fillColor="#3DDC84"
android:pathData="M0,0h108v108h-108z"/>
<path
android:fillColor="#00000000"
android:pathData="M9,0L9,108"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M19,0L19,108"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M29,0L29,108"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M39,0L39,108"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M49,0L49,108"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M59,0L59,108"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M69,0L69,108"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M79,0L79,108"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M89,0L89,108"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M99,0L99,108"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M0,9L108,9"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M0,19L108,19"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M0,29L108,29"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M0,39L108,39"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M0,49L108,49"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M0,59L108,59"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M0,69L108,69"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M0,79L108,79"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M0,89L108,89"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M0,99L108,99"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M19,29L89,29"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M19,39L89,39"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M19,49L89,49"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M19,59L89,59"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M19,69L89,69"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M19,79L89,79"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M29,19L29,89"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M39,19L39,89"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M49,19L49,89"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M59,19L59,89"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M69,19L69,89"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M79,19L79,89"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path android:fillColor="#00000000" android:pathData="M9,0L9,108"
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
<path android:fillColor="#00000000" android:pathData="M19,0L19,108"
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
<path android:fillColor="#00000000" android:pathData="M29,0L29,108"
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
<path android:fillColor="#00000000" android:pathData="M39,0L39,108"
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
<path android:fillColor="#00000000" android:pathData="M49,0L49,108"
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
<path android:fillColor="#00000000" android:pathData="M59,0L59,108"
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
<path android:fillColor="#00000000" android:pathData="M69,0L69,108"
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
<path android:fillColor="#00000000" android:pathData="M79,0L79,108"
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
<path android:fillColor="#00000000" android:pathData="M89,0L89,108"
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
<path android:fillColor="#00000000" android:pathData="M99,0L99,108"
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
<path android:fillColor="#00000000" android:pathData="M0,9L108,9"
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
<path android:fillColor="#00000000" android:pathData="M0,19L108,19"
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
<path android:fillColor="#00000000" android:pathData="M0,29L108,29"
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
<path android:fillColor="#00000000" android:pathData="M0,39L108,39"
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
<path android:fillColor="#00000000" android:pathData="M0,49L108,49"
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
<path android:fillColor="#00000000" android:pathData="M0,59L108,59"
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
<path android:fillColor="#00000000" android:pathData="M0,69L108,69"
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
<path android:fillColor="#00000000" android:pathData="M0,79L108,79"
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
<path android:fillColor="#00000000" android:pathData="M0,89L108,89"
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
<path android:fillColor="#00000000" android:pathData="M0,99L108,99"
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
<path android:fillColor="#00000000" android:pathData="M19,29L89,29"
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
<path android:fillColor="#00000000" android:pathData="M19,39L89,39"
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
<path android:fillColor="#00000000" android:pathData="M19,49L89,49"
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
<path android:fillColor="#00000000" android:pathData="M19,59L89,59"
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
<path android:fillColor="#00000000" android:pathData="M19,69L89,69"
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
<path android:fillColor="#00000000" android:pathData="M19,79L89,79"
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
<path android:fillColor="#00000000" android:pathData="M29,19L29,89"
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
<path android:fillColor="#00000000" android:pathData="M39,19L39,89"
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
<path android:fillColor="#00000000" android:pathData="M49,19L49,89"
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
<path android:fillColor="#00000000" android:pathData="M59,19L59,89"
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
<path android:fillColor="#00000000" android:pathData="M69,19L69,89"
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
<path android:fillColor="#00000000" android:pathData="M79,19L79,89"
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
</vector>

View File

@ -1,30 +1,20 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:aapt="http://schemas.android.com/aapt"
android:width="108dp"
android:height="108dp"
android:viewportWidth="108"
android:viewportHeight="108">
<path android:pathData="M31,63.928c0,0 6.4,-11 12.1,-13.1c7.2,-2.6 26,-1.4 26,-1.4l38.1,38.1L107,108.928l-32,-1L31,63.928z">
<aapt:attr name="android:fillColor">
<gradient
android:endX="85.84757"
android:endY="92.4963"
android:startX="42.9492"
android:startY="49.59793"
android:type="linear">
<item
android:color="#44000000"
android:offset="0.0" />
<item
android:color="#00000000"
android:offset="1.0" />
</gradient>
</aapt:attr>
</path>
android:viewportWidth="64"
android:viewportHeight="64">
<group android:scaleX="0.6722222"
android:scaleY="0.6722222"
android:translateX="10.488889"
android:translateY="10.488889">
<path
android:fillColor="#FFFFFF"
android:fillType="nonZero"
android:pathData="M65.3,45.828l3.8,-6.6c0.2,-0.4 0.1,-0.9 -0.3,-1.1c-0.4,-0.2 -0.9,-0.1 -1.1,0.3l-3.9,6.7c-6.3,-2.8 -13.4,-2.8 -19.7,0l-3.9,-6.7c-0.2,-0.4 -0.7,-0.5 -1.1,-0.3C38.8,38.328 38.7,38.828 38.9,39.228l3.8,6.6C36.2,49.428 31.7,56.028 31,63.928h46C76.3,56.028 71.8,49.428 65.3,45.828zM43.4,57.328c-0.8,0 -1.5,-0.5 -1.8,-1.2c-0.3,-0.7 -0.1,-1.5 0.4,-2.1c0.5,-0.5 1.4,-0.7 2.1,-0.4c0.7,0.3 1.2,1 1.2,1.8C45.3,56.528 44.5,57.328 43.4,57.328L43.4,57.328zM64.6,57.328c-0.8,0 -1.5,-0.5 -1.8,-1.2s-0.1,-1.5 0.4,-2.1c0.5,-0.5 1.4,-0.7 2.1,-0.4c0.7,0.3 1.2,1 1.2,1.8C66.5,56.528 65.6,57.328 64.6,57.328L64.6,57.328z"
android:strokeWidth="1"
android:strokeColor="#00000000" />
android:pathData="M0,0h64v64h-64z"
android:fillColor="#489EC6"/>
<path
android:pathData="M11.868,58C10.523,58 9.399,57.538 8.497,56.614C7.594,55.69 7.144,54.537 7.146,53.155V29.074C5.912,28.14 5.009,26.915 4.438,25.399C3.867,23.883 3.854,22.266 4.4,20.548L7.245,10.924C7.635,9.7 8.264,8.74 9.131,8.044C10.001,7.348 11.075,7 12.354,7H51.536C52.813,7 53.883,7.326 54.747,7.978C55.608,8.63 56.24,9.573 56.641,10.807L59.598,20.545C60.146,22.265 60.134,23.896 59.563,25.438C58.992,26.98 58.089,28.23 56.855,29.188V53.152C56.855,54.534 56.404,55.687 55.501,56.611C54.599,57.535 53.476,57.998 52.133,58H11.868ZM38.433,28C40.311,28 41.712,27.46 42.638,26.38C43.564,25.302 43.954,24.188 43.808,23.038L41.866,10H33.465V22.6C33.465,24.074 33.957,25.342 34.939,26.404C35.922,27.468 37.084,28 38.433,28ZM25.278,28C26.849,28 28.119,27.468 29.088,26.404C30.057,25.34 30.541,24.072 30.541,22.6V10H22.138L20.19,23.269C20.071,24.201 20.468,25.222 21.38,26.332C22.292,27.442 23.594,27.998 25.278,28ZM12.263,28C13.551,28 14.647,27.55 15.55,26.65C16.452,25.75 17.014,24.627 17.234,23.281L19.067,10H12.354C11.716,10 11.209,10.144 10.833,10.432C10.457,10.72 10.176,11.153 9.991,11.731L7.292,21.205C6.812,22.781 7.017,24.308 7.906,25.786C8.795,27.264 10.247,28.002 12.263,28ZM51.738,28C53.488,28 54.886,27.3 55.931,25.9C56.978,24.5 57.237,22.935 56.709,21.205L53.864,11.617C53.676,11.039 53.395,10.625 53.019,10.375C52.642,10.125 52.137,10 51.501,10H44.933L46.767,23.281C46.987,24.627 47.549,25.75 48.451,26.65C49.354,27.55 50.449,28 51.738,28Z"
android:fillColor="#ffffff"/>
<path
android:pathData="M20.382,39V30.6H23.97C24.554,30.6 25.046,30.692 25.446,30.876C25.846,31.052 26.15,31.304 26.358,31.632C26.574,31.952 26.682,32.332 26.682,32.772C26.682,33.196 26.59,33.552 26.406,33.84C26.222,34.128 25.978,34.348 25.674,34.5C25.378,34.652 25.05,34.744 24.69,34.776L24.882,34.632C25.274,34.648 25.618,34.752 25.914,34.944C26.21,35.136 26.442,35.388 26.61,35.7C26.786,36.004 26.874,36.34 26.874,36.708C26.874,37.164 26.766,37.564 26.55,37.908C26.334,38.252 26.018,38.52 25.602,38.712C25.186,38.904 24.682,39 24.09,39H20.382ZM22.182,37.536H23.79C24.19,37.536 24.498,37.448 24.714,37.272C24.938,37.088 25.05,36.824 25.05,36.48C25.05,36.136 24.934,35.868 24.702,35.676C24.478,35.484 24.166,35.388 23.766,35.388H22.182V37.536ZM22.182,34.056H23.658C24.042,34.056 24.334,33.968 24.534,33.792C24.742,33.616 24.846,33.368 24.846,33.048C24.846,32.728 24.742,32.48 24.534,32.304C24.334,32.12 24.038,32.028 23.646,32.028H22.182V34.056ZM28.163,39V32.952H29.963V39H28.163ZM29.063,32.256C28.743,32.256 28.483,32.164 28.283,31.98C28.083,31.796 27.983,31.564 27.983,31.284C27.983,30.996 28.083,30.76 28.283,30.576C28.483,30.392 28.743,30.3 29.063,30.3C29.391,30.3 29.655,30.392 29.855,30.576C30.063,30.76 30.167,30.996 30.167,31.284C30.167,31.564 30.063,31.796 29.855,31.98C29.655,32.164 29.391,32.256 29.063,32.256ZM34.069,39.144C33.501,39.144 33.009,39.056 32.593,38.88C32.186,38.696 31.861,38.448 31.622,38.136C31.389,37.824 31.257,37.472 31.226,37.08H33.014C33.046,37.216 33.102,37.34 33.181,37.452C33.27,37.556 33.386,37.64 33.529,37.704C33.681,37.76 33.849,37.788 34.034,37.788C34.234,37.788 34.394,37.764 34.514,37.716C34.641,37.66 34.737,37.588 34.801,37.5C34.866,37.412 34.897,37.32 34.897,37.224C34.897,37.072 34.849,36.956 34.754,36.876C34.666,36.796 34.534,36.732 34.357,36.684C34.181,36.628 33.97,36.576 33.722,36.528C33.433,36.464 33.146,36.392 32.857,36.312C32.577,36.224 32.326,36.116 32.102,35.988C31.885,35.86 31.709,35.696 31.573,35.496C31.445,35.288 31.382,35.036 31.382,34.74C31.382,34.38 31.482,34.056 31.681,33.768C31.882,33.472 32.169,33.24 32.546,33.072C32.922,32.896 33.377,32.808 33.914,32.808C34.674,32.808 35.27,32.976 35.701,33.312C36.133,33.648 36.389,34.1 36.47,34.668H34.79C34.742,34.508 34.641,34.388 34.489,34.308C34.338,34.22 34.146,34.176 33.914,34.176C33.65,34.176 33.45,34.22 33.313,34.308C33.178,34.396 33.11,34.512 33.11,34.656C33.11,34.752 33.153,34.84 33.242,34.92C33.338,34.992 33.473,35.056 33.65,35.112C33.826,35.168 34.042,35.224 34.298,35.28C34.785,35.384 35.206,35.496 35.557,35.616C35.917,35.736 36.197,35.912 36.397,36.144C36.597,36.368 36.694,36.696 36.686,37.128C36.694,37.52 36.59,37.868 36.374,38.172C36.166,38.476 35.866,38.716 35.473,38.892C35.082,39.06 34.613,39.144 34.069,39.144ZM40.094,39.144C39.59,39.144 39.17,39.064 38.834,38.904C38.506,38.744 38.262,38.528 38.102,38.256C37.95,37.976 37.874,37.668 37.874,37.332C37.874,36.972 37.962,36.656 38.138,36.384C38.322,36.104 38.606,35.884 38.99,35.724C39.374,35.556 39.858,35.472 40.442,35.472H41.906C41.906,35.2 41.87,34.976 41.798,34.8C41.734,34.624 41.626,34.492 41.474,34.404C41.322,34.316 41.114,34.272 40.85,34.272C40.57,34.272 40.334,34.328 40.142,34.44C39.95,34.552 39.83,34.728 39.782,34.968H38.054C38.094,34.536 38.234,34.16 38.474,33.84C38.722,33.52 39.05,33.268 39.458,33.084C39.866,32.9 40.334,32.808 40.862,32.808C41.438,32.808 41.938,32.904 42.362,33.096C42.786,33.28 43.114,33.552 43.346,33.912C43.586,34.272 43.706,34.72 43.706,35.256V39H42.206L41.99,38.124C41.902,38.276 41.798,38.416 41.678,38.544C41.558,38.664 41.418,38.772 41.258,38.868C41.098,38.956 40.922,39.024 40.73,39.072C40.538,39.12 40.326,39.144 40.094,39.144ZM40.538,37.776C40.73,37.776 40.898,37.744 41.042,37.68C41.186,37.616 41.31,37.528 41.414,37.416C41.518,37.304 41.602,37.176 41.666,37.032C41.738,36.88 41.79,36.716 41.822,36.54V36.528H40.658C40.458,36.528 40.29,36.556 40.154,36.612C40.026,36.66 39.93,36.732 39.866,36.828C39.802,36.924 39.77,37.036 39.77,37.164C39.77,37.3 39.802,37.416 39.866,37.512C39.938,37.6 40.03,37.668 40.142,37.716C40.262,37.756 40.394,37.776 40.538,37.776ZM17.132,53.144C16.5,53.144 15.924,53.02 15.404,52.772C14.892,52.516 14.484,52.136 14.18,51.632C13.884,51.128 13.736,50.492 13.736,49.724V44.6H15.536V49.736C15.536,50.112 15.596,50.432 15.716,50.696C15.844,50.96 16.028,51.16 16.268,51.296C16.516,51.424 16.812,51.488 17.156,51.488C17.508,51.488 17.804,51.424 18.044,51.296C18.292,51.16 18.48,50.96 18.608,50.696C18.736,50.432 18.8,50.112 18.8,49.736V44.6H20.6V49.724C20.6,50.492 20.44,51.128 20.12,51.632C19.808,52.136 19.388,52.516 18.86,52.772C18.34,53.02 17.764,53.144 17.132,53.144ZM22.128,53V44.6H24.288L26.736,49.652L29.16,44.6H31.308V53H29.508V47.636L27.444,51.824H26.004L23.928,47.636V53H22.128ZM32.921,53V44.6H34.721V47.78L37.625,44.6H39.833L36.749,47.924L39.941,53H37.733L35.465,49.316L34.721,50.12V53H32.921ZM41.007,53V44.6H43.167L45.615,49.652L48.039,44.6H50.187V53H48.387V47.636L46.323,51.824H44.883L42.807,47.636V53H41.007Z"
android:fillColor="#489EC6"/>
</group>
</vector>

View File

@ -0,0 +1,9 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="19"
android:viewportHeight="16">
<path
android:pathData="M0,16V10L8,8L0,6V0L19,8L0,16Z"
android:fillColor="#000000"/>
</vector>

View File

@ -54,19 +54,9 @@
android:textStyle="bold"
app:layout_constraintStart_toEndOf="@+id/imgProfile"
app:layout_constraintTop_toTopOf="@+id/imgProfile"
app:layout_constraintEnd_toStartOf="@+id/btnOptions" />
app:layout_constraintEnd_toStartOf="@+id/btnOptions"
app:layout_constraintBottom_toBottomOf="parent"/>
<!-- <TextView-->
<!-- android:id="@+id/tvLastActive"-->
<!-- android:layout_width="0dp"-->
<!-- android:layout_height="wrap_content"-->
<!-- android:layout_marginStart="8dp"-->
<!-- android:text="Aktif 3 jam lalu"-->
<!-- android:textColor="#888888"-->
<!-- android:textSize="12sp"-->
<!-- app:layout_constraintStart_toEndOf="@+id/imgProfile"-->
<!-- app:layout_constraintTop_toBottomOf="@+id/tvStoreName"-->
<!-- app:layout_constraintEnd_toEndOf="@+id/tvStoreName" />-->
<ImageButton
android:id="@+id/btnOptions"
@ -178,22 +168,47 @@
android:clipToPadding="false"
android:paddingTop="8dp"
android:paddingBottom="8dp"
app:layout_constraintBottom_toTopOf="@+id/tvTypingIndicator"
app:layout_constraintBottom_toTopOf="@+id/layoutChatInput"
app:layout_constraintTop_toBottomOf="@+id/cardProduct" />
<!-- Typing indicator -->
<TextView
android:id="@+id/tvTypingIndicator"
<androidx.cardview.widget.CardView
android:id="@+id/layoutAttachImage"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:padding="4dp"
android:text="User is typing..."
android:textColor="#666666"
android:textSize="12sp"
android:textStyle="italic"
android:visibility="gone"
app:layout_constraintBottom_toTopOf="@+id/layoutChatInput"
tools:visibility="visible" />
android:padding="4dp"
app:layout_constraintBottom_toTopOf="@id/layoutChatInput"
app:layout_constraintStart_toStartOf="parent">
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:padding="4dp">
<ImageView
android:id="@+id/iv_attach"
android:layout_width="120dp"
android:layout_height="150dp"
android:clipToOutline="true"
android:layout_marginStart="8dp"
android:layout_marginVertical="8dp"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
/>
<ImageButton
android:id="@+id/btn_close_chat"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:backgroundTint="@android:color/transparent"
android:layout_marginEnd="16dp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintBottom_toBottomOf="parent"
android:src="@drawable/ic_close_chat"
/>
</androidx.constraintlayout.widget.ConstraintLayout>
</androidx.cardview.widget.CardView>
<!-- Chat input area -->
<LinearLayout
@ -239,7 +254,7 @@
android:layout_gravity="center_vertical"
android:background="?attr/selectableItemBackgroundBorderless"
android:contentDescription="Send"
android:src="@drawable/baseline_attach_file_24" />
android:src="@drawable/ic_sent" />
</LinearLayout>
</androidx.constraintlayout.widget.ConstraintLayout>

View File

@ -1,6 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">
</androidx.constraintlayout.widget.ConstraintLayout>

View File

@ -2,5 +2,4 @@
<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
<background android:drawable="@drawable/ic_launcher_background"/>
<foreground android:drawable="@drawable/ic_launcher_foreground"/>
<monochrome android:drawable="@drawable/ic_launcher_foreground" />
</adaptive-icon>

View File

@ -2,5 +2,4 @@
<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
<background android:drawable="@drawable/ic_launcher_background"/>
<foreground android:drawable="@drawable/ic_launcher_foreground"/>
<monochrome android:drawable="@drawable/ic_launcher_foreground" />
</adaptive-icon>

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.4 KiB

After

Width:  |  Height:  |  Size: 2.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.8 KiB

After

Width:  |  Height:  |  Size: 4.0 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 982 B

After

Width:  |  Height:  |  Size: 1.6 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.7 KiB

After

Width:  |  Height:  |  Size: 2.6 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.9 KiB

After

Width:  |  Height:  |  Size: 3.0 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.8 KiB

After

Width:  |  Height:  |  Size: 5.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.8 KiB

After

Width:  |  Height:  |  Size: 4.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.8 KiB

After

Width:  |  Height:  |  Size: 8.0 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.8 KiB

After

Width:  |  Height:  |  Size: 5.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 7.6 KiB

After

Width:  |  Height:  |  Size: 11 KiB

View File

@ -1,5 +1,5 @@
<resources>
<string name="app_name">ecommerce_serang</string>
<string name="app_name">Bisa UMKM</string>
<!--Placeholder-->