fix: give user feedback when trying to add podcast/radio on unsupported back servers

This commit is contained in:
eddyizm 2025-12-25 14:03:30 -08:00
parent bbd6d0864c
commit 43a96faca4
No known key found for this signature in database
GPG key ID: CF5F671829E8158A
7 changed files with 335 additions and 138 deletions

View file

@ -1,14 +1,24 @@
package com.cappielloantonio.tempo.viewmodel;
import android.app.Application;
import android.util.Log;
import android.widget.Toast;
import androidx.annotation.NonNull;
import androidx.lifecycle.AndroidViewModel;
import com.cappielloantonio.tempo.repository.PodcastRepository;
import com.cappielloantonio.tempo.subsonic.base.ApiResponse;
import com.cappielloantonio.tempo.subsonic.models.PodcastChannel;
import java.io.IOException;
import retrofit2.Call;
import retrofit2.Callback;
import retrofit2.Response;
public class PodcastChannelBottomSheetViewModel extends AndroidViewModel {
private static final String TAG = "PodcastChannelBottomSheetViewModel";
private final PodcastRepository podcastRepository;
private PodcastChannel podcastChannel;
@ -28,6 +38,59 @@ public class PodcastChannelBottomSheetViewModel extends AndroidViewModel {
}
public void deletePodcastChannel() {
if (podcastChannel != null) podcastRepository.deletePodcastChannel(podcastChannel.getId());
if (podcastChannel != null && podcastChannel.getId() != null) {
podcastRepository.deletePodcastChannel(podcastChannel.getId())
.enqueue(new Callback<ApiResponse>() {
@Override
public void onResponse(@NonNull Call<ApiResponse> call, @NonNull Response<ApiResponse> response) {
if (response.code() == 501) {
Toast.makeText(getApplication(),
"Podcasts are not supported by this server",
Toast.LENGTH_LONG).show();
return;
}
if (response.isSuccessful() && response.body() != null) {
ApiResponse apiResponse = response.body();
String status = apiResponse.subsonicResponse.getStatus();
if ("ok".equals(status)) {
Toast.makeText(getApplication(),
"Podcast channel deleted",
Toast.LENGTH_SHORT).show();
//TODO refresh the UI after deleting
//podcastRepository.refreshPodcasts();
}
} else {
handleHttpError(response);
}
}
@Override
public void onFailure(@NonNull Call<ApiResponse> call, @NonNull Throwable t) {
Toast.makeText(getApplication(),
"Network error: " + t.getMessage(),
Toast.LENGTH_LONG).show();
}
});
}
}
private void handleHttpError(Response<ApiResponse> response) {
String errorMsg = "HTTP error: " + response.code();
if (response.errorBody() != null) {
try {
String serverMsg = response.errorBody().string();
if (!serverMsg.isEmpty()) {
errorMsg += " - " + serverMsg;
}
} catch (IOException e) {
Log.e(TAG, "Error reading error body", e);
}
}
Toast.makeText(getApplication(), errorMsg, Toast.LENGTH_LONG).show();
}
}

View file

@ -1,27 +1,99 @@
package com.cappielloantonio.tempo.viewmodel;
import android.app.Application;
import android.util.Log;
import android.widget.Toast;
import androidx.annotation.NonNull;
import androidx.lifecycle.AndroidViewModel;
import androidx.lifecycle.LiveData;
import androidx.lifecycle.MutableLiveData;
import com.cappielloantonio.tempo.R;
import com.cappielloantonio.tempo.repository.PodcastRepository;
import com.cappielloantonio.tempo.subsonic.models.InternetRadioStation;
import com.cappielloantonio.tempo.subsonic.base.ApiResponse;
import java.io.IOException;
import retrofit2.Call;
import retrofit2.Callback;
import retrofit2.Response;
public class PodcastChannelEditorViewModel extends AndroidViewModel {
private static final String TAG = "RadioEditorViewModel";
private static final String TAG = "PodcastChannelEditorViewModel";
private final PodcastRepository podcastRepository;
private InternetRadioStation toEdit;
private final MutableLiveData<Boolean> isSuccess = new MutableLiveData<>(false);
private final MutableLiveData<String> errorMessage = new MutableLiveData<>();
public PodcastChannelEditorViewModel(@NonNull Application application) {
super(application);
podcastRepository = new PodcastRepository();
}
public void createChannel(String url) {
podcastRepository.createPodcastChannel(url);
public LiveData<Boolean> getIsSuccess() {
return isSuccess;
}
}
public LiveData<String> getErrorMessage() {
return errorMessage;
}
public void clearError() {
errorMessage.setValue(null);
}
public void createChannel(String url) {
errorMessage.setValue(null);
isSuccess.setValue(false);
podcastRepository.createPodcastChannel(url)
.enqueue(new Callback<ApiResponse>() {
@Override
public void onResponse(@NonNull Call<ApiResponse> call, @NonNull Response<ApiResponse> response) {
if (response.code() == 501) {
showError(getApplication().getString(R.string.podcast_channel_not_supported_snackbar));
return;
}
if (response.isSuccessful() && response.body() != null) {
ApiResponse apiResponse = response.body();
String status = apiResponse.subsonicResponse.getStatus();
if ("ok".equals(status)) {
isSuccess.setValue(true);
}
} else {
handleHttpError(response);
}
}
@Override
public void onFailure(@NonNull Call<ApiResponse> call, @NonNull Throwable t) {
showError("Network error: " + t.getMessage());
Log.e(TAG, "Network error", t);
}
});
}
private void handleHttpError(Response<ApiResponse> response) {
String errorMsg = "HTTP error: " + response.code();
if (response.errorBody() != null) {
try {
String serverMsg = response.errorBody().string();
if (!serverMsg.isEmpty()) {
errorMsg += " - " + serverMsg;
}
} catch (IOException e) {
Log.e(TAG, "Error reading error body", e);
}
}
showError(errorMsg);
}
private void showError(String message) {
Toast.makeText(getApplication(), message, Toast.LENGTH_LONG).show();
errorMessage.setValue(message);
Log.e(TAG, "Error shown: " + message);
}
}

View file

@ -1,26 +1,47 @@
package com.cappielloantonio.tempo.viewmodel;
import android.app.Application;
import android.util.Log;
import android.widget.Toast;
import androidx.annotation.NonNull;
import androidx.lifecycle.AndroidViewModel;
import androidx.lifecycle.LiveData;
import androidx.lifecycle.MutableLiveData;
import com.cappielloantonio.tempo.R;
import com.cappielloantonio.tempo.repository.RadioRepository;
import com.cappielloantonio.tempo.subsonic.base.ApiResponse;
import com.cappielloantonio.tempo.subsonic.models.InternetRadioStation;
import java.io.IOException;
import retrofit2.Call;
import retrofit2.Callback;
import retrofit2.Response;
public class RadioEditorViewModel extends AndroidViewModel {
private static final String TAG = "RadioEditorViewModel";
private final RadioRepository radioRepository;
private InternetRadioStation toEdit;
private final MutableLiveData<Boolean> isSuccess = new MutableLiveData<>(false);
private final MutableLiveData<String> errorMessage = new MutableLiveData<>();
public RadioEditorViewModel(@NonNull Application application) {
super(application);
radioRepository = new RadioRepository();
}
public LiveData<Boolean> getIsSuccess() { return isSuccess; }
public LiveData<String> getErrorMessage() { return errorMessage; }
public void clearError() {
errorMessage.setValue(null);
}
public InternetRadioStation getRadioToEdit() {
return toEdit;
}
@ -30,14 +51,120 @@ public class RadioEditorViewModel extends AndroidViewModel {
}
public void createRadio(String name, String streamURL, String homepageURL) {
radioRepository.createInternetRadioStation(name, streamURL, homepageURL);
errorMessage.setValue(null);
isSuccess.setValue(false);
radioRepository.createInternetRadioStation(name, streamURL, homepageURL)
.enqueue(new Callback<ApiResponse>() {
@Override
public void onResponse(@NonNull Call<ApiResponse> call, @NonNull Response<ApiResponse> response) {
// Handle HTTP 501 (Not Implemented) from Navidrome
if (response.code() == 501) {
showError(getApplication().getString(R.string.radio_dialog_not_supported_snackbar));
return;
}
if (response.isSuccessful() && response.body() != null) {
ApiResponse apiResponse = response.body();
String status = apiResponse.subsonicResponse.getStatus();
if ("ok".equals(status)) {
isSuccess.setValue(true);
} else if ("failed".equals(status)) {
handleFailedResponse(apiResponse);
}
} else {
errorMessage.setValue("HTTP error: " + response.code());
}
}
@Override
public void onFailure(@NonNull Call<ApiResponse> call, @NonNull Throwable t) {
errorMessage.setValue("Network error: " + t.getMessage());
}
});
}
public void updateRadio(String name, String streamURL, String homepageURL) {
if (toEdit != null) radioRepository.updateInternetRadioStation(toEdit.getId(), name, streamURL, homepageURL);
if (toEdit != null && toEdit.getId() != null) {
errorMessage.setValue(null);
isSuccess.setValue(false);
radioRepository.updateInternetRadioStation(toEdit.getId(), name, streamURL, homepageURL)
.enqueue(new Callback<ApiResponse>() {
@Override
public void onResponse(@NonNull Call<ApiResponse> call, @NonNull Response<ApiResponse> response) {
if (response.isSuccessful() && response.body() != null) {
ApiResponse apiResponse = response.body();
if (apiResponse.subsonicResponse != null) {
String status = apiResponse.subsonicResponse.getStatus();
if ("ok".equals(status)) {
isSuccess.setValue(true);
} else if ("failed".equals(status)) {
handleFailedResponse(apiResponse);
}
}
} else {
errorMessage.setValue("HTTP error: " + response.code());
}
}
@Override
public void onFailure(@NonNull Call<ApiResponse> call, @NonNull Throwable t) {
errorMessage.setValue("Network error: " + t.getMessage());
}
});
}
}
public void deleteRadio() {
if (toEdit != null) radioRepository.deleteInternetRadioStation(toEdit.getId());
if (toEdit != null && toEdit.getId() != null) {
errorMessage.setValue(null);
isSuccess.setValue(false);
radioRepository.deleteInternetRadioStation(toEdit.getId())
.enqueue(new Callback<ApiResponse>() {
@Override
public void onResponse(@NonNull Call<ApiResponse> call, @NonNull Response<ApiResponse> response) {
if (response.isSuccessful() && response.body() != null) {
ApiResponse apiResponse = response.body();
String status = apiResponse.subsonicResponse.getStatus();
if ("ok".equals(status)) {
isSuccess.setValue(true);
} else if ("failed".equals(status)) {
handleFailedResponse(apiResponse);
}
} else {
errorMessage.setValue("HTTP error: " + response.code());
}
}
@Override
public void onFailure(@NonNull Call<ApiResponse> call, @NonNull Throwable t) {
errorMessage.setValue("Network error: " + t.getMessage());
}
});
}
}
}
private void showError(String message) {
Toast.makeText(getApplication(), message, Toast.LENGTH_LONG).show();
errorMessage.setValue(message);
}
private void handleFailedResponse(ApiResponse apiResponse) {
String errorMsg = "Unknown server error";
if (apiResponse.subsonicResponse.getError() != null) {
errorMsg = apiResponse.subsonicResponse.getError().getMessage();
if ("Not implemented".equals(errorMsg)) {
errorMsg = getApplication().getString((R.string.radio_dialog_not_supported_snackbar));
}
}
Toast.makeText(getApplication(), errorMsg, Toast.LENGTH_LONG).show();
errorMessage.setValue(errorMsg);
}
}