服务器备份与恢复

master
fengyuecanzhu 3 years ago
parent 59f950915a
commit 973d6552ce
  1. 4
      .idea/misc.xml
  2. 75
      app/src/main/java/xyz/fycz/myreader/model/storage/Backup.kt
  3. 79
      app/src/main/java/xyz/fycz/myreader/model/user/UserService2.kt
  4. 9
      app/src/main/java/xyz/fycz/myreader/ui/activity/LoginActivity.java
  5. 10
      app/src/main/java/xyz/fycz/myreader/ui/activity/RegisterActivity.java
  6. 172
      app/src/main/java/xyz/fycz/myreader/ui/fragment/MineFragment.java
  7. 59
      app/src/main/java/xyz/fycz/myreader/ui/presenter/BookcasePresenter.java
  8. 2
      app/src/main/java/xyz/fycz/myreader/util/help/JsExtensions.java
  9. 13
      app/src/main/java/xyz/fycz/myreader/util/utils/OkHttpUtils.java
  10. 26
      app/src/main/res/drawable/ic_restore.xml
  11. 2
      app/src/main/res/drawable/login_btn_selector.xml
  12. 67
      app/src/main/res/layout/fragment_mine.xml

@ -4,7 +4,9 @@
<option name="filePathToZoomLevelMap">
<map>
<entry key="..\:/android/FYReader/app/src/main/res/drawable/ic_delete.xml" value="0.18518518518518517" />
<entry key="..\:/android/FYReader/app/src/main/res/drawable/ic_online_syn.xml" value="0.19074074074074074" />
<entry key="..\:/android/FYReader/app/src/main/res/drawable/ic_re_seg.xml" value="0.1962962962962963" />
<entry key="..\:/android/FYReader/app/src/main/res/drawable/ic_restore.xml" value="0.19074074074074074" />
<entry key="..\:/android/FYReader/app/src/main/res/drawable/ic_search_word.xml" value="0.21944444444444444" />
<entry key="..\:/android/FYReader/app/src/main/res/drawable/login_btn_selector.xml" value="0.17777777777777778" />
<entry key="..\:/android/FYReader/app/src/main/res/drawable/selector_btn_add.xml" value="0.17777777777777778" />
@ -27,7 +29,7 @@
<entry key="..\:/android/FYReader/app/src/main/res/layout/fragment_file_category.xml" value="0.2318840579710145" />
<entry key="..\:/android/FYReader/app/src/main/res/layout/fragment_find_book_2.xml" value="0.12132725430597771" />
<entry key="..\:/android/FYReader/app/src/main/res/layout/fragment_local_source.xml" value="0.1947463768115942" />
<entry key="..\:/android/FYReader/app/src/main/res/layout/fragment_mine.xml" value="0.176" />
<entry key="..\:/android/FYReader/app/src/main/res/layout/fragment_mine.xml" value="0.37037037037037035" />
<entry key="..\:/android/FYReader/app/src/main/res/layout/fragment_private_bookcase.xml" value="0.21195652173913043" />
<entry key="..\:/android/FYReader/app/src/main/res/layout/fragment_webdav_setting.xml" value="0.4" />
<entry key="..\:/android/FYReader/app/src/main/res/layout/gridview_book_detailed_item.xml" value="0.1947463768115942" />

@ -33,17 +33,17 @@ object Backup {
val backupFileNames by lazy {
arrayOf(
"myBooks.json",
"mySearchHistory.json",
"myBookMark.json",
"myBookGroup.json",
"setting.json",
"readStyles.json",
"replaceRule.json",
"bookSource.json",
"readRecord.json",
"searchWord.json",
"config.xml"
"myBooks.json",
"mySearchHistory.json",
"myBookMark.json",
"myBookGroup.json",
"setting.json",
"readStyles.json",
"replaceRule.json",
"bookSource.json",
"readRecord.json",
"searchWord.json",
"config.xml"
)
}
@ -61,8 +61,27 @@ object Backup {
}
fun backup(context: Context, path: String, callBack: CallBack?, isAuto: Boolean = false) {
backup(context, path, isAuto).subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(object : MySingleObserver<Boolean>() {
override fun onSuccess(t: Boolean) {
callBack?.backupSuccess()
}
override fun onError(e: Throwable) {
e.printStackTrace()
callBack?.backupError(e.localizedMessage ?: "ERROR")
}
})
}
fun backup(
context: Context,
path: String,
isAuto: Boolean = false
): Single<Boolean> {
SharedPreUtils.getInstance().putLong("lastBackup", System.currentTimeMillis())
Single.create(SingleOnSubscribe<Boolean> { e ->
return Single.create { e ->
BookService.getInstance().allBooks.let {
if (it.isNotEmpty()) {
val json = GSON.toJson(it)
@ -73,35 +92,35 @@ object Backup {
if (it.isNotEmpty()) {
val json = GSON.toJson(it)
FileUtils.getFile(backupPath + File.separator + "mySearchHistory.json")
.writeText(json)
.writeText(json)
}
}
DbManager.getInstance().session.bookMarkDao.queryBuilder().list().let {
if (it.isNotEmpty()) {
val json = GSON.toJson(it)
FileUtils.getFile(backupPath + File.separator + "myBookMark.json")
.writeText(json)
.writeText(json)
}
}
DbManager.getInstance().session.bookGroupDao.queryBuilder().list().let {
if (it.isNotEmpty()) {
val json = GSON.toJson(it)
FileUtils.getFile(backupPath + File.separator + "myBookGroup.json")
.writeText(json)
.writeText(json)
}
}
DbManager.getInstance().session.replaceRuleBeanDao.queryBuilder().list().let {
if (it.isNotEmpty()) {
val json = GSON.toJson(it)
FileUtils.getFile(backupPath + File.separator + "replaceRule.json")
.writeText(json)
.writeText(json)
}
}
DbManager.getInstance().session.bookSourceDao.queryBuilder().list().let {
if (it.isNotEmpty()) {
val json = GSON.toJson(it)
FileUtils.getFile(backupPath + File.separator + "bookSource.json")
.writeText(json)
.writeText(json)
}
}
DbManager.getInstance().session.readRecordDao.queryBuilder().list().let {
@ -125,9 +144,9 @@ object Backup {
setting.readStyles = null
val settingJson = GSON.toJson(setting)
FileUtils.getFile(backupPath + File.separator + "setting.json")
.writeText(settingJson)
.writeText(settingJson)
FileUtils.getFile(backupPath + File.separator + "readStyles.json")
.writeText(readStylesJson)
.writeText(readStylesJson)
} catch (e: Exception) {
e.printStackTrace()
}
@ -153,18 +172,7 @@ object Backup {
copyBackup(path, isAuto)
}
e.onSuccess(true)
}).subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(object : MySingleObserver<Boolean>() {
override fun onSuccess(t: Boolean) {
callBack?.backupSuccess()
}
override fun onError(e: Throwable) {
e.printStackTrace()
callBack?.backupError(e.localizedMessage ?: "ERROR")
}
})
}
}
@Throws(Exception::class)
@ -202,7 +210,10 @@ object Backup {
if (isAuto) {
val file = File(backupPath + File.separator + fileName)
if (file.exists()) {
file.copyTo(FileUtils.getFile(path + File.separator + "auto" + File.separator + fileName), true)
file.copyTo(
FileUtils.getFile(path + File.separator + "auto" + File.separator + fileName),
true
)
}
} else {
val file = File(backupPath + File.separator + fileName)

@ -1,12 +1,16 @@
package xyz.fycz.myreader.model.user
import io.reactivex.ObservableSource
import io.reactivex.Single
import io.reactivex.SingleOnSubscribe
import io.reactivex.SingleSource
import io.reactivex.functions.Function
import okhttp3.MediaType
import okhttp3.RequestBody
import xyz.fycz.myreader.application.App
import xyz.fycz.myreader.common.APPCONST
import xyz.fycz.myreader.common.URLCONST
import xyz.fycz.myreader.entity.StrResponse
import xyz.fycz.myreader.model.storage.Backup
import xyz.fycz.myreader.model.storage.Restore
import xyz.fycz.myreader.model.storage.Restore.restore
@ -15,6 +19,7 @@ import xyz.fycz.myreader.util.utils.FileUtils
import xyz.fycz.myreader.util.utils.GSON
import xyz.fycz.myreader.util.utils.OkHttpUtils
import xyz.fycz.myreader.util.utils.RxUtils
import java.io.File
/**
* @author fengyue
@ -91,46 +96,48 @@ object UserService2 {
}
fun webBackup(user: User): Single<Result> {
return Single.create(SingleOnSubscribe<Result> {
Backup.backup(App.getmContext(), APPCONST.FILE_DIR + "webBackup/",
object : Backup.CallBack {
override fun backupSuccess() {
val inputFile = FileUtils.getFile(APPCONST.FILE_DIR + "webBackup")
val zipFile = FileUtils.getFile(APPCONST.FILE_DIR + "webBackup.zip")
//压缩文件
ZipUtils.zipFile(inputFile, zipFile)
val ret = OkHttpUtils.upload(
URLCONST.USER_URL + "/do/bak?" +
"username=${user.userName}" +
makeAuth(),
zipFile.absolutePath,
zipFile.name
)
zipFile.delete()
it.onSuccess(GSON.fromJson(ret, Result::class.java))
}
override fun backupError(msg: String) {
it.onError(Throwable(msg))
}
})
}).compose { RxUtils.toSimpleSingle(it) }
return Backup.backup(App.getmContext(), APPCONST.FILE_DIR + "webBackup/")
.flatMap(Function<Boolean, SingleSource<Result>> {
Single.create {
val inputFile = FileUtils.getFile(APPCONST.FILE_DIR + "webBackup")
val zipFile = FileUtils.getFile(APPCONST.FILE_DIR + "webBackup.zip")
//压缩文件
ZipUtils.zipFile(inputFile, zipFile)
FileUtils.deleteFile(zipFile.absolutePath)
val ret = OkHttpUtils.upload(
URLCONST.USER_URL + "/do/bak?" +
"username=${user.userName}" +
makeAuth(),
zipFile.absolutePath,
zipFile.name
)
zipFile.delete()
it.onSuccess(GSON.fromJson(ret, Result::class.java))
}
}).compose { RxUtils.toSimpleSingle(it) }
}
fun webRestore(user: User): Single<Result> {
return Single.create(SingleOnSubscribe<Result> {
val zipFile = FileUtils.getFile(APPCONST.FILE_DIR + "webBackup.zip")
val mediaType = MediaType.parse("application/x-www-form-urlencoded")
val body = "username=${user.userName}" +
makeAuth()
val requestBody = RequestBody.create(mediaType, body)
val input = OkHttpUtils.getInputStream(
URLCONST.USER_URL + "/do/ret?" +
"username=${user.userName}" +
makeAuth()
URLCONST.USER_URL + "/do/ret", requestBody
)
if (FileUtils.writeFile(input.readBytes(), zipFile)) {
val bytes = input.readBytes()
if (bytes.size < 50) {
it.onError(Throwable(String(bytes)))
return@SingleOnSubscribe
}
if (FileUtils.writeFile(bytes, zipFile)) {
ZipUtils.unzipFile(zipFile.absolutePath, APPCONST.FILE_DIR)
zipFile.delete()
restore(APPCONST.FILE_DIR + "webBackup/", object : Restore.CallBack {
override fun restoreSuccess() {
zipFile.delete()
FileUtils.deleteFile(zipFile.absolutePath)
it.onSuccess(Result(100, "成功从网络同步到本地"))
}
@ -162,10 +169,20 @@ object UserService2 {
return FileUtils.readText(APPCONST.QQ_DATA_DIR + "user")
}
/**
* 判断是否登录
* @return
*/
fun isLogin(): Boolean {
val file = App.getApplication().getFileStreamPath("userConfig.fy")
return file.exists()
}
private fun makeAuth(): String {
return "&signal=" + AppInfoUtils.getSingInfo(
App.getmContext(),
App.getApplication().packageName, AppInfoUtils.SHA1
App.getApplication().packageName,
AppInfoUtils.SHA1
) + "&appVersion=" + App.getVersionCode()
}
}

@ -1,12 +1,9 @@
package xyz.fycz.myreader.ui.activity;
import android.annotation.SuppressLint;
import android.app.Activity;
import android.content.Intent;
import android.graphics.Bitmap;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.text.Editable;
import android.text.TextWatcher;
import android.view.MotionEvent;
@ -17,9 +14,6 @@ import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.appcompat.widget.Toolbar;
import java.util.HashMap;
import java.util.Map;
import io.reactivex.disposables.Disposable;
import xyz.fycz.myreader.R;
import xyz.fycz.myreader.base.BaseActivity;
@ -29,7 +23,6 @@ import xyz.fycz.myreader.common.APPCONST;
import xyz.fycz.myreader.databinding.ActivityLoginBinding;
import xyz.fycz.myreader.model.user.Result;
import xyz.fycz.myreader.model.user.User;
import xyz.fycz.myreader.model.user.UserService;
import xyz.fycz.myreader.model.user.UserService2;
import xyz.fycz.myreader.ui.dialog.DialogCreator;
import xyz.fycz.myreader.ui.dialog.LoadingDialog;
@ -37,9 +30,7 @@ import xyz.fycz.myreader.util.CodeUtil;
import xyz.fycz.myreader.util.CyptoUtils;
import xyz.fycz.myreader.util.ToastUtils;
import xyz.fycz.myreader.util.utils.NetworkUtils;
import xyz.fycz.myreader.util.utils.ProgressUtils;
import xyz.fycz.myreader.util.utils.StringUtils;
import xyz.fycz.myreader.webapi.ResultCallback;
/**
* @author fengyue

@ -1,21 +1,14 @@
package xyz.fycz.myreader.ui.activity;
import android.annotation.SuppressLint;
import android.graphics.Bitmap;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.text.Editable;
import android.text.TextWatcher;
import android.text.method.LinkMovementMethod;
import android.view.View;
import androidx.annotation.NonNull;
import androidx.appcompat.widget.Toolbar;
import java.util.HashMap;
import java.util.Map;
import io.reactivex.disposables.Disposable;
import xyz.fycz.myreader.R;
import xyz.fycz.myreader.application.App;
@ -26,16 +19,13 @@ import xyz.fycz.myreader.common.APPCONST;
import xyz.fycz.myreader.databinding.ActivityRegisterBinding;
import xyz.fycz.myreader.model.user.Result;
import xyz.fycz.myreader.model.user.User;
import xyz.fycz.myreader.model.user.UserService;
import xyz.fycz.myreader.model.user.UserService2;
import xyz.fycz.myreader.ui.dialog.DialogCreator;
import xyz.fycz.myreader.ui.dialog.LoadingDialog;
import xyz.fycz.myreader.util.CodeUtil;
import xyz.fycz.myreader.util.CyptoUtils;
import xyz.fycz.myreader.util.ToastUtils;
import xyz.fycz.myreader.util.utils.ProgressUtils;
import xyz.fycz.myreader.util.utils.StringUtils;
import xyz.fycz.myreader.webapi.ResultCallback;
/**
* @author fengyue

@ -1,5 +1,7 @@
package xyz.fycz.myreader.ui.fragment;
import static android.app.Activity.RESULT_OK;
import android.annotation.SuppressLint;
import android.content.Intent;
import android.os.Bundle;
@ -37,12 +39,11 @@ import xyz.fycz.myreader.databinding.FragmentMineBinding;
import xyz.fycz.myreader.entity.Setting;
import xyz.fycz.myreader.greendao.entity.Book;
import xyz.fycz.myreader.greendao.service.BookService;
import xyz.fycz.myreader.model.user.Result;
import xyz.fycz.myreader.model.user.User;
import xyz.fycz.myreader.model.user.UserService;
import xyz.fycz.myreader.model.storage.BackupRestoreUi;
import xyz.fycz.myreader.model.storage.Restore;
import xyz.fycz.myreader.model.storage.WebDavHelp;
import xyz.fycz.myreader.model.user.Result;
import xyz.fycz.myreader.model.user.User;
import xyz.fycz.myreader.model.user.UserService2;
import xyz.fycz.myreader.ui.activity.AboutActivity;
import xyz.fycz.myreader.ui.activity.AdSettingActivity;
@ -55,13 +56,9 @@ import xyz.fycz.myreader.ui.activity.MoreSettingActivity;
import xyz.fycz.myreader.ui.activity.ReadRecordActivity;
import xyz.fycz.myreader.ui.dialog.DialogCreator;
import xyz.fycz.myreader.ui.dialog.LoadingDialog;
import xyz.fycz.myreader.ui.dialog.MyAlertDialog;
import xyz.fycz.myreader.util.SharedPreUtils;
import xyz.fycz.myreader.util.ToastUtils;
import xyz.fycz.myreader.util.utils.NetworkUtils;
import xyz.fycz.myreader.webapi.ResultCallback;
import static android.app.Activity.RESULT_OK;
/**
* @author fengyue
@ -164,6 +161,70 @@ public class MineFragment extends BaseFragment {
getActivity().startActivityForResult(intent, APPCONST.REQUEST_LOGIN);
}
});
binding.mineRlSyn.setOnClickListener(v -> {
if (!isLogin) {
ToastUtils.showWarring("请先登录!");
Intent loginIntent = new Intent(getActivity(), LoginActivity.class);
getActivity().startActivityForResult(loginIntent, APPCONST.REQUEST_LOGIN);
return;
}
if (mSetting.isAutoSyn()) {
webSynMenu[2] = App.getmContext().getString(R.string.menu_backup_autoSyn) + "已开启";
} else {
webSynMenu[2] = App.getmContext().getString(R.string.menu_backup_autoSyn) + "已关闭";
}
/*MyAlertDialog.build(getContext())
.setTitle(getActivity().getString(R.string.menu_bookcase_syn))
.setItems(webSynMenu, (dialog, which) -> {
switch (which) {
case 0:
synBookcaseToWeb(false);
break;
case 1:
webRestore();
break;
case 2:
String tip = "";
if (mSetting.isAutoSyn()) {
mSetting.setAutoSyn(false);
tip = "每日自动同步已关闭!";
} else {
mSetting.setAutoSyn(true);
tip = "每日自动同步已开启!";
}
SysManager.saveSetting(mSetting);
ToastUtils.showSuccess(tip);
break;
}
})
.setNegativeButton(null, null)
.setPositiveButton(null, null)
.show();*/
BottomMenu.show("同步书架", webSynMenu)
.setOnMenuItemClickListener((dialog1, text, which) -> {
switch (which) {
case 0:
synBookcaseToWeb(false);
break;
case 1:
webRestore();
break;
case 2:
String tip = "";
if (mSetting.isAutoSyn()) {
mSetting.setAutoSyn(false);
tip = "每日自动同步已关闭!";
} else {
mSetting.setAutoSyn(true);
tip = "每日自动同步已开启!";
}
SysManager.saveSetting(mSetting);
ToastUtils.showSuccess(tip);
break;
}
return false;
}).setCancelButton(R.string.cancel);
});
binding.mineRlWebdav.setOnClickListener(v -> {
Intent intent = new Intent(getActivity(), MoreSettingActivity.class);
@ -171,7 +232,7 @@ public class MineFragment extends BaseFragment {
startActivity(intent);
});
/*binding.mineRlSyn.setOnClickListener(v -> {
binding.mineRlSynWebdav.setOnClickListener(v -> {
String account = SharedPreUtils.getInstance().getString("webdavAccount");
String password = SharedPreUtils.getInstance().getString("webdavPassword");
if (TextUtils.isEmpty(account) || TextUtils.isEmpty(password)) {
@ -212,7 +273,7 @@ public class MineFragment extends BaseFragment {
}
}
});
});*/
});
binding.mineRlBookSource.setOnClickListener(v -> {
startActivity(new Intent(getContext(), BookSourceActivity.class));
});
@ -247,46 +308,6 @@ public class MineFragment extends BaseFragment {
return false;
}).setCancelButton(R.string.cancel);
});
binding.mineRlSyn.setOnClickListener(v -> {
if (!isLogin) {
ToastUtils.showWarring("请先登录!");
Intent loginIntent = new Intent(getActivity(), LoginActivity.class);
getActivity().startActivityForResult(loginIntent, APPCONST.REQUEST_LOGIN);
return;
}
if (mSetting.isAutoSyn()) {
webSynMenu[2] = App.getmContext().getString(R.string.menu_backup_autoSyn) + "已开启";
} else {
webSynMenu[2] = App.getmContext().getString(R.string.menu_backup_autoSyn) + "已关闭";
}
MyAlertDialog.build(getContext())
.setTitle(getActivity().getString(R.string.menu_bookcase_syn))
.setItems(webSynMenu, (dialog, which) -> {
switch (which) {
case 0:
synBookcaseToWeb(false);
break;
case 1:
webRestore();
break;
case 2:
String tip = "";
if (mSetting.isAutoSyn()) {
mSetting.setAutoSyn(false);
tip = "每日自动同步已关闭!";
} else {
mSetting.setAutoSyn(true);
tip = "每日自动同步已开启!";
}
SysManager.saveSetting(mSetting);
ToastUtils.showSuccess(tip);
break;
}
})
.setNegativeButton(null, null)
.setPositiveButton(null, null)
.show();
});
binding.mineRlReadRecord.setOnClickListener(v -> {
startActivity(new Intent(getContext(), ReadRecordActivity.class));
@ -524,7 +545,6 @@ public class MineFragment extends BaseFragment {
DialogCreator.createCommonDialog(getContext(), "确认同步吗?", "将书架从网络同步至本地会覆盖原有书架!", true,
(dialogInterface, i) -> {
dialogInterface.dismiss();
App.getApplication().newThread(() -> {
/*if (UserService.webRestore()) {
mHandler.sendMessage(mHandler.obtainMessage(7));
// DialogCreator.createTipDialog(mMainActivity,
@ -534,38 +554,38 @@ public class MineFragment extends BaseFragment {
} else {
DialogCreator.createTipDialog(getContext(), "未找到同步文件,同步失败!");
}*/
dialog.show();
UserService2.INSTANCE.webRestore(user).subscribe(new MySingleObserver<Result>() {
@Override
public void onSubscribe(Disposable d) {
addDisposable(d);
disp = d;
}
dialog.show();
UserService2.INSTANCE.webRestore(user).subscribe(new MySingleObserver<Result>() {
@Override
public void onSubscribe(Disposable d) {
addDisposable(d);
disp = d;
}
@Override
public void onSuccess(@NonNull Result result) {
if (result.getCode() < 200) {
mHandler.sendMessage(mHandler.obtainMessage(7));
@Override
public void onSuccess(@NonNull Result result) {
if (result.getCode() < 200) {
mHandler.sendMessage(mHandler.obtainMessage(7));
// DialogCreator.createTipDialog(mMainActivity,
// "恢复成功!\n注意:本功能属于实验功能,书架恢复后,书籍初次加载时可能加载失败,返回重新加载即可!");、
SysManager.regetmSetting();
ToastUtils.showSuccess("成功将书架从网络同步至本地!");
if (getActivity() != null) {
getActivity().finish();
}
startActivity(new Intent(getContext(), MainActivity.class));
} else {
DialogCreator.createTipDialog(getContext(), "未找到同步文件,同步失败!");
SysManager.regetmSetting();
ToastUtils.showSuccess("成功将书架从网络同步至本地!");
if (getActivity() != null) {
getActivity().finish();
}
dialog.dismiss();
startActivity(new Intent(getContext(), MainActivity.class));
} else {
DialogCreator.createTipDialog(getContext(), "未找到同步文件,同步失败!");
}
dialog.dismiss();
}
@Override
public void onError(Throwable e) {
DialogCreator.createTipDialog(getContext(), "未找到同步文件,同步失败!\n" + e.getLocalizedMessage());
DialogCreator.createTipDialog(getContext(), "未找到同步文件,同步失败!\n" + e.getLocalizedMessage());
}
});
@Override
public void onError(Throwable e) {
if (App.isDebug()) e.printStackTrace();
DialogCreator.createTipDialog(getContext(), "未找到同步文件,同步失败!\n" + e.getLocalizedMessage());
dialog.dismiss();
}
});
}, (dialogInterface, i) -> dialogInterface.dismiss());
}

@ -1,19 +1,23 @@
package xyz.fycz.myreader.ui.presenter;
import static xyz.fycz.myreader.application.App.checkVersionByServer;
import android.Manifest;
import android.annotation.SuppressLint;
import android.app.Notification;
import android.app.PendingIntent;
import android.content.*;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.graphics.BitmapFactory;
import android.os.Handler;
import android.os.Message;
import android.view.Gravity;
import android.view.MenuItem;
import android.view.View;
import android.widget.PopupMenu;
import androidx.annotation.NonNull;
import androidx.recyclerview.widget.GridLayoutManager;
import androidx.recyclerview.widget.ItemTouchHelper;
import androidx.recyclerview.widget.LinearLayoutManager;
@ -41,35 +45,38 @@ import xyz.fycz.myreader.application.App;
import xyz.fycz.myreader.application.SysManager;
import xyz.fycz.myreader.base.BasePresenter;
import xyz.fycz.myreader.base.observer.MyObserver;
import xyz.fycz.myreader.ui.adapter.helper.ItemTouchCallback;
import xyz.fycz.myreader.ui.dialog.BookGroupDialog;
import xyz.fycz.myreader.util.help.StringHelper;
import xyz.fycz.myreader.util.utils.RxUtils;
import xyz.fycz.myreader.webapi.ResultCallback;
import xyz.fycz.myreader.base.observer.MySingleObserver;
import xyz.fycz.myreader.common.APPCONST;
import xyz.fycz.myreader.greendao.entity.BookGroup;
import xyz.fycz.myreader.greendao.service.BookGroupService;
import xyz.fycz.myreader.model.user.UserService;
import xyz.fycz.myreader.ui.activity.*;
import xyz.fycz.myreader.webapi.crawler.base.ReadCrawler;
import xyz.fycz.myreader.webapi.crawler.ReadCrawlerUtil;
import xyz.fycz.myreader.ui.dialog.DialogCreator;
import xyz.fycz.myreader.entity.Setting;
import xyz.fycz.myreader.enums.BookcaseStyle;
import xyz.fycz.myreader.greendao.entity.Book;
import xyz.fycz.myreader.greendao.entity.BookGroup;
import xyz.fycz.myreader.greendao.entity.Chapter;
import xyz.fycz.myreader.greendao.service.BookGroupService;
import xyz.fycz.myreader.greendao.service.BookService;
import xyz.fycz.myreader.greendao.service.ChapterService;
import xyz.fycz.myreader.model.user.Result;
import xyz.fycz.myreader.model.user.UserService2;
import xyz.fycz.myreader.ui.activity.FileSystemActivity;
import xyz.fycz.myreader.ui.activity.GroupManagerActivity;
import xyz.fycz.myreader.ui.activity.MainActivity;
import xyz.fycz.myreader.ui.activity.SearchBookActivity;
import xyz.fycz.myreader.ui.adapter.BookcaseAdapter;
import xyz.fycz.myreader.ui.adapter.BookcaseDetailedAdapter;
import xyz.fycz.myreader.ui.adapter.BookcaseDragAdapter;
import xyz.fycz.myreader.ui.adapter.helper.ItemTouchCallback;
import xyz.fycz.myreader.ui.dialog.BookGroupDialog;
import xyz.fycz.myreader.ui.dialog.DialogCreator;
import xyz.fycz.myreader.ui.fragment.BookcaseFragment;
import xyz.fycz.myreader.util.*;
import xyz.fycz.myreader.util.SharedPreUtils;
import xyz.fycz.myreader.util.ToastUtils;
import xyz.fycz.myreader.util.help.StringHelper;
import xyz.fycz.myreader.util.notification.NotificationUtil;
import xyz.fycz.myreader.util.utils.NetworkUtils;
import xyz.fycz.myreader.util.utils.RxUtils;
import xyz.fycz.myreader.webapi.BookApi;
import static xyz.fycz.myreader.application.App.checkVersionByServer;
import xyz.fycz.myreader.webapi.crawler.ReadCrawlerUtil;
import xyz.fycz.myreader.webapi.crawler.base.ReadCrawler;
public class BookcasePresenter implements BasePresenter {
@ -168,9 +175,9 @@ public class BookcasePresenter implements BasePresenter {
getData();
/*if (mSetting.isAutoSyn() && UserService.isLogin()) {
if (mSetting.isAutoSyn() && UserService2.INSTANCE.isLogin()) {
synBookcaseToWeb(true);
}*/
}
//设置是否启用内容视图拖动效果
mBookcaseFragment.getSrlContent().setEnableHeaderTranslationContent(false);
@ -979,10 +986,15 @@ public class BookcasePresenter implements BasePresenter {
SharedPreUtils spb = SharedPreUtils.getInstance();
String synTime = spb.getString(mMainActivity.getString(R.string.synTime));
if (!nowTimeStr.equals(synTime) || !isAutoSyn) {
UserService.webBackup(new ResultCallback() {
UserService2.INSTANCE.webBackup(UserService2.INSTANCE.readConfig()).subscribe(new MySingleObserver<Result>() {
@Override
public void onFinish(Object o, int code) {
if ((boolean) o) {
public void onSubscribe(Disposable d) {
mMainActivity.addDisposable(d);
}
@Override
public void onSuccess(@NonNull Result result) {
if (result.getCode() == 104) {
spb.putString(mMainActivity.getString(R.string.synTime), nowTimeStr);
if (!isAutoSyn) {
DialogCreator.createTipDialog(mMainActivity, "成功将书架同步至网络!");
@ -993,9 +1005,8 @@ public class BookcasePresenter implements BasePresenter {
}
}
}
@Override
public void onError(Exception e) {
public void onError(Throwable e) {
if (!isAutoSyn) {
DialogCreator.createTipDialog(mMainActivity, "同步失败,请重试!\n" + e.getLocalizedMessage());
}

@ -35,6 +35,8 @@ import xyz.fycz.myreader.util.utils.StringUtils;
@Keep
@SuppressWarnings({"unused"})
public interface JsExtensions {
String TAG = JsExtensions.class.getSimpleName();

@ -142,8 +142,18 @@ public class OkHttpUtils {
}
public static InputStream getInputStream(String url) throws IOException {
return getInputStream(url, null);
}
public static InputStream getInputStream(String url, RequestBody body) throws IOException {
Request.Builder builder = new Request.Builder()
.addHeader("user-agent", APPCONST.DEFAULT_USER_AGENT);
if (body != null) {
builder.post(body);
Log.d("HttpPost URl", url);
} else {
Log.d("HttpGet URl", url);
}
Request request = builder
.url(url)
.build();
@ -331,7 +341,8 @@ public class OkHttpUtils {
OkHttpClient client = getOkHttpClient();
RequestBody requestBody = new MultipartBody.Builder()
.setType(MultipartBody.FORM)
.addFormDataPart("file", fileName, RequestBody.create(MediaType.parse("multipart/form-data"), new File(filePath)))
.addFormDataPart("file", fileName,
RequestBody.create(MediaType.parse("multipart/form-data"), new File(filePath)))
.build();
Request request = new Request.Builder()

@ -0,0 +1,26 @@
<?xml version="1.0" encoding="utf-8"?>
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="24"
android:viewportHeight="24">
<path
android:fillColor="#595757"
android:pathData="M18.807,13.043 C18.035,12.273,17.011,11.848,15.924,11.848 C14.876,11.848,13.893,12.25,13.134,12.966 L13.134,12.281 L11.847,12.281 L11.847,15.095 L12.49,15.095 L13.135,15.095 L14.908,15.095 L14.908,13.806 L14.128,13.806 C14.632,13.378,15.256,13.132,15.924,13.132 C16.668,13.132,17.369,13.425,17.896,13.952 C18.423,14.477,18.713,15.179,18.713,15.925 C18.713,16.667,18.423,17.366,17.896,17.896 C17.37,18.421,16.668,18.71,15.924,18.71 C15.178,18.71,14.479,18.421,13.949,17.896 C13.425,17.367,13.135,16.669,13.135,15.925 L11.848,15.925 C11.848,17.013,12.27,18.038,13.041,18.804 C13.81,19.576,14.834,20,15.924,20 C17.011,20,18.035,19.576,18.807,18.805 C19.576,18.037,20,17.012,20,15.926 C20,14.836,19.576,13.813,18.807,13.043 Z" />
<path
android:fillColor="#595757"
android:pathData="M5.287,5.625 C5.287,5.437,5.439,5.287,5.625,5.287 L16.412,5.287 C16.596,5.287,16.751,5.441,16.751,5.625 L16.751,11.02 L18.038,11.02 L18.038,5.625 C18.038,4.727,17.308,3.998,16.412,3.998 L5.625,3.998 C4.73,3.998,4,4.727,4,5.625 L4,18.377 C4,19.273,4.73,20.002,5.625,20.002 L11.018,20.002 L11.018,18.713 L5.625,18.713 C5.439,18.713,5.287,18.563,5.287,18.377 L5.287,18.039 L11.018,18.039 L11.018,16.754 L5.287,16.754 L5.287,5.625 Z" />
<path
android:fillColor="#595757"
android:pathData="M5.96,6.117 L7.247,6.117 L7.247,7.097 L5.96,7.097 L5.96,6.117 Z" />
<path
android:fillColor="#595757"
android:pathData="M14.789,6.117 L16.076,6.117 L16.076,7.097 L14.789,7.097 L14.789,6.117 Z" />
<path
android:fillColor="#595757"
android:pathData="M5.96,14.945 L7.247,14.945 L7.247,15.925 L5.96,15.925 L5.96,14.945 Z" />
<path
android:fillColor="#595757"
android:pathData="M11.473,11.475 L13.387,9.562 C13.65,9.988,13.809,10.484,13.809,11.02 L15.097,11.02 C15.097,10.128,14.801,9.309,14.312,8.637 L14.908,8.041 L13.996,7.133 L13.401,7.728 C12.729,7.24,11.91,6.944,11.018,6.944 C8.769,6.944,6.941,8.774,6.941,11.02 C6.941,13.268,8.77,15.096,11.018,15.096 L11.018,13.807 C9.48,13.807,8.228,12.557,8.228,11.02 C8.228,9.481,9.48,8.229,11.018,8.229 C11.554,8.229,12.051,8.388,12.476,8.652 L10.562,10.565 L11.473,11.475 Z" />
</vector>

@ -4,7 +4,7 @@
<item android:state_enabled="false">
<shape android:shape="rectangle">
<corners android:radius="5dp"/>
<solid android:color="@color/textSecondary"/>
<solid android:color="@color/textAssistSecondary"/>
</shape>
</item>

@ -31,7 +31,7 @@
<RelativeLayout
android:id="@+id/mine_rl_user"
android:layout_width="match_parent"
android:layout_height="60dp"
android:layout_height="50dp"
android:paddingLeft="20dp"
android:paddingRight="20dp"
android:background="@drawable/selector_common_bg">
@ -56,6 +56,35 @@
android:textSize="@dimen/text_medium_size"
android:text="登录/注册"/>
</RelativeLayout>
<RelativeLayout
android:id="@+id/mine_rl_syn"
android:layout_width="match_parent"
android:layout_height="50dp"
android:background="@drawable/selector_common_bg"
android:paddingLeft="20dp"
android:paddingRight="20dp">
<ImageView
android:id="@+id/iv_syn"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentStart="true"
android:layout_centerVertical="true"
android:src="@drawable/ic_online_syn"
app:tint="@color/textPrimary" />
<TextView
android:id="@+id/tv_syn"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerVertical="true"
android:layout_marginStart="15dp"
android:layout_toEndOf="@id/iv_syn"
android:text="@string/menu_bookcase_syn"
android:textColor="@color/textSecondary"
android:textSize="@dimen/text_normal_size" />
</RelativeLayout>
<RelativeLayout
android:layout_width="match_parent"
@ -68,7 +97,7 @@
android:layout_height="wrap_content"
android:layout_alignParentStart="true"
android:layout_centerInParent="true"
android:text="云服务"
android:text="WebDav云服务"
android:textColor="@color/textPrimary" />
</RelativeLayout>
@ -76,7 +105,7 @@
<RelativeLayout
android:id="@+id/mine_rl_webdav"
android:layout_width="match_parent"
android:layout_height="60dp"
android:layout_height="50dp"
android:background="@drawable/selector_common_bg"
android:paddingLeft="20dp"
android:paddingRight="20dp">
@ -104,30 +133,30 @@
</RelativeLayout>
<RelativeLayout
android:id="@+id/mine_rl_syn"
android:id="@+id/mine_rl_syn_webdav"
android:layout_width="match_parent"
android:layout_height="60dp"
android:layout_height="50dp"
android:background="@drawable/selector_common_bg"
android:paddingLeft="20dp"
android:paddingRight="20dp">
<ImageView
android:id="@+id/iv_syn"
android:id="@+id/iv_syn_webdav"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentStart="true"
android:layout_centerVertical="true"
android:src="@drawable/ic_online_syn"
android:src="@drawable/ic_restore"
app:tint="@color/textPrimary" />
<TextView
android:id="@+id/tv_syn"
android:id="@+id/tv_syn_webdav"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerVertical="true"
android:layout_marginStart="15dp"
android:layout_toEndOf="@id/iv_syn"
android:text="@string/menu_bookcase_syn"
android:layout_toEndOf="@id/iv_syn_webdav"
android:text="@string/webdav_restore_tip"
android:textColor="@color/textSecondary"
android:textSize="@dimen/text_normal_size" />
@ -152,7 +181,7 @@
<RelativeLayout
android:id="@+id/mine_rl_book_source"
android:layout_width="match_parent"
android:layout_height="60dp"
android:layout_height="50dp"
android:background="@drawable/selector_common_bg"
android:paddingLeft="20dp"
android:paddingRight="20dp">
@ -182,7 +211,7 @@
<RelativeLayout
android:id="@+id/mine_rl_backup"
android:layout_width="match_parent"
android:layout_height="60dp"
android:layout_height="50dp"
android:background="@drawable/selector_common_bg"
android:paddingLeft="20dp"
android:paddingRight="20dp">
@ -211,7 +240,7 @@
<RelativeLayout
android:id="@+id/mine_rl_read_record"
android:layout_width="match_parent"
android:layout_height="60dp"
android:layout_height="50dp"
android:background="@drawable/selector_common_bg"
android:paddingLeft="20dp"
android:paddingRight="20dp">
@ -257,7 +286,7 @@
<RelativeLayout
android:id="@+id/mine_rl_setting"
android:layout_width="match_parent"
android:layout_height="60dp"
android:layout_height="50dp"
android:background="@drawable/selector_common_bg"
android:paddingLeft="20dp"
android:paddingRight="20dp">
@ -287,7 +316,7 @@
<RelativeLayout
android:id="@+id/mine_rl_theme_mode"
android:layout_width="match_parent"
android:layout_height="60dp"
android:layout_height="50dp"
android:background="@drawable/selector_common_bg"
android:paddingLeft="20dp"
android:paddingRight="20dp">
@ -327,7 +356,7 @@
android:id="@+id/mine_rl_ad_setting"
android:visibility="gone"
android:layout_width="match_parent"
android:layout_height="60dp"
android:layout_height="50dp"
android:background="@drawable/selector_common_bg"
android:paddingLeft="20dp"
android:paddingRight="20dp">
@ -374,7 +403,7 @@
<RelativeLayout
android:id="@+id/mine_rl_feedback"
android:layout_width="match_parent"
android:layout_height="60dp"
android:layout_height="50dp"
android:background="@drawable/selector_common_bg"
android:paddingLeft="20dp"
android:paddingRight="20dp">
@ -404,7 +433,7 @@
<RelativeLayout
android:id="@+id/mine_rl_donate"
android:layout_width="match_parent"
android:layout_height="60dp"
android:layout_height="50dp"
android:background="@drawable/selector_common_bg"
android:paddingLeft="20dp"
android:paddingRight="20dp">
@ -433,7 +462,7 @@
<RelativeLayout
android:id="@+id/mine_rl_about"
android:layout_width="match_parent"
android:layout_height="60dp"
android:layout_height="50dp"
android:background="@drawable/selector_common_bg"
android:paddingLeft="20dp"
android:paddingRight="20dp">

Loading…
Cancel
Save