ADD: Fetch Remotely Modified Songs
This commit is contained in:
parent
007f6a8501
commit
a53bc4bee7
@ -163,6 +163,16 @@ public class SongSyncRepository {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void markSongsAsRemotelyModified(List<String> serverIDs) {
|
||||||
|
Executors.newSingleThreadExecutor().execute(() -> {
|
||||||
|
List<Song> songs = songDao.getSongsByServerIDs(serverIDs);
|
||||||
|
for(Song song : songs) {
|
||||||
|
song.setSyncStatus(SyncStatus.REMOTE_MODIFIED);
|
||||||
|
}
|
||||||
|
songDao.updateSongs(songs);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
public interface LoadDataCallback<T> {
|
public interface LoadDataCallback<T> {
|
||||||
void onResult(T result);
|
void onResult(T result);
|
||||||
}
|
}
|
||||||
|
@ -6,10 +6,9 @@ import com.stormtales.notevault.network.sync.models.*;
|
|||||||
import okhttp3.MultipartBody;
|
import okhttp3.MultipartBody;
|
||||||
import okhttp3.RequestBody;
|
import okhttp3.RequestBody;
|
||||||
import retrofit2.Call;
|
import retrofit2.Call;
|
||||||
import retrofit2.http.Body;
|
import retrofit2.http.*;
|
||||||
import retrofit2.http.Multipart;
|
|
||||||
import retrofit2.http.POST;
|
import java.time.LocalDateTime;
|
||||||
import retrofit2.http.Part;
|
|
||||||
|
|
||||||
public interface SongSyncAPI {
|
public interface SongSyncAPI {
|
||||||
|
|
||||||
@ -29,4 +28,7 @@ public interface SongSyncAPI {
|
|||||||
@Multipart
|
@Multipart
|
||||||
@POST("/sync/songs/note_sheet/update")
|
@POST("/sync/songs/note_sheet/update")
|
||||||
Call<UploadResponse> updateNoteSheet(@Part("server_filename") RequestBody server_filename, @Part MultipartBody.Part image);
|
Call<UploadResponse> updateNoteSheet(@Part("server_filename") RequestBody server_filename, @Part MultipartBody.Part image);
|
||||||
|
|
||||||
|
@GET("/sync/songs/fetch")
|
||||||
|
Call<FetchResponse> fetchRemoteModifiedSongs(@Query(value = "last_client_sync") String last_client_sync);
|
||||||
}
|
}
|
||||||
|
@ -4,12 +4,10 @@ import android.content.Context;
|
|||||||
import com.stormtales.notevault.data.entities.Song;
|
import com.stormtales.notevault.data.entities.Song;
|
||||||
import com.stormtales.notevault.data.repositories.SongRepository;
|
import com.stormtales.notevault.data.repositories.SongRepository;
|
||||||
import com.stormtales.notevault.data.repositories.SongSyncRepository;
|
import com.stormtales.notevault.data.repositories.SongSyncRepository;
|
||||||
import com.stormtales.notevault.network.sync.models.BatchCreateResponse;
|
import com.stormtales.notevault.network.sync.models.*;
|
||||||
import com.stormtales.notevault.network.sync.models.BatchModifyResponse;
|
|
||||||
import com.stormtales.notevault.network.sync.models.SongModifyBatchResponse;
|
|
||||||
import com.stormtales.notevault.network.sync.models.UploadResponse;
|
|
||||||
import com.stormtales.notevault.ui.gallery.GalleryViewModel;
|
import com.stormtales.notevault.ui.gallery.GalleryViewModel;
|
||||||
|
|
||||||
|
import java.time.LocalDateTime;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
@ -80,6 +78,17 @@ public class SongSyncModule {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void fetchRemoteModifiedSongs() {
|
||||||
|
//Todo: Determine Last Client Sync; for testing use LocalDateTime.MIN
|
||||||
|
songSyncService.fetchRemoteModifiedSongs(LocalDateTime.now().minusDays(35), new SongSyncRepository.LoadDataCallback<FetchResponse>() {
|
||||||
|
@Override
|
||||||
|
public void onResult(FetchResponse result) {
|
||||||
|
songSyncRepository.markSongsAsRemotelyModified(result.getServerIDs());
|
||||||
|
syncViewModel.finishFetching();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
public interface FinishSongCreateSyncingCallback {
|
public interface FinishSongCreateSyncingCallback {
|
||||||
void finishSongSyncing(BatchCreateResponse response);
|
void finishSongSyncing(BatchCreateResponse response);
|
||||||
}
|
}
|
||||||
|
@ -4,6 +4,7 @@ import android.content.Context;
|
|||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
import com.stormtales.notevault.data.entities.NoteSheet;
|
import com.stormtales.notevault.data.entities.NoteSheet;
|
||||||
import com.stormtales.notevault.data.entities.Song;
|
import com.stormtales.notevault.data.entities.Song;
|
||||||
|
import com.stormtales.notevault.data.repositories.SongSyncRepository;
|
||||||
import com.stormtales.notevault.network.NetworkModule;
|
import com.stormtales.notevault.network.NetworkModule;
|
||||||
import com.stormtales.notevault.network.auth.AuthAPI;
|
import com.stormtales.notevault.network.auth.AuthAPI;
|
||||||
import com.stormtales.notevault.network.sync.models.*;
|
import com.stormtales.notevault.network.sync.models.*;
|
||||||
@ -16,6 +17,8 @@ import retrofit2.Callback;
|
|||||||
import retrofit2.Response;
|
import retrofit2.Response;
|
||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
|
import java.time.LocalDateTime;
|
||||||
|
import java.time.format.DateTimeFormatter;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
@ -156,6 +159,23 @@ public class SongSyncService {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void fetchRemoteModifiedSongs(LocalDateTime lastClientSync, SongSyncRepository.LoadDataCallback<FetchResponse> callback) {
|
||||||
|
String formattedTime = lastClientSync.format(DateTimeFormatter.ISO_LOCAL_DATE_TIME);
|
||||||
|
songSyncAPI.fetchRemoteModifiedSongs(formattedTime).enqueue(new Callback<FetchResponse>() {
|
||||||
|
@Override
|
||||||
|
public void onResponse(Call<FetchResponse> call, Response<FetchResponse> response) {
|
||||||
|
if(response.isSuccessful() && response.body() != null) {
|
||||||
|
callback.onResult(response.body());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onFailure(Call<FetchResponse> call, Throwable throwable) {
|
||||||
|
Log.d("SongSyncService", "Fetch failed: " + throwable.getMessage(), throwable);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
public interface SyncDeletedSongsCallback {
|
public interface SyncDeletedSongsCallback {
|
||||||
void finishSongSyncing(List<String> remoteDeletedSongs, List<Integer> localDeletedSongs);
|
void finishSongSyncing(List<String> remoteDeletedSongs, List<Integer> localDeletedSongs);
|
||||||
|
@ -0,0 +1,15 @@
|
|||||||
|
package com.stormtales.notevault.network.sync.models;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
public class FetchResponse {
|
||||||
|
private List<String> serverIDs;
|
||||||
|
|
||||||
|
public List<String> getServerIDs() {
|
||||||
|
return serverIDs;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setServerIDs(List<String> serverIDs) {
|
||||||
|
this.serverIDs = serverIDs;
|
||||||
|
}
|
||||||
|
}
|
@ -27,6 +27,9 @@ public class GalleryFragment extends Fragment {
|
|||||||
private ProgressBar progress_sync_deleted_songs;
|
private ProgressBar progress_sync_deleted_songs;
|
||||||
private Button sync_deleted_songs_btn;
|
private Button sync_deleted_songs_btn;
|
||||||
|
|
||||||
|
private ProgressBar progress_fetching_songs;
|
||||||
|
private Button sync_fetching_songs_btn;
|
||||||
|
|
||||||
|
|
||||||
public View onCreateView(@NonNull LayoutInflater inflater,
|
public View onCreateView(@NonNull LayoutInflater inflater,
|
||||||
ViewGroup container, Bundle savedInstanceState) {
|
ViewGroup container, Bundle savedInstanceState) {
|
||||||
@ -47,6 +50,10 @@ public class GalleryFragment extends Fragment {
|
|||||||
sync_deleted_songs_btn = binding.syncDeletedBtn;
|
sync_deleted_songs_btn = binding.syncDeletedBtn;
|
||||||
sync_deleted_songs_btn.setOnClickListener(v -> onSyncDeletedSongs());
|
sync_deleted_songs_btn.setOnClickListener(v -> onSyncDeletedSongs());
|
||||||
|
|
||||||
|
progress_fetching_songs = binding.progressFetchSongs;
|
||||||
|
sync_fetching_songs_btn = binding.fetchSongsBtn;
|
||||||
|
sync_fetching_songs_btn.setOnClickListener(v -> onFetchRemoteModifiedSongs());
|
||||||
|
|
||||||
galleryViewModel.setSongSyncModule(new SongSyncModule(getContext(), galleryViewModel));
|
galleryViewModel.setSongSyncModule(new SongSyncModule(getContext(), galleryViewModel));
|
||||||
|
|
||||||
galleryViewModel.getIsCreatedSongSyncing().observe(getViewLifecycleOwner(), isCreatedSyncinc -> {
|
galleryViewModel.getIsCreatedSongSyncing().observe(getViewLifecycleOwner(), isCreatedSyncinc -> {
|
||||||
@ -78,9 +85,23 @@ public class GalleryFragment extends Fragment {
|
|||||||
sync_deleted_songs_btn.setEnabled(true);
|
sync_deleted_songs_btn.setEnabled(true);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
galleryViewModel.getIsFetchingActive().observe(getViewLifecycleOwner(), isFetchingActiveSyncinc -> {
|
||||||
|
if(isFetchingActiveSyncinc) {
|
||||||
|
progress_fetching_songs.setIndeterminate(true);
|
||||||
|
sync_fetching_songs_btn.setEnabled(false);
|
||||||
|
} else {
|
||||||
|
progress_fetching_songs.setIndeterminate(false);
|
||||||
|
sync_fetching_songs_btn.setEnabled(true);
|
||||||
|
}
|
||||||
|
});
|
||||||
return root;
|
return root;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void onFetchRemoteModifiedSongs() {
|
||||||
|
galleryViewModel.startFetchingActive();
|
||||||
|
}
|
||||||
|
|
||||||
private void onSyncDeletedSongs() {
|
private void onSyncDeletedSongs() {
|
||||||
galleryViewModel.startDeletedSongSyncing();
|
galleryViewModel.startDeletedSongSyncing();
|
||||||
}
|
}
|
||||||
|
@ -11,6 +11,7 @@ public class GalleryViewModel extends ViewModel {
|
|||||||
private final MutableLiveData<Boolean> isCreatedSongSyncing;
|
private final MutableLiveData<Boolean> isCreatedSongSyncing;
|
||||||
private final MutableLiveData<Boolean> isModifiedSongSyncing;
|
private final MutableLiveData<Boolean> isModifiedSongSyncing;
|
||||||
private final MutableLiveData<Boolean> isDeletedSongSyncing;
|
private final MutableLiveData<Boolean> isDeletedSongSyncing;
|
||||||
|
private final MutableLiveData<Boolean> isFetchingActive;
|
||||||
private SongSyncModule songSyncModule;
|
private SongSyncModule songSyncModule;
|
||||||
|
|
||||||
public GalleryViewModel() {
|
public GalleryViewModel() {
|
||||||
@ -23,6 +24,9 @@ public class GalleryViewModel extends ViewModel {
|
|||||||
|
|
||||||
isDeletedSongSyncing = new MutableLiveData<>();
|
isDeletedSongSyncing = new MutableLiveData<>();
|
||||||
isDeletedSongSyncing.setValue(false);
|
isDeletedSongSyncing.setValue(false);
|
||||||
|
|
||||||
|
isFetchingActive = new MutableLiveData<>();
|
||||||
|
isFetchingActive.setValue(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
public MutableLiveData<Boolean> getIsCreatedSongSyncing() {
|
public MutableLiveData<Boolean> getIsCreatedSongSyncing() {
|
||||||
@ -71,4 +75,18 @@ public class GalleryViewModel extends ViewModel {
|
|||||||
public void finishDeleteSongSyncinc() {
|
public void finishDeleteSongSyncinc() {
|
||||||
this.isDeletedSongSyncing.setValue(false);
|
this.isDeletedSongSyncing.setValue(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void startFetchingActive() {
|
||||||
|
if(this.songSyncModule == null) throw new RuntimeException("SongSyncModule is not initialized");
|
||||||
|
this.isFetchingActive.setValue(true);
|
||||||
|
this.songSyncModule.fetchRemoteModifiedSongs();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void finishFetching() {
|
||||||
|
this.isFetchingActive.setValue(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
public MutableLiveData<Boolean> getIsFetchingActive() {
|
||||||
|
return isFetchingActive;
|
||||||
|
}
|
||||||
}
|
}
|
@ -147,5 +147,48 @@
|
|||||||
android:layout_marginEnd="16dp" />
|
android:layout_marginEnd="16dp" />
|
||||||
|
|
||||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||||
|
<androidx.constraintlayout.widget.ConstraintLayout
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content">
|
||||||
|
|
||||||
|
<!-- Label -->
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/fetch_songs"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:text="Fetch Remote Modified Songs"
|
||||||
|
android:textSize="16sp"
|
||||||
|
android:textColor="@android:color/black"
|
||||||
|
app:layout_constraintStart_toStartOf="parent"
|
||||||
|
app:layout_constraintTop_toTopOf="parent"
|
||||||
|
app:layout_constraintBottom_toBottomOf="parent"
|
||||||
|
android:layout_marginEnd="8dp" />
|
||||||
|
|
||||||
|
<!-- Progress Bar -->
|
||||||
|
<ProgressBar
|
||||||
|
android:id="@+id/progress_fetch_songs"
|
||||||
|
style="?android:attr/progressBarStyleHorizontal"
|
||||||
|
android:layout_width="0dp"
|
||||||
|
android:layout_height="44dp"
|
||||||
|
android:indeterminate="true"
|
||||||
|
android:layout_marginEnd="16dp"
|
||||||
|
android:layout_marginStart="16dp"
|
||||||
|
app:layout_constraintStart_toEndOf="@id/fetch_songs"
|
||||||
|
app:layout_constraintEnd_toStartOf="@id/fetch_songs_btn"
|
||||||
|
app:layout_constraintTop_toTopOf="@id/fetch_songs"
|
||||||
|
app:layout_constraintBottom_toBottomOf="@id/fetch_songs"/>
|
||||||
|
|
||||||
|
<!-- Sync Button -->
|
||||||
|
<Button
|
||||||
|
android:id="@+id/fetch_songs_btn"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:text="Sync"
|
||||||
|
app:layout_constraintEnd_toEndOf="parent"
|
||||||
|
app:layout_constraintTop_toTopOf="@id/fetch_songs"
|
||||||
|
app:layout_constraintBottom_toBottomOf="@id/fetch_songs"
|
||||||
|
android:layout_marginEnd="16dp" />
|
||||||
|
|
||||||
|
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||||
|
Loading…
Reference in New Issue
Block a user