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