diff --git a/app/src/main/java/com/stormtales/notevault/data/repositories/SongSyncRepository.java b/app/src/main/java/com/stormtales/notevault/data/repositories/SongSyncRepository.java index ae1cb12..f17708c 100644 --- a/app/src/main/java/com/stormtales/notevault/data/repositories/SongSyncRepository.java +++ b/app/src/main/java/com/stormtales/notevault/data/repositories/SongSyncRepository.java @@ -163,6 +163,16 @@ public class SongSyncRepository { }); } + public void markSongsAsRemotelyModified(List serverIDs) { + Executors.newSingleThreadExecutor().execute(() -> { + List songs = songDao.getSongsByServerIDs(serverIDs); + for(Song song : songs) { + song.setSyncStatus(SyncStatus.REMOTE_MODIFIED); + } + songDao.updateSongs(songs); + }); + } + public interface LoadDataCallback { void onResult(T result); } diff --git a/app/src/main/java/com/stormtales/notevault/network/sync/SongSyncAPI.java b/app/src/main/java/com/stormtales/notevault/network/sync/SongSyncAPI.java index a463ed3..52306fd 100644 --- a/app/src/main/java/com/stormtales/notevault/network/sync/SongSyncAPI.java +++ b/app/src/main/java/com/stormtales/notevault/network/sync/SongSyncAPI.java @@ -6,10 +6,9 @@ import com.stormtales.notevault.network.sync.models.*; import okhttp3.MultipartBody; import okhttp3.RequestBody; import retrofit2.Call; -import retrofit2.http.Body; -import retrofit2.http.Multipart; -import retrofit2.http.POST; -import retrofit2.http.Part; +import retrofit2.http.*; + +import java.time.LocalDateTime; public interface SongSyncAPI { @@ -29,4 +28,7 @@ public interface SongSyncAPI { @Multipart @POST("/sync/songs/note_sheet/update") Call updateNoteSheet(@Part("server_filename") RequestBody server_filename, @Part MultipartBody.Part image); + + @GET("/sync/songs/fetch") + Call fetchRemoteModifiedSongs(@Query(value = "last_client_sync") String last_client_sync); } diff --git a/app/src/main/java/com/stormtales/notevault/network/sync/SongSyncModule.java b/app/src/main/java/com/stormtales/notevault/network/sync/SongSyncModule.java index bb99c96..e79a81a 100644 --- a/app/src/main/java/com/stormtales/notevault/network/sync/SongSyncModule.java +++ b/app/src/main/java/com/stormtales/notevault/network/sync/SongSyncModule.java @@ -4,12 +4,10 @@ import android.content.Context; import com.stormtales.notevault.data.entities.Song; import com.stormtales.notevault.data.repositories.SongRepository; import com.stormtales.notevault.data.repositories.SongSyncRepository; -import com.stormtales.notevault.network.sync.models.BatchCreateResponse; -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.network.sync.models.*; import com.stormtales.notevault.ui.gallery.GalleryViewModel; +import java.time.LocalDateTime; import java.util.ArrayList; import java.util.List; 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() { + @Override + public void onResult(FetchResponse result) { + songSyncRepository.markSongsAsRemotelyModified(result.getServerIDs()); + syncViewModel.finishFetching(); + } + }); + } + public interface FinishSongCreateSyncingCallback { void finishSongSyncing(BatchCreateResponse response); } diff --git a/app/src/main/java/com/stormtales/notevault/network/sync/SongSyncService.java b/app/src/main/java/com/stormtales/notevault/network/sync/SongSyncService.java index 63bff7d..d8f390b 100644 --- a/app/src/main/java/com/stormtales/notevault/network/sync/SongSyncService.java +++ b/app/src/main/java/com/stormtales/notevault/network/sync/SongSyncService.java @@ -4,6 +4,7 @@ import android.content.Context; import android.util.Log; import com.stormtales.notevault.data.entities.NoteSheet; 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.auth.AuthAPI; import com.stormtales.notevault.network.sync.models.*; @@ -16,6 +17,8 @@ import retrofit2.Callback; import retrofit2.Response; import java.io.File; +import java.time.LocalDateTime; +import java.time.format.DateTimeFormatter; import java.util.ArrayList; import java.util.List; import java.util.Map; @@ -156,6 +159,23 @@ public class SongSyncService { } } + public void fetchRemoteModifiedSongs(LocalDateTime lastClientSync, SongSyncRepository.LoadDataCallback callback) { + String formattedTime = lastClientSync.format(DateTimeFormatter.ISO_LOCAL_DATE_TIME); + songSyncAPI.fetchRemoteModifiedSongs(formattedTime).enqueue(new Callback() { + @Override + public void onResponse(Call call, Response response) { + if(response.isSuccessful() && response.body() != null) { + callback.onResult(response.body()); + } + } + + @Override + public void onFailure(Call call, Throwable throwable) { + Log.d("SongSyncService", "Fetch failed: " + throwable.getMessage(), throwable); + } + }); + } + public interface SyncDeletedSongsCallback { void finishSongSyncing(List remoteDeletedSongs, List localDeletedSongs); diff --git a/app/src/main/java/com/stormtales/notevault/network/sync/models/FetchResponse.java b/app/src/main/java/com/stormtales/notevault/network/sync/models/FetchResponse.java new file mode 100644 index 0000000..29a9b91 --- /dev/null +++ b/app/src/main/java/com/stormtales/notevault/network/sync/models/FetchResponse.java @@ -0,0 +1,15 @@ +package com.stormtales.notevault.network.sync.models; + +import java.util.List; + +public class FetchResponse { + private List serverIDs; + + public List getServerIDs() { + return serverIDs; + } + + public void setServerIDs(List serverIDs) { + this.serverIDs = serverIDs; + } +} diff --git a/app/src/main/java/com/stormtales/notevault/ui/gallery/GalleryFragment.java b/app/src/main/java/com/stormtales/notevault/ui/gallery/GalleryFragment.java index 157cdff..cf47f96 100644 --- a/app/src/main/java/com/stormtales/notevault/ui/gallery/GalleryFragment.java +++ b/app/src/main/java/com/stormtales/notevault/ui/gallery/GalleryFragment.java @@ -27,6 +27,9 @@ public class GalleryFragment extends Fragment { private ProgressBar progress_sync_deleted_songs; private Button sync_deleted_songs_btn; + private ProgressBar progress_fetching_songs; + private Button sync_fetching_songs_btn; + public View onCreateView(@NonNull LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { @@ -47,6 +50,10 @@ public class GalleryFragment extends Fragment { sync_deleted_songs_btn = binding.syncDeletedBtn; 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.getIsCreatedSongSyncing().observe(getViewLifecycleOwner(), isCreatedSyncinc -> { @@ -78,9 +85,23 @@ public class GalleryFragment extends Fragment { 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; } + private void onFetchRemoteModifiedSongs() { + galleryViewModel.startFetchingActive(); + } + private void onSyncDeletedSongs() { galleryViewModel.startDeletedSongSyncing(); } diff --git a/app/src/main/java/com/stormtales/notevault/ui/gallery/GalleryViewModel.java b/app/src/main/java/com/stormtales/notevault/ui/gallery/GalleryViewModel.java index d6207dd..14da487 100644 --- a/app/src/main/java/com/stormtales/notevault/ui/gallery/GalleryViewModel.java +++ b/app/src/main/java/com/stormtales/notevault/ui/gallery/GalleryViewModel.java @@ -11,6 +11,7 @@ public class GalleryViewModel extends ViewModel { private final MutableLiveData isCreatedSongSyncing; private final MutableLiveData isModifiedSongSyncing; private final MutableLiveData isDeletedSongSyncing; + private final MutableLiveData isFetchingActive; private SongSyncModule songSyncModule; public GalleryViewModel() { @@ -23,6 +24,9 @@ public class GalleryViewModel extends ViewModel { isDeletedSongSyncing = new MutableLiveData<>(); isDeletedSongSyncing.setValue(false); + + isFetchingActive = new MutableLiveData<>(); + isFetchingActive.setValue(false); } public MutableLiveData getIsCreatedSongSyncing() { @@ -71,4 +75,18 @@ public class GalleryViewModel extends ViewModel { public void finishDeleteSongSyncinc() { 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 getIsFetchingActive() { + return isFetchingActive; + } } \ No newline at end of file diff --git a/app/src/main/res/layout/fragment_gallery.xml b/app/src/main/res/layout/fragment_gallery.xml index 19ef9d4..8c2fe91 100644 --- a/app/src/main/res/layout/fragment_gallery.xml +++ b/app/src/main/res/layout/fragment_gallery.xml @@ -147,5 +147,48 @@ android:layout_marginEnd="16dp" /> + + + + + + + + + +