fix photo loading issue on pets and products
This commit is contained in:
@@ -107,7 +107,8 @@ public class PetAdapter extends RecyclerView.Adapter<PetAdapter.PetViewHolder> {
|
||||
Glide.with(holder.itemView.getContext())
|
||||
.load(loadTarget)
|
||||
.circleCrop()
|
||||
.diskCacheStrategy(DiskCacheStrategy.ALL) // Changed to ALL for better performance
|
||||
.skipMemoryCache(true)
|
||||
.diskCacheStrategy(DiskCacheStrategy.NONE)
|
||||
.placeholder(R.drawable.placeholder)
|
||||
.error(R.drawable.placeholder)
|
||||
.into(holder.ivPetProfile);
|
||||
|
||||
@@ -83,7 +83,8 @@ public class ProductAdapter extends RecyclerView.Adapter<ProductAdapter.ProductV
|
||||
Glide.with(holder.itemView.getContext())
|
||||
.load(loadTarget)
|
||||
.circleCrop()
|
||||
.diskCacheStrategy(DiskCacheStrategy.ALL)
|
||||
.skipMemoryCache(true)
|
||||
.diskCacheStrategy(DiskCacheStrategy.NONE)
|
||||
.placeholder(R.drawable.placeholder)
|
||||
.error(R.drawable.placeholder)
|
||||
.into(holder.ivProductImage);
|
||||
|
||||
@@ -56,6 +56,8 @@ public class ProductDetailFragment extends Fragment {
|
||||
private boolean isEditing = false;
|
||||
private long preselectedCategoryId = -1;
|
||||
private boolean hasImage = false;
|
||||
private boolean isImageChanged = false;
|
||||
private boolean isImageRemoved = false;
|
||||
|
||||
private List<CategoryDTO> categoryList = new ArrayList<>();
|
||||
private Uri photoUri;
|
||||
@@ -77,13 +79,12 @@ public class ProductDetailFragment extends Fragment {
|
||||
result -> {
|
||||
if (result.getResultCode() == Activity.RESULT_OK && result.getData() != null) {
|
||||
Uri selectedImage = result.getData().getData();
|
||||
if (isEditing) {
|
||||
uploadProductImage(selectedImage);
|
||||
} else {
|
||||
ivProductImage.setImageURI(selectedImage);
|
||||
photoUri = selectedImage;
|
||||
hasImage = true;
|
||||
}
|
||||
// Update image view locally
|
||||
Glide.with(this).load(selectedImage).into(ivProductImage);
|
||||
photoUri = selectedImage;
|
||||
hasImage = true;
|
||||
isImageChanged = true;
|
||||
isImageRemoved = false;
|
||||
}
|
||||
}
|
||||
);
|
||||
@@ -91,12 +92,11 @@ public class ProductDetailFragment extends Fragment {
|
||||
new ActivityResultContracts.TakePicture(),
|
||||
success -> {
|
||||
if (success) {
|
||||
if (isEditing) {
|
||||
uploadProductImage(photoUri);
|
||||
} else {
|
||||
ivProductImage.setImageURI(photoUri);
|
||||
hasImage = true;
|
||||
}
|
||||
// Update image view locally
|
||||
Glide.with(this).load(photoUri).into(ivProductImage);
|
||||
hasImage = true;
|
||||
isImageChanged = true;
|
||||
isImageRemoved = false;
|
||||
}
|
||||
}
|
||||
);
|
||||
@@ -167,31 +167,13 @@ public class ProductDetailFragment extends Fragment {
|
||||
.show();
|
||||
}
|
||||
|
||||
// Helper function to remove the photo
|
||||
// Helper function to remove the photo locally
|
||||
private void removePhoto() {
|
||||
if (isEditing) {
|
||||
productApi.deleteProductImage(prodId)
|
||||
.enqueue(new Callback<Void>() {
|
||||
@Override
|
||||
public void onResponse(Call<Void> call, Response<Void> response) {
|
||||
if (response.isSuccessful()) {
|
||||
Toast.makeText(getContext(), "Photo removed", Toast.LENGTH_SHORT).show();
|
||||
ivProductImage.setImageResource(R.drawable.placeholder2);
|
||||
hasImage = false;
|
||||
} else {
|
||||
Toast.makeText(getContext(), "Failed to remove photo", Toast.LENGTH_SHORT).show();
|
||||
}
|
||||
}
|
||||
@Override
|
||||
public void onFailure(Call<Void> call, Throwable t) {
|
||||
Toast.makeText(getContext(), "Network error", Toast.LENGTH_SHORT).show();
|
||||
}
|
||||
});
|
||||
} else {
|
||||
photoUri = null;
|
||||
hasImage = false;
|
||||
ivProductImage.setImageResource(R.drawable.placeholder2);
|
||||
}
|
||||
photoUri = null;
|
||||
hasImage = false;
|
||||
isImageChanged = false;
|
||||
isImageRemoved = true;
|
||||
Glide.with(this).load(R.drawable.placeholder2).into(ivProductImage);
|
||||
}
|
||||
|
||||
// Helper function to launch the camera
|
||||
@@ -201,6 +183,7 @@ public class ProductDetailFragment extends Fragment {
|
||||
cameraLauncher.launch(photoUri);
|
||||
}
|
||||
|
||||
// Helper function to load categories from the backend for the spinner
|
||||
private void loadCategories() {
|
||||
categoryApi.getAllCategories(0, 100)
|
||||
.enqueue(new Callback<PageResponse<CategoryDTO>>() {
|
||||
@@ -217,6 +200,7 @@ public class ProductDetailFragment extends Fragment {
|
||||
});
|
||||
}
|
||||
|
||||
// Helper function to populate the category spinner
|
||||
private void populateCategorySpinner() {
|
||||
List<String> names = new ArrayList<>();
|
||||
names.add("-- Select Category --");
|
||||
@@ -270,17 +254,50 @@ public class ProductDetailFragment extends Fragment {
|
||||
|
||||
Glide.with(this)
|
||||
.load(loadTarget)
|
||||
.diskCacheStrategy(DiskCacheStrategy.ALL)
|
||||
.skipMemoryCache(true)
|
||||
.diskCacheStrategy(DiskCacheStrategy.NONE)
|
||||
.placeholder(R.drawable.placeholder2)
|
||||
.error(R.drawable.placeholder2)
|
||||
.into(ivProductImage);
|
||||
}
|
||||
|
||||
// Function to upload the product image by calling the backend
|
||||
private void uploadProductImage(Uri uri) {
|
||||
// Function to check any changes to the image and perform the appropriate action
|
||||
// updating/adding photo, removing photo or no change
|
||||
private void performPendingImageActions(String successMsg) {
|
||||
if (isImageRemoved) {
|
||||
//if the image is removed then delete the image
|
||||
productApi.deleteProductImage(prodId).enqueue(new Callback<Void>() {
|
||||
@Override
|
||||
public void onResponse(Call<Void> call, Response<Void> response) {
|
||||
Toast.makeText(getContext(), successMsg, Toast.LENGTH_SHORT).show();
|
||||
navigateBack();
|
||||
}
|
||||
@Override
|
||||
public void onFailure(Call<Void> call, Throwable t) {
|
||||
Toast.makeText(getContext(), successMsg + " (but image removal failed)", Toast.LENGTH_SHORT).show();
|
||||
navigateBack();
|
||||
}
|
||||
});
|
||||
} else if (isImageChanged && photoUri != null) {
|
||||
//if the image is changed then upload it
|
||||
uploadProductImageAndNavigate(photoUri, successMsg);
|
||||
} else {
|
||||
//if no changes then navigate back
|
||||
Toast.makeText(getContext(), successMsg, Toast.LENGTH_SHORT).show();
|
||||
navigateBack();
|
||||
}
|
||||
}
|
||||
|
||||
// Helper function to upload the product image by calling the backend
|
||||
// and then navigate back to the previous screen
|
||||
private void uploadProductImageAndNavigate(Uri uri, String successMsg) {
|
||||
try {
|
||||
File file = getFileFromUri(uri);
|
||||
if (file == null) return;
|
||||
if (file == null) {
|
||||
Toast.makeText(getContext(), successMsg, Toast.LENGTH_SHORT).show();
|
||||
navigateBack();
|
||||
return;
|
||||
}
|
||||
|
||||
RequestBody requestFile = RequestBody.create(file, MediaType.parse(requireContext().getContentResolver().getType(uri)));
|
||||
MultipartBody.Part body = MultipartBody.Part.createFormData("image", file.getName(), requestFile);
|
||||
@@ -290,20 +307,22 @@ public class ProductDetailFragment extends Fragment {
|
||||
@Override
|
||||
public void onResponse(Call<Void> call, Response<Void> response) {
|
||||
if (response.isSuccessful()) {
|
||||
Toast.makeText(getContext(), "Image uploaded", Toast.LENGTH_SHORT).show();
|
||||
hasImage = true;
|
||||
loadProductImage();
|
||||
Toast.makeText(getContext(), successMsg, Toast.LENGTH_SHORT).show();
|
||||
} else {
|
||||
Toast.makeText(getContext(), "Upload failed", Toast.LENGTH_SHORT).show();
|
||||
Toast.makeText(getContext(), successMsg + " (but image upload failed)", Toast.LENGTH_SHORT).show();
|
||||
}
|
||||
navigateBack();
|
||||
}
|
||||
@Override
|
||||
public void onFailure(Call<Void> call, Throwable t) {
|
||||
Toast.makeText(getContext(), "Network error", Toast.LENGTH_SHORT).show();
|
||||
Toast.makeText(getContext(), successMsg + " (network error during upload)", Toast.LENGTH_SHORT).show();
|
||||
navigateBack();
|
||||
}
|
||||
});
|
||||
} catch (Exception e) {
|
||||
Log.e("ProductDetail", "Error uploading image", e);
|
||||
Toast.makeText(getContext(), successMsg, Toast.LENGTH_SHORT).show();
|
||||
navigateBack();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -326,6 +345,7 @@ public class ProductDetailFragment extends Fragment {
|
||||
}
|
||||
}
|
||||
|
||||
// Function to save the product to the server
|
||||
private void saveProduct() {
|
||||
String name = etProductName.getText().toString().trim();
|
||||
String desc = etProductDesc.getText().toString().trim();
|
||||
@@ -352,19 +372,27 @@ public class ProductDetailFragment extends Fragment {
|
||||
ProductDTO dto = new ProductDTO(name, category.getCategoryId(), desc, price);
|
||||
|
||||
if (isEditing) {
|
||||
productApi.updateProduct(prodId, dto).enqueue(simpleCallback("Updated"));
|
||||
productApi.updateProduct(prodId, dto).enqueue(new Callback<ProductDTO>() {
|
||||
@Override
|
||||
public void onResponse(Call<ProductDTO> call, Response<ProductDTO> response) {
|
||||
if (response.isSuccessful()) {
|
||||
performPendingImageActions("Updated");
|
||||
} else {
|
||||
Toast.makeText(getContext(), "Error " + response.code(), Toast.LENGTH_SHORT).show();
|
||||
}
|
||||
}
|
||||
@Override
|
||||
public void onFailure(Call<ProductDTO> call, Throwable t) {
|
||||
Toast.makeText(getContext(), "Network error", Toast.LENGTH_SHORT).show();
|
||||
}
|
||||
});
|
||||
} else {
|
||||
productApi.createProduct(dto).enqueue(new Callback<ProductDTO>() {
|
||||
@Override
|
||||
public void onResponse(Call<ProductDTO> call, Response<ProductDTO> response) {
|
||||
if (response.isSuccessful() && response.body() != null) {
|
||||
long newId = response.body().getProdId();
|
||||
if (photoUri != null) {
|
||||
prodId = newId;
|
||||
uploadProductImage(photoUri);
|
||||
}
|
||||
Toast.makeText(getContext(), "Saved", Toast.LENGTH_SHORT).show();
|
||||
navigateBack();
|
||||
prodId = response.body().getProdId();
|
||||
performPendingImageActions("Saved");
|
||||
} else {
|
||||
Toast.makeText(getContext(), "Error saving", Toast.LENGTH_SHORT).show();
|
||||
}
|
||||
@@ -377,22 +405,7 @@ public class ProductDetailFragment extends Fragment {
|
||||
}
|
||||
}
|
||||
|
||||
private Callback<ProductDTO> simpleCallback(String msg) {
|
||||
return new Callback<>() {
|
||||
public void onResponse(Call<ProductDTO> c, Response<ProductDTO> r) {
|
||||
if (r.isSuccessful()) {
|
||||
Toast.makeText(getContext(), msg, Toast.LENGTH_SHORT).show();
|
||||
navigateBack();
|
||||
} else {
|
||||
Toast.makeText(getContext(), "Error " + r.code(), Toast.LENGTH_SHORT).show();
|
||||
}
|
||||
}
|
||||
public void onFailure(Call<ProductDTO> c, Throwable t) {
|
||||
Toast.makeText(getContext(), "Network error", Toast.LENGTH_SHORT).show();
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
// Function to delete the product from the server
|
||||
private void confirmDelete() {
|
||||
new AlertDialog.Builder(requireContext())
|
||||
.setTitle("Delete Product?")
|
||||
|
||||
@@ -212,7 +212,8 @@ public class PetProfileFragment extends Fragment {
|
||||
|
||||
Glide.with(this)
|
||||
.load(loadTarget)
|
||||
.diskCacheStrategy(DiskCacheStrategy.ALL)
|
||||
.skipMemoryCache(true)
|
||||
.diskCacheStrategy(DiskCacheStrategy.NONE)
|
||||
.placeholder(R.drawable.placeholder)
|
||||
.error(R.drawable.placeholder)
|
||||
.listener(new com.bumptech.glide.request.RequestListener<android.graphics.drawable.Drawable>() {
|
||||
@@ -311,4 +312,4 @@ public class PetProfileFragment extends Fragment {
|
||||
photoUri = FileProvider.getUriForFile(requireContext(), requireContext().getPackageName() + ".fileprovider", photoFile);
|
||||
cameraLauncher.launch(photoUri);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -16,7 +16,7 @@
|
||||
android:name="androidx.navigation.fragment.NavHostFragment"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
app:defaultNavHost="false"
|
||||
app:defaultNavHost="true"
|
||||
app:navGraph="@navigation/list_nav_graph" />
|
||||
|
||||
<View
|
||||
@@ -252,4 +252,4 @@
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
</androidx.drawerlayout.widget.DrawerLayout>
|
||||
</androidx.drawerlayout.widget.DrawerLayout>
|
||||
|
||||
Reference in New Issue
Block a user