Merge branch 'develop' into feature/support_tag

# Conflicts:
#	app/src/main/java/org/houxg/leamonax/ui/edit/NoteEditActivity.java
This commit is contained in:
houxg
2016-11-29 16:12:25 +08:00
11 changed files with 164 additions and 122 deletions

View File

@@ -27,6 +27,16 @@ android {
versionName "1.0.1"
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
}
lintOptions {
abortOnError false
}
packagingOptions {
exclude 'META-INF/LICENSE.txt'
exclude 'META-INF/NOTICE.txt'
}
buildTypes {
release {
minifyEnabled false
@@ -82,4 +92,6 @@ dependencies {
compile 'com.facebook.stetho:stetho:1.4.1'
compile 'com.github.houxg:FlexLayout:1.2'
compile 'com.flurry.android:analytics:6.4.2'
compile 'net.danlew:android.joda:2.9.5'
}

View File

@@ -9,6 +9,8 @@ import com.flurry.android.FlurryAgent;
import com.raizlabs.android.dbflow.config.FlowConfig;
import com.raizlabs.android.dbflow.config.FlowManager;
import net.danlew.android.joda.JodaTimeAndroid;
import org.greenrobot.eventbus.EventBus;
public class Leamonax extends Application {
@@ -33,5 +35,6 @@ public class Leamonax extends Application {
.installDefaultEventBus();
FlowManager.init(new FlowConfig.Builder(this).build());
Stetho.initializeWithDefaults(this);
JodaTimeAndroid.init(this);
}
}

View File

@@ -208,19 +208,18 @@ public class NoteService {
}, noteLocalId);
}
public static boolean updateNote(final Note modifiedNote) {
public static void updateNote(final long noteLocalId) {
Note localNote = AppDataBase.getNoteByLocalId(noteLocalId);
NoteService.updateNote(localNote);
}
private static void updateNote(final Note modifiedNote) throws IllegalStateException {
Note note;
if (modifiedNote.getUsn() == 0) {
note = RetrofitUtils.excute(addNote(modifiedNote));
note = RetrofitUtils.excuteWithException(addNote(modifiedNote));
} else {
Note remoteNote = RetrofitUtils.excute(getNoteByServerId(modifiedNote.getNoteId()));
if (remoteNote == null) {
return false;
}
note = RetrofitUtils.excute(updateNote(remoteNote, modifiedNote));
}
if (note == null) {
return false;
Note remoteNote = RetrofitUtils.excuteWithException(getNoteByServerId(modifiedNote.getNoteId()));
note = RetrofitUtils.excuteWithException(updateNote(remoteNote, modifiedNote));
}
if (note.isOk()) {
note.setId(modifiedNote.getId());
@@ -232,9 +231,8 @@ public class NoteService {
note.save();
updateUsnIfNeed(note.getUsn());
} else {
throw new IllegalArgumentException(note.getMsg());
throw new IllegalStateException(note.getMsg());
}
return true;
}
private static String convertToServerImageLinkForMD(String noteContent) {

View File

@@ -29,7 +29,6 @@ import org.greenrobot.eventbus.Subscribe;
import org.greenrobot.eventbus.ThreadMode;
import org.houxg.leamonax.R;
import org.houxg.leamonax.adapter.NotebookAdapter;
import org.houxg.leamonax.database.AppDataBase;
import org.houxg.leamonax.model.Account;
import org.houxg.leamonax.model.Note;
import org.houxg.leamonax.model.Notebook;
@@ -243,8 +242,6 @@ public class MainActivity extends BaseActivity implements NotebookAdapter.Notebo
void clickedFab() {
Account account = AccountService.getCurrent();
Note newNote = new Note();
Notebook notebook = AppDataBase.getRecentNoteBook(account.getUserId());
newNote.setNoteBookId(notebook.getNotebookId());
newNote.setUserId(account.getUserId());
newNote.setIsMarkDown(account.getDefaultEditor() == Account.EDITOR_MARKDOWN);
newNote.save();

View File

@@ -16,6 +16,7 @@ import org.houxg.leamonax.model.Note;
import org.houxg.leamonax.service.NoteService;
import org.houxg.leamonax.ui.edit.EditorFragment;
import org.houxg.leamonax.ui.edit.NoteEditActivity;
import org.houxg.leamonax.utils.DialogDisplayer;
import org.houxg.leamonax.utils.NetworkUtils;
import org.houxg.leamonax.utils.ToastUtils;
@@ -23,6 +24,7 @@ import butterknife.BindView;
import butterknife.ButterKnife;
import butterknife.OnClick;
import rx.Observable;
import rx.Observer;
import rx.Subscriber;
import rx.android.schedulers.AndroidSchedulers;
import rx.functions.Action0;
@@ -95,16 +97,14 @@ public class NotePreviewActivity extends BaseActivity implements EditorFragment.
@OnClick(R.id.tv_save)
void push() {
if (!NetworkUtils.isNetworkAvailable(this)) {
ToastUtils.showNetworkUnavailable(this);
return;
}
Observable.create(
new Observable.OnSubscribe<Boolean>() {
new Observable.OnSubscribe<Long>() {
@Override
public void call(Subscriber<? super Boolean> subscriber) {
public void call(Subscriber<? super Long> subscriber) {
if (!subscriber.isUnsubscribed()) {
subscriber.onNext(NoteService.updateNote(AppDataBase.getNoteByLocalId(mNote.getId())));
NetworkUtils.checkNetwork();
NoteService.updateNote(mNote.getId());
subscriber.onNext(mNote.getId());
subscriber.onCompleted();
}
}
@@ -114,26 +114,27 @@ public class NotePreviewActivity extends BaseActivity implements EditorFragment.
.doOnSubscribe(new Action0() {
@Override
public void call() {
showProgress(getString(R.string.saving_note));
DialogDisplayer.showProgress(NotePreviewActivity.this, R.string.saving_note);
}
})
.doOnCompleted(new Action0() {
.subscribe(new Observer<Long>() {
@Override
public void call() {
dismissProgress();
public void onCompleted() {
DialogDisplayer.dismissProgress();
}
})
.subscribe(new Action1<Boolean>() {
@Override
public void call(Boolean isSucceed) {
if (isSucceed) {
mNote = AppDataBase.getNoteByLocalId(mNote.getId());
mNote.setIsDirty(false);
mNote.save();
refresh();
} else {
ToastUtils.show(NotePreviewActivity.this, R.string.save_note_failed);
}
public void onError(Throwable e) {
DialogDisplayer.dismissProgress();
ToastUtils.show(NotePreviewActivity.this, e.getMessage());
}
@Override
public void onNext(Long aLong) {
mNote = AppDataBase.getNoteByLocalId(mNote.getId());
mNote.setIsDirty(false);
mNote.save();
refresh();
}
});
}
@@ -159,13 +160,13 @@ public class NotePreviewActivity extends BaseActivity implements EditorFragment.
.doOnSubscribe(new Action0() {
@Override
public void call() {
showProgress(getString(R.string.reverting));
DialogDisplayer.showProgress(NotePreviewActivity.this, R.string.reverting);
}
})
.doOnCompleted(new Action0() {
@Override
public void call() {
dismissProgress();
DialogDisplayer.dismissProgress();
}
})
.subscribe(new Action1<Boolean>() {
@@ -180,18 +181,6 @@ public class NotePreviewActivity extends BaseActivity implements EditorFragment.
}
private void showProgress(String message) {
dismissProgress();
mProgressDialog = ProgressDialog.show(NotePreviewActivity.this, "", message, false);
}
private void dismissProgress() {
if (mProgressDialog != null && mProgressDialog.isShowing()) {
mProgressDialog.dismiss();
mProgressDialog = null;
}
}
@Override
public Uri createImage(String filePath) {
return null;

View File

@@ -22,6 +22,7 @@ import org.houxg.leamonax.service.NoteFileService;
import org.houxg.leamonax.service.NoteService;
import org.houxg.leamonax.ui.BaseActivity;
import org.houxg.leamonax.utils.CollectionUtils;
import org.houxg.leamonax.utils.DialogDisplayer;
import org.houxg.leamonax.utils.NetworkUtils;
import org.houxg.leamonax.utils.ToastUtils;
import org.houxg.leamonax.widget.LeaViewPager;
@@ -30,10 +31,12 @@ import java.util.ArrayList;
import java.util.List;
import rx.Observable;
import rx.Observer;
import rx.Subscriber;
import rx.android.schedulers.AndroidSchedulers;
import rx.functions.Action0;
import rx.functions.Action1;
import rx.functions.Func1;
import rx.schedulers.Schedulers;
//TODO: hide action bar
@@ -107,31 +110,50 @@ public class NoteEditActivity extends BaseActivity implements EditorFragment.Edi
switch (item.getItemId()) {
case R.id.action_save:
filterUnchanged()
.doOnCompleted(new Action0() {
@Override
public void call() {
finish();
}
})
.observeOn(AndroidSchedulers.mainThread())
.subscribe(new Action1<Wrapper>() {
.doOnNext(new Action1<Wrapper>() {
@Override
public void call(Wrapper wrapper) {
saveAsDraft(wrapper);
setResult(RESULT_OK);
if (NetworkUtils.isNetworkAvailable(NoteEditActivity.this)) {
boolean isSucceed = NoteService.updateNote(AppDataBase.getNoteByLocalId(wrapper.note.getId()));
if (isSucceed) {
Note localNote = AppDataBase.getNoteByLocalId(wrapper.note.getId());
localNote.setIsDirty(false);
localNote.save();
} else {
ToastUtils.show(NoteEditActivity.this, R.string.save_note_failed);
}
} else {
ToastUtils.showNetworkUnavailable(NoteEditActivity.this);
NetworkUtils.checkNetwork();
}
})
.flatMap(new Func1<Wrapper, Observable<Long>>() {
@Override
public Observable<Long> call(Wrapper wrapper) {
return uploadToServer(wrapper.note.getId());
}
})
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.doOnSubscribe(new Action0() {
@Override
public void call() {
DialogDisplayer.showProgress(NoteEditActivity.this, R.string.saving_note);
}
})
.subscribe(new Observer<Long>() {
@Override
public void onCompleted() {
DialogDisplayer.dismissProgress();
finish();
}
@Override
public void onError(Throwable e) {
DialogDisplayer.dismissProgress();
ToastUtils.show(NoteEditActivity.this, e.getMessage());
if (e instanceof NetworkUtils.NetworkUnavailableException) {
finish();
}
}
@Override
public void onNext(Long noteLocalId) {
Note localNote = AppDataBase.getNoteByLocalId(noteLocalId);
localNote.setIsDirty(false);
localNote.save();
}
});
return true;
case R.id.action_settings:
@@ -141,6 +163,20 @@ public class NoteEditActivity extends BaseActivity implements EditorFragment.Edi
return super.onOptionsItemSelected(item);
}
private Observable<Long> uploadToServer(final long noteLocalId) {
return Observable.create(
new Observable.OnSubscribe<Long>() {
@Override
public void call(Subscriber<? super Long> subscriber) {
if (!subscriber.isUnsubscribed()) {
NoteService.updateNote(noteLocalId);
subscriber.onNext(noteLocalId);
subscriber.onCompleted();
}
}
});
}
@Override
public void onBackPressed() {
if (mPager.getCurrentItem() > FRAG_EDITOR) {

View File

@@ -0,0 +1,25 @@
package org.houxg.leamonax.utils;
import android.app.ProgressDialog;
import android.content.Context;
public class DialogDisplayer {
private static ProgressDialog mProgressDialog;
public static void showProgress(Context context, String message) {
dismissProgress();
mProgressDialog = ProgressDialog.show(context, "", message, false);
}
public static void showProgress(Context context, int messageResId) {
showProgress(context, context.getString(messageResId));
}
public static void dismissProgress() {
if (mProgressDialog != null && mProgressDialog.isShowing()) {
mProgressDialog.dismiss();
mProgressDialog = null;
}
}
}

View File

@@ -5,6 +5,9 @@ import android.content.Context;
import android.net.ConnectivityManager;
import android.net.NetworkInfo;
import org.houxg.leamonax.Leamonax;
import org.houxg.leamonax.R;
public class NetworkUtils {
private static NetworkInfo getActiveNetworkInfo(Context context) {
@@ -23,4 +26,16 @@ public class NetworkUtils {
NetworkInfo info = getActiveNetworkInfo(context);
return (info != null && info.isConnected());
}
public static void checkNetwork() throws NetworkUnavailableException {
if (!isNetworkAvailable(Leamonax.getContext())) {
throw new NetworkUnavailableException();
}
}
public static class NetworkUnavailableException extends IllegalStateException {
public NetworkUnavailableException() {
super(Leamonax.getContext().getResources().getString(R.string.network_is_unavailable));
}
}
}

View File

@@ -1,6 +1,9 @@
package org.houxg.leamonax.utils;
import org.houxg.leamonax.Leamonax;
import org.houxg.leamonax.R;
import java.io.IOException;
import retrofit2.Call;
@@ -50,10 +53,10 @@ public class RetrofitUtils {
if (response.isSuccessful()) {
return response.body();
} else {
throw new IllegalStateException("response not successful");
throw new IllegalStateException(Leamonax.getContext().getString(R.string.network_error));
}
} catch (IOException e) {
throw new IllegalStateException(e.getCause());
throw new IllegalStateException(Leamonax.getContext().getString(R.string.network_error));
}
}
}

View File

@@ -1,73 +1,32 @@
package org.houxg.leamonax.utils;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import org.joda.time.DateTime;
import org.joda.time.format.DateTimeFormat;
import java.util.Calendar;
import java.util.Date;
import java.util.Locale;
public class TimeUtils {
private static final SimpleDateFormat mServerWithMillsFormat = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSSXXX", Locale.US);
private static final SimpleDateFormat mServerFormat = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssXXX", Locale.US);
private static final SimpleDateFormat mTimeFormat = new SimpleDateFormat("H:mm:ss", Locale.US);
private static final SimpleDateFormat mDateFormat = new SimpleDateFormat("M-dd H:mm:ss", Locale.US);
private static final SimpleDateFormat mYearFormat = new SimpleDateFormat("yyyy-M-dd H:mm:ss", Locale.US);
public static final String TAG = "TimeUtils";
public static long toTimestamp(String serverTime) {
try {
serverTime = StringUtils.replace(serverTime,
"T\\d{2}:\\d{2}:\\d{2}.\\d+\\+",
"\\.\\d+",
new StringUtils.Replacer() {
@Override
public String replaceWith(String original, Object... extraData) {
String modified;
if (original.length() > 4) {
modified = original.substring(0, 4);
} else {
modified = original;
}
return modified;
}
});
serverTime = StringUtils.replace(serverTime,
"\\+\\d+:\\d+",
"\\d+:\\d+",
new StringUtils.Replacer() {
@Override
public String replaceWith(String original, Object... extraData) {
String[] vals = original.split(":");
return String.format(Locale.US, "%02d:%02d", Integer.valueOf(vals[0]), Integer.valueOf(vals[1]));
}
});
Date date = mServerWithMillsFormat.parse(serverTime);
return date.getTime();
} catch (ParseException e) {
try {
return mServerFormat.parse(serverTime).getTime();
} catch (ParseException e1) {
e.printStackTrace();
return -1;
}
}
return DateTime.parse(serverTime).getMillis();
}
public static String toServerTime(long timeInMills) {
return mServerWithMillsFormat.format(new Date(timeInMills));
return DateTimeFormat.forPattern("yyyy-MM-dd'T'HH:mm:ss.SSS'Z'").print(timeInMills);
}
public static String toTimeFormat(long timeInMills) {
return mTimeFormat.format(new Date(timeInMills));
return DateTimeFormat.forPattern("H:mm:ss").print(timeInMills);
}
public static String toDateFormat(long timeInMills) {
return mDateFormat.format(new Date(timeInMills));
return DateTimeFormat.forPattern("M-dd H:mm:ss").print(timeInMills);
}
public static String toYearFormat(long timeInMills) {
return mYearFormat.format(new Date(timeInMills));
return DateTimeFormat.forPattern("yyyy-M-dd H:mm:ss").print(timeInMills);
}
public static Calendar getToday() {

View File

@@ -12,6 +12,11 @@ android {
versionCode 7
versionName "1.2.0"
}
lintOptions {
abortOnError false
}
buildTypes {
release {
minifyEnabled false