mirror of
https://github.com/antebudimir/tempus.git
synced 2026-04-15 16:27:26 +00:00
Merge branch 'development' into bug/instant-mix-issue
This commit is contained in:
commit
3ce34fb874
8 changed files with 336 additions and 139 deletions
|
|
@ -11,7 +11,7 @@ android {
|
||||||
targetSdk 35
|
targetSdk 35
|
||||||
|
|
||||||
versionCode 11
|
versionCode 11
|
||||||
versionName '4.6.0'
|
versionName '4.6.1'
|
||||||
testInstrumentationRunner 'androidx.test.runner.AndroidJUnitRunner'
|
testInstrumentationRunner 'androidx.test.runner.AndroidJUnitRunner'
|
||||||
|
|
||||||
javaCompileOptions {
|
javaCompileOptions {
|
||||||
|
|
|
||||||
|
|
@ -66,88 +66,33 @@ public class PodcastRepository {
|
||||||
return liveNewestPodcastEpisodes;
|
return liveNewestPodcastEpisodes;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void refreshPodcasts() {
|
public Call<ApiResponse> refreshPodcasts() {
|
||||||
App.getSubsonicClientInstance(false)
|
return App.getSubsonicClientInstance(false)
|
||||||
.getPodcastClient()
|
.getPodcastClient()
|
||||||
.refreshPodcasts()
|
.refreshPodcasts();
|
||||||
.enqueue(new Callback<ApiResponse>() {
|
|
||||||
@Override
|
|
||||||
public void onResponse(@NonNull Call<ApiResponse> call, @NonNull Response<ApiResponse> response) {
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
public Call<ApiResponse> createPodcastChannel(String url) {
|
||||||
public void onFailure(@NonNull Call<ApiResponse> call, @NonNull Throwable t) {
|
return App.getSubsonicClientInstance(false)
|
||||||
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
public void createPodcastChannel(String url) {
|
|
||||||
App.getSubsonicClientInstance(false)
|
|
||||||
.getPodcastClient()
|
.getPodcastClient()
|
||||||
.createPodcastChannel(url)
|
.createPodcastChannel(url);
|
||||||
.enqueue(new Callback<ApiResponse>() {
|
|
||||||
@Override
|
|
||||||
public void onResponse(@NonNull Call<ApiResponse> call, @NonNull Response<ApiResponse> response) {
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
public Call<ApiResponse> deletePodcastChannel(String channelId) {
|
||||||
public void onFailure(@NonNull Call<ApiResponse> call, @NonNull Throwable t) {
|
return App.getSubsonicClientInstance(false)
|
||||||
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
public void deletePodcastChannel(String channelId) {
|
|
||||||
App.getSubsonicClientInstance(false)
|
|
||||||
.getPodcastClient()
|
.getPodcastClient()
|
||||||
.deletePodcastChannel(channelId)
|
.deletePodcastChannel(channelId);
|
||||||
.enqueue(new Callback<ApiResponse>() {
|
|
||||||
@Override
|
|
||||||
public void onResponse(@NonNull Call<ApiResponse> call, @NonNull Response<ApiResponse> response) {
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
public Call<ApiResponse> deletePodcastEpisode(String episodeId) {
|
||||||
public void onFailure(@NonNull Call<ApiResponse> call, @NonNull Throwable t) {
|
return App.getSubsonicClientInstance(false)
|
||||||
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
public void deletePodcastEpisode(String episodeId) {
|
|
||||||
App.getSubsonicClientInstance(false)
|
|
||||||
.getPodcastClient()
|
.getPodcastClient()
|
||||||
.deletePodcastEpisode(episodeId)
|
.deletePodcastEpisode(episodeId);
|
||||||
.enqueue(new Callback<ApiResponse>() {
|
|
||||||
@Override
|
|
||||||
public void onResponse(@NonNull Call<ApiResponse> call, @NonNull Response<ApiResponse> response) {
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
public Call<ApiResponse> downloadPodcastEpisode(String episodeId) {
|
||||||
public void onFailure(@NonNull Call<ApiResponse> call, @NonNull Throwable t) {
|
return App.getSubsonicClientInstance(false)
|
||||||
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
public void downloadPodcastEpisode(String episodeId) {
|
|
||||||
App.getSubsonicClientInstance(false)
|
|
||||||
.getPodcastClient()
|
.getPodcastClient()
|
||||||
.downloadPodcastEpisode(episodeId)
|
.downloadPodcastEpisode(episodeId);
|
||||||
.enqueue(new Callback<ApiResponse>() {
|
|
||||||
@Override
|
|
||||||
public void onResponse(@NonNull Call<ApiResponse> call, @NonNull Response<ApiResponse> response) {
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onFailure(@NonNull Call<ApiResponse> call, @NonNull Throwable t) {
|
|
||||||
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -38,54 +38,22 @@ public class RadioRepository {
|
||||||
return radioStation;
|
return radioStation;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void createInternetRadioStation(String name, String streamURL, String homepageURL) {
|
public Call<ApiResponse> createInternetRadioStation(String name, String streamURL, String homepageURL) {
|
||||||
App.getSubsonicClientInstance(false)
|
return App.getSubsonicClientInstance(false)
|
||||||
.getInternetRadioClient()
|
.getInternetRadioClient()
|
||||||
.createInternetRadioStation(streamURL, name, homepageURL)
|
.createInternetRadioStation(streamURL, name, homepageURL);
|
||||||
.enqueue(new Callback<ApiResponse>() {
|
|
||||||
@Override
|
|
||||||
public void onResponse(@NonNull Call<ApiResponse> call, @NonNull Response<ApiResponse> response) {
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
public Call<ApiResponse> updateInternetRadioStation(String id, String name, String streamURL, String homepageURL) {
|
||||||
public void onFailure(@NonNull Call<ApiResponse> call, @NonNull Throwable t) {
|
return App.getSubsonicClientInstance(false)
|
||||||
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
public void updateInternetRadioStation(String id, String name, String streamURL, String homepageURL) {
|
|
||||||
App.getSubsonicClientInstance(false)
|
|
||||||
.getInternetRadioClient()
|
.getInternetRadioClient()
|
||||||
.updateInternetRadioStation(id, streamURL, name, homepageURL)
|
.updateInternetRadioStation(id, streamURL, name, homepageURL);
|
||||||
.enqueue(new Callback<ApiResponse>() {
|
|
||||||
@Override
|
|
||||||
public void onResponse(@NonNull Call<ApiResponse> call, @NonNull Response<ApiResponse> response) {
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
public Call<ApiResponse> deleteInternetRadioStation(String id) {
|
||||||
public void onFailure(@NonNull Call<ApiResponse> call, @NonNull Throwable t) {
|
return App.getSubsonicClientInstance(false)
|
||||||
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
public void deleteInternetRadioStation(String id) {
|
|
||||||
App.getSubsonicClientInstance(false)
|
|
||||||
.getInternetRadioClient()
|
.getInternetRadioClient()
|
||||||
.deleteInternetRadioStation(id)
|
.deleteInternetRadioStation(id);
|
||||||
.enqueue(new Callback<ApiResponse>() {
|
|
||||||
@Override
|
|
||||||
public void onResponse(@NonNull Call<ApiResponse> call, @NonNull Response<ApiResponse> response) {
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onFailure(@NonNull Call<ApiResponse> call, @NonNull Throwable t) {
|
|
||||||
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -3,11 +3,13 @@ package com.cappielloantonio.tempo.ui.dialog;
|
||||||
import android.app.Dialog;
|
import android.app.Dialog;
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
import android.text.TextUtils;
|
import android.text.TextUtils;
|
||||||
|
import android.widget.Toast;
|
||||||
|
|
||||||
import androidx.annotation.NonNull;
|
import androidx.annotation.NonNull;
|
||||||
import androidx.fragment.app.DialogFragment;
|
import androidx.fragment.app.DialogFragment;
|
||||||
import androidx.lifecycle.ViewModelProvider;
|
import androidx.lifecycle.ViewModelProvider;
|
||||||
|
|
||||||
|
import com.cappielloantonio.tempo.App;
|
||||||
import com.cappielloantonio.tempo.R;
|
import com.cappielloantonio.tempo.R;
|
||||||
import com.cappielloantonio.tempo.databinding.DialogRadioEditorBinding;
|
import com.cappielloantonio.tempo.databinding.DialogRadioEditorBinding;
|
||||||
import com.cappielloantonio.tempo.interfaces.RadioCallback;
|
import com.cappielloantonio.tempo.interfaces.RadioCallback;
|
||||||
|
|
@ -21,7 +23,6 @@ import java.util.Objects;
|
||||||
public class RadioEditorDialog extends DialogFragment {
|
public class RadioEditorDialog extends DialogFragment {
|
||||||
private DialogRadioEditorBinding bind;
|
private DialogRadioEditorBinding bind;
|
||||||
private RadioEditorViewModel radioEditorViewModel;
|
private RadioEditorViewModel radioEditorViewModel;
|
||||||
|
|
||||||
private final RadioCallback radioCallback;
|
private final RadioCallback radioCallback;
|
||||||
|
|
||||||
private String radioName;
|
private String radioName;
|
||||||
|
|
@ -36,25 +37,26 @@ public class RadioEditorDialog extends DialogFragment {
|
||||||
@Override
|
@Override
|
||||||
public Dialog onCreateDialog(Bundle savedInstanceState) {
|
public Dialog onCreateDialog(Bundle savedInstanceState) {
|
||||||
bind = DialogRadioEditorBinding.inflate(getLayoutInflater());
|
bind = DialogRadioEditorBinding.inflate(getLayoutInflater());
|
||||||
|
|
||||||
radioEditorViewModel = new ViewModelProvider(requireActivity()).get(RadioEditorViewModel.class);
|
radioEditorViewModel = new ViewModelProvider(requireActivity()).get(RadioEditorViewModel.class);
|
||||||
|
|
||||||
|
setupObservers();
|
||||||
|
|
||||||
return new MaterialAlertDialogBuilder(requireContext())
|
return new MaterialAlertDialogBuilder(requireContext())
|
||||||
.setView(bind.getRoot())
|
.setView(bind.getRoot())
|
||||||
.setTitle(R.string.radio_editor_dialog_title)
|
.setTitle(R.string.radio_editor_dialog_title)
|
||||||
.setPositiveButton(R.string.radio_editor_dialog_positive_button, (dialog, id) -> {
|
.setPositiveButton(R.string.radio_editor_dialog_positive_button, (dialog, id) -> {
|
||||||
if (validateInput()) {
|
if (validateInput()) {
|
||||||
if (radioEditorViewModel.getRadioToEdit() == null) {
|
if (radioEditorViewModel.getRadioToEdit() == null) {
|
||||||
radioEditorViewModel.createRadio(radioName, radioStreamURL, radioHomepageURL.isEmpty() ? null : radioHomepageURL);
|
radioEditorViewModel.createRadio(radioName, radioStreamURL,
|
||||||
|
radioHomepageURL.isEmpty() ? null : radioHomepageURL);
|
||||||
} else {
|
} else {
|
||||||
radioEditorViewModel.updateRadio(radioName, radioStreamURL, radioHomepageURL.isEmpty() ? null : radioHomepageURL);
|
radioEditorViewModel.updateRadio(radioName, radioStreamURL,
|
||||||
|
radioHomepageURL.isEmpty() ? null : radioHomepageURL);
|
||||||
}
|
}
|
||||||
dismissDialog();
|
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
.setNeutralButton(R.string.radio_editor_dialog_neutral_button, (dialog, id) -> {
|
.setNeutralButton(R.string.radio_editor_dialog_neutral_button, (dialog, id) -> {
|
||||||
radioEditorViewModel.deleteRadio();
|
radioEditorViewModel.deleteRadio();
|
||||||
dismissDialog();
|
|
||||||
})
|
})
|
||||||
.setNegativeButton(R.string.radio_editor_dialog_negative_button, (dialog, id) -> {
|
.setNegativeButton(R.string.radio_editor_dialog_negative_button, (dialog, id) -> {
|
||||||
dialog.cancel();
|
dialog.cancel();
|
||||||
|
|
@ -62,6 +64,24 @@ public class RadioEditorDialog extends DialogFragment {
|
||||||
.create();
|
.create();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void setupObservers() {
|
||||||
|
radioEditorViewModel.getIsSuccess().observe(this, isSuccess -> {
|
||||||
|
if (isSuccess != null && isSuccess) {
|
||||||
|
Toast.makeText(requireContext(),
|
||||||
|
radioEditorViewModel.getRadioToEdit() == null ?
|
||||||
|
App.getContext().getString(R.string.radio_editor_dialog_added) : App.getContext().getString(R.string.radio_editor_dialog_updated),
|
||||||
|
Toast.LENGTH_SHORT).show();
|
||||||
|
dismissDialog();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
radioEditorViewModel.getErrorMessage().observe(this, error -> {
|
||||||
|
if (error != null && !error.isEmpty()) {
|
||||||
|
Toast.makeText(requireContext(), error, Toast.LENGTH_LONG).show();
|
||||||
|
radioEditorViewModel.clearError();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onStart() {
|
public void onStart() {
|
||||||
super.onStart();
|
super.onStart();
|
||||||
|
|
@ -77,7 +97,6 @@ public class RadioEditorDialog extends DialogFragment {
|
||||||
private void setParameterInfo() {
|
private void setParameterInfo() {
|
||||||
if (getArguments() != null && getArguments().getParcelable(Constants.INTERNET_RADIO_STATION_OBJECT) != null) {
|
if (getArguments() != null && getArguments().getParcelable(Constants.INTERNET_RADIO_STATION_OBJECT) != null) {
|
||||||
InternetRadioStation toEdit = requireArguments().getParcelable(Constants.INTERNET_RADIO_STATION_OBJECT);
|
InternetRadioStation toEdit = requireArguments().getParcelable(Constants.INTERNET_RADIO_STATION_OBJECT);
|
||||||
|
|
||||||
radioEditorViewModel.setRadioToEdit(toEdit);
|
radioEditorViewModel.setRadioToEdit(toEdit);
|
||||||
|
|
||||||
bind.internetRadioStationNameTextView.setText(toEdit.getName());
|
bind.internetRadioStationNameTextView.setText(toEdit.getName());
|
||||||
|
|
@ -90,22 +109,21 @@ public class RadioEditorDialog extends DialogFragment {
|
||||||
radioName = Objects.requireNonNull(bind.internetRadioStationNameTextView.getText()).toString().trim();
|
radioName = Objects.requireNonNull(bind.internetRadioStationNameTextView.getText()).toString().trim();
|
||||||
radioStreamURL = Objects.requireNonNull(bind.internetRadioStationStreamUrlTextView.getText()).toString().trim();
|
radioStreamURL = Objects.requireNonNull(bind.internetRadioStationStreamUrlTextView.getText()).toString().trim();
|
||||||
radioHomepageURL = Objects.requireNonNull(bind.internetRadioStationHomepageUrlTextView.getText()).toString().trim();
|
radioHomepageURL = Objects.requireNonNull(bind.internetRadioStationHomepageUrlTextView.getText()).toString().trim();
|
||||||
|
|
||||||
if (TextUtils.isEmpty(radioName)) {
|
if (TextUtils.isEmpty(radioName)) {
|
||||||
bind.internetRadioStationNameTextView.setError(getString(R.string.error_required));
|
bind.internetRadioStationNameTextView.setError(getString(R.string.error_required));
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (TextUtils.isEmpty(radioStreamURL)) {
|
if (TextUtils.isEmpty(radioStreamURL)) {
|
||||||
bind.internetRadioStationStreamUrlTextView.setError(getString(R.string.error_required));
|
bind.internetRadioStationStreamUrlTextView.setError(getString(R.string.error_required));
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void dismissDialog() {
|
private void dismissDialog() {
|
||||||
|
if (radioCallback != null) {
|
||||||
radioCallback.onDismiss();
|
radioCallback.onDismiss();
|
||||||
|
}
|
||||||
Objects.requireNonNull(getDialog()).dismiss();
|
Objects.requireNonNull(getDialog()).dismiss();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -1,14 +1,24 @@
|
||||||
package com.cappielloantonio.tempo.viewmodel;
|
package com.cappielloantonio.tempo.viewmodel;
|
||||||
|
|
||||||
import android.app.Application;
|
import android.app.Application;
|
||||||
|
import android.util.Log;
|
||||||
|
import android.widget.Toast;
|
||||||
|
|
||||||
import androidx.annotation.NonNull;
|
import androidx.annotation.NonNull;
|
||||||
import androidx.lifecycle.AndroidViewModel;
|
import androidx.lifecycle.AndroidViewModel;
|
||||||
|
|
||||||
import com.cappielloantonio.tempo.repository.PodcastRepository;
|
import com.cappielloantonio.tempo.repository.PodcastRepository;
|
||||||
|
import com.cappielloantonio.tempo.subsonic.base.ApiResponse;
|
||||||
import com.cappielloantonio.tempo.subsonic.models.PodcastChannel;
|
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 {
|
public class PodcastChannelBottomSheetViewModel extends AndroidViewModel {
|
||||||
|
private static final String TAG = "PodcastChannelBottomSheetViewModel";
|
||||||
private final PodcastRepository podcastRepository;
|
private final PodcastRepository podcastRepository;
|
||||||
|
|
||||||
private PodcastChannel podcastChannel;
|
private PodcastChannel podcastChannel;
|
||||||
|
|
@ -28,6 +38,59 @@ public class PodcastChannelBottomSheetViewModel extends AndroidViewModel {
|
||||||
}
|
}
|
||||||
|
|
||||||
public void deletePodcastChannel() {
|
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();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,27 +1,99 @@
|
||||||
package com.cappielloantonio.tempo.viewmodel;
|
package com.cappielloantonio.tempo.viewmodel;
|
||||||
|
|
||||||
import android.app.Application;
|
import android.app.Application;
|
||||||
|
import android.util.Log;
|
||||||
|
import android.widget.Toast;
|
||||||
|
|
||||||
import androidx.annotation.NonNull;
|
import androidx.annotation.NonNull;
|
||||||
import androidx.lifecycle.AndroidViewModel;
|
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.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 {
|
public class PodcastChannelEditorViewModel extends AndroidViewModel {
|
||||||
private static final String TAG = "RadioEditorViewModel";
|
private static final String TAG = "PodcastChannelEditorViewModel";
|
||||||
|
|
||||||
private final PodcastRepository podcastRepository;
|
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) {
|
public PodcastChannelEditorViewModel(@NonNull Application application) {
|
||||||
super(application);
|
super(application);
|
||||||
|
|
||||||
podcastRepository = new PodcastRepository();
|
podcastRepository = new PodcastRepository();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public LiveData<Boolean> getIsSuccess() {
|
||||||
|
return isSuccess;
|
||||||
|
}
|
||||||
|
|
||||||
|
public LiveData<String> getErrorMessage() {
|
||||||
|
return errorMessage;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void clearError() {
|
||||||
|
errorMessage.setValue(null);
|
||||||
|
}
|
||||||
|
|
||||||
public void createChannel(String url) {
|
public void createChannel(String url) {
|
||||||
podcastRepository.createPodcastChannel(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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -1,26 +1,47 @@
|
||||||
package com.cappielloantonio.tempo.viewmodel;
|
package com.cappielloantonio.tempo.viewmodel;
|
||||||
|
|
||||||
import android.app.Application;
|
import android.app.Application;
|
||||||
|
import android.util.Log;
|
||||||
|
import android.widget.Toast;
|
||||||
|
|
||||||
import androidx.annotation.NonNull;
|
import androidx.annotation.NonNull;
|
||||||
import androidx.lifecycle.AndroidViewModel;
|
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.repository.RadioRepository;
|
||||||
|
import com.cappielloantonio.tempo.subsonic.base.ApiResponse;
|
||||||
import com.cappielloantonio.tempo.subsonic.models.InternetRadioStation;
|
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 {
|
public class RadioEditorViewModel extends AndroidViewModel {
|
||||||
private static final String TAG = "RadioEditorViewModel";
|
private static final String TAG = "RadioEditorViewModel";
|
||||||
|
|
||||||
private final RadioRepository radioRepository;
|
private final RadioRepository radioRepository;
|
||||||
|
|
||||||
private InternetRadioStation toEdit;
|
private InternetRadioStation toEdit;
|
||||||
|
|
||||||
|
private final MutableLiveData<Boolean> isSuccess = new MutableLiveData<>(false);
|
||||||
|
private final MutableLiveData<String> errorMessage = new MutableLiveData<>();
|
||||||
|
|
||||||
public RadioEditorViewModel(@NonNull Application application) {
|
public RadioEditorViewModel(@NonNull Application application) {
|
||||||
super(application);
|
super(application);
|
||||||
|
|
||||||
radioRepository = new RadioRepository();
|
radioRepository = new RadioRepository();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public LiveData<Boolean> getIsSuccess() { return isSuccess; }
|
||||||
|
public LiveData<String> getErrorMessage() { return errorMessage; }
|
||||||
|
|
||||||
|
public void clearError() {
|
||||||
|
errorMessage.setValue(null);
|
||||||
|
}
|
||||||
|
|
||||||
public InternetRadioStation getRadioToEdit() {
|
public InternetRadioStation getRadioToEdit() {
|
||||||
return toEdit;
|
return toEdit;
|
||||||
}
|
}
|
||||||
|
|
@ -30,14 +51,120 @@ public class RadioEditorViewModel extends AndroidViewModel {
|
||||||
}
|
}
|
||||||
|
|
||||||
public void createRadio(String name, String streamURL, String homepageURL) {
|
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) {
|
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() {
|
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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -256,6 +256,7 @@
|
||||||
<string name="podcast_channel_catalogue_title_expanded">Browse Channels</string>
|
<string name="podcast_channel_catalogue_title_expanded">Browse Channels</string>
|
||||||
<string name="podcast_channel_editor_dialog_hint_rss_url">RSS Url</string>
|
<string name="podcast_channel_editor_dialog_hint_rss_url">RSS Url</string>
|
||||||
<string name="podcast_channel_editor_dialog_title">Podcast Channel</string>
|
<string name="podcast_channel_editor_dialog_title">Podcast Channel</string>
|
||||||
|
<string name="podcast_channel_not_supported_snackbar">Podcasts are not supported by this server.</string>
|
||||||
<string name="podcast_channel_page_title_description_section">Description</string>
|
<string name="podcast_channel_page_title_description_section">Description</string>
|
||||||
<string name="podcast_channel_page_title_episode_section">Episodes</string>
|
<string name="podcast_channel_page_title_episode_section">Episodes</string>
|
||||||
<string name="podcast_channel_page_title_no_episode_available">No episodes available</string>
|
<string name="podcast_channel_page_title_no_episode_available">No episodes available</string>
|
||||||
|
|
@ -270,10 +271,13 @@
|
||||||
<string name="radio_editor_dialog_negative_button">Cancel</string>
|
<string name="radio_editor_dialog_negative_button">Cancel</string>
|
||||||
<string name="radio_editor_dialog_neutral_button">Delete</string>
|
<string name="radio_editor_dialog_neutral_button">Delete</string>
|
||||||
<string name="radio_editor_dialog_positive_button">Save</string>
|
<string name="radio_editor_dialog_positive_button">Save</string>
|
||||||
|
<string name="radio_editor_dialog_added">Radio station added</string>
|
||||||
|
<string name="radio_editor_dialog_updated">Radio station updated</string>
|
||||||
<string name="radio_editor_dialog_title">Internet Radio Station</string>
|
<string name="radio_editor_dialog_title">Internet Radio Station</string>
|
||||||
<string name="radio_station_info_empty_button">Click to hide the section\nThe effects will be visible on restart</string>
|
<string name="radio_station_info_empty_button">Click to hide the section\nThe effects will be visible on restart</string>
|
||||||
<string name="radio_station_info_empty_subtitle">Once you add a radio station, you\'ll find it here</string>
|
<string name="radio_station_info_empty_subtitle">Once you add a radio station, you\'ll find it here</string>
|
||||||
<string name="radio_station_info_empty_title">No stations found!</string>
|
<string name="radio_station_info_empty_title">No stations found!</string>
|
||||||
|
<string name="radio_dialog_not_supported_snackbar">Internet radio management are not supported by this server.</string>
|
||||||
<string name="rating_dialog_negative_button">Cancel</string>
|
<string name="rating_dialog_negative_button">Cancel</string>
|
||||||
<string name="rating_dialog_positive_button">Save</string>
|
<string name="rating_dialog_positive_button">Save</string>
|
||||||
<string name="rating_dialog_title">Rate</string>
|
<string name="rating_dialog_title">Rate</string>
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue