diff --git a/app/src/main/java/com/stormtales/notevault/data/dao/SongDao.java b/app/src/main/java/com/stormtales/notevault/data/dao/SongDao.java index e2debca..886faea 100644 --- a/app/src/main/java/com/stormtales/notevault/data/dao/SongDao.java +++ b/app/src/main/java/com/stormtales/notevault/data/dao/SongDao.java @@ -39,4 +39,7 @@ public interface SongDao { @Query("SELECT * FROM Song WHERE localID IN (:localIDs)") List getSongsByLocalIDs(List localIDs); + + @Query("SELECT * FROM Song WHERE serverID IN (:serverIDs)") + List getSongsByServerIDs(List serverIDs); } 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 671372c..9060197 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 @@ -8,6 +8,7 @@ import com.stormtales.notevault.data.dao.SongDao; import com.stormtales.notevault.data.entities.Song; import com.stormtales.notevault.data.sync.SyncStatus; import com.stormtales.notevault.network.sync.models.BatchCreateResponse; +import com.stormtales.notevault.network.sync.models.BatchModifyResponse; import com.stormtales.notevault.network.sync.models.CreateResponse; import java.time.LocalDateTime; @@ -32,6 +33,14 @@ public class SongSyncRepository { }); } + public void loadModifiedSongs(LoadDataCallback> callback) { + Executors.newSingleThreadExecutor().execute(() -> { + List modifiedSongs = songDao.getSongsBySyncStatus(SyncStatus.MODIFIED); + Handler mainHandler = new Handler(Looper.getMainLooper()); + mainHandler.post(()-> callback.onResult(modifiedSongs)); + }); + } + public void markCreatedSongsAsSynced(BatchCreateResponse createdSongs) { Executors.newSingleThreadExecutor().execute(() -> { List localIDs = createdSongs.getCreateResponses().stream().map(CreateResponse::getLocalID).collect(Collectors.toList()); @@ -58,6 +67,17 @@ public class SongSyncRepository { } } + public void markModifiedSongsAsSynced(BatchModifyResponse response) { + Executors.newSingleThreadExecutor().execute(() -> { + List requestedSongs = songDao.getSongsByServerIDs(response.getModifiedServerObjects()); + for(Song song : requestedSongs) { + song.setSyncStatus(SyncStatus.SYNCED); + song.setSyncTime(LocalDateTime.now()); + } + songDao.updateSongs(requestedSongs); + }); + } + 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 85d0910..ddec0fb 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 @@ -3,7 +3,9 @@ package com.stormtales.notevault.network.sync; import com.stormtales.notevault.network.auth.LoginRequest; import com.stormtales.notevault.network.auth.LoginResponse; import com.stormtales.notevault.network.sync.models.BatchCreateResponse; +import com.stormtales.notevault.network.sync.models.BatchModifyResponse; import com.stormtales.notevault.network.sync.models.SongCreateBatchRequest; +import com.stormtales.notevault.network.sync.models.SongModifyBatchRequest; import retrofit2.Call; import retrofit2.http.Body; import retrofit2.http.POST; @@ -12,4 +14,7 @@ public interface SongSyncAPI { @POST("/sync/songs/create") Call syncCreatedSongs(@Body SongCreateBatchRequest songCreateBatchRequest); + + @POST("/sync/songs/modify") + Call syncModifiedSongs(@Body SongModifyBatchRequest songModifyBatchRequest); } 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 f5c959f..8c0b6ff 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 @@ -1,14 +1,12 @@ package com.stormtales.notevault.network.sync; 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.ui.gallery.GalleryViewModel; -import java.util.List; - public class SongSyncModule { private SongRepository songRepository; private SongSyncRepository songSyncRepository; @@ -22,19 +20,29 @@ public class SongSyncModule { this.syncViewModel = syncViewModel; } - public void syncCreatedSongs(FinishSongSyncingCallback callback) { + public void syncCreatedSongs() { songSyncRepository.loadCreatedSongs(result -> { - songSyncService.syncCreatedSongs(result, new FinishSongSyncingCallback() { - @Override - public void finishSongSyncing(BatchCreateResponse response) { - songSyncRepository.markCreatedSongsAsSynced(response); - callback.finishSongSyncing(response); - } + songSyncService.syncCreatedSongs(result, response -> { + songSyncRepository.markCreatedSongsAsSynced(response); + syncViewModel.finishCreateSongSyncing(); }); }); } - public interface FinishSongSyncingCallback { + public void syncModifiedSongs() { + songSyncRepository.loadModifiedSongs(result -> { + songSyncService.syncModifiedSongs(result, response -> { + songSyncRepository.markModifiedSongsAsSynced(response); + syncViewModel.finishModifiedSongSyncinc(); + }); + }); + } + + public interface FinishSongCreateSyncingCallback { void finishSongSyncing(BatchCreateResponse response); } + + public interface FinishSongSyncingCallback { + void finishSongSyncing(BatchModifyResponse 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 35f279f..469dfb4 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,9 +4,7 @@ import android.content.Context; import com.stormtales.notevault.data.entities.Song; import com.stormtales.notevault.network.NetworkModule; import com.stormtales.notevault.network.auth.AuthAPI; -import com.stormtales.notevault.network.sync.models.BatchCreateResponse; -import com.stormtales.notevault.network.sync.models.SongCreateBatchRequest; -import com.stormtales.notevault.network.sync.models.SongCreateRequest; +import com.stormtales.notevault.network.sync.models.*; import com.stormtales.notevault.ui.gallery.GalleryViewModel; import retrofit2.Call; import retrofit2.Callback; @@ -23,7 +21,7 @@ public class SongSyncService { songSyncAPI = NetworkModule.getRetrofitInstance(context).create(SongSyncAPI.class); } - public void syncCreatedSongs(List songs, SongSyncModule.FinishSongSyncingCallback callback) { + public void syncCreatedSongs(List songs, SongSyncModule.FinishSongCreateSyncingCallback callback) { List createRequests = new ArrayList<>(); for(Song song : songs) { createRequests.add(new SongCreateRequest(song)); @@ -41,4 +39,23 @@ public class SongSyncService { } }); } + + public void syncModifiedSongs(List songs, SongSyncModule.FinishSongSyncingCallback callback) { + List modifyRequests = new ArrayList<>(); + for(Song song : songs) { + modifyRequests.add(new SongModifyRequest(song)); + } + SongModifyBatchRequest songModifyBatchRequest = new SongModifyBatchRequest(modifyRequests); + songSyncAPI.syncModifiedSongs(songModifyBatchRequest).enqueue(new Callback() { + @Override + public void onResponse(Call call, Response response) { + callback.finishSongSyncing(response.body()); + } + + @Override + public void onFailure(Call call, Throwable throwable) { + + } + }); + } } diff --git a/app/src/main/java/com/stormtales/notevault/network/sync/models/BatchModifyResponse.java b/app/src/main/java/com/stormtales/notevault/network/sync/models/BatchModifyResponse.java new file mode 100644 index 0000000..ad08584 --- /dev/null +++ b/app/src/main/java/com/stormtales/notevault/network/sync/models/BatchModifyResponse.java @@ -0,0 +1,15 @@ +package com.stormtales.notevault.network.sync.models; + +import java.util.List; + +public class BatchModifyResponse { + private List modifiedServerObjects; + + public List getModifiedServerObjects() { + return modifiedServerObjects; + } + + public void setModifiedServerObjects(List modifiedServerObjects) { + this.modifiedServerObjects = modifiedServerObjects; + } +} diff --git a/app/src/main/java/com/stormtales/notevault/network/sync/models/SongModifyBatchRequest.java b/app/src/main/java/com/stormtales/notevault/network/sync/models/SongModifyBatchRequest.java new file mode 100644 index 0000000..33247bf --- /dev/null +++ b/app/src/main/java/com/stormtales/notevault/network/sync/models/SongModifyBatchRequest.java @@ -0,0 +1,19 @@ +package com.stormtales.notevault.network.sync.models; + +import java.util.List; + +public class SongModifyBatchRequest { + private List songs; + + public SongModifyBatchRequest(List songs) { + this.songs = songs; + } + + public List getSongs() { + return songs; + } + + public void setSongs(List songs) { + this.songs = songs; + } +} diff --git a/app/src/main/java/com/stormtales/notevault/network/sync/models/SongModifyRequest.java b/app/src/main/java/com/stormtales/notevault/network/sync/models/SongModifyRequest.java new file mode 100644 index 0000000..910b929 --- /dev/null +++ b/app/src/main/java/com/stormtales/notevault/network/sync/models/SongModifyRequest.java @@ -0,0 +1,68 @@ +package com.stormtales.notevault.network.sync.models; + +import com.stormtales.notevault.data.entities.Song; + +public class SongModifyRequest { + + private String serverID; + private String title; + private String composer; + private String genre; + private int year; + + public SongModifyRequest(String serverID, String title, String composer, String genre, int year) { + this.serverID = serverID; + this.title = title; + this.composer = composer; + this.genre = genre; + this.year = year; + } + + public SongModifyRequest(Song song) { + this.serverID = song.getServerID(); + this.title = song.getTitle(); + this.composer = song.getComposer(); + this.genre = song.getGenre(); + this.year = song.getYear(); + } + + public String getServerID() { + return serverID; + } + + public void setServerID(String serverID) { + this.serverID = serverID; + } + + public String getTitle() { + return title; + } + + public void setTitle(String title) { + this.title = title; + } + + public String getComposer() { + return composer; + } + + public void setComposer(String composer) { + this.composer = composer; + } + + public String getGenre() { + return genre; + } + + public void setGenre(String genre) { + this.genre = genre; + } + + public int getYear() { + return year; + } + + public void setYear(int year) { + this.year = year; + } +} 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 d080afb..16b804d 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 @@ -22,6 +22,8 @@ public class GalleryFragment extends Fragment { private FragmentGalleryBinding binding; private ProgressBar progress_sync_created_songs; private Button sync_created_songs_btn; + private ProgressBar progress_sync_modified_songs; + private Button sync_modified_songs_btn; public View onCreateView(@NonNull LayoutInflater inflater, @@ -34,6 +36,9 @@ public class GalleryFragment extends Fragment { progress_sync_created_songs = binding.progressSyncCreatedSongs; sync_created_songs_btn = binding.syncCreatedBtn; sync_created_songs_btn.setOnClickListener(v -> onSyncCreatedSongs()); + progress_sync_modified_songs = binding.progressSyncModifiedSongs; + sync_modified_songs_btn = binding.syncModifiedBtn; + sync_modified_songs_btn.setOnClickListener(v -> onSyncModifiedSogs()); galleryViewModel.setSongSyncModule(new SongSyncModule(getContext(), galleryViewModel)); @@ -46,16 +51,32 @@ public class GalleryFragment extends Fragment { sync_created_songs_btn.setEnabled(true); } }); + + galleryViewModel.getIsModifiedSongSyncing().observe(getViewLifecycleOwner(), isModifiedSyncinc -> { + if(isModifiedSyncinc) { + progress_sync_modified_songs.setIndeterminate(true); + sync_modified_songs_btn.setEnabled(false); + } else { + progress_sync_modified_songs.setIndeterminate(false); + sync_modified_songs_btn.setEnabled(true); + } + }); return root; } + @Override public void onDestroyView() { super.onDestroyView(); binding = null; } - public void onSyncCreatedSongs() { + private void onSyncCreatedSongs() { galleryViewModel.startCreateSongSyncing(); } + + + private void onSyncModifiedSogs() { + galleryViewModel.startModifiedSongSyncinc(); + } } \ No newline at end of file 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 30151d3..bf33e43 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 @@ -9,12 +9,16 @@ import com.stormtales.notevault.network.sync.SongSyncModule; public class GalleryViewModel extends ViewModel { private final MutableLiveData isCreatedSongSyncing; + private final MutableLiveData isModifiedSongSyncing; private SongSyncModule songSyncModule; public GalleryViewModel() { isCreatedSongSyncing = new MutableLiveData<>(); isCreatedSongSyncing.setValue(false); + + isModifiedSongSyncing = new MutableLiveData<>(); + isModifiedSongSyncing.setValue(false); } public MutableLiveData getIsCreatedSongSyncing() { @@ -25,12 +29,28 @@ public class GalleryViewModel extends ViewModel { if(this.songSyncModule == null) throw new RuntimeException("SongSyncModule is not initialized"); this.isCreatedSongSyncing.setValue(true); - this.songSyncModule.syncCreatedSongs(batchResponse -> { - this.isCreatedSongSyncing.setValue(false); - }); + this.songSyncModule.syncCreatedSongs(); + } + + public void finishCreateSongSyncing() { + this.isCreatedSongSyncing.setValue(false); } public void setSongSyncModule(SongSyncModule songSyncModule) { this.songSyncModule = songSyncModule; } + + public void startModifiedSongSyncinc() { + if(this.songSyncModule == null) throw new RuntimeException("SongSyncModule is not initialized"); + this.isModifiedSongSyncing.setValue(true); + this.songSyncModule.syncModifiedSongs(); + } + + public MutableLiveData getIsModifiedSongSyncing() { + return isModifiedSongSyncing; + } + + public void finishModifiedSongSyncinc() { + this.isModifiedSongSyncing.setValue(false); + } } \ 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 be9fe77..6ce550d 100644 --- a/app/src/main/res/layout/fragment_gallery.xml +++ b/app/src/main/res/layout/fragment_gallery.xml @@ -6,14 +6,18 @@ android:layout_width="match_parent" android:layout_height="match_parent" tools:context=".ui.gallery.GalleryFragment"> + + android:layout_height="match_parent" + android:padding="16dp"> + + + android:layout_height="wrap_content" + android:layout_marginBottom="16dp"> @@ -35,9 +38,9 @@ style="?android:attr/progressBarStyleHorizontal" android:layout_width="0dp" android:layout_height="44dp" - android:progress="0" - android:layout_marginEnd="15dp" - android:layout_marginStart="15dp" + android:indeterminate="true" + android:layout_marginEnd="16dp" + android:layout_marginStart="16dp" app:layout_constraintStart_toEndOf="@id/sync_created_songs" app:layout_constraintEnd_toStartOf="@id/sync_created_btn" app:layout_constraintTop_toTopOf="@id/sync_created_songs" @@ -56,5 +59,50 @@ + + + + + + + + + + +