mirror of
https://github.com/nextcloud/notes-android.git
synced 2024-11-25 14:26:13 +03:00
#1167 Use retrofit
This commit is contained in:
parent
ef7e2815b0
commit
4676bb8b6b
6 changed files with 219 additions and 67 deletions
|
@ -98,6 +98,12 @@ dependencies {
|
||||||
implementation "androidx.room:room-runtime:2.3.0"
|
implementation "androidx.room:room-runtime:2.3.0"
|
||||||
annotationProcessor "androidx.room:room-compiler:2.3.0"
|
annotationProcessor "androidx.room:room-compiler:2.3.0"
|
||||||
|
|
||||||
|
// Retrofit
|
||||||
|
implementation 'com.squareup.retrofit2:retrofit:2.6.4'
|
||||||
|
|
||||||
|
// Gson
|
||||||
|
implementation 'com.google.code.gson:gson:2.8.6'
|
||||||
|
|
||||||
coreLibraryDesugaring 'com.android.tools:desugar_jdk_libs:1.1.5'
|
coreLibraryDesugaring 'com.android.tools:desugar_jdk_libs:1.1.5'
|
||||||
|
|
||||||
// Testing
|
// Testing
|
||||||
|
|
|
@ -312,6 +312,9 @@ public class NotesRepository {
|
||||||
db.getNoteDao().deleteByNoteId(id, forceDBStatus);
|
db.getNoteDao().deleteByNoteId(id, forceDBStatus);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Please note, that db.updateNote() realized an optimistic conflict resolution, which is required for parallel changes of this Note from the UI.
|
||||||
|
*/
|
||||||
public int updateIfNotModifiedLocallyDuringSync(long noteId, Long targetModified, String targetTitle, boolean targetFavorite, String targetETag, String targetContent, String targetExcerpt, String contentBeforeSyncStart, String categoryBeforeSyncStart, boolean favoriteBeforeSyncStart) {
|
public int updateIfNotModifiedLocallyDuringSync(long noteId, Long targetModified, String targetTitle, boolean targetFavorite, String targetETag, String targetContent, String targetExcerpt, String contentBeforeSyncStart, String categoryBeforeSyncStart, boolean favoriteBeforeSyncStart) {
|
||||||
return db.getNoteDao().updateIfNotModifiedLocallyDuringSync(noteId, targetModified, targetTitle, targetFavorite, targetETag, targetContent, targetExcerpt, contentBeforeSyncStart, categoryBeforeSyncStart, favoriteBeforeSyncStart);
|
return db.getNoteDao().updateIfNotModifiedLocallyDuringSync(noteId, targetModified, targetTitle, targetFavorite, targetETag, targetContent, targetExcerpt, contentBeforeSyncStart, categoryBeforeSyncStart, favoriteBeforeSyncStart);
|
||||||
}
|
}
|
||||||
|
@ -779,10 +782,8 @@ public class NotesRepository {
|
||||||
Log.d(TAG, "Sync requested (" + (onlyLocalChanges ? "onlyLocalChanges" : "full") + "; " + (Boolean.TRUE.equals(syncActive.get(account.getId())) ? "sync active" : "sync NOT active") + ") ...");
|
Log.d(TAG, "Sync requested (" + (onlyLocalChanges ? "onlyLocalChanges" : "full") + "; " + (Boolean.TRUE.equals(syncActive.get(account.getId())) ? "sync active" : "sync NOT active") + ") ...");
|
||||||
if (isSyncPossible() && (!Boolean.TRUE.equals(syncActive.get(account.getId())) || onlyLocalChanges)) {
|
if (isSyncPossible() && (!Boolean.TRUE.equals(syncActive.get(account.getId())) || onlyLocalChanges)) {
|
||||||
try {
|
try {
|
||||||
SingleSignOnAccount ssoAccount = AccountImporter.getSingleSignOnAccount(context, account.getAccountName());
|
|
||||||
Log.d(TAG, "... starting now");
|
Log.d(TAG, "... starting now");
|
||||||
final NotesClient notesClient = NotesClient.newInstance(account.getPreferredApiVersion(), context);
|
final NotesServerSyncTask syncTask = new NotesServerSyncTask(context, this, account, onlyLocalChanges) {
|
||||||
final NotesServerSyncTask syncTask = new NotesServerSyncTask(notesClient, this, account, ssoAccount, onlyLocalChanges) {
|
|
||||||
@Override
|
@Override
|
||||||
void onPreExecute() {
|
void onPreExecute() {
|
||||||
syncStatus.postValue(true);
|
syncStatus.postValue(true);
|
||||||
|
|
|
@ -1,26 +1,34 @@
|
||||||
package it.niedermann.owncloud.notes.persistence;
|
package it.niedermann.owncloud.notes.persistence;
|
||||||
|
|
||||||
|
import android.content.Context;
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
|
|
||||||
import androidx.annotation.NonNull;
|
import androidx.annotation.NonNull;
|
||||||
|
|
||||||
|
import com.nextcloud.android.sso.AccountImporter;
|
||||||
|
import com.nextcloud.android.sso.api.NextcloudAPI;
|
||||||
|
import com.nextcloud.android.sso.exceptions.NextcloudFilesAppAccountNotFoundException;
|
||||||
import com.nextcloud.android.sso.exceptions.NextcloudHttpRequestFailedException;
|
import com.nextcloud.android.sso.exceptions.NextcloudHttpRequestFailedException;
|
||||||
import com.nextcloud.android.sso.exceptions.TokenMismatchException;
|
import com.nextcloud.android.sso.exceptions.TokenMismatchException;
|
||||||
import com.nextcloud.android.sso.model.SingleSignOnAccount;
|
import com.nextcloud.android.sso.model.SingleSignOnAccount;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
|
import java.util.Calendar;
|
||||||
|
import java.util.Date;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.HashSet;
|
import java.util.HashSet;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
import java.util.Objects;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
|
||||||
import it.niedermann.owncloud.notes.persistence.entity.Account;
|
import it.niedermann.owncloud.notes.persistence.entity.Account;
|
||||||
import it.niedermann.owncloud.notes.persistence.entity.Note;
|
import it.niedermann.owncloud.notes.persistence.entity.Note;
|
||||||
|
import it.niedermann.owncloud.notes.persistence.sync.ApiProvider;
|
||||||
import it.niedermann.owncloud.notes.shared.model.DBStatus;
|
import it.niedermann.owncloud.notes.shared.model.DBStatus;
|
||||||
import it.niedermann.owncloud.notes.shared.model.ISyncCallback;
|
import it.niedermann.owncloud.notes.shared.model.ISyncCallback;
|
||||||
import it.niedermann.owncloud.notes.shared.model.ServerResponse;
|
|
||||||
import it.niedermann.owncloud.notes.shared.model.SyncResultStatus;
|
import it.niedermann.owncloud.notes.shared.model.SyncResultStatus;
|
||||||
|
import retrofit2.Response;
|
||||||
|
|
||||||
import static it.niedermann.owncloud.notes.shared.model.DBStatus.LOCAL_DELETED;
|
import static it.niedermann.owncloud.notes.shared.model.DBStatus.LOCAL_DELETED;
|
||||||
import static it.niedermann.owncloud.notes.shared.util.NoteUtil.generateNoteExcerpt;
|
import static it.niedermann.owncloud.notes.shared.util.NoteUtil.generateNoteExcerpt;
|
||||||
|
@ -36,8 +44,13 @@ abstract class NotesServerSyncTask extends Thread {
|
||||||
|
|
||||||
private static final String TAG = NotesServerSyncTask.class.getSimpleName();
|
private static final String TAG = NotesServerSyncTask.class.getSimpleName();
|
||||||
|
|
||||||
|
private static final String HEADER_KEY_X_NOTES_API_VERSIONS = "X-Notes-API-Versions";
|
||||||
|
private static final String HEADER_KEY_ETAG = "ETag";
|
||||||
|
private static final String HEADER_KEY_LAST_MODIFIED = "Last-Modified";
|
||||||
@NonNull
|
@NonNull
|
||||||
private final NotesClient notesClient;
|
private final Context context;
|
||||||
|
@NonNull
|
||||||
|
private ApiProvider notesClient;
|
||||||
@NonNull
|
@NonNull
|
||||||
private final NotesRepository repo;
|
private final NotesRepository repo;
|
||||||
@NonNull
|
@NonNull
|
||||||
|
@ -50,12 +63,12 @@ abstract class NotesServerSyncTask extends Thread {
|
||||||
@NonNull
|
@NonNull
|
||||||
protected final ArrayList<Throwable> exceptions = new ArrayList<>();
|
protected final ArrayList<Throwable> exceptions = new ArrayList<>();
|
||||||
|
|
||||||
NotesServerSyncTask(@NonNull NotesClient notesClient, @NonNull NotesRepository repo, @NonNull Account localAccount, @NonNull SingleSignOnAccount ssoAccount, boolean onlyLocalChanges) {
|
NotesServerSyncTask(@NonNull Context context, @NonNull NotesRepository repo, @NonNull Account localAccount, boolean onlyLocalChanges) throws NextcloudFilesAppAccountNotFoundException {
|
||||||
super(TAG);
|
super(TAG);
|
||||||
this.notesClient = notesClient;
|
this.context = context;
|
||||||
this.repo = repo;
|
this.repo = repo;
|
||||||
this.localAccount = localAccount;
|
this.localAccount = localAccount;
|
||||||
this.ssoAccount = ssoAccount;
|
this.ssoAccount = AccountImporter.getSingleSignOnAccount(context, localAccount.getAccountName());
|
||||||
this.onlyLocalChanges = onlyLocalChanges;
|
this.onlyLocalChanges = onlyLocalChanges;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -67,15 +80,30 @@ abstract class NotesServerSyncTask extends Thread {
|
||||||
public void run() {
|
public void run() {
|
||||||
onPreExecute();
|
onPreExecute();
|
||||||
|
|
||||||
Log.i(TAG, "STARTING SYNCHRONIZATION");
|
notesClient = new ApiProvider(context, ssoAccount, new NextcloudAPI.ApiConnectedListener() {
|
||||||
final SyncResultStatus status = new SyncResultStatus();
|
@Override
|
||||||
status.pushSuccessful = pushLocalChanges();
|
public void onConnected() {
|
||||||
if (!onlyLocalChanges) {
|
new Thread(() -> {
|
||||||
status.pullSuccessful = pullRemoteChanges();
|
Log.i(TAG, "STARTING SYNCHRONIZATION");
|
||||||
}
|
final SyncResultStatus status = new SyncResultStatus();
|
||||||
Log.i(TAG, "SYNCHRONIZATION FINISHED");
|
status.pushSuccessful = pushLocalChanges();
|
||||||
|
if (!onlyLocalChanges) {
|
||||||
|
status.pullSuccessful = pullRemoteChanges();
|
||||||
|
}
|
||||||
|
Log.i(TAG, "SYNCHRONIZATION FINISHED");
|
||||||
|
|
||||||
onPostExecute(status);
|
onPostExecute(status);
|
||||||
|
}).start();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onError(Exception ex) {
|
||||||
|
final SyncResultStatus status = new SyncResultStatus();
|
||||||
|
status.pullSuccessful = false;
|
||||||
|
status.pushSuccessful = false;
|
||||||
|
onPostExecute(status);
|
||||||
|
}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
abstract void onPreExecute();
|
abstract void onPreExecute();
|
||||||
|
@ -99,20 +127,31 @@ abstract class NotesServerSyncTask extends Thread {
|
||||||
Log.v(TAG, " ...create/edit");
|
Log.v(TAG, " ...create/edit");
|
||||||
if (note.getRemoteId() != null) {
|
if (note.getRemoteId() != null) {
|
||||||
Log.v(TAG, " ...Note has remoteId → try to edit");
|
Log.v(TAG, " ...Note has remoteId → try to edit");
|
||||||
try {
|
final Response<Note> editResponse = notesClient.getNotesAPI().editNote(note, note.getRemoteId()).execute();
|
||||||
remoteNote = notesClient.editNote(ssoAccount, note).getNote();
|
if (editResponse.isSuccessful()) {
|
||||||
} catch (NextcloudHttpRequestFailedException e) {
|
remoteNote = editResponse.body();
|
||||||
if (e.getStatusCode() == HTTP_NOT_FOUND) {
|
} else {
|
||||||
|
if (editResponse.code() == HTTP_NOT_FOUND) {
|
||||||
Log.v(TAG, " ...Note does no longer exist on server → recreate");
|
Log.v(TAG, " ...Note does no longer exist on server → recreate");
|
||||||
remoteNote = notesClient.createNote(ssoAccount, note).getNote();
|
final Response<Note> createResponse = notesClient.getNotesAPI().createNote(note).execute();
|
||||||
|
if (createResponse.isSuccessful()) {
|
||||||
|
remoteNote = createResponse.body();
|
||||||
|
} else {
|
||||||
|
throw new Exception(createResponse.errorBody().string());
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
throw e;
|
throw new Exception(editResponse.errorBody().string());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
Log.v(TAG, " ...Note does not have a remoteId yet → create");
|
Log.v(TAG, " ...Note does not have a remoteId yet → create");
|
||||||
remoteNote = notesClient.createNote(ssoAccount, note).getNote();
|
final Response<Note> createResponse = notesClient.getNotesAPI().createNote(note).execute();
|
||||||
repo.updateRemoteId(note.getId(), remoteNote.getRemoteId());
|
if (createResponse.isSuccessful()) {
|
||||||
|
remoteNote = createResponse.body();
|
||||||
|
repo.updateRemoteId(note.getId(), remoteNote.getRemoteId());
|
||||||
|
} else {
|
||||||
|
throw new Exception(createResponse.errorBody().string());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
// Please note, that db.updateNote() realized an optimistic conflict resolution, which is required for parallel changes of this Note from the UI.
|
// Please note, that db.updateNote() realized an optimistic conflict resolution, which is required for parallel changes of this Note from the UI.
|
||||||
repo.updateIfNotModifiedLocallyDuringSync(note.getId(), remoteNote.getModified().getTimeInMillis(), remoteNote.getTitle(), remoteNote.getFavorite(), remoteNote.getETag(), remoteNote.getContent(), generateNoteExcerpt(remoteNote.getContent(), remoteNote.getTitle()), note.getContent(), note.getCategory(), note.getFavorite());
|
repo.updateIfNotModifiedLocallyDuringSync(note.getId(), remoteNote.getModified().getTimeInMillis(), remoteNote.getTitle(), remoteNote.getFavorite(), remoteNote.getETag(), remoteNote.getContent(), generateNoteExcerpt(remoteNote.getContent(), remoteNote.getTitle()), note.getContent(), note.getCategory(), note.getFavorite());
|
||||||
|
@ -122,13 +161,12 @@ abstract class NotesServerSyncTask extends Thread {
|
||||||
Log.v(TAG, " ...delete (only local, since it has never been synchronized)");
|
Log.v(TAG, " ...delete (only local, since it has never been synchronized)");
|
||||||
} else {
|
} else {
|
||||||
Log.v(TAG, " ...delete (from server and local)");
|
Log.v(TAG, " ...delete (from server and local)");
|
||||||
try {
|
final Response<Note> deleteResponse = notesClient.getNotesAPI().deleteNote(note.getRemoteId()).execute();
|
||||||
notesClient.deleteNote(ssoAccount, note.getRemoteId());
|
if (!deleteResponse.isSuccessful()) {
|
||||||
} catch (NextcloudHttpRequestFailedException e) {
|
if (deleteResponse.code() == HTTP_NOT_FOUND) {
|
||||||
if (e.getStatusCode() == HTTP_NOT_FOUND) {
|
|
||||||
Log.v(TAG, " ...delete (note has already been deleted remotely)");
|
Log.v(TAG, " ...delete (note has already been deleted remotely)");
|
||||||
} else {
|
} else {
|
||||||
throw e;
|
throw new Exception(deleteResponse.errorBody().string());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -173,51 +211,71 @@ abstract class NotesServerSyncTask extends Thread {
|
||||||
localAccount.setModified(accountFromDatabase.getModified());
|
localAccount.setModified(accountFromDatabase.getModified());
|
||||||
localAccount.setETag(accountFromDatabase.getETag());
|
localAccount.setETag(accountFromDatabase.getETag());
|
||||||
|
|
||||||
final ServerResponse.NotesResponse response = notesClient.getNotes(ssoAccount, localAccount.getModified(), localAccount.getETag());
|
final Response<List<Note>> fetchResponse = notesClient.getNotesAPI().getNotes(localAccount.getModified(), localAccount.getETag()).execute();
|
||||||
final List<Note> remoteNotes = response.getNotes();
|
if (fetchResponse.isSuccessful()) {
|
||||||
final Set<Long> remoteIDs = new HashSet<>();
|
final List<Note> remoteNotes = fetchResponse.body();
|
||||||
// pull remote changes: update or create each remote note
|
final Set<Long> remoteIDs = new HashSet<>();
|
||||||
for (Note remoteNote : remoteNotes) {
|
// pull remote changes: update or create each remote note
|
||||||
Log.v(TAG, " Process Remote Note: " + remoteNote);
|
for (Note remoteNote : remoteNotes) {
|
||||||
remoteIDs.add(remoteNote.getRemoteId());
|
Log.v(TAG, " Process Remote Note: " + remoteNote);
|
||||||
if (remoteNote.getModified() == null) {
|
remoteIDs.add(remoteNote.getRemoteId());
|
||||||
Log.v(TAG, " ... unchanged");
|
if (remoteNote.getModified() == null) {
|
||||||
} else if (idMap.containsKey(remoteNote.getRemoteId())) {
|
Log.v(TAG, " ... unchanged");
|
||||||
Log.v(TAG, " ... found → Update");
|
} else if (idMap.containsKey(remoteNote.getRemoteId())) {
|
||||||
Long localId = idMap.get(remoteNote.getRemoteId());
|
Log.v(TAG, " ... found → Update");
|
||||||
if (localId != null) {
|
Long localId = idMap.get(remoteNote.getRemoteId());
|
||||||
repo.updateIfNotModifiedLocallyAndAnyRemoteColumnHasChanged(
|
if (localId != null) {
|
||||||
localId, remoteNote.getModified().getTimeInMillis(), remoteNote.getTitle(), remoteNote.getFavorite(), remoteNote.getCategory(), remoteNote.getETag(), remoteNote.getContent(), generateNoteExcerpt(remoteNote.getContent(), remoteNote.getTitle()));
|
repo.updateIfNotModifiedLocallyAndAnyRemoteColumnHasChanged(
|
||||||
|
localId, remoteNote.getModified().getTimeInMillis(), remoteNote.getTitle(), remoteNote.getFavorite(), remoteNote.getCategory(), remoteNote.getETag(), remoteNote.getContent(), generateNoteExcerpt(remoteNote.getContent(), remoteNote.getTitle()));
|
||||||
|
} else {
|
||||||
|
Log.e(TAG, "Tried to update note from server, but local id of note is null. " + remoteNote);
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
Log.e(TAG, "Tried to update note from server, but local id of note is null. " + remoteNote);
|
Log.v(TAG, " ... create");
|
||||||
|
repo.addNote(localAccount.getId(), remoteNote);
|
||||||
}
|
}
|
||||||
} else {
|
|
||||||
Log.v(TAG, " ... create");
|
|
||||||
repo.addNote(localAccount.getId(), remoteNote);
|
|
||||||
}
|
}
|
||||||
}
|
Log.d(TAG, " Remove remotely deleted Notes (only those without local changes)");
|
||||||
Log.d(TAG, " Remove remotely deleted Notes (only those without local changes)");
|
// remove remotely deleted notes (only those without local changes)
|
||||||
// remove remotely deleted notes (only those without local changes)
|
for (Map.Entry<Long, Long> entry : idMap.entrySet()) {
|
||||||
for (Map.Entry<Long, Long> entry : idMap.entrySet()) {
|
if (!remoteIDs.contains(entry.getKey())) {
|
||||||
if (!remoteIDs.contains(entry.getKey())) {
|
Log.v(TAG, " ... remove " + entry.getValue());
|
||||||
Log.v(TAG, " ... remove " + entry.getValue());
|
repo.deleteByNoteId(entry.getValue(), DBStatus.VOID);
|
||||||
repo.deleteByNoteId(entry.getValue(), DBStatus.VOID);
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
// update ETag and Last-Modified in order to reduce size of next response
|
// update ETag and Last-Modified in order to reduce size of next response
|
||||||
localAccount.setETag(response.getETag());
|
localAccount.setETag(fetchResponse.headers().get(HEADER_KEY_ETAG));
|
||||||
localAccount.setModified(response.getLastModified());
|
|
||||||
repo.updateETag(localAccount.getId(), localAccount.getETag());
|
final Calendar lastModified = Calendar.getInstance();
|
||||||
repo.updateModified(localAccount.getId(), localAccount.getModified().getTimeInMillis());
|
lastModified.setTimeInMillis(0);
|
||||||
try {
|
final String lastModifiedHeader = fetchResponse.headers().get(HEADER_KEY_LAST_MODIFIED);
|
||||||
if (repo.updateApiVersion(localAccount.getId(), response.getSupportedApiVersions())) {
|
if (lastModifiedHeader != null)
|
||||||
localAccount.setApiVersion(response.getSupportedApiVersions());
|
lastModified.setTimeInMillis(Date.parse(lastModifiedHeader));
|
||||||
|
Log.d(TAG, "ETag: " + fetchResponse.headers().get(HEADER_KEY_ETAG) + "; Last-Modified: " + lastModified + " (" + lastModified + ")");
|
||||||
|
|
||||||
|
localAccount.setModified(lastModified);
|
||||||
|
|
||||||
|
repo.updateETag(localAccount.getId(), localAccount.getETag());
|
||||||
|
repo.updateModified(localAccount.getId(), localAccount.getModified().getTimeInMillis());
|
||||||
|
|
||||||
|
|
||||||
|
String supportedApiVersions = null;
|
||||||
|
final String supportedApiVersionsHeader = fetchResponse.headers().get(HEADER_KEY_X_NOTES_API_VERSIONS);
|
||||||
|
if (supportedApiVersionsHeader != null) {
|
||||||
|
supportedApiVersions = "[" + Objects.requireNonNull(supportedApiVersionsHeader) + "]";
|
||||||
}
|
}
|
||||||
} catch (Exception e) {
|
try {
|
||||||
exceptions.add(e);
|
if (repo.updateApiVersion(localAccount.getId(), supportedApiVersions)) {
|
||||||
|
localAccount.setApiVersion(supportedApiVersions);
|
||||||
|
}
|
||||||
|
} catch (Exception e) {
|
||||||
|
exceptions.add(e);
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
} else {
|
||||||
|
throw new Exception(fetchResponse.errorBody().string());
|
||||||
}
|
}
|
||||||
return true;
|
|
||||||
} catch (NextcloudHttpRequestFailedException e) {
|
} catch (NextcloudHttpRequestFailedException e) {
|
||||||
Log.d(TAG, "Server returned HTTP Status Code " + e.getStatusCode() + " - " + e.getMessage());
|
Log.d(TAG, "Server returned HTTP Status Code " + e.getStatusCode() + " - " + e.getMessage());
|
||||||
if (e.getStatusCode() == HTTP_NOT_MODIFIED) {
|
if (e.getStatusCode() == HTTP_NOT_MODIFIED) {
|
||||||
|
|
|
@ -9,6 +9,9 @@ import androidx.room.Ignore;
|
||||||
import androidx.room.Index;
|
import androidx.room.Index;
|
||||||
import androidx.room.PrimaryKey;
|
import androidx.room.PrimaryKey;
|
||||||
|
|
||||||
|
import com.google.gson.annotations.Expose;
|
||||||
|
import com.google.gson.annotations.SerializedName;
|
||||||
|
|
||||||
import java.io.Serializable;
|
import java.io.Serializable;
|
||||||
import java.util.Calendar;
|
import java.util.Calendar;
|
||||||
|
|
||||||
|
@ -34,31 +37,51 @@ import it.niedermann.owncloud.notes.shared.model.Item;
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
public class Note implements Serializable, Item {
|
public class Note implements Serializable, Item {
|
||||||
|
@SerializedName("localId")
|
||||||
@PrimaryKey(autoGenerate = true)
|
@PrimaryKey(autoGenerate = true)
|
||||||
private long id;
|
private long id;
|
||||||
|
|
||||||
@Nullable
|
@Nullable
|
||||||
|
@Expose
|
||||||
|
@SerializedName("id")
|
||||||
private Long remoteId;
|
private Long remoteId;
|
||||||
|
|
||||||
private long accountId;
|
private long accountId;
|
||||||
|
|
||||||
@NonNull
|
@NonNull
|
||||||
private DBStatus status = DBStatus.VOID;
|
private DBStatus status = DBStatus.VOID;
|
||||||
|
|
||||||
@NonNull
|
@NonNull
|
||||||
@ColumnInfo(defaultValue = "")
|
@ColumnInfo(defaultValue = "")
|
||||||
|
@Expose
|
||||||
private String title = "";
|
private String title = "";
|
||||||
|
|
||||||
@NonNull
|
@NonNull
|
||||||
|
@Expose
|
||||||
@ColumnInfo(defaultValue = "")
|
@ColumnInfo(defaultValue = "")
|
||||||
private String category = "";
|
private String category = "";
|
||||||
|
|
||||||
|
@Expose
|
||||||
@Nullable
|
@Nullable
|
||||||
private Calendar modified;
|
private Calendar modified;
|
||||||
|
|
||||||
@NonNull
|
@NonNull
|
||||||
@ColumnInfo(defaultValue = "")
|
@ColumnInfo(defaultValue = "")
|
||||||
|
@Expose
|
||||||
private String content = "";
|
private String content = "";
|
||||||
|
|
||||||
|
@Expose
|
||||||
@ColumnInfo(defaultValue = "0")
|
@ColumnInfo(defaultValue = "0")
|
||||||
private boolean favorite = false;
|
private boolean favorite = false;
|
||||||
|
|
||||||
|
@Expose
|
||||||
@Nullable
|
@Nullable
|
||||||
private String eTag;
|
private String eTag;
|
||||||
|
|
||||||
@NonNull
|
@NonNull
|
||||||
@ColumnInfo(defaultValue = "")
|
@ColumnInfo(defaultValue = "")
|
||||||
private String excerpt = "";
|
private String excerpt = "";
|
||||||
|
|
||||||
@ColumnInfo(defaultValue = "0")
|
@ColumnInfo(defaultValue = "0")
|
||||||
private int scrollY = 0;
|
private int scrollY = 0;
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,30 @@
|
||||||
|
package it.niedermann.owncloud.notes.persistence.sync;
|
||||||
|
|
||||||
|
import android.content.Context;
|
||||||
|
|
||||||
|
import androidx.annotation.NonNull;
|
||||||
|
|
||||||
|
import com.google.gson.GsonBuilder;
|
||||||
|
import com.nextcloud.android.sso.api.NextcloudAPI;
|
||||||
|
import com.nextcloud.android.sso.model.SingleSignOnAccount;
|
||||||
|
|
||||||
|
import retrofit2.NextcloudRetrofitApiBuilder;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Created by david on 26.05.17.
|
||||||
|
*/
|
||||||
|
public class ApiProvider {
|
||||||
|
|
||||||
|
private static final String API_ENDPOINT_NOTES = "/index.php/apps/notes/api/v1/";
|
||||||
|
|
||||||
|
private final NotesAPI notesAPI;
|
||||||
|
|
||||||
|
public ApiProvider(@NonNull Context context, @NonNull SingleSignOnAccount ssoAccount, @NonNull final NextcloudAPI.ApiConnectedListener callback) {
|
||||||
|
final NextcloudAPI nextcloudAPI = new NextcloudAPI(context, ssoAccount, new GsonBuilder().create(), callback);
|
||||||
|
notesAPI = new NextcloudRetrofitApiBuilder(nextcloudAPI, API_ENDPOINT_NOTES).create(NotesAPI.class);
|
||||||
|
}
|
||||||
|
|
||||||
|
public NotesAPI getNotesAPI() {
|
||||||
|
return notesAPI;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,34 @@
|
||||||
|
package it.niedermann.owncloud.notes.persistence.sync;
|
||||||
|
|
||||||
|
|
||||||
|
import java.util.Calendar;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import it.niedermann.owncloud.notes.persistence.entity.Note;
|
||||||
|
import retrofit2.Call;
|
||||||
|
import retrofit2.http.Body;
|
||||||
|
import retrofit2.http.DELETE;
|
||||||
|
import retrofit2.http.GET;
|
||||||
|
import retrofit2.http.POST;
|
||||||
|
import retrofit2.http.PUT;
|
||||||
|
import retrofit2.http.Path;
|
||||||
|
import retrofit2.http.Query;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @link <a href="https://deck.readthedocs.io/en/latest/API/">Deck REST API</a>
|
||||||
|
*/
|
||||||
|
public interface NotesAPI {
|
||||||
|
|
||||||
|
@GET("notes")
|
||||||
|
Call<List<Note>> getNotes(@Query("pruneBefore") Calendar lastModified, @Query("If-None-Match") String lastETag);
|
||||||
|
|
||||||
|
@POST("notes")
|
||||||
|
Call<Note> createNote(@Body Note note);
|
||||||
|
|
||||||
|
@PUT("notes/{remoteId}")
|
||||||
|
Call<Note> editNote(@Body Note note, @Path("remoteId") long remoteId);
|
||||||
|
|
||||||
|
@DELETE("notes/{remoteId}")
|
||||||
|
Call<Note> deleteNote(@Path("remoteId") long noteId);
|
||||||
|
|
||||||
|
}
|
Loading…
Reference in a new issue