mirror of
https://github.com/nextcloud/notes-android.git
synced 2024-10-25 22:26:00 +03:00
Merge Edit & Preview into one activity.
This commit is contained in:
parent
92917f0cce
commit
467d2e578b
19 changed files with 501 additions and 285 deletions
|
@ -39,12 +39,6 @@
|
|||
android:resource="@xml/shortcuts" />
|
||||
</activity>
|
||||
|
||||
<activity
|
||||
android:name="it.niedermann.owncloud.notes.android.activity.NoteActivity"
|
||||
android:label="@string/app_name"
|
||||
android:parentActivityName="it.niedermann.owncloud.notes.android.activity.EditNoteActivity"
|
||||
/>
|
||||
|
||||
<activity
|
||||
android:name="it.niedermann.owncloud.notes.android.activity.SettingsActivity"
|
||||
android:label="@string/app_name"
|
||||
|
@ -94,4 +88,4 @@
|
|||
android:resource="@xml/create_note_widget_provider" />
|
||||
</receiver>
|
||||
</application>
|
||||
</manifest>
|
||||
</manifest>
|
||||
|
|
|
@ -1,37 +1,28 @@
|
|||
package it.niedermann.owncloud.notes.android.activity;
|
||||
|
||||
import android.app.Fragment;
|
||||
import android.app.FragmentManager;
|
||||
import android.content.Intent;
|
||||
import android.content.SharedPreferences;
|
||||
import android.os.Bundle;
|
||||
import android.os.IBinder;
|
||||
import android.preference.PreferenceManager;
|
||||
import android.support.v4.content.ContextCompat;
|
||||
import android.support.v7.app.ActionBar;
|
||||
import android.support.v7.app.AppCompatActivity;
|
||||
import android.text.Editable;
|
||||
import android.text.TextWatcher;
|
||||
import android.text.format.DateUtils;
|
||||
import android.util.Log;
|
||||
import android.view.Menu;
|
||||
import android.view.MenuItem;
|
||||
import android.widget.EditText;
|
||||
import android.widget.TextView;
|
||||
|
||||
import com.yydcdut.rxmarkdown.RxMDEditText;
|
||||
import com.yydcdut.rxmarkdown.RxMarkdown;
|
||||
import com.yydcdut.rxmarkdown.factory.EditFactory;
|
||||
|
||||
import java.util.Timer;
|
||||
import java.util.TimerTask;
|
||||
import java.util.concurrent.Executors;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import android.view.inputmethod.InputMethodManager;
|
||||
|
||||
import it.niedermann.owncloud.notes.R;
|
||||
import it.niedermann.owncloud.notes.android.fragment.CategoryDialogFragment;
|
||||
import it.niedermann.owncloud.notes.android.fragment.NoteEditFragment;
|
||||
import it.niedermann.owncloud.notes.android.fragment.NoteFragmentI;
|
||||
import it.niedermann.owncloud.notes.android.fragment.NotePreviewFragment;
|
||||
import it.niedermann.owncloud.notes.model.DBNote;
|
||||
import it.niedermann.owncloud.notes.persistence.NoteSQLiteOpenHelper;
|
||||
import it.niedermann.owncloud.notes.util.ICallback;
|
||||
import it.niedermann.owncloud.notes.util.MarkDownUtil;
|
||||
import rx.Subscriber;
|
||||
|
||||
public class EditNoteActivity extends AppCompatActivity implements CategoryDialogFragment.CategoryDialogListener {
|
||||
public class EditNoteActivity extends AppCompatActivity {
|
||||
|
||||
public static final String PARAM_NOTE = "note";
|
||||
public static final String PARAM_ORIGINAL_NOTE = "original_note";
|
||||
|
@ -41,18 +32,16 @@ public class EditNoteActivity extends AppCompatActivity implements CategoryDialo
|
|||
private static final long DELAY = 2000; // in ms
|
||||
private static final long DELAY_AFTER_SYNC = 5000; // in ms
|
||||
|
||||
private RxMDEditText content = null;
|
||||
private DBNote note, originalNote;
|
||||
private DBNote originalNote;
|
||||
private int notePosition = 0;
|
||||
private Timer timer, timerNextSync;
|
||||
private boolean saveActive = false;
|
||||
private ActionBar actionBar;
|
||||
private NoteSQLiteOpenHelper db;
|
||||
private NoteFragmentI fragment;
|
||||
|
||||
@Override
|
||||
protected void onCreate(final Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
setContentView(R.layout.activity_edit);
|
||||
DBNote note = null;
|
||||
|
||||
if (savedInstanceState == null) {
|
||||
Log.d(getClass().getSimpleName(), "Starting from Intent");
|
||||
note = originalNote = (DBNote) getIntent().getSerializableExtra(PARAM_NOTE);
|
||||
|
@ -63,75 +52,55 @@ public class EditNoteActivity extends AppCompatActivity implements CategoryDialo
|
|||
originalNote = (DBNote) savedInstanceState.getSerializable(PARAM_ORIGINAL_NOTE);
|
||||
notePosition = savedInstanceState.getInt(PARAM_NOTE_POSITION);
|
||||
}
|
||||
content = (RxMDEditText) findViewById(R.id.editContent);
|
||||
content.setText(note.getContent());
|
||||
content.setEnabled(true);
|
||||
|
||||
RxMarkdown.live(content)
|
||||
.config(MarkDownUtil.getMarkDownConfiguration(getApplicationContext()))
|
||||
.factory(EditFactory.create())
|
||||
.intoObservable()
|
||||
.subscribe(new Subscriber<CharSequence>() {
|
||||
@Override
|
||||
public void onCompleted() {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onError(Throwable e) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onNext(CharSequence charSequence) {
|
||||
content.setText(charSequence, TextView.BufferType.SPANNABLE);
|
||||
}
|
||||
});
|
||||
|
||||
db = NoteSQLiteOpenHelper.getInstance(this);
|
||||
actionBar = getSupportActionBar();
|
||||
|
||||
SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(getApplicationContext());
|
||||
String mode = preferences.getString("noteMode", "edit");
|
||||
String lastMode = preferences.getString("noteLastMode", "edit");
|
||||
if ("preview".equals(mode)) {
|
||||
createPreviewFragment(note);
|
||||
} else if (mode.equals("last") && "preview".equals(lastMode)) {
|
||||
createPreviewFragment(note);
|
||||
/* TODO enhancement: store last mode in note
|
||||
for cross device functionality per note mode should be stored on the server.
|
||||
} else if(mode.equals("note") && "preview".equals(note.getMode())) {
|
||||
createPreviewFragment(note);
|
||||
*/
|
||||
} else {
|
||||
createEditFragment(note);
|
||||
}
|
||||
}
|
||||
|
||||
private void createEditFragment(DBNote note) {
|
||||
configureActionBar(note, false);
|
||||
fragment = NoteEditFragment.newInstance(note);
|
||||
getFragmentManager().beginTransaction().replace(android.R.id.content, (Fragment) fragment).commit();
|
||||
}
|
||||
|
||||
private void createPreviewFragment(DBNote note) {
|
||||
configureActionBar(note, true);
|
||||
fragment = NotePreviewFragment.newInstance(note);
|
||||
getFragmentManager().beginTransaction().replace(android.R.id.content, (Fragment) fragment).commit();
|
||||
}
|
||||
|
||||
private void configureActionBar(DBNote note, boolean timestamp) {
|
||||
ActionBar actionBar = getSupportActionBar();
|
||||
if (actionBar != null) {
|
||||
actionBar.setTitle(note.getTitle());
|
||||
actionBar.setSubtitle(getString(R.string.action_edit_editing));
|
||||
if (timestamp) {
|
||||
actionBar.setSubtitle(DateUtils.getRelativeDateTimeString(getApplicationContext(), note.getModified().getTimeInMillis(), DateUtils.MINUTE_IN_MILLIS, DateUtils.WEEK_IN_MILLIS, 0));
|
||||
} else {
|
||||
actionBar.setSubtitle(getString(R.string.action_edit_editing));
|
||||
}
|
||||
|
||||
actionBar.setDisplayHomeAsUpEnabled(true);
|
||||
}
|
||||
content.addTextChangedListener(new TextWatcher() {
|
||||
@Override
|
||||
public void beforeTextChanged(CharSequence s, int start, int count, int after) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onTextChanged(final CharSequence s, int start, int before, int count) {
|
||||
if (timer != null) {
|
||||
timer.cancel();
|
||||
timer = null;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void afterTextChanged(final Editable s) {
|
||||
if(timer != null) {
|
||||
timer.cancel();
|
||||
}
|
||||
if(!saveActive) {
|
||||
timer = new Timer();
|
||||
timer.schedule(new TimerTask() {
|
||||
@Override
|
||||
public void run() {
|
||||
runOnUiThread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
autoSave();
|
||||
}
|
||||
});
|
||||
}
|
||||
}, DELAY);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onSaveInstanceState(Bundle outState) {
|
||||
outState.putSerializable(PARAM_NOTE, note);
|
||||
outState.putSerializable(PARAM_NOTE, fragment.getNote());
|
||||
outState.putSerializable(PARAM_ORIGINAL_NOTE, originalNote);
|
||||
outState.putInt(PARAM_NOTE_POSITION, notePosition);
|
||||
super.onSaveInstanceState(outState);
|
||||
|
@ -139,7 +108,7 @@ public class EditNoteActivity extends AppCompatActivity implements CategoryDialo
|
|||
|
||||
@Override
|
||||
public void onBackPressed() {
|
||||
saveAndClose(true);
|
||||
close(fragment.getNote());
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -155,11 +124,16 @@ public class EditNoteActivity extends AppCompatActivity implements CategoryDialo
|
|||
@Override
|
||||
public boolean onPrepareOptionsMenu(Menu menu) {
|
||||
MenuItem itemFavorite = menu.findItem(R.id.menu_favorite);
|
||||
itemFavorite.setIcon(note.isFavorite() ? R.drawable.ic_star_white_24dp : R.drawable.ic_star_outline_white_24dp);
|
||||
itemFavorite.setChecked(note.isFavorite());
|
||||
prepareFavoriteOption(itemFavorite);
|
||||
return super.onPrepareOptionsMenu(menu);
|
||||
}
|
||||
|
||||
private void prepareFavoriteOption(MenuItem item) {
|
||||
DBNote note = fragment.getNote();
|
||||
item.setIcon(note.isFavorite() ? R.drawable.ic_star_white_24dp : R.drawable.ic_star_outline_white_24dp);
|
||||
item.setChecked(note.isFavorite());
|
||||
}
|
||||
|
||||
/**
|
||||
* Main-Menu-Handler
|
||||
*/
|
||||
|
@ -167,38 +141,36 @@ public class EditNoteActivity extends AppCompatActivity implements CategoryDialo
|
|||
public boolean onOptionsItemSelected(MenuItem item) {
|
||||
switch (item.getItemId()) {
|
||||
case android.R.id.home:
|
||||
saveAndClose(true);
|
||||
close(fragment.getNote());
|
||||
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);
|
||||
Log.d(LOG_TAG, "CANCEL: original: " + originalNote);
|
||||
db.updateNoteAndSync(originalNote, null, null);
|
||||
close(originalNote);
|
||||
return true;
|
||||
case R.id.menu_delete:
|
||||
db.deleteNoteAndSync(note.getId());
|
||||
db.deleteNoteAndSync(originalNote.getId());
|
||||
Intent data = new Intent();
|
||||
data.putExtra(PARAM_NOTE_POSITION, notePosition);
|
||||
setResult(RESULT_FIRST_USER, data);
|
||||
finish();
|
||||
return true;
|
||||
case R.id.menu_favorite:
|
||||
db.toggleFavorite(note, null);
|
||||
invalidateOptionsMenu();
|
||||
return true;
|
||||
case R.id.menu_category:
|
||||
showCategorySelector();
|
||||
db.toggleFavorite(fragment.getNote(), null);
|
||||
prepareFavoriteOption(item);
|
||||
return true;
|
||||
case R.id.menu_preview:
|
||||
saveData(null);
|
||||
Intent previewIntent = new Intent(getApplicationContext(), NoteActivity.class);
|
||||
previewIntent.putExtra(NoteActivity.PARAM_NOTE, note);
|
||||
startActivity(previewIntent);
|
||||
if (fragment instanceof NoteEditFragment) {
|
||||
createPreviewFragment(fragment.getNote());
|
||||
} else {
|
||||
createEditFragment(fragment.getNote());
|
||||
}
|
||||
return true;
|
||||
case R.id.menu_share:
|
||||
Intent shareIntent = new Intent();
|
||||
shareIntent.setAction(Intent.ACTION_SEND);
|
||||
shareIntent.setType("text/plain");
|
||||
DBNote note = fragment.getNote();
|
||||
shareIntent.putExtra(android.content.Intent.EXTRA_SUBJECT, note.getTitle());
|
||||
shareIntent.putExtra(android.content.Intent.EXTRA_TEXT, note.getContent());
|
||||
startActivity(shareIntent);
|
||||
|
@ -216,47 +188,19 @@ public class EditNoteActivity extends AppCompatActivity implements CategoryDialo
|
|||
}
|
||||
|
||||
/**
|
||||
* Opens a dialog in order to chose a category
|
||||
* Send result and closes the Activity
|
||||
*/
|
||||
private void showCategorySelector() {
|
||||
final String fragmentId = "fragment_category";
|
||||
FragmentManager manager = getFragmentManager();
|
||||
Fragment frag = manager.findFragmentByTag(fragmentId);
|
||||
if(frag!=null) {
|
||||
manager.beginTransaction().remove(frag).commit();
|
||||
}
|
||||
Bundle arguments = new Bundle();
|
||||
arguments.putString(CategoryDialogFragment.PARAM_CATEGORY, note.getCategory());
|
||||
CategoryDialogFragment categoryFragment = new CategoryDialogFragment();
|
||||
categoryFragment.setArguments(arguments);
|
||||
categoryFragment.show(manager, fragmentId);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCategoryChosen(String category) {
|
||||
note.setCategory(category);
|
||||
autoSave();
|
||||
}
|
||||
|
||||
/**
|
||||
* Saves all changes and closes the Activity
|
||||
*/
|
||||
private void saveAndClose(boolean save) {
|
||||
content.setEnabled(false);
|
||||
if(timer!=null) {
|
||||
timer.cancel();
|
||||
timer = null;
|
||||
}
|
||||
if(timerNextSync!=null) {
|
||||
timerNextSync.cancel();
|
||||
timerNextSync = null;
|
||||
}
|
||||
if(save) {
|
||||
Log.d(LOG_TAG, "saveAndClose with SAVE");
|
||||
saveData(null);
|
||||
private void close(DBNote note) {
|
||||
/* TODO enhancement: store last mode in note
|
||||
* for cross device functionality per note mode should be stored on the server.
|
||||
*/
|
||||
SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(getApplicationContext());
|
||||
if (fragment instanceof NoteEditFragment) {
|
||||
preferences.edit().putString("noteLastMode", "edit").commit();
|
||||
} else {
|
||||
Log.d(LOG_TAG, "saveAndClose WITHOUT save");
|
||||
preferences.edit().putString("noteLastMode", "preview").commit();
|
||||
}
|
||||
|
||||
Intent data = new Intent();
|
||||
data.setAction(Intent.ACTION_VIEW);
|
||||
data.putExtra(PARAM_NOTE, note);
|
||||
|
@ -264,83 +208,4 @@ public class EditNoteActivity extends AppCompatActivity implements CategoryDialo
|
|||
setResult(RESULT_OK, data);
|
||||
finish();
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the current content of the EditText field in the UI.
|
||||
* @return String of the current content.
|
||||
*/
|
||||
private String getContent() {
|
||||
return ((EditText) findViewById(R.id.editContent)).getText().toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* Saves the current changes and show the status in the ActionBar
|
||||
*/
|
||||
private void autoSave() {
|
||||
Log.d(LOG_TAG, "START save+sync");
|
||||
saveActive = true;
|
||||
if (actionBar != null) {
|
||||
actionBar.setSubtitle(getString(R.string.action_edit_saving));
|
||||
}
|
||||
final String content = getContent();
|
||||
saveData(new ICallback() {
|
||||
@Override
|
||||
public void onFinish() {
|
||||
onSaved();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onScheduled() {
|
||||
onSaved();
|
||||
}
|
||||
|
||||
public void onSaved() {
|
||||
// AFTER SYNCHRONIZATION
|
||||
Log.d(LOG_TAG, "...sync finished");
|
||||
actionBar.setTitle(note.getTitle());
|
||||
actionBar.setSubtitle(getResources().getString(R.string.action_edit_saved));
|
||||
Executors.newSingleThreadScheduledExecutor().schedule(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
runOnUiThread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
// AFTER 1 SECOND: set ActionBar to default title
|
||||
actionBar.setSubtitle(getString(R.string.action_edit_editing));
|
||||
}
|
||||
});
|
||||
}
|
||||
}, 1, TimeUnit.SECONDS);
|
||||
|
||||
timerNextSync = new Timer();
|
||||
timerNextSync.schedule(new TimerTask() {
|
||||
@Override
|
||||
public void run() {
|
||||
runOnUiThread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
// AFTER "DELAY_AFTER_SYNC" SECONDS: allow next auto-save or start it directly
|
||||
if(getContent().equals(content)) {
|
||||
saveActive = false;
|
||||
Log.d(LOG_TAG, "FINISH, no new changes");
|
||||
} else {
|
||||
Log.d(LOG_TAG, "content has changed meanwhile -> restart save");
|
||||
autoSave();
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
}, DELAY_AFTER_SYNC);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Save the current state in the database and schedule synchronization if needed.
|
||||
* @param callback
|
||||
*/
|
||||
private void saveData(ICallback callback) {
|
||||
Log.d(LOG_TAG, "saveData()");
|
||||
note = db.updateNoteAndSync(note, getContent(), callback);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -3,6 +3,7 @@ package it.niedermann.owncloud.notes.android.fragment;
|
|||
import android.app.AlertDialog;
|
||||
import android.app.Dialog;
|
||||
import android.app.DialogFragment;
|
||||
import android.app.Fragment;
|
||||
import android.content.DialogInterface;
|
||||
import android.os.Bundle;
|
||||
import android.view.View;
|
||||
|
@ -12,6 +13,7 @@ import it.niedermann.owncloud.notes.R;
|
|||
|
||||
/**
|
||||
* This {@link DialogFragment} allows for the selection of a category.
|
||||
* It targetFragment is set it must implement the interface {@link CategoryDialogListener}.
|
||||
* The calling Activity must implement the interface {@link CategoryDialogListener}.
|
||||
*/
|
||||
public class CategoryDialogFragment extends DialogFragment {
|
||||
|
@ -46,7 +48,13 @@ public class CategoryDialogFragment extends DialogFragment {
|
|||
.setPositiveButton(R.string.action_edit_save, new DialogInterface.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(DialogInterface dialog, int which) {
|
||||
CategoryDialogListener listener = (CategoryDialogListener) getActivity();
|
||||
CategoryDialogListener listener;
|
||||
Fragment target = getTargetFragment();
|
||||
if(target != null && target instanceof CategoryDialogListener) {
|
||||
listener = (CategoryDialogListener) target;
|
||||
} else {
|
||||
listener = (CategoryDialogListener) getActivity();
|
||||
}
|
||||
listener.onCategoryChosen(textCategory.getText().toString());
|
||||
}
|
||||
})
|
||||
|
|
|
@ -0,0 +1,293 @@
|
|||
package it.niedermann.owncloud.notes.android.fragment;
|
||||
|
||||
import android.app.Fragment;
|
||||
import android.app.FragmentManager;
|
||||
import android.os.Bundle;
|
||||
import android.support.annotation.Nullable;
|
||||
import android.support.v4.content.ContextCompat;
|
||||
import android.support.v7.app.ActionBar;
|
||||
import android.support.v7.app.AppCompatActivity;
|
||||
import android.text.Editable;
|
||||
import android.text.TextWatcher;
|
||||
import android.util.Log;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.Menu;
|
||||
import android.view.MenuItem;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.EditText;
|
||||
import android.widget.TextView;
|
||||
|
||||
import com.yydcdut.rxmarkdown.RxMDEditText;
|
||||
import com.yydcdut.rxmarkdown.RxMarkdown;
|
||||
import com.yydcdut.rxmarkdown.factory.EditFactory;
|
||||
|
||||
import java.util.Timer;
|
||||
import java.util.TimerTask;
|
||||
import java.util.concurrent.Executors;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import it.niedermann.owncloud.notes.R;
|
||||
import it.niedermann.owncloud.notes.model.DBNote;
|
||||
import it.niedermann.owncloud.notes.persistence.NoteSQLiteOpenHelper;
|
||||
import it.niedermann.owncloud.notes.util.ICallback;
|
||||
import it.niedermann.owncloud.notes.util.MarkDownUtil;
|
||||
import rx.Subscriber;
|
||||
|
||||
public class NoteEditFragment extends Fragment implements NoteFragmentI, CategoryDialogFragment.CategoryDialogListener {
|
||||
|
||||
public static final String PARAM_NOTE = "note";
|
||||
|
||||
private static final String LOG_TAG = "NoteEditFragment";
|
||||
private static final long DELAY = 2000; // in ms
|
||||
private static final long DELAY_AFTER_SYNC = 5000; // in ms
|
||||
|
||||
private DBNote note;
|
||||
private Timer timer, timerNextSync;
|
||||
private boolean saveActive = false;
|
||||
private NoteSQLiteOpenHelper db;
|
||||
|
||||
public static NoteEditFragment newInstance(DBNote note) {
|
||||
NoteEditFragment f = new NoteEditFragment();
|
||||
Bundle b = new Bundle();
|
||||
b.putSerializable(PARAM_NOTE, note);
|
||||
f.setArguments(b);
|
||||
return f;
|
||||
}
|
||||
|
||||
public DBNote getNote() {
|
||||
saveData(null);
|
||||
return note;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCreate(@Nullable Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
setHasOptionsMenu(true);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPrepareOptionsMenu(Menu menu) {
|
||||
super.onPrepareOptionsMenu(menu);
|
||||
MenuItem itemPreview = menu.findItem(R.id.menu_preview);
|
||||
itemPreview.setIcon(ContextCompat.getDrawable(getActivity(), R.drawable.ic_eye_white_24dp));
|
||||
MenuItem itemCategory = menu.findItem(R.id.menu_category);
|
||||
itemCategory.setVisible(true);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onOptionsItemSelected(MenuItem item) {
|
||||
switch (item.getItemId()) {
|
||||
case R.id.menu_category:
|
||||
showCategorySelector();
|
||||
return true;
|
||||
default:
|
||||
return super.onOptionsItemSelected(item);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Opens a dialog in order to chose a category
|
||||
*/
|
||||
private void showCategorySelector() {
|
||||
final String fragmentId = "fragment_category";
|
||||
FragmentManager manager = getFragmentManager();
|
||||
Fragment frag = manager.findFragmentByTag(fragmentId);
|
||||
if(frag!=null) {
|
||||
manager.beginTransaction().remove(frag).commit();
|
||||
}
|
||||
Bundle arguments = new Bundle();
|
||||
arguments.putString(CategoryDialogFragment.PARAM_CATEGORY, note.getCategory());
|
||||
CategoryDialogFragment categoryFragment = new CategoryDialogFragment();
|
||||
categoryFragment.setTargetFragment(this, 1);
|
||||
categoryFragment.setArguments(arguments);
|
||||
categoryFragment.show(manager, fragmentId);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCategoryChosen(String category) {
|
||||
note.setCategory(category);
|
||||
autoSave();
|
||||
}
|
||||
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, Bundle savedInstanceState) {
|
||||
return inflater.inflate(R.layout.activity_edit, container, false);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onActivityCreated(@Nullable Bundle savedInstanceState) {
|
||||
super.onActivityCreated(savedInstanceState);
|
||||
|
||||
note = (DBNote) getArguments().getSerializable(PARAM_NOTE);
|
||||
db = NoteSQLiteOpenHelper.getInstance(getActivity());
|
||||
|
||||
final RxMDEditText content = getContentView();
|
||||
content.setText(note.getContent());
|
||||
content.setEnabled(true);
|
||||
|
||||
RxMarkdown.live(content)
|
||||
.config(MarkDownUtil.getMarkDownConfiguration(getActivity().getApplicationContext()))
|
||||
.factory(EditFactory.create())
|
||||
.intoObservable()
|
||||
.subscribe(new Subscriber<CharSequence>() {
|
||||
@Override
|
||||
public void onCompleted() {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onError(Throwable e) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onNext(CharSequence charSequence) {
|
||||
content.setText(charSequence, TextView.BufferType.SPANNABLE);
|
||||
}
|
||||
});
|
||||
|
||||
content.addTextChangedListener(new TextWatcher() {
|
||||
@Override
|
||||
public void beforeTextChanged(CharSequence s, int start, int count, int after) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onTextChanged(final CharSequence s, int start, int before, int count) {
|
||||
if (timer != null) {
|
||||
timer.cancel();
|
||||
timer = null;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void afterTextChanged(final Editable s) {
|
||||
if(timer != null) {
|
||||
timer.cancel();
|
||||
}
|
||||
if(!saveActive) {
|
||||
timer = new Timer();
|
||||
timer.schedule(new TimerTask() {
|
||||
@Override
|
||||
public void run() {
|
||||
getActivity().runOnUiThread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
autoSave();
|
||||
}
|
||||
});
|
||||
}
|
||||
}, DELAY);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPause() {
|
||||
super.onPause();
|
||||
if (timer != null) {
|
||||
timer.cancel();
|
||||
timer = null;
|
||||
}
|
||||
if (timerNextSync != null) {
|
||||
timerNextSync.cancel();
|
||||
timerNextSync = null;
|
||||
}
|
||||
}
|
||||
|
||||
private RxMDEditText getContentView() {
|
||||
return (RxMDEditText) getActivity().findViewById(R.id.editContent);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the current content of the EditText field in the UI.
|
||||
*
|
||||
* @return String of the current content.
|
||||
*/
|
||||
private String getContent() {
|
||||
return ((EditText) getContentView()).getText().toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* Saves the current changes and show the status in the ActionBar
|
||||
*/
|
||||
private void autoSave() {
|
||||
Log.d(LOG_TAG, "START save+sync");
|
||||
final ActionBar actionBar = ((AppCompatActivity) getActivity()).getSupportActionBar();
|
||||
saveActive = true;
|
||||
if (actionBar != null) {
|
||||
actionBar.setSubtitle(getString(R.string.action_edit_saving));
|
||||
}
|
||||
final String content = getContent();
|
||||
saveData(new ICallback() {
|
||||
@Override
|
||||
public void onFinish() {
|
||||
onSaved();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onScheduled() {
|
||||
onSaved();
|
||||
}
|
||||
|
||||
public void onSaved() {
|
||||
// AFTER SYNCHRONIZATION
|
||||
Log.d(LOG_TAG, "...sync finished");
|
||||
if (getActivity() != null && actionBar != null) {
|
||||
actionBar.setTitle(note.getTitle());
|
||||
actionBar.setSubtitle(getResources().getString(R.string.action_edit_saved));
|
||||
Executors.newSingleThreadScheduledExecutor().schedule(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
if (getActivity() != null) {
|
||||
getActivity().runOnUiThread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
// AFTER 1 SECOND: set ActionBar to default title
|
||||
if (getActivity() != null && actionBar != null)
|
||||
actionBar.setSubtitle(getString(R.string.action_edit_editing));
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
}, 1, TimeUnit.SECONDS);
|
||||
|
||||
timerNextSync = new Timer();
|
||||
timerNextSync.schedule(new TimerTask() {
|
||||
@Override
|
||||
public void run() {
|
||||
if (getActivity() != null) {
|
||||
getActivity().runOnUiThread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
// AFTER "DELAY_AFTER_SYNC" SECONDS: allow next auto-save or start it directly
|
||||
if (getContent().equals(content)) {
|
||||
saveActive = false;
|
||||
Log.d(LOG_TAG, "FINISH, no new changes");
|
||||
} else {
|
||||
Log.d(LOG_TAG, "content has changed meanwhile -> restart save");
|
||||
autoSave();
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
}, DELAY_AFTER_SYNC);
|
||||
}
|
||||
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Save the current state in the database and schedule synchronization if needed.
|
||||
*
|
||||
* @param callback
|
||||
*/
|
||||
private void saveData(ICallback callback) {
|
||||
Log.d(LOG_TAG, "saveData()");
|
||||
note = db.updateNoteAndSync(note, getContent(), callback);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,7 @@
|
|||
package it.niedermann.owncloud.notes.android.fragment;
|
||||
|
||||
import it.niedermann.owncloud.notes.model.DBNote;
|
||||
|
||||
public interface NoteFragmentI {
|
||||
public DBNote getNote();
|
||||
}
|
|
@ -1,13 +1,17 @@
|
|||
package it.niedermann.owncloud.notes.android.activity;
|
||||
package it.niedermann.owncloud.notes.android.fragment;
|
||||
|
||||
import android.app.Fragment;
|
||||
import android.os.Bundle;
|
||||
import android.support.v7.app.ActionBar;
|
||||
import android.support.v7.app.AppCompatActivity;
|
||||
import android.text.format.DateUtils;
|
||||
import android.support.annotation.Nullable;
|
||||
import android.support.v4.content.ContextCompat;
|
||||
import android.text.method.LinkMovementMethod;
|
||||
import android.util.Log;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.Menu;
|
||||
import android.view.MenuItem;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.view.WindowManager;
|
||||
import android.widget.TextView;
|
||||
|
||||
import com.yydcdut.rxmarkdown.RxMDTextView;
|
||||
|
@ -15,33 +19,61 @@ import com.yydcdut.rxmarkdown.RxMarkdown;
|
|||
import com.yydcdut.rxmarkdown.factory.TextFactory;
|
||||
|
||||
import it.niedermann.owncloud.notes.R;
|
||||
import it.niedermann.owncloud.notes.android.activity.EditNoteActivity;
|
||||
import it.niedermann.owncloud.notes.model.DBNote;
|
||||
import it.niedermann.owncloud.notes.util.MarkDownUtil;
|
||||
import rx.Subscriber;
|
||||
import rx.android.schedulers.AndroidSchedulers;
|
||||
import rx.schedulers.Schedulers;
|
||||
|
||||
public class NoteActivity extends AppCompatActivity {
|
||||
public class NotePreviewFragment extends Fragment implements NoteFragmentI {
|
||||
|
||||
public static final String PARAM_NOTE = EditNoteActivity.PARAM_NOTE;
|
||||
|
||||
private DBNote note = null;
|
||||
private RxMDTextView noteContent = null;
|
||||
|
||||
public static NotePreviewFragment newInstance(DBNote note) {
|
||||
NotePreviewFragment f = new NotePreviewFragment();
|
||||
Bundle b = new Bundle();
|
||||
b.putSerializable(PARAM_NOTE, note);
|
||||
f.setArguments(b);
|
||||
return f;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onCreate(Bundle savedInstanceState) {
|
||||
public DBNote getNote() {
|
||||
return note;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCreate(@Nullable Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
setContentView(R.layout.activity_single_note);
|
||||
note = (DBNote) getIntent().getSerializableExtra(PARAM_NOTE);
|
||||
if (savedInstanceState != null) {
|
||||
note = (DBNote) savedInstanceState.getSerializable(PARAM_NOTE);
|
||||
}
|
||||
ActionBar actionBar = getSupportActionBar();
|
||||
if (actionBar != null) {
|
||||
actionBar.setTitle(note.getTitle());
|
||||
actionBar.setSubtitle(DateUtils.getRelativeDateTimeString(getApplicationContext(), note.getModified().getTimeInMillis(), DateUtils.MINUTE_IN_MILLIS, DateUtils.WEEK_IN_MILLIS, 0));
|
||||
}
|
||||
noteContent = (RxMDTextView) findViewById(R.id.single_note_content);
|
||||
setHasOptionsMenu(true);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPrepareOptionsMenu(Menu menu) {
|
||||
super.onPrepareOptionsMenu(menu);
|
||||
MenuItem itemPreview = menu.findItem(R.id.menu_preview);
|
||||
itemPreview.setIcon(ContextCompat.getDrawable(getActivity(), R.drawable.ic_action_edit_24dp));
|
||||
MenuItem itemCategory = menu.findItem(R.id.menu_category);
|
||||
itemCategory.setVisible(false);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
|
||||
return inflater.inflate(R.layout.activity_single_note, container, false);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onActivityCreated(@Nullable Bundle savedInstanceState) {
|
||||
super.onActivityCreated(savedInstanceState);
|
||||
|
||||
getActivity().getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_HIDDEN);
|
||||
|
||||
note = (DBNote) getArguments().getSerializable(PARAM_NOTE);
|
||||
final RxMDTextView noteContent = (RxMDTextView) getActivity().findViewById(R.id.single_note_content);
|
||||
|
||||
String content = note.getContent();
|
||||
/*
|
||||
|
@ -58,8 +90,8 @@ public class NoteActivity extends AppCompatActivity {
|
|||
*/
|
||||
content = content.replaceAll("(?<![(])(https?://[-a-zA-Z0-9+&@#/%?=~_|!:,.;]*[-a-zA-Z0-9+&@#/%=~_|])(?![^\\[]*\\])", "[$1]($1)");
|
||||
|
||||
RxMarkdown.with(content, this)
|
||||
.config(MarkDownUtil.getMarkDownConfiguration(getApplicationContext()))
|
||||
RxMarkdown.with(content, getActivity())
|
||||
.config(MarkDownUtil.getMarkDownConfiguration(getActivity().getApplicationContext()))
|
||||
.factory(TextFactory.create())
|
||||
.intoObservable()
|
||||
.subscribeOn(Schedulers.computation())
|
||||
|
@ -80,24 +112,7 @@ public class NoteActivity extends AppCompatActivity {
|
|||
}
|
||||
});
|
||||
noteContent.setText(content);
|
||||
findViewById(R.id.fab_edit).setVisibility(View.GONE);
|
||||
((TextView) findViewById(R.id.single_note_content)).setMovementMethod(LinkMovementMethod.getInstance());
|
||||
((TextView) getActivity().findViewById(R.id.single_note_content)).setMovementMethod(LinkMovementMethod.getInstance());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onSaveInstanceState(Bundle outState) {
|
||||
outState.putSerializable(PARAM_NOTE, note);
|
||||
super.onSaveInstanceState(outState);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onOptionsItemSelected(MenuItem item) {
|
||||
switch (item.getItemId()) {
|
||||
case android.R.id.home:
|
||||
finish();
|
||||
return true;
|
||||
default:
|
||||
return super.onOptionsItemSelected(item);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -180,4 +180,4 @@ public class NotesClient {
|
|||
// return these header fields since they should only be saved after successful processing the result!
|
||||
return new ResponseData(result.toString(), etag, lastModified);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
BIN
app/src/main/res/drawable-hdpi/ic_action_edit_24dp.png
Normal file
BIN
app/src/main/res/drawable-hdpi/ic_action_edit_24dp.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 339 B |
BIN
app/src/main/res/drawable-xhdpi/ic_action_edit_24dp.png
Normal file
BIN
app/src/main/res/drawable-xhdpi/ic_action_edit_24dp.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 239 B |
BIN
app/src/main/res/drawable-xxhdpi/ic_action_edit_24dp.png
Normal file
BIN
app/src/main/res/drawable-xxhdpi/ic_action_edit_24dp.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 302 B |
BIN
app/src/main/res/drawable-xxxhdpi/ic_action_edit_24dp.png
Normal file
BIN
app/src/main/res/drawable-xxxhdpi/ic_action_edit_24dp.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 355 B |
|
@ -1,9 +1,12 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<merge xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:id="@+id/editContentContainer"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:orientation="vertical">
|
||||
android:orientation="vertical"
|
||||
tools:context="it.niedermann.owncloud.notes.android.activity.CreateNoteActivity">
|
||||
|
||||
|
||||
<ScrollView
|
||||
android:layout_width="match_parent"
|
||||
|
@ -19,10 +22,5 @@
|
|||
android:textIsSelectable="true" />
|
||||
</ScrollView>
|
||||
|
||||
<android.support.design.widget.FloatingActionButton
|
||||
android:id="@+id/fab_edit"
|
||||
style="@style/fab"
|
||||
android:src="@drawable/ic_action_edit"
|
||||
app:backgroundTint="@color/primary"
|
||||
app:rippleColor="@color/primary_dark" />
|
||||
</merge>
|
||||
|
||||
</LinearLayout>
|
|
@ -1,17 +1,17 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<menu xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto">
|
||||
<item
|
||||
android:id="@+id/menu_category"
|
||||
android:orderInCategory="40"
|
||||
android:title="@string/menu_change_category"
|
||||
app:showAsAction="ifRoom" />
|
||||
<item
|
||||
android:id="@+id/menu_favorite"
|
||||
android:orderInCategory="50"
|
||||
android:title="@string/menu_favorite"
|
||||
android:checkable="true"
|
||||
app:showAsAction="ifRoom" />
|
||||
<item
|
||||
android:id="@+id/menu_category"
|
||||
android:orderInCategory="60"
|
||||
android:title="@string/menu_change_category"
|
||||
app:showAsAction="ifRoom" />
|
||||
<item
|
||||
android:id="@+id/menu_preview"
|
||||
android:icon="@drawable/ic_eye_white_24dp"
|
||||
|
|
|
@ -46,6 +46,7 @@
|
|||
<string name="settings_password_check_description">Zeigt an, ob die angegebenen Zugangsdaten korrekt sind.</string>
|
||||
<string name="settings_submit">Verbinden</string>
|
||||
<string name="settings_submitting">Verbindet…</string>
|
||||
<string name="settings_view_category">Darstellung</string>
|
||||
<string name="settings_notification_category">Benachrichtigung</string>
|
||||
<string name="settings_notification">Aktivieren, um eine dauerhafte Benachrichtigung zur schnellen Eingabe von Notizen anzuzeigen.</string>
|
||||
<string name="settings_cert_category">Zertifikate</string>
|
||||
|
|
8
app/src/main/res/values-de/arrays.xml
Normal file
8
app/src/main/res/values-de/arrays.xml
Normal file
|
@ -0,0 +1,8 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources>
|
||||
<string-array name="noteMode_entries">
|
||||
<item>Immer zum Bearbeiten öffnen</item>
|
||||
<item>Immer Vorschau öffnen</item>
|
||||
<item>Letzte Einstellung merken</item>
|
||||
</string-array>
|
||||
</resources>
|
|
@ -46,6 +46,8 @@
|
|||
<string name="settings_password_check_description">Zeigt an, ob die angegebenen Zugangsdaten korrekt sind.</string>
|
||||
<string name="settings_submit">Verbinden</string>
|
||||
<string name="settings_submitting">Verbindet…</string>
|
||||
<string name="settings_view_category">Darstellung</string>
|
||||
<string name="settings_note_mode">Darstellung der Notizen beim Öffnen</string>
|
||||
<string name="settings_notification_category">Benachrichtigung</string>
|
||||
<string name="settings_notification">Aktivieren um eine dauerhafte Benachrichtigung zur schnellen Eingabe von Notizen anzuzeigen.</string>
|
||||
<string name="settings_cert_category">Zertifikate</string>
|
||||
|
|
13
app/src/main/res/values/arrays.xml
Normal file
13
app/src/main/res/values/arrays.xml
Normal file
|
@ -0,0 +1,13 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources>
|
||||
<string-array name="noteMode_values">
|
||||
<item>edit</item>
|
||||
<item>preview</item>
|
||||
<item>last</item>
|
||||
</string-array>
|
||||
<string-array name="noteMode_entries">
|
||||
<item>Always open notes in Edit mode</item>
|
||||
<item>Always open notes in Preview mode</item>
|
||||
<item>Remember my last selection</item>
|
||||
</string-array>
|
||||
</resources>
|
|
@ -49,6 +49,8 @@
|
|||
<string name="settings_password_check_description">Shows if the credentials are correct.</string>
|
||||
<string name="settings_submit">Connect</string>
|
||||
<string name="settings_submitting">Connecting …</string>
|
||||
<string name="settings_view_category">View Settings</string>
|
||||
<string name="settings_note_mode">How should notes be opened</string>
|
||||
<string name="settings_notification_category">Notification</string>
|
||||
<string name="settings_notification">Enable to show a persistant notification for quickly creating new notes.</string>
|
||||
<string name="settings_cert_category">Certificates</string>
|
||||
|
@ -123,4 +125,4 @@
|
|||
<item quantity="one">%d selected</item>
|
||||
<item quantity="other">%d selected</item>
|
||||
</plurals>
|
||||
</resources>
|
||||
</resources>
|
||||
|
|
|
@ -16,6 +16,16 @@
|
|||
android:title="@string/settings_notification" />
|
||||
</PreferenceCategory>
|
||||
|
||||
<PreferenceCategory android:title="@string/settings_view_category">
|
||||
<ListPreference
|
||||
android:defaultValue="edit"
|
||||
android:key="noteMode"
|
||||
android:title="@string/settings_note_mode"
|
||||
android:summary="%s"
|
||||
android:entries="@array/noteMode_entries"
|
||||
android:entryValues="@array/noteMode_values" />
|
||||
</PreferenceCategory>
|
||||
|
||||
<PreferenceCategory android:title="@string/settings_cert_category">
|
||||
<CheckBoxPreference
|
||||
android:defaultValue="true"
|
||||
|
@ -25,4 +35,4 @@
|
|||
android:key="resetTrust"
|
||||
android:title="@string/settings_cert_reset" />
|
||||
</PreferenceCategory>
|
||||
</PreferenceScreen>
|
||||
</PreferenceScreen>
|
||||
|
|
Loading…
Reference in a new issue