mirror of
https://github.com/nextcloud/notes-android.git
synced 2024-11-22 04:46:04 +03:00
Fix #146: don't autosave if the note isn't modified
New feature: cancel edit; refactoring of NotesClient; send local modified time to server
This commit is contained in:
parent
a57ecfeb4c
commit
aa33b89927
7 changed files with 76 additions and 106 deletions
|
@ -24,6 +24,7 @@ import it.niedermann.owncloud.notes.util.ICallback;
|
|||
public class EditNoteActivity extends AppCompatActivity {
|
||||
|
||||
public static final String PARAM_NOTE = "note";
|
||||
public static final String PARAM_ORIGINAL_NOTE = "original_note";
|
||||
public static final String PARAM_NOTE_POSITION = "note_position";
|
||||
|
||||
private static final String LOG_TAG = "EditNote/SAVE";
|
||||
|
@ -31,7 +32,7 @@ public class EditNoteActivity extends AppCompatActivity {
|
|||
private static final long DELAY_AFTER_SYNC = 5000; // in ms
|
||||
|
||||
private EditText content = null;
|
||||
private DBNote note = null;
|
||||
private DBNote note, originalNote;
|
||||
private int notePosition = 0;
|
||||
private Timer timer, timerNextSync;
|
||||
private boolean saveActive = false;
|
||||
|
@ -44,11 +45,12 @@ public class EditNoteActivity extends AppCompatActivity {
|
|||
setContentView(R.layout.activity_edit);
|
||||
if (savedInstanceState == null) {
|
||||
Log.d(getClass().getSimpleName(), "Starting from Intent");
|
||||
note = (DBNote) getIntent().getSerializableExtra(PARAM_NOTE);
|
||||
note = originalNote = (DBNote) getIntent().getSerializableExtra(PARAM_NOTE);
|
||||
notePosition = getIntent().getIntExtra(PARAM_NOTE_POSITION, 0);
|
||||
} else {
|
||||
Log.d(getClass().getSimpleName(), "Starting from SavedState");
|
||||
note = (DBNote) savedInstanceState.getSerializable(PARAM_NOTE);
|
||||
originalNote = (DBNote) savedInstanceState.getSerializable(PARAM_ORIGINAL_NOTE);
|
||||
notePosition = savedInstanceState.getInt(PARAM_NOTE_POSITION);
|
||||
}
|
||||
content = (EditText) findViewById(R.id.editContent);
|
||||
|
@ -102,13 +104,14 @@ public class EditNoteActivity extends AppCompatActivity {
|
|||
@Override
|
||||
public void onSaveInstanceState(Bundle outState) {
|
||||
outState.putSerializable(PARAM_NOTE, note);
|
||||
outState.putSerializable(PARAM_ORIGINAL_NOTE, originalNote);
|
||||
outState.putInt(PARAM_NOTE_POSITION, notePosition);
|
||||
super.onSaveInstanceState(outState);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onBackPressed() {
|
||||
saveAndClose();
|
||||
saveAndClose(true);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -126,13 +129,17 @@ public class EditNoteActivity extends AppCompatActivity {
|
|||
*/
|
||||
@Override
|
||||
public boolean onOptionsItemSelected(MenuItem item) {
|
||||
NoteSQLiteOpenHelper db;
|
||||
switch (item.getItemId()) {
|
||||
case android.R.id.home:
|
||||
saveAndClose();
|
||||
saveAndClose(true);
|
||||
return true;
|
||||
case R.id.menu_cancel:
|
||||
Log.d(LOG_TAG, "CANCEL: changed: "+note);
|
||||
Log.d(LOG_TAG, "CANCEL: original: "+originalNote);
|
||||
note = db.updateNoteAndSync(originalNote, null, null);
|
||||
saveAndClose(false);
|
||||
return true;
|
||||
case R.id.menu_delete:
|
||||
db = new NoteSQLiteOpenHelper(this);
|
||||
db.deleteNoteAndSync(note.getId());
|
||||
Intent data = new Intent();
|
||||
data.putExtra(PARAM_NOTE_POSITION, notePosition);
|
||||
|
@ -168,7 +175,7 @@ public class EditNoteActivity extends AppCompatActivity {
|
|||
/**
|
||||
* Saves all changes and closes the Activity
|
||||
*/
|
||||
private void saveAndClose() {
|
||||
private void saveAndClose(boolean save) {
|
||||
content.setEnabled(false);
|
||||
if(timer!=null) {
|
||||
timer.cancel();
|
||||
|
@ -178,7 +185,12 @@ public class EditNoteActivity extends AppCompatActivity {
|
|||
timerNextSync.cancel();
|
||||
timerNextSync = null;
|
||||
}
|
||||
if(save) {
|
||||
Log.d(LOG_TAG, "saveAndClose with SAVE");
|
||||
saveData(null);
|
||||
} else {
|
||||
Log.d(LOG_TAG, "saveAndClose WITHOUT save");
|
||||
}
|
||||
Intent data = new Intent();
|
||||
data.setAction(Intent.ACTION_VIEW);
|
||||
data.putExtra(PARAM_NOTE, note);
|
||||
|
@ -261,6 +273,7 @@ public class EditNoteActivity extends AppCompatActivity {
|
|||
* @param callback
|
||||
*/
|
||||
private void saveData(ICallback callback) {
|
||||
Log.d(LOG_TAG, "saveData()");
|
||||
note = db.updateNoteAndSync(note, getContent(), callback);
|
||||
}
|
||||
}
|
|
@ -243,13 +243,18 @@ public class NoteSQLiteOpenHelper extends SQLiteOpenHelper {
|
|||
* The title is derived from the new content automatically, and modified date as well as DBStatus are updated, too -- if the content differs to the state in the database.
|
||||
*
|
||||
* @param oldNote Note to be changed
|
||||
* @param newContent New content
|
||||
* @param newContent New content. If this is <code>null</code>, then <code>oldNote</code> is saved again (useful for undoing changes).
|
||||
* @param callback When the synchronization is finished, this callback will be invoked (optional).
|
||||
* @return changed note if differs from database, otherwise the old note.
|
||||
*/
|
||||
public DBNote updateNoteAndSync(DBNote oldNote, String newContent, ICallback callback) {
|
||||
debugPrintFullDB();
|
||||
DBNote newNote = new DBNote(oldNote.getId(), oldNote.getRemoteId(), Calendar.getInstance(), NoteUtil.generateNoteTitle(newContent), newContent, DBStatus.LOCAL_EDITED);
|
||||
DBNote newNote;
|
||||
if(newContent==null) {
|
||||
newNote = new DBNote(oldNote.getId(), oldNote.getRemoteId(), oldNote.getModified(), oldNote.getTitle(), oldNote.getContent(), DBStatus.LOCAL_EDITED);
|
||||
} else {
|
||||
newNote = new DBNote(oldNote.getId(), oldNote.getRemoteId(), Calendar.getInstance(), NoteUtil.generateNoteTitle(newContent), newContent, DBStatus.LOCAL_EDITED);
|
||||
}
|
||||
SQLiteDatabase db = this.getWritableDatabase();
|
||||
ContentValues values = new ContentValues();
|
||||
values.put(key_status, newNote.getStatus().getTitle());
|
||||
|
|
|
@ -222,13 +222,13 @@ public class NoteServerSyncHelper {
|
|||
// if note is not new, try to edit it.
|
||||
if (note.getRemoteId()>0) {
|
||||
Log.d(getClass().getSimpleName(), " ...try to edit");
|
||||
remoteNote = client.editNote(note.getRemoteId(), note.getContent());
|
||||
remoteNote = client.editNote(note);
|
||||
}
|
||||
// However, the note may be deleted on the server meanwhile; or was never synchronized -> (re)create
|
||||
// Please note, thas dbHelper.updateNote() realizes an optimistic conflict resolution, which is required for parallel changes of this Note from the UI.
|
||||
if (remoteNote == null) {
|
||||
Log.d(getClass().getSimpleName(), " ...Note does not exist on server -> (re)create");
|
||||
remoteNote = client.createNote(note.getContent());
|
||||
remoteNote = client.createNote(note);
|
||||
dbHelper.updateNote(note.getId(), remoteNote, note);
|
||||
} else {
|
||||
dbHelper.updateNote(note.getId(), remoteNote, note);
|
||||
|
|
|
@ -41,41 +41,40 @@ public class NotesClient {
|
|||
this.password = password;
|
||||
}
|
||||
|
||||
public List<OwnCloudNote> getNotes() throws JSONException,
|
||||
IOException {
|
||||
List<OwnCloudNote> notesList = new ArrayList<>();
|
||||
JSONArray notes = new JSONArray(requestServer("notes", METHOD_GET, null));
|
||||
private OwnCloudNote getNoteFromJSON(JSONObject json) throws JSONException {
|
||||
long noteId = 0;
|
||||
String noteTitle = "";
|
||||
String noteContent = "";
|
||||
Calendar noteModified = null;
|
||||
JSONObject currentItem;
|
||||
for (int i = 0; i < notes.length(); i++) {
|
||||
currentItem = notes.getJSONObject(i);
|
||||
|
||||
if (!currentItem.isNull(key_id)) {
|
||||
noteId = currentItem.getLong(key_id);
|
||||
if (!json.isNull(key_id)) {
|
||||
noteId = json.getLong(key_id);
|
||||
}
|
||||
if (!currentItem.isNull(key_title)) {
|
||||
noteTitle = currentItem.getString(key_title);
|
||||
if (!json.isNull(key_title)) {
|
||||
noteTitle = json.getString(key_title);
|
||||
}
|
||||
if (!currentItem.isNull(key_content)) {
|
||||
noteContent = currentItem.getString(key_content);
|
||||
if (!json.isNull(key_content)) {
|
||||
noteContent = json.getString(key_content);
|
||||
}
|
||||
if (!currentItem.isNull(key_modified)) {
|
||||
if (!json.isNull(key_modified)) {
|
||||
noteModified = GregorianCalendar.getInstance();
|
||||
noteModified
|
||||
.setTimeInMillis(currentItem.getLong(key_modified) * 1000);
|
||||
.setTimeInMillis(json.getLong(key_modified) * 1000);
|
||||
}
|
||||
notesList
|
||||
.add(new OwnCloudNote(noteId, noteModified, noteTitle, noteContent));
|
||||
return new OwnCloudNote(noteId, noteModified, noteTitle, noteContent);
|
||||
}
|
||||
|
||||
public List<OwnCloudNote> getNotes() throws JSONException, IOException {
|
||||
List<OwnCloudNote> notesList = new ArrayList<>();
|
||||
JSONArray notes = new JSONArray(requestServer("notes", METHOD_GET, null));
|
||||
for (int i = 0; i < notes.length(); i++) {
|
||||
JSONObject json = notes.getJSONObject(i);
|
||||
notesList.add(getNoteFromJSON(json));
|
||||
}
|
||||
return notesList;
|
||||
}
|
||||
|
||||
/**
|
||||
* Fetches a Note by ID from Server
|
||||
* TODO Maybe fetch only id, title and modified from server until a note has been opened?
|
||||
*
|
||||
* @param id long - ID of the wanted note
|
||||
* @return Requested Note
|
||||
|
@ -83,88 +82,33 @@ public class NotesClient {
|
|||
* @throws IOException
|
||||
*/
|
||||
@SuppressWarnings("unused")
|
||||
public OwnCloudNote getNoteById(long id) throws
|
||||
JSONException, IOException {
|
||||
long noteId = 0;
|
||||
String noteTitle = "";
|
||||
String noteContent = "";
|
||||
Calendar noteModified = null;
|
||||
JSONObject currentItem = new JSONObject(
|
||||
requestServer("notes/" + id, METHOD_GET, null));
|
||||
public OwnCloudNote getNoteById(long id) throws JSONException, IOException {
|
||||
JSONObject json = new JSONObject(requestServer("notes/" + id, METHOD_GET, null));
|
||||
return getNoteFromJSON(json);
|
||||
}
|
||||
|
||||
if (!currentItem.isNull(key_id)) {
|
||||
noteId = currentItem.getLong(key_id);
|
||||
}
|
||||
if (!currentItem.isNull(key_title)) {
|
||||
noteTitle = currentItem.getString(key_title);
|
||||
}
|
||||
if (!currentItem.isNull(key_content)) {
|
||||
noteContent = currentItem.getString(key_content);
|
||||
}
|
||||
if (!currentItem.isNull(key_modified)) {
|
||||
noteModified = GregorianCalendar.getInstance();
|
||||
noteModified
|
||||
.setTimeInMillis(currentItem.getLong(key_modified) * 1000);
|
||||
}
|
||||
return new OwnCloudNote(noteId, noteModified, noteTitle, noteContent);
|
||||
private OwnCloudNote putNote(OwnCloudNote note, String path) throws JSONException, IOException {
|
||||
JSONObject paramObject = new JSONObject();
|
||||
paramObject.accumulate(key_content, note.getContent());
|
||||
paramObject.accumulate(key_modified, note.getModified().getTimeInMillis()/1000);
|
||||
JSONObject json = new JSONObject(requestServer(path, METHOD_PUT, paramObject));
|
||||
return getNoteFromJSON(json);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a Note on the Server
|
||||
*
|
||||
* @param content String - Content of the new Note
|
||||
* @param note {@link OwnCloudNote} - the new Note
|
||||
* @return Created Note including generated Title, ID and lastModified-Date
|
||||
* @throws JSONException
|
||||
* @throws IOException
|
||||
*/
|
||||
public OwnCloudNote createNote(String content) throws
|
||||
JSONException, IOException {
|
||||
long noteId = 0;
|
||||
String noteTitle = "";
|
||||
String noteContent = "";
|
||||
Calendar noteModified = null;
|
||||
|
||||
JSONObject paramObject = new JSONObject();
|
||||
paramObject.accumulate(key_content, content);
|
||||
JSONObject currentItem = new JSONObject(requestServer("notes", METHOD_POST,
|
||||
paramObject));
|
||||
|
||||
if (!currentItem.isNull(key_id)) {
|
||||
noteId = currentItem.getLong(key_id);
|
||||
}
|
||||
if (!currentItem.isNull(key_title)) {
|
||||
noteTitle = currentItem.getString(key_title);
|
||||
}
|
||||
if (!currentItem.isNull(key_content)) {
|
||||
noteContent = currentItem.getString(key_content);
|
||||
}
|
||||
if (!currentItem.isNull(key_modified)) {
|
||||
noteModified = GregorianCalendar.getInstance();
|
||||
noteModified
|
||||
.setTimeInMillis(currentItem.getLong(key_modified) * 1000);
|
||||
}
|
||||
return new OwnCloudNote(noteId, noteModified, noteTitle, noteContent);
|
||||
public OwnCloudNote createNote(OwnCloudNote note) throws JSONException, IOException {
|
||||
return putNote(note, "notes");
|
||||
}
|
||||
|
||||
public OwnCloudNote editNote(long noteId, String content)
|
||||
throws JSONException, IOException {
|
||||
String noteTitle = "";
|
||||
Calendar noteModified = null;
|
||||
|
||||
JSONObject paramObject = new JSONObject();
|
||||
paramObject.accumulate(key_content, content);
|
||||
JSONObject currentItem = new JSONObject(requestServer(
|
||||
"notes/" + noteId, METHOD_PUT, paramObject));
|
||||
|
||||
if (!currentItem.isNull(key_title)) {
|
||||
noteTitle = currentItem.getString(key_title);
|
||||
}
|
||||
if (!currentItem.isNull(key_modified)) {
|
||||
noteModified = GregorianCalendar.getInstance();
|
||||
noteModified
|
||||
.setTimeInMillis(currentItem.getLong(key_modified) * 1000);
|
||||
}
|
||||
return new OwnCloudNote(noteId, noteModified, noteTitle, content);
|
||||
public OwnCloudNote editNote(OwnCloudNote note) throws JSONException, IOException {
|
||||
return putNote(note, "notes/" + note.getRemoteId());
|
||||
}
|
||||
|
||||
public void deleteNote(long noteId) throws
|
||||
|
|
|
@ -20,6 +20,12 @@
|
|||
android:orderInCategory="110"
|
||||
app:showAsAction="never"
|
||||
android:title="@string/menu_copy"/-->
|
||||
<item
|
||||
android:id="@+id/menu_cancel"
|
||||
android:icon="@drawable/ic_action_cancel"
|
||||
android:orderInCategory="110"
|
||||
android:title="@string/menu_cancel"
|
||||
app:showAsAction="never" />
|
||||
<item
|
||||
android:id="@+id/menu_delete"
|
||||
android:icon="@drawable/ic_action_delete"
|
||||
|
|
|
@ -16,6 +16,7 @@
|
|||
<string name="menu_delete">Löschen</string>
|
||||
<string name="menu_copy">Kopieren</string>
|
||||
<string name="menu_edit">Bearbeiten</string>
|
||||
<string name="menu_cancel">Abbrechen</string>
|
||||
<string name="menu_preview">Vorschau</string>
|
||||
<string name="menu_share">Teilen</string>
|
||||
<string name="menu_about">Über</string>
|
||||
|
|
|
@ -17,6 +17,7 @@
|
|||
<string name="menu_delete">Delete</string>
|
||||
<string name="menu_copy">Copy</string>
|
||||
<string name="menu_edit">Edit</string>
|
||||
<string name="menu_cancel">Cancel</string>
|
||||
<string name="menu_preview">Preview</string>
|
||||
<string name="menu_share">Share</string>
|
||||
<string name="menu_about">About</string>
|
||||
|
|
Loading…
Reference in a new issue