用户注册与登录

master
fengyuecanzhu 3 years ago
parent 98e8fdbb33
commit 59f950915a
  1. 7
      .idea/misc.xml
  2. 2
      app/build.gradle
  3. 1
      app/src/main/AndroidManifest.xml
  4. 4
      app/src/main/java/xyz/fycz/myreader/application/App.java
  5. 15
      app/src/main/java/xyz/fycz/myreader/base/MyTextWatcher.kt
  6. 5
      app/src/main/java/xyz/fycz/myreader/common/APPCONST.java
  7. 8
      app/src/main/java/xyz/fycz/myreader/common/URLCONST.java
  8. 10
      app/src/main/java/xyz/fycz/myreader/model/user/Result.kt
  9. 70
      app/src/main/java/xyz/fycz/myreader/model/user/User.java
  10. 6
      app/src/main/java/xyz/fycz/myreader/model/user/UserService.java
  11. 171
      app/src/main/java/xyz/fycz/myreader/model/user/UserService2.kt
  12. 225
      app/src/main/java/xyz/fycz/myreader/ui/activity/AuthEmailActivity.kt
  13. 124
      app/src/main/java/xyz/fycz/myreader/ui/activity/LoginActivity.java
  14. 237
      app/src/main/java/xyz/fycz/myreader/ui/activity/RegisterActivity.java
  15. 2
      app/src/main/java/xyz/fycz/myreader/ui/activity/SearchWordActivity.kt
  16. 102
      app/src/main/java/xyz/fycz/myreader/ui/fragment/MineFragment.java
  17. 9
      app/src/main/java/xyz/fycz/myreader/ui/presenter/BookcasePresenter.java
  18. 8
      app/src/main/java/xyz/fycz/myreader/util/help/StringHelper.java
  19. 2
      app/src/main/java/xyz/fycz/myreader/util/utils/AdUtils.java
  20. 2
      app/src/main/java/xyz/fycz/myreader/util/utils/FileUtils.java
  21. 5
      app/src/main/res/color/selector_get_emali_code.xml
  22. BIN
      app/src/main/res/drawable-xhdpi/bg_login.jpg
  23. 2
      app/src/main/res/drawable/login_btn_selector.xml
  24. 125
      app/src/main/res/layout/activity_auth_email.xml
  25. 162
      app/src/main/res/layout/activity_login.xml
  26. 122
      app/src/main/res/layout/activity_register.xml
  27. 4
      app/src/main/res/layout/fragment_mine.xml
  28. 1
      app/src/main/res/values/dimens.xml
  29. 13
      app/src/main/res/values/strings.xml
  30. 2
      app/version_code.properties

@ -6,21 +6,28 @@
<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_delete.xml" value="0.18518518518518517" />
<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_re_seg.xml" value="0.1962962962962963" />
<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/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" />
<entry key="..\:/android/FYReader/app/src/main/res/layout/activity_about.xml" value="0.12132725430597771" /> <entry key="..\:/android/FYReader/app/src/main/res/layout/activity_about.xml" value="0.12132725430597771" />
<entry key="..\:/android/FYReader/app/src/main/res/layout/activity_auth_email.xml" value="0.1897644927536232" />
<entry key="..\:/android/FYReader/app/src/main/res/layout/activity_donate.xml" value="0.536" /> <entry key="..\:/android/FYReader/app/src/main/res/layout/activity_donate.xml" value="0.536" />
<entry key="..\:/android/FYReader/app/src/main/res/layout/activity_feedback.xml" value="0.12132725430597771" /> <entry key="..\:/android/FYReader/app/src/main/res/layout/activity_feedback.xml" value="0.12132725430597771" />
<entry key="..\:/android/FYReader/app/src/main/res/layout/activity_file_picker.xml" value="0.2318840579710145" /> <entry key="..\:/android/FYReader/app/src/main/res/layout/activity_file_picker.xml" value="0.2318840579710145" />
<entry key="..\:/android/FYReader/app/src/main/res/layout/activity_group_manager.xml" value="0.12132725430597771" /> <entry key="..\:/android/FYReader/app/src/main/res/layout/activity_group_manager.xml" value="0.12132725430597771" />
<entry key="..\:/android/FYReader/app/src/main/res/layout/activity_login.xml" value="0.176" />
<entry key="..\:/android/FYReader/app/src/main/res/layout/activity_manage_group.xml" value="0.21195652173913043" /> <entry key="..\:/android/FYReader/app/src/main/res/layout/activity_manage_group.xml" value="0.21195652173913043" />
<entry key="..\:/android/FYReader/app/src/main/res/layout/activity_more_setting.xml" value="0.264" /> <entry key="..\:/android/FYReader/app/src/main/res/layout/activity_more_setting.xml" value="0.264" />
<entry key="..\:/android/FYReader/app/src/main/res/layout/activity_read.xml" value="0.17028985507246377" /> <entry key="..\:/android/FYReader/app/src/main/res/layout/activity_read.xml" value="0.17028985507246377" />
<entry key="..\:/android/FYReader/app/src/main/res/layout/activity_register.xml" value="0.2796934865900383" />
<entry key="..\:/android/FYReader/app/src/main/res/layout/activity_search_book.xml" value="0.12132725430597771" /> <entry key="..\:/android/FYReader/app/src/main/res/layout/activity_search_book.xml" value="0.12132725430597771" />
<entry key="..\:/android/FYReader/app/src/main/res/layout/activity_search_word.xml" value="0.144" /> <entry key="..\:/android/FYReader/app/src/main/res/layout/activity_search_word.xml" value="0.144" />
<entry key="..\:/android/FYReader/app/src/main/res/layout/dialog_loading.xml" value="0.1" />
<entry key="..\:/android/FYReader/app/src/main/res/layout/dialog_textview.xml" value="0.1947463768115942" /> <entry key="..\:/android/FYReader/app/src/main/res/layout/dialog_textview.xml" value="0.1947463768115942" />
<entry key="..\:/android/FYReader/app/src/main/res/layout/fingerprint_dialog.xml" value="0.20425724637681159" /> <entry key="..\:/android/FYReader/app/src/main/res/layout/fingerprint_dialog.xml" value="0.20425724637681159" />
<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_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_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_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_private_bookcase.xml" value="0.21195652173913043" /> <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/fragment_webdav_setting.xml" value="0.4" />
<entry key="..\:/android/FYReader/app/src/main/res/layout/gridview_book_detailed_item.xml" value="0.1947463768115942" /> <entry key="..\:/android/FYReader/app/src/main/res/layout/gridview_book_detailed_item.xml" value="0.1947463768115942" />

@ -185,8 +185,6 @@ dependencies {
implementation 'androidx.constraintlayout:constraintlayout:1.1.3' implementation 'androidx.constraintlayout:constraintlayout:1.1.3'
implementation 'io.alterac.blurkit:blurkit:1.1.0'
implementation 'com.google.android.material:material:1.1.0' implementation 'com.google.android.material:material:1.1.0'
//Scroller //Scroller

@ -121,6 +121,7 @@
<activity android:name=".ui.activity.FindBookActivity" /> <activity android:name=".ui.activity.FindBookActivity" />
<activity android:name=".ui.activity.GroupManagerActivity" /> <activity android:name=".ui.activity.GroupManagerActivity" />
<activity android:name=".ui.activity.SearchWordActivity" /> <activity android:name=".ui.activity.SearchWordActivity" />
<activity android:name=".ui.activity.AuthEmailActivity" />
<receiver android:name=".util.notification.NotificationClickReceiver" /> <receiver android:name=".util.notification.NotificationClickReceiver" />
<receiver android:name=".ui.presenter.BookcasePresenter$cancelDownloadReceiver" /> <receiver android:name=".ui.presenter.BookcasePresenter$cancelDownloadReceiver" />

@ -247,7 +247,6 @@ public class App extends Application {
try { try {
PackageManager manager = application.getPackageManager(); PackageManager manager = application.getPackageManager();
PackageInfo info = manager.getPackageInfo(application.getPackageName(), 0); PackageInfo info = manager.getPackageInfo(application.getPackageName(), 0);
return info.versionCode; return info.versionCode;
} catch (Exception e) { } catch (Exception e) {
e.printStackTrace(); e.printStackTrace();
@ -335,6 +334,9 @@ public class App extends Application {
forceUpdateVersion = Integer.parseInt(contents[8].substring(contents[8].indexOf(":") + 1)); forceUpdateVersion = Integer.parseInt(contents[8].substring(contents[8].indexOf(":") + 1));
spu.putInt("forceUpdateVersion", forceUpdateVersion); spu.putInt("forceUpdateVersion", forceUpdateVersion);
String domain = contents[9].substring(contents[9].indexOf(":") + 1);
spu.putString("domain", domain);
int versionCode = getVersionCode(); int versionCode = getVersionCode();
isForceUpdate = isForceUpdate && forceUpdateVersion > versionCode; isForceUpdate = isForceUpdate && forceUpdateVersion > versionCode;

@ -0,0 +1,15 @@
package xyz.fycz.myreader.base
import android.text.TextWatcher
/**
* @author fengyue
* @date 2021/12/9 12:32
*/
abstract class MyTextWatcher : TextWatcher {
override fun beforeTextChanged(s: CharSequence?, start: Int, count: Int, after: Int) {
}
override fun onTextChanged(s: CharSequence?, start: Int, before: Int, count: Int) {
}
}

@ -21,8 +21,8 @@ import javax.script.ScriptEngineManager;
public class APPCONST { public class APPCONST {
public static String publicKey = "";//服务端公钥 public static String publicKey = "fyds2.0";//服务端公钥
public static final String KEY = ""; public static final String KEY = "readerByFengyue";
public static final String[] STORAGE_PERMISSIONS = new String[]{Permission.WRITE_EXTERNAL_STORAGE, public static final String[] STORAGE_PERMISSIONS = new String[]{Permission.WRITE_EXTERNAL_STORAGE,
Permission.READ_EXTERNAL_STORAGE}; Permission.READ_EXTERNAL_STORAGE};
@ -99,6 +99,7 @@ public class APPCONST {
public static final int REQUEST_EDIT_BOOK = 1013; public static final int REQUEST_EDIT_BOOK = 1013;
public static final int REQUEST_GROUP_MANAGER = 1014; public static final int REQUEST_GROUP_MANAGER = 1014;
public static final int REQUEST_SEARCH_WORD = 1015; public static final int REQUEST_SEARCH_WORD = 1015;
public static final int REQUEST_AUTH_EMAIL = 1016;
public static final int REQUEST_READ = 1; public static final int REQUEST_READ = 1;

@ -1,5 +1,7 @@
package xyz.fycz.myreader.common; package xyz.fycz.myreader.common;
import xyz.fycz.myreader.util.SharedPreUtils;
public class URLCONST { public class URLCONST {
public static final String OFFICIAL_WEB = "https://reader.fycz.tk/"; public static final String OFFICIAL_WEB = "https://reader.fycz.tk/";
@ -19,11 +21,15 @@ public class URLCONST {
public static final String YOU_DAO_SEARCH = "http://m.youdao.com/dict?le=eng&q={key}"; public static final String YOU_DAO_SEARCH = "http://m.youdao.com/dict?le=eng&q={key}";
public static final String FY_READER_URL = "https://fyreader.fycz.tk"; public static final String DEFAULT_DOMAIN =
SharedPreUtils.getInstance().getString("domain", "fycz.tk");
public static final String FY_READER_URL = "https://fyreader." + DEFAULT_DOMAIN;
public static final String AD_URL = FY_READER_URL + "/ad"; public static final String AD_URL = FY_READER_URL + "/ad";
public static final String LOG_UPLOAD_URL = FY_READER_URL + "/logUpload"; public static final String LOG_UPLOAD_URL = FY_READER_URL + "/logUpload";
public static final String THANKS_URL = FY_READER_URL + "/thanks/"; public static final String THANKS_URL = FY_READER_URL + "/thanks/";
public static final String USER_URL = "https://user." + DEFAULT_DOMAIN;
public static final String DONATE = "https://gitee.com/fengyuecanzhu/Donate/raw/master"; public static final String DONATE = "https://gitee.com/fengyuecanzhu/Donate/raw/master";

@ -0,0 +1,10 @@
package xyz.fycz.myreader.model.user
/**
* @author fengyue
* @date 2021/12/9 10:19
*/
data class Result(
val code: Int,
val result: Any
)

@ -0,0 +1,70 @@
package xyz.fycz.myreader.model.user;
/**
* @author fengyue
* @date 2020/7/12 17:35
*/
public class User {
private Integer userId;
private String userName;
private String password;
private String email;
public User() {
}
public User(String userName) {
this.userName = userName;
}
public User(String userName, String password) {
this.userName = userName;
this.password = password;
}
public User(String userName, String password, String email) {
this.userName = userName;
this.password = password;
this.email = email;
}
public User(Integer userId, String userName, String password, String email) {
this.userId = userId;
this.userName = userName;
this.password = password;
this.email = email;
}
public Integer getUserId() {
return userId;
}
public String getUserName() {
return userName;
}
public void setUserName(String userName) {
this.userName = userName;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
public void setUserId(Integer userId) {
this.userId = userId;
}
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
}

@ -1,4 +1,6 @@
package xyz.fycz.myreader.model.backup; package xyz.fycz.myreader.model.user;
import android.content.Context;
import io.reactivex.annotations.NonNull; import io.reactivex.annotations.NonNull;
import xyz.fycz.myreader.application.App; import xyz.fycz.myreader.application.App;
@ -111,7 +113,7 @@ public class UserService {
public static boolean writeConfig(Map<String,String> userLoginInfo){ public static boolean writeConfig(Map<String,String> userLoginInfo){
FileOutputStream fos = null; FileOutputStream fos = null;
try { try {
fos = App.getApplication().openFileOutput("userConfig.fy", App.getApplication().MODE_PRIVATE); fos = App.getApplication().openFileOutput("userConfig.fy", Context.MODE_PRIVATE);
String userInfo = "username='" + userLoginInfo.get("loginName") + "',\npassword='" + userLoginInfo.get("loginPwd") + "'"; String userInfo = "username='" + userLoginInfo.get("loginName") + "',\npassword='" + userLoginInfo.get("loginPwd") + "'";
byte[] bs = userInfo.getBytes(); byte[] bs = userInfo.getBytes();
fos.write(bs); fos.write(bs);

@ -0,0 +1,171 @@
package xyz.fycz.myreader.model.user
import io.reactivex.Single
import io.reactivex.SingleOnSubscribe
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.model.storage.Backup
import xyz.fycz.myreader.model.storage.Restore
import xyz.fycz.myreader.model.storage.Restore.restore
import xyz.fycz.myreader.util.*
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
/**
* @author fengyue
* @date 2021/12/9 10:17
*/
object UserService2 {
fun login(user: User): Single<Result> {
return Single.create(SingleOnSubscribe<Result> {
val mediaType = MediaType.parse("application/x-www-form-urlencoded")
val body = "username=${user.userName}" +
"&password=${user.password}" +
makeAuth()
val requestBody = RequestBody.create(mediaType, body)
val ret = OkHttpUtils.getHtml(URLCONST.USER_URL + "/do/login", requestBody, "UTF-8")
it.onSuccess(GSON.fromJson(ret, Result::class.java))
}).compose { RxUtils.toSimpleSingle(it) }
}
fun register(user: User, code: String, keyc: String): Single<Result> {
return Single.create(SingleOnSubscribe<Result> {
val mediaType = MediaType.parse("application/x-www-form-urlencoded")
val body = "username=${user.userName}" +
"&password=${user.password}" +
"&email=${user.email}" +
"&code=${code}" +
"&keyc=${keyc}" +
"&key=${CyptoUtils.encode(APPCONST.KEY, APPCONST.publicKey)}" +
makeAuth()
val requestBody = RequestBody.create(mediaType, body)
val ret = OkHttpUtils.getHtml(URLCONST.USER_URL + "/do/reg", requestBody, "UTF-8")
it.onSuccess(GSON.fromJson(ret, Result::class.java))
}).compose { RxUtils.toSimpleSingle(it) }
}
fun bindEmail(user: User, code: String, keyc: String): Single<Result> {
return Single.create(SingleOnSubscribe<Result> {
val mediaType = MediaType.parse("application/x-www-form-urlencoded")
val body = "username=${user.userName}" +
"&email=${user.email}" +
"&code=${code}" +
"&keyc=${keyc}" +
makeAuth()
val requestBody = RequestBody.create(mediaType, body)
val ret = OkHttpUtils.getHtml(URLCONST.USER_URL + "/do/bindEmail", requestBody, "UTF-8")
it.onSuccess(GSON.fromJson(ret, Result::class.java))
}).compose { RxUtils.toSimpleSingle(it) }
}
fun resetPwd(user: User, code: String, keyc: String): Single<Result> {
return Single.create(SingleOnSubscribe<Result> {
val mediaType = MediaType.parse("application/x-www-form-urlencoded")
val body = "email=${user.email}" +
"&password=${user.password}" +
"&code=${code}" +
"&keyc=${keyc}" +
makeAuth()
val requestBody = RequestBody.create(mediaType, body)
val ret = OkHttpUtils.getHtml(URLCONST.USER_URL + "/do/resetPwd", requestBody, "UTF-8")
it.onSuccess(GSON.fromJson(ret, Result::class.java))
}).compose { RxUtils.toSimpleSingle(it) }
}
fun sendEmail(email: String, type: String, keyc: String = ""): Single<Result> {
return Single.create(SingleOnSubscribe<Result> {
val mediaType = MediaType.parse("application/x-www-form-urlencoded")
val body = "email=${email}" +
"&type=${type}" +
"&keyc=${keyc}" +
makeAuth()
val requestBody = RequestBody.create(mediaType, body)
val ret = OkHttpUtils.getHtml(URLCONST.USER_URL + "/do/sendEmail", requestBody, "UTF-8")
it.onSuccess(GSON.fromJson(ret, Result::class.java))
}).compose { RxUtils.toSimpleSingle(it) }
}
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) }
}
fun webRestore(user: User): Single<Result> {
return Single.create(SingleOnSubscribe<Result> {
val zipFile = FileUtils.getFile(APPCONST.FILE_DIR + "webBackup.zip")
val input = OkHttpUtils.getInputStream(
URLCONST.USER_URL + "/do/ret?" +
"username=${user.userName}" +
makeAuth()
)
if (FileUtils.writeFile(input.readBytes(), zipFile)) {
ZipUtils.unzipFile(zipFile.absolutePath, APPCONST.FILE_DIR)
restore(APPCONST.FILE_DIR + "webBackup/", object : Restore.CallBack {
override fun restoreSuccess() {
zipFile.delete()
it.onSuccess(Result(100, "成功从网络同步到本地"))
}
override fun restoreError(msg: String) {
it.onError(Throwable(msg))
}
})
}
}).compose { RxUtils.toSimpleSingle(it) }
}
fun writeConfig(user: User) {
FileUtils.write(App.getmContext(), "userConfig.fy", GSON.toJson(user))
}
fun readConfig(): User? {
val config = FileUtils.read(App.getmContext(), "userConfig.fy")
if ("" != config) {
return GSON.fromJson(config, User::class.java)
}
return null
}
fun writeUsername(username: String) {
FileUtils.writeText(username, FileUtils.getFile(APPCONST.QQ_DATA_DIR + "user"))
}
fun readUsername(): String {
return FileUtils.readText(APPCONST.QQ_DATA_DIR + "user")
}
private fun makeAuth(): String {
return "&signal=" + AppInfoUtils.getSingInfo(
App.getmContext(),
App.getApplication().packageName, AppInfoUtils.SHA1
) + "&appVersion=" + App.getVersionCode()
}
}

@ -0,0 +1,225 @@
package xyz.fycz.myreader.ui.activity
import android.app.Activity
import android.content.Intent
import android.os.Bundle
import android.text.Editable
import android.view.View
import androidx.appcompat.widget.Toolbar
import io.reactivex.SingleObserver
import io.reactivex.disposables.Disposable
import xyz.fycz.myreader.R
import xyz.fycz.myreader.application.App
import xyz.fycz.myreader.base.BaseActivity
import xyz.fycz.myreader.base.BitIntentDataManager
import xyz.fycz.myreader.base.MyTextWatcher
import xyz.fycz.myreader.base.observer.MySingleObserver
import xyz.fycz.myreader.common.APPCONST
import xyz.fycz.myreader.databinding.ActivityAuthEmailBinding
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.model.user.UserService2.bindEmail
import xyz.fycz.myreader.model.user.UserService2.register
import xyz.fycz.myreader.model.user.UserService2.resetPwd
import xyz.fycz.myreader.model.user.UserService2.sendEmail
import xyz.fycz.myreader.model.user.UserService2.writeUsername
import xyz.fycz.myreader.ui.dialog.DialogCreator
import xyz.fycz.myreader.ui.dialog.LoadingDialog
import xyz.fycz.myreader.util.CyptoUtils
import xyz.fycz.myreader.util.ToastUtils
import java.util.*
/**
* @author fengyue
* @date 2021/12/9 15:20
*/
class AuthEmailActivity : BaseActivity(), SingleObserver<Result> {
private lateinit var binding: ActivityAuthEmailBinding
private var email = ""
private var password = ""
private var emailCode = ""
private var keyc = ""
private lateinit var dialog: LoadingDialog
private var disp: Disposable? = null
private lateinit var operator: String
private var user: User? = null
private var isBind: Boolean = false
override fun bindView() {
binding = ActivityAuthEmailBinding.inflate(layoutInflater)
setContentView(binding.root)
}
override fun initData(savedInstanceState: Bundle?) {
user = BitIntentDataManager.getInstance().getData(intent) as User?
isBind = user != null
operator = if (isBind) "绑定邮箱" else "重置密码"
dialog = LoadingDialog(this, "正在请求") {
disp?.dispose()
}
}
override fun setUpToolbar(toolbar: Toolbar?) {
super.setUpToolbar(toolbar)
setStatusBarColor(R.color.colorPrimary, true)
supportActionBar?.title = operator
}
override fun initWidget() {
binding.tvTitle.text = operator
binding.btSubmit.text = operator
binding.etEmail.editText?.addTextChangedListener(object : MyTextWatcher() {
override fun afterTextChanged(s: Editable) {
email = s.toString()
if (!email.matches("^[_a-z0-9-]+(\\.[_a-z0-9-]+)*@[a-z0-9-]+(\\.[a-z0-9-]+)*(\\.[a-z]{2,})$".toRegex())) {
showTip("邮箱格式错误")
} else {
binding.tvRegisterTip.visibility = View.GONE
}
checkNotNone()
}
})
binding.etEmailCode.editText?.addTextChangedListener(object : MyTextWatcher() {
override fun afterTextChanged(s: Editable) {
emailCode = s.toString().trim()
checkNotNone()
}
})
binding.etPassword.editText!!.addTextChangedListener(object : MyTextWatcher() {
override fun afterTextChanged(s: Editable) {
password = s.toString()
if (password.length < 8 || password.length > 16) {
showTip("密码必须在8-16位之间")
} else if (password.matches("^\\d+$".toRegex())) {
showTip("密码不能是纯数字")
} else {
binding.tvRegisterTip.visibility = View.GONE
}
checkNotNone()
}
})
if (!isBind) {
binding.etPassword.visibility = View.VISIBLE
}
}
override fun initClick() {
binding.tvGetEmailCode.setOnClickListener {
if (!email.matches("^[_a-z0-9-]+(\\.[_a-z0-9-]+)*@[a-z0-9-]+(\\.[a-z0-9-]+)*(\\.[a-z]{2,})$".toRegex())) {
ToastUtils.showWarring("请正确输入邮箱")
return@setOnClickListener
}
dialog.show()
dialog.setmMessage("正在发送")
sendEmail(email, if (isBind) "bind" else "auth", keyc)
.subscribe(object : MySingleObserver<Result?>() {
override fun onSubscribe(d: Disposable) {
addDisposable(d)
disp = d
}
override fun onSuccess(result: Result) {
if (result.code == 106) {
ToastUtils.showSuccess("验证码发送成功")
keyc = result.result.toString()
timeDown(60)
} else {
ToastUtils.showWarring(result.result.toString())
}
dialog.dismiss()
}
override fun onError(e: Throwable) {
ToastUtils.showError("验证码发送失败:${e.localizedMessage}")
dialog.dismiss()
}
})
}
binding.btSubmit.setOnClickListener {
if (!isBind && (password.matches("^\\d+$".toRegex()) || !password.matches("^.{8,16}$".toRegex()))) {
DialogCreator.createTipDialog(
this, "密码格式错误",
"密码必须在8-16位之间\n密码不能是纯数字"
)
} else if (!email.matches("^[_a-z0-9-]+(\\.[_a-z0-9-]+)*@[a-z0-9-]+(\\.[a-z0-9-]+)*(\\.[a-z]{2,})$".toRegex())) {
DialogCreator.createTipDialog(
this, "邮箱格式错误",
"电子邮箱的正确写法为:用户名@邮箱网站.com(.cn等)"
)
} else if ("" == keyc) {
DialogCreator.createTipDialog(this, "请先获取邮箱验证码")
} else if (emailCode.length < 6) {
DialogCreator.createTipDialog(this, "请输入6位邮箱验证码")
} else {
dialog.show()
dialog.setmMessage("正在请求")
if (isBind) {
val user = User().apply {
email = this@AuthEmailActivity.email
userName = this@AuthEmailActivity.user?.userName
}
bindEmail(user, emailCode, keyc)
.subscribe(this)
} else {
val user = User().apply {
email = this@AuthEmailActivity.email
password = CyptoUtils.encode(APPCONST.KEY, this@AuthEmailActivity.password)
}
resetPwd(user, emailCode, keyc)
.subscribe(this)
}
}
}
}
fun showTip(tip: String?) {
binding.tvRegisterTip.visibility = View.VISIBLE
binding.tvRegisterTip.text = tip
}
private fun timeDown(time: Int) {
if (time == 0) {
binding.tvGetEmailCode.text = getString(R.string.re_get_email_code, "")
binding.tvGetEmailCode.isEnabled = true
} else {
binding.tvGetEmailCode.isEnabled = false
val timeStr = "($time)"
binding.tvGetEmailCode.text = getString(R.string.re_get_email_code, timeStr)
App.getHandler().postDelayed({ timeDown(time - 1) }, 1000)
}
}
fun checkNotNone() {
binding.btSubmit.isEnabled = "" != email && "" != emailCode && (isBind || "" != password)
}
override fun onDestroy() {
dialog.dismiss()
super.onDestroy()
}
override fun onSubscribe(d: Disposable) {
addDisposable(d)
disp = d
}
override fun onSuccess(result: Result) {
if (result.code < 200) {
ToastUtils.showSuccess(result.result.toString())
setResult(Activity.RESULT_OK)
finish()
} else {
ToastUtils.showWarring(result.result.toString())
}
dialog.dismiss()
}
override fun onError(e: Throwable) {
ToastUtils.showError("失败:${e.localizedMessage}")
dialog.dismiss()
}
}

@ -13,17 +13,26 @@ import android.view.MotionEvent;
import android.view.View; import android.view.View;
import android.view.inputmethod.InputMethodManager; import android.view.inputmethod.InputMethodManager;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.appcompat.widget.Toolbar; import androidx.appcompat.widget.Toolbar;
import java.util.HashMap; import java.util.HashMap;
import java.util.Map; import java.util.Map;
import io.reactivex.disposables.Disposable;
import xyz.fycz.myreader.R; import xyz.fycz.myreader.R;
import xyz.fycz.myreader.base.BaseActivity; import xyz.fycz.myreader.base.BaseActivity;
import xyz.fycz.myreader.base.BitIntentDataManager;
import xyz.fycz.myreader.base.observer.MySingleObserver;
import xyz.fycz.myreader.common.APPCONST; import xyz.fycz.myreader.common.APPCONST;
import xyz.fycz.myreader.databinding.ActivityLoginBinding; import xyz.fycz.myreader.databinding.ActivityLoginBinding;
import xyz.fycz.myreader.model.backup.UserService; 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.DialogCreator;
import xyz.fycz.myreader.ui.dialog.LoadingDialog;
import xyz.fycz.myreader.util.CodeUtil; import xyz.fycz.myreader.util.CodeUtil;
import xyz.fycz.myreader.util.CyptoUtils; import xyz.fycz.myreader.util.CyptoUtils;
import xyz.fycz.myreader.util.ToastUtils; import xyz.fycz.myreader.util.ToastUtils;
@ -40,23 +49,9 @@ public class LoginActivity extends BaseActivity implements TextWatcher {
private ActivityLoginBinding binding; private ActivityLoginBinding binding;
private String code; private String code;
private Disposable loginDisp;
@SuppressLint("HandlerLeak") private LoadingDialog dialog;
private Handler mHandler = new Handler() { private User user;
@SuppressLint("HandlerLeak")
@Override
public void handleMessage(Message msg) {
switch (msg.what) {
case 1:
binding.btLogin.setEnabled(true);
break;
case 2:
createCaptcha();
break;
}
}
};
@Override @Override
protected void bindView() { protected void bindView() {
@ -74,13 +69,18 @@ public class LoginActivity extends BaseActivity implements TextWatcher {
@Override @Override
protected void initData(Bundle savedInstanceState) { protected void initData(Bundle savedInstanceState) {
super.initData(savedInstanceState); super.initData(savedInstanceState);
dialog = new LoadingDialog(this, "正在登录", () -> {
if (loginDisp != null) {
loginDisp.dispose();
}
});
} }
@Override @Override
protected void initWidget() { protected void initWidget() {
super.initWidget(); super.initWidget();
mHandler.sendMessage(mHandler.obtainMessage(2)); createCaptcha();
String username = UserService.readUsername(); String username = UserService2.INSTANCE.readUsername();
binding.etUser.getEditText().setText(username); binding.etUser.getEditText().setText(username);
binding.etUser.getEditText().requestFocus(username.length()); binding.etUser.getEditText().requestFocus(username.length());
//监听内容改变 -> 控制按钮的点击状态 //监听内容改变 -> 控制按钮的点击状态
@ -92,11 +92,10 @@ public class LoginActivity extends BaseActivity implements TextWatcher {
@Override @Override
protected void initClick() { protected void initClick() {
super.initClick(); super.initClick();
binding.ivCaptcha.setOnClickListener(v -> mHandler.sendMessage(mHandler.obtainMessage(2))); binding.ivCaptcha.setOnClickListener(v -> createCaptcha());
binding.btLogin.setOnClickListener(v -> { binding.btLogin.setOnClickListener(v -> {
mHandler.sendMessage(mHandler.obtainMessage(2)); if (!code.equalsIgnoreCase(binding.etCaptcha.getEditText().getText().toString())) {
if (!code.toLowerCase().equals(binding.etCaptcha.getEditText().getText().toString().toLowerCase())){
DialogCreator.createTipDialog(this, "验证码错误!"); DialogCreator.createTipDialog(this, "验证码错误!");
return; return;
} }
@ -104,46 +103,48 @@ public class LoginActivity extends BaseActivity implements TextWatcher {
ToastUtils.showError("无网络连接!"); ToastUtils.showError("无网络连接!");
return; return;
} }
ProgressUtils.show(this, "正在登陆...");
binding.btLogin.setEnabled(false); binding.btLogin.setEnabled(false);
final String loginName = binding.etUser.getEditText().getText().toString().trim(); final String loginName = binding.etUser.getEditText().getText().toString().trim();
String loginPwd = binding.etPassword.getEditText().getText().toString(); String loginPwd = binding.etPassword.getEditText().getText().toString();
final Map<String, String> userLoginInfo = new HashMap<>(); user = new User(loginName, CyptoUtils.encode(APPCONST.KEY, loginPwd));
userLoginInfo.put("loginName", loginName); dialog.show();
userLoginInfo.put("loginPwd", CyptoUtils.encode(APPCONST.KEY, loginPwd)); UserService2.INSTANCE.login(user).subscribe(new MySingleObserver<Result>() {
//验证用户名和密码
UserService.login(userLoginInfo, new ResultCallback() {
@Override @Override
public void onFinish(Object o, int code) { public void onSubscribe(Disposable d) {
String result = (String) o; addDisposable(d);
String[] info = result.split(":"); loginDisp = d;
int resultCode = Integer.parseInt(info[0].trim());
String resultName = info[1].trim();
//最后输出结果
if (resultCode == 102) {
UserService.writeConfig(userLoginInfo);
UserService.writeUsername(loginName);
Intent intent = new Intent();
intent.putExtra("isLogin", true);
setResult(Activity.RESULT_OK, intent);
finish();
ToastUtils.showSuccess(resultName);
} else {
mHandler.sendMessage(mHandler.obtainMessage(1));
ProgressUtils.dismiss();
ToastUtils.showWarring(resultName);
} }
@Override
public void onSuccess(@NonNull Result result) {
if (result.getCode() == 102) {
loginSuccess();
ToastUtils.showSuccess(result.getResult().toString());
} else if (result.getCode() == 301) {
Intent intent = new Intent(LoginActivity.this, AuthEmailActivity.class);
BitIntentDataManager.getInstance().putData(intent, user);
startActivityForResult(intent, APPCONST.REQUEST_AUTH_EMAIL);
ToastUtils.showWarring(result.getResult().toString());
} else {
ToastUtils.showWarring(result.getResult().toString());
}
binding.btLogin.setEnabled(false);
dialog.dismiss();
} }
@Override @Override
public void onError(Exception e) { public void onError(Throwable e) {
ToastUtils.showError("登录失败\n" + e.getLocalizedMessage()); ToastUtils.showError("登录失败\n" + e.getLocalizedMessage());
mHandler.sendMessage(mHandler.obtainMessage(1)); binding.btLogin.setEnabled(false);
ProgressUtils.dismiss(); dialog.dismiss();
createCaptcha();
} }
}); });
});
binding.tvForgotPwd.setOnClickListener(v -> {
Intent intent = new Intent(LoginActivity.this, AuthEmailActivity.class);
startActivity(intent);
}); });
binding.tvRegister.setOnClickListener(v -> { binding.tvRegister.setOnClickListener(v -> {
@ -152,6 +153,15 @@ public class LoginActivity extends BaseActivity implements TextWatcher {
}); });
} }
private void loginSuccess() {
UserService2.INSTANCE.writeConfig(user);
UserService2.INSTANCE.writeUsername(user.getUserName());
Intent intent = new Intent();
intent.putExtra("isLogin", true);
setResult(Activity.RESULT_OK, intent);
finish();
}
public void createCaptcha() { public void createCaptcha() {
code = CodeUtil.getInstance().createCode(); code = CodeUtil.getInstance().createCode();
Bitmap codeBitmap = CodeUtil.getInstance().createBitmap(code); Bitmap codeBitmap = CodeUtil.getInstance().createBitmap(code);
@ -165,7 +175,7 @@ public class LoginActivity extends BaseActivity implements TextWatcher {
* 2. 代码控制 InputMethodManager * 2. 代码控制 InputMethodManager
* requestFocus * requestFocus
* showSoftInput:显示键盘 必须先让这个view成为焦点requestFocus * showSoftInput:显示键盘 必须先让这个view成为焦点requestFocus
* * <p>
* hideSoftInputFromWindow 隐藏键盘 * hideSoftInputFromWindow 隐藏键盘
*/ */
@Override @Override
@ -218,9 +228,19 @@ public class LoginActivity extends BaseActivity implements TextWatcher {
} }
} }
@Override
protected void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (resultCode == Activity.RESULT_OK) {
if (requestCode == APPCONST.REQUEST_AUTH_EMAIL) {
loginSuccess();
}
}
}
@Override @Override
protected void onDestroy() { protected void onDestroy() {
dialog.dismiss();
super.onDestroy(); super.onDestroy();
ProgressUtils.dismiss();
} }
} }

@ -2,6 +2,7 @@ package xyz.fycz.myreader.ui.activity;
import android.annotation.SuppressLint; import android.annotation.SuppressLint;
import android.graphics.Bitmap; import android.graphics.Bitmap;
import android.os.Bundle;
import android.os.Handler; import android.os.Handler;
import android.os.Message; import android.os.Message;
import android.text.Editable; import android.text.Editable;
@ -9,17 +10,28 @@ import android.text.TextWatcher;
import android.text.method.LinkMovementMethod; import android.text.method.LinkMovementMethod;
import android.view.View; import android.view.View;
import androidx.annotation.NonNull;
import androidx.appcompat.widget.Toolbar; import androidx.appcompat.widget.Toolbar;
import java.util.HashMap; import java.util.HashMap;
import java.util.Map; import java.util.Map;
import io.reactivex.disposables.Disposable;
import xyz.fycz.myreader.R; import xyz.fycz.myreader.R;
import xyz.fycz.myreader.application.App;
import xyz.fycz.myreader.base.BaseActivity; import xyz.fycz.myreader.base.BaseActivity;
import xyz.fycz.myreader.base.MyTextWatcher;
import xyz.fycz.myreader.base.observer.MySingleObserver;
import xyz.fycz.myreader.common.APPCONST;
import xyz.fycz.myreader.databinding.ActivityRegisterBinding; import xyz.fycz.myreader.databinding.ActivityRegisterBinding;
import xyz.fycz.myreader.model.backup.UserService; 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.DialogCreator;
import xyz.fycz.myreader.ui.dialog.LoadingDialog;
import xyz.fycz.myreader.util.CodeUtil; import xyz.fycz.myreader.util.CodeUtil;
import xyz.fycz.myreader.util.CyptoUtils;
import xyz.fycz.myreader.util.ToastUtils; import xyz.fycz.myreader.util.ToastUtils;
import xyz.fycz.myreader.util.utils.ProgressUtils; import xyz.fycz.myreader.util.utils.ProgressUtils;
import xyz.fycz.myreader.util.utils.StringUtils; import xyz.fycz.myreader.util.utils.StringUtils;
@ -36,27 +48,12 @@ public class RegisterActivity extends BaseActivity {
private String code; private String code;
private String username = ""; private String username = "";
private String password = ""; private String password = "";
private String rpPassword = ""; private String email = "";
private String emailCode = "";
private String keyc = "";
private String inputCode = ""; private String inputCode = "";
private LoadingDialog dialog;
@SuppressLint("HandlerLeak") private Disposable disp;
private Handler mHandler = new Handler() {
@SuppressLint("HandlerLeak")
@Override
public void handleMessage(Message msg) {
switch (msg.what) {
case 1:
createCaptcha();
break;
case 2:
showTip((String) msg.obj);
break;
case 3:
binding.tvRegisterTip.setVisibility(View.GONE);
break;
}
}
};
@Override @Override
protected void bindView() { protected void bindView() {
@ -72,119 +69,126 @@ public class RegisterActivity extends BaseActivity {
} }
@Override @Override
protected void initWidget() { protected void initData(Bundle savedInstanceState) {
super.initWidget(); dialog = new LoadingDialog(this, "正在注册", () -> {
mHandler.sendMessage(mHandler.obtainMessage(1)); if (disp != null) {
binding.etUsername.requestFocus(); disp.dispose();
binding.etUsername.getEditText().addTextChangedListener(new TextWatcher() {
@Override
public void beforeTextChanged(CharSequence s, int start, int count, int after) {
} }
});
@Override
public void onTextChanged(CharSequence s, int start, int before, int count) {
} }
@Override
protected void initWidget() {
super.initWidget();
createCaptcha();
binding.etUsername.requestFocus();
binding.etUsername.getEditText().addTextChangedListener(new MyTextWatcher() {
@Override @Override
public void afterTextChanged(Editable s) { public void afterTextChanged(Editable s) {
StringUtils.isNotChinese(s); StringUtils.isNotChinese(s);
username = s.toString(); username = s.toString();
if (username.length() < 6 || username.length() > 14) { if (username.length() < 6 || username.length() > 14) {
mHandler.sendMessage(mHandler.obtainMessage(2, "用户名必须在6-14位之间")); showTip("用户名必须在6-14位之间");
} else if (!username.substring(0, 1).matches("^[A-Za-z]$")) { } else if (!username.substring(0, 1).matches("^[A-Za-z]$")) {
mHandler.sendMessage(mHandler.obtainMessage(2, showTip("用户名只能以字母开头");
"用户名只能以字母开头"));
} else if (!username.matches("^[A-Za-z0-9-_]+$")) { } else if (!username.matches("^[A-Za-z0-9-_]+$")) {
mHandler.sendMessage(mHandler.obtainMessage(2, showTip("用户名只能由数字、字母、下划线、减号组成");
"用户名只能由数字、字母、下划线、减号组成"));
} else { } else {
mHandler.sendMessage(mHandler.obtainMessage(3)); binding.tvRegisterTip.setVisibility(View.GONE);
} }
checkNotNone(); checkNotNone();
} }
}); });
binding.etPassword.getEditText().addTextChangedListener(new TextWatcher() { binding.etPassword.getEditText().addTextChangedListener(new MyTextWatcher() {
@Override
public void beforeTextChanged(CharSequence s, int start, int count, int after) {
}
@Override
public void onTextChanged(CharSequence s, int start, int before, int count) {
}
@Override @Override
public void afterTextChanged(Editable s) { public void afterTextChanged(Editable s) {
password = s.toString(); password = s.toString();
if (password.length() < 8 || password.length() > 16) { if (password.length() < 8 || password.length() > 16) {
mHandler.sendMessage(mHandler.obtainMessage(2, "密码必须在8-16位之间")); showTip("密码必须在8-16位之间");
} else if (password.matches("^\\d+$")) { } else if (password.matches("^\\d+$")) {
mHandler.sendMessage(mHandler.obtainMessage(2, "密码不能是纯数字")); showTip("密码不能是纯数字");
} else { } else {
mHandler.sendMessage(mHandler.obtainMessage(3)); binding.tvRegisterTip.setVisibility(View.GONE);
} }
checkNotNone(); checkNotNone();
} }
}); });
binding.etRpPassword.getEditText().addTextChangedListener(new TextWatcher() { binding.etEmail.getEditText().addTextChangedListener(new MyTextWatcher() {
@Override
public void beforeTextChanged(CharSequence s, int start, int count, int after) {
}
@Override
public void onTextChanged(CharSequence s, int start, int before, int count) {
}
@Override @Override
public void afterTextChanged(Editable s) { public void afterTextChanged(Editable s) {
rpPassword = s.toString(); email = s.toString();
if (!rpPassword.equals(password)){ if (!email.matches("^[_a-z0-9-]+(\\.[_a-z0-9-]+)*@[a-z0-9-]+(\\.[a-z0-9-]+)*(\\.[a-z]{2,})$")) {
mHandler.sendMessage(mHandler.obtainMessage(2, "两次输入的密码不一致")); showTip("邮箱格式错误");
} else { } else {
mHandler.sendMessage(mHandler.obtainMessage(3)); binding.tvRegisterTip.setVisibility(View.GONE);
} }
checkNotNone(); checkNotNone();
} }
}); });
binding.etCaptcha.getEditText().addTextChangedListener(new TextWatcher() { binding.etEmailCode.getEditText().addTextChangedListener(new MyTextWatcher() {
@Override @Override
public void beforeTextChanged(CharSequence s, int start, int count, int after) { public void afterTextChanged(Editable s) {
emailCode = s.toString().trim();
} checkNotNone();
@Override
public void onTextChanged(CharSequence s, int start, int before, int count) {
} }
});
binding.etCaptcha.getEditText().addTextChangedListener(new MyTextWatcher() {
@Override @Override
public void afterTextChanged(Editable s) { public void afterTextChanged(Editable s) {
inputCode = s.toString().trim().toLowerCase(); inputCode = s.toString().trim().toLowerCase();
if (!inputCode.equals(code.toLowerCase())) { if (!inputCode.equals(code.toLowerCase())) {
mHandler.sendMessage(mHandler.obtainMessage(2, "验证码错误")); showTip("验证码错误");
} else { } else {
mHandler.sendMessage(mHandler.obtainMessage(3)); binding.tvRegisterTip.setVisibility(View.GONE);
} }
checkNotNone(); checkNotNone();
} }
}); });
binding.tvAgreement.setMovementMethod(LinkMovementMethod.getInstance()); binding.cbAgreement.setMovementMethod(LinkMovementMethod.getInstance());
} }
@Override @Override
protected void initClick() { protected void initClick() {
super.initClick(); super.initClick();
binding.ivCaptcha.setOnClickListener(v -> mHandler.sendMessage(mHandler.obtainMessage(1))); binding.ivCaptcha.setOnClickListener(v -> createCaptcha());
binding.tvGetEmailCode.setOnClickListener(v -> {
if (!email.matches("^[_a-z0-9-]+(\\.[_a-z0-9-]+)*@[a-z0-9-]+(\\.[a-z0-9-]+)*(\\.[a-z]{2,})$")) {
ToastUtils.showWarring("请正确输入邮箱");
return;
}
dialog.show();
dialog.setmMessage("正在发送");
UserService2.INSTANCE.sendEmail(email, "reg", keyc).subscribe(new MySingleObserver<Result>() {
@Override
public void onSubscribe(Disposable d) {
addDisposable(d);
disp = d;
}
@Override
public void onSuccess(@NonNull Result result) {
if (result.getCode() == 106) {
ToastUtils.showSuccess("验证码发送成功");
keyc = result.getResult().toString();
timeDown(60);
} else {
ToastUtils.showWarring(result.getResult().toString());
}
dialog.dismiss();
}
@Override
public void onError(Throwable e) {
ToastUtils.showError("验证码发送失败:\n" + e.getLocalizedMessage());
dialog.dismiss();
}
});
});
binding.btRegister.setOnClickListener(v -> { binding.btRegister.setOnClickListener(v -> {
if (!username.matches("^[A-Za-z][A-Za-z0-9]{5,13}$")) { if (!username.matches("^[A-Za-z][A-Za-z0-9]{5,13}$")) {
@ -193,42 +197,49 @@ public class RegisterActivity extends BaseActivity {
} else if (password.matches("^\\d+$") || !password.matches("^.{8,16}$")) { } else if (password.matches("^\\d+$") || !password.matches("^.{8,16}$")) {
DialogCreator.createTipDialog(this, "密码格式错误", DialogCreator.createTipDialog(this, "密码格式错误",
"密码必须在8-16位之间\n密码不能是纯数字"); "密码必须在8-16位之间\n密码不能是纯数字");
}else if(!password.equals(rpPassword)){ } else if (!email.matches("^[_a-z0-9-]+(\\.[_a-z0-9-]+)*@[a-z0-9-]+(\\.[a-z0-9-]+)*(\\.[a-z]{2,})$")) {
DialogCreator.createTipDialog(this, "重复密码错误", DialogCreator.createTipDialog(this, "邮箱格式错误",
"两次输入的密码不一致"); "电子邮箱的正确写法为:用户名@邮箱网站.com(.cn等)");
}else if(!inputCode.trim().toLowerCase().equals(code.toLowerCase())){ } else if ("".equals(keyc)) {
DialogCreator.createTipDialog(this, "请先获取邮箱验证码");
} else if (emailCode.length() < 6) {
DialogCreator.createTipDialog(this, "请输入6位邮箱验证码");
} else if (!inputCode.trim().equalsIgnoreCase(code)) {
DialogCreator.createTipDialog(this, "验证码错误"); DialogCreator.createTipDialog(this, "验证码错误");
} else if (!binding.cbAgreement.isChecked()) { } else if (!binding.cbAgreement.isChecked()) {
DialogCreator.createTipDialog(this, "请勾选同意《用户服务协议》"); DialogCreator.createTipDialog(this, "请勾选同意《用户服务协议》");
} else { } else {
ProgressUtils.show(this, "正在注册..."); dialog.show();
Map<String, String> userRegisterInfo = new HashMap<>(); dialog.setmMessage("正在注册");
userRegisterInfo.put("username", username); User user = new User(username, CyptoUtils.encode(APPCONST.KEY, password), email);
userRegisterInfo.put("password", password); UserService2.INSTANCE.register(user, emailCode, keyc).subscribe(new MySingleObserver<Result>() {
UserService.register(userRegisterInfo, new ResultCallback() {
@Override @Override
public void onFinish(Object o, int code) { public void onSubscribe(Disposable d) {
String[] info = ((String) o).split(":"); addDisposable(d);
int result = Integer.parseInt(info[0].trim()); disp = d;
if (result == 101){ }
UserService.writeUsername(username);
ToastUtils.showSuccess(info[1]); @Override
public void onSuccess(@NonNull Result result) {
if (result.getCode() == 101) {
UserService2.INSTANCE.writeUsername(user.getUserName());
ToastUtils.showSuccess(result.getResult().toString());
finish(); finish();
} else { } else {
ToastUtils.showWarring(info[1]); ToastUtils.showWarring(result.getResult().toString());
} }
ProgressUtils.dismiss(); dialog.dismiss();
} }
@Override @Override
public void onError(Exception e) { public void onError(Throwable e) {
ToastUtils.showError("注册失败:\n" + e.getLocalizedMessage()); ToastUtils.showError("注册失败:\n" + e.getLocalizedMessage());
ProgressUtils.dismiss(); dialog.dismiss();
createCaptcha();
} }
}); });
} }
mHandler.sendMessage(mHandler.obtainMessage(1));
}); });
} }
public void createCaptcha() { public void createCaptcha() {
@ -242,17 +253,29 @@ public class RegisterActivity extends BaseActivity {
binding.tvRegisterTip.setText(tip); binding.tvRegisterTip.setText(tip);
} }
public void checkNotNone(){ private void timeDown(int time) {
if ("".equals(username) || "".equals(password) || "".equals(rpPassword) || "".equals(inputCode)){ if (time == 0) {
binding.btRegister.setEnabled(false); binding.tvGetEmailCode.setText(getString(R.string.re_get_email_code, ""));
binding.tvGetEmailCode.setEnabled(true);
} else { } else {
binding.btRegister.setEnabled(true); binding.tvGetEmailCode.setEnabled(false);
String timeStr = "(" + time + ")";
binding.tvGetEmailCode.setText(getString(R.string.re_get_email_code, timeStr));
App.getHandler().postDelayed(() -> timeDown(time - 1), 1000);
}
} }
public void checkNotNone() {
binding.btRegister.setEnabled(!"".equals(username) &&
!"".equals(password) &&
!"".equals(email) &&
!"".equals(emailCode) &&
!"".equals(inputCode));
} }
@Override @Override
protected void onDestroy() { protected void onDestroy() {
dialog.dismiss();
super.onDestroy(); super.onDestroy();
ProgressUtils.dismiss();
} }
} }

@ -165,7 +165,7 @@ class SearchWordActivity : BaseActivity() {
private fun search() { private fun search() {
val keyword = binding.etSearchKey.text.toString() val keyword = binding.etSearchKey.text.toString()
if (keyword.isNotEmpty() && this.keyword != keyword) { if (keyword.isNotEmpty() && (this.keyword != keyword || adapter.itemSize == 0)) {
this.keyword = keyword this.keyword = keyword
adapter.clear() adapter.clear()
binding.fabSearchStop.visibility = View.VISIBLE binding.fabSearchStop.visibility = View.VISIBLE

@ -2,7 +2,6 @@ package xyz.fycz.myreader.ui.fragment;
import android.annotation.SuppressLint; import android.annotation.SuppressLint;
import android.content.Intent; import android.content.Intent;
import android.net.Uri;
import android.os.Bundle; import android.os.Bundle;
import android.os.Handler; import android.os.Handler;
import android.os.Message; import android.os.Message;
@ -13,12 +12,12 @@ import android.view.ViewGroup;
import androidx.annotation.NonNull; import androidx.annotation.NonNull;
import androidx.annotation.Nullable; import androidx.annotation.Nullable;
import androidx.appcompat.app.AlertDialog;
import com.kongzue.dialogx.dialogs.BottomMenu; import com.kongzue.dialogx.dialogs.BottomMenu;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import java.io.File;
import java.text.SimpleDateFormat; import java.text.SimpleDateFormat;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Date; import java.util.Date;
@ -37,30 +36,29 @@ import xyz.fycz.myreader.common.APPCONST;
import xyz.fycz.myreader.databinding.FragmentMineBinding; import xyz.fycz.myreader.databinding.FragmentMineBinding;
import xyz.fycz.myreader.entity.Setting; import xyz.fycz.myreader.entity.Setting;
import xyz.fycz.myreader.greendao.entity.Book; import xyz.fycz.myreader.greendao.entity.Book;
import xyz.fycz.myreader.greendao.entity.ReadRecord;
import xyz.fycz.myreader.greendao.service.BookService; import xyz.fycz.myreader.greendao.service.BookService;
import xyz.fycz.myreader.model.backup.UserService; import xyz.fycz.myreader.model.user.Result;
import xyz.fycz.myreader.model.storage.Backup; 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.BackupRestoreUi;
import xyz.fycz.myreader.model.storage.BackupRestoreUiKt;
import xyz.fycz.myreader.model.storage.Restore; import xyz.fycz.myreader.model.storage.Restore;
import xyz.fycz.myreader.model.storage.WebDavHelp; import xyz.fycz.myreader.model.storage.WebDavHelp;
import xyz.fycz.myreader.model.user.UserService2;
import xyz.fycz.myreader.ui.activity.AboutActivity; import xyz.fycz.myreader.ui.activity.AboutActivity;
import xyz.fycz.myreader.ui.activity.AdSettingActivity; import xyz.fycz.myreader.ui.activity.AdSettingActivity;
import xyz.fycz.myreader.ui.activity.BookSourceActivity; import xyz.fycz.myreader.ui.activity.BookSourceActivity;
import xyz.fycz.myreader.ui.activity.DonateActivity; import xyz.fycz.myreader.ui.activity.DonateActivity;
import xyz.fycz.myreader.ui.activity.FeedbackActivity; import xyz.fycz.myreader.ui.activity.FeedbackActivity;
import xyz.fycz.myreader.ui.activity.LoginActivity;
import xyz.fycz.myreader.ui.activity.MainActivity; import xyz.fycz.myreader.ui.activity.MainActivity;
import xyz.fycz.myreader.ui.activity.MoreSettingActivity; import xyz.fycz.myreader.ui.activity.MoreSettingActivity;
import xyz.fycz.myreader.ui.activity.ReadRecordActivity; import xyz.fycz.myreader.ui.activity.ReadRecordActivity;
import xyz.fycz.myreader.ui.dialog.DialogCreator; 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.ui.dialog.MyAlertDialog;
import xyz.fycz.myreader.util.SharedPreUtils; import xyz.fycz.myreader.util.SharedPreUtils;
import xyz.fycz.myreader.util.ToastUtils; import xyz.fycz.myreader.util.ToastUtils;
import xyz.fycz.myreader.util.utils.GsonExtensionsKt;
import xyz.fycz.myreader.util.utils.ImageLoader;
import xyz.fycz.myreader.util.utils.NetworkUtils; import xyz.fycz.myreader.util.utils.NetworkUtils;
import xyz.fycz.myreader.util.utils.StoragePermissionUtils;
import xyz.fycz.myreader.webapi.ResultCallback; import xyz.fycz.myreader.webapi.ResultCallback;
import static android.app.Activity.RESULT_OK; import static android.app.Activity.RESULT_OK;
@ -73,20 +71,23 @@ public class MineFragment extends BaseFragment {
private FragmentMineBinding binding; private FragmentMineBinding binding;
//private boolean isLogin; private boolean isLogin;
private Setting mSetting; private Setting mSetting;
// private String[] webSynMenu; private String[] webSynMenu;
private String[] backupMenu; private String[] backupMenu;
// private AlertDialog themeModeDia; // private AlertDialog themeModeDia;
private int themeMode; private int themeMode;
private String[] themeModeArr; private String[] themeModeArr;
private User user;
private Disposable disp;
private LoadingDialog dialog;
@SuppressLint("HandlerLeak") @SuppressLint("HandlerLeak")
private Handler mHandler = new Handler() { private Handler mHandler = new Handler() {
@Override @Override
public void handleMessage(@NonNull Message msg) { public void handleMessage(@NonNull Message msg) {
switch (msg.what) { switch (msg.what) {
case 1: case 1:
//binding.tvUser.setText("登录/注册"); binding.tvUser.setText("登录/注册");
break; break;
case 2: case 2:
backup(); backup();
@ -110,34 +111,40 @@ public class MineFragment extends BaseFragment {
@Override @Override
protected void initData(Bundle savedInstanceState) { protected void initData(Bundle savedInstanceState) {
super.initData(savedInstanceState); super.initData(savedInstanceState);
//isLogin = UserService.isLogin(); user = UserService2.INSTANCE.readConfig();
isLogin = user != null && !TextUtils.isEmpty(user.getUserName());
mSetting = SysManager.getSetting(); mSetting = SysManager.getSetting();
/*webSynMenu = new String[]{ webSynMenu = new String[]{
App.getmContext().getString(R.string.menu_backup_webBackup), App.getmContext().getString(R.string.menu_backup_webBackup),
App.getmContext().getString(R.string.menu_backup_webRestore), App.getmContext().getString(R.string.menu_backup_webRestore),
App.getmContext().getString(R.string.menu_backup_autoSyn) App.getmContext().getString(R.string.menu_backup_autoSyn)
};*/ };
backupMenu = new String[]{ backupMenu = new String[]{
App.getmContext().getResources().getString(R.string.menu_backup_backup), App.getmContext().getResources().getString(R.string.menu_backup_backup),
App.getmContext().getResources().getString(R.string.menu_backup_restore), App.getmContext().getResources().getString(R.string.menu_backup_restore),
}; };
themeMode = App.getApplication().isNightFS() ? 0 : mSetting.isDayStyle() ? 1 : 2; themeMode = App.getApplication().isNightFS() ? 0 : mSetting.isDayStyle() ? 1 : 2;
themeModeArr = getResources().getStringArray(R.array.theme_mode_arr); themeModeArr = getResources().getStringArray(R.array.theme_mode_arr);
dialog = new LoadingDialog(getContext(), "正在同步", (LoadingDialog.OnCancelListener) () -> {
if (disp != null) {
disp.dispose();
}
});
} }
@Override @Override
protected void initWidget(Bundle savedInstanceState) { protected void initWidget(Bundle savedInstanceState) {
super.initWidget(savedInstanceState); super.initWidget(savedInstanceState);
/*if (isLogin) { if (isLogin) {
binding.tvUser.setText(UserService.readUsername()); binding.tvUser.setText(user.getUserName());
}*/ }
binding.tvThemeModeSelect.setText(themeModeArr[themeMode]); binding.tvThemeModeSelect.setText(themeModeArr[themeMode]);
} }
@Override @Override
protected void initClick() { protected void initClick() {
super.initClick(); super.initClick();
/*binding.mineRlUser.setOnClickListener(v -> { binding.mineRlUser.setOnClickListener(v -> {
if (isLogin) { if (isLogin) {
DialogCreator.createCommonDialog(getActivity(), "退出登录", "确定要退出登录吗?" DialogCreator.createCommonDialog(getActivity(), "退出登录", "确定要退出登录吗?"
, true, (dialog, which) -> { , true, (dialog, which) -> {
@ -156,7 +163,7 @@ public class MineFragment extends BaseFragment {
Intent intent = new Intent(getActivity(), LoginActivity.class); Intent intent = new Intent(getActivity(), LoginActivity.class);
getActivity().startActivityForResult(intent, APPCONST.REQUEST_LOGIN); getActivity().startActivityForResult(intent, APPCONST.REQUEST_LOGIN);
} }
});*/ });
binding.mineRlWebdav.setOnClickListener(v -> { binding.mineRlWebdav.setOnClickListener(v -> {
Intent intent = new Intent(getActivity(), MoreSettingActivity.class); Intent intent = new Intent(getActivity(), MoreSettingActivity.class);
@ -164,7 +171,7 @@ public class MineFragment extends BaseFragment {
startActivity(intent); startActivity(intent);
}); });
binding.mineRlSyn.setOnClickListener(v -> { /*binding.mineRlSyn.setOnClickListener(v -> {
String account = SharedPreUtils.getInstance().getString("webdavAccount"); String account = SharedPreUtils.getInstance().getString("webdavAccount");
String password = SharedPreUtils.getInstance().getString("webdavPassword"); String password = SharedPreUtils.getInstance().getString("webdavPassword");
if (TextUtils.isEmpty(account) || TextUtils.isEmpty(password)) { if (TextUtils.isEmpty(account) || TextUtils.isEmpty(password)) {
@ -182,6 +189,7 @@ public class MineFragment extends BaseFragment {
public void onSubscribe(Disposable d) { public void onSubscribe(Disposable d) {
addDisposable(d); addDisposable(d);
} }
@Override @Override
public void onSuccess(ArrayList<String> strings) { public void onSuccess(ArrayList<String> strings) {
if (!WebDavHelp.INSTANCE.showRestoreDialog(strings, new Restore.CallBack() { if (!WebDavHelp.INSTANCE.showRestoreDialog(strings, new Restore.CallBack() {
@ -204,7 +212,7 @@ public class MineFragment extends BaseFragment {
} }
} }
}); });
}); });*/
binding.mineRlBookSource.setOnClickListener(v -> { binding.mineRlBookSource.setOnClickListener(v -> {
startActivity(new Intent(getContext(), BookSourceActivity.class)); startActivity(new Intent(getContext(), BookSourceActivity.class));
}); });
@ -239,8 +247,8 @@ public class MineFragment extends BaseFragment {
return false; return false;
}).setCancelButton(R.string.cancel); }).setCancelButton(R.string.cancel);
}); });
/*binding.mineRlSyn.setOnClickListener(v -> { binding.mineRlSyn.setOnClickListener(v -> {
if (!UserService.isLogin()) { if (!isLogin) {
ToastUtils.showWarring("请先登录!"); ToastUtils.showWarring("请先登录!");
Intent loginIntent = new Intent(getActivity(), LoginActivity.class); Intent loginIntent = new Intent(getActivity(), LoginActivity.class);
getActivity().startActivityForResult(loginIntent, APPCONST.REQUEST_LOGIN); getActivity().startActivityForResult(loginIntent, APPCONST.REQUEST_LOGIN);
@ -278,7 +286,7 @@ public class MineFragment extends BaseFragment {
.setNegativeButton(null, null) .setNegativeButton(null, null)
.setPositiveButton(null, null) .setPositiveButton(null, null)
.show(); .show();
});*/ });
binding.mineRlReadRecord.setOnClickListener(v -> { binding.mineRlReadRecord.setOnClickListener(v -> {
startActivity(new Intent(getContext(), ReadRecordActivity.class)); startActivity(new Intent(getContext(), ReadRecordActivity.class));
@ -470,10 +478,17 @@ public class MineFragment extends BaseFragment {
SharedPreUtils spb = SharedPreUtils.getInstance(); SharedPreUtils spb = SharedPreUtils.getInstance();
String synTime = spb.getString(getString(R.string.synTime)); String synTime = spb.getString(getString(R.string.synTime));
if (!nowTimeStr.equals(synTime) || !isAutoSyn) { if (!nowTimeStr.equals(synTime) || !isAutoSyn) {
UserService.webBackup(new ResultCallback() { dialog.show();
UserService2.INSTANCE.webBackup(user).subscribe(new MySingleObserver<Result>() {
@Override @Override
public void onFinish(Object o, int code) { public void onSubscribe(Disposable d) {
if ((boolean) o) { addDisposable(d);
disp = d;
}
@Override
public void onSuccess(@NonNull Result result) {
if (result.getCode() == 104) {
spb.putString(getString(R.string.synTime), nowTimeStr); spb.putString(getString(R.string.synTime), nowTimeStr);
if (!isAutoSyn) { if (!isAutoSyn) {
DialogCreator.createTipDialog(getContext(), "成功将书架同步至网络!"); DialogCreator.createTipDialog(getContext(), "成功将书架同步至网络!");
@ -483,16 +498,19 @@ public class MineFragment extends BaseFragment {
DialogCreator.createTipDialog(getContext(), "同步失败,请重试!"); DialogCreator.createTipDialog(getContext(), "同步失败,请重试!");
} }
} }
dialog.dismiss();
} }
@Override @Override
public void onError(Exception e) { public void onError(Throwable e) {
if (!isAutoSyn) { if (!isAutoSyn) {
DialogCreator.createTipDialog(getContext(), "同步失败,请重试!\n" + e.getLocalizedMessage()); DialogCreator.createTipDialog(getContext(), "同步失败,请重试!\n" + e.getLocalizedMessage());
} }
dialog.dismiss();
} }
}); });
} }
} }
/** /**
@ -516,10 +534,17 @@ public class MineFragment extends BaseFragment {
} else { } else {
DialogCreator.createTipDialog(getContext(), "未找到同步文件,同步失败!"); DialogCreator.createTipDialog(getContext(), "未找到同步文件,同步失败!");
}*/ }*/
UserService.webRestore(new ResultCallback() { dialog.show();
UserService2.INSTANCE.webRestore(user).subscribe(new MySingleObserver<Result>() {
@Override @Override
public void onFinish(Object o, int code) { public void onSubscribe(Disposable d) {
if ((boolean) o) { addDisposable(d);
disp = d;
}
@Override
public void onSuccess(@NonNull Result result) {
if (result.getCode() < 200) {
mHandler.sendMessage(mHandler.obtainMessage(7)); mHandler.sendMessage(mHandler.obtainMessage(7));
// DialogCreator.createTipDialog(mMainActivity, // DialogCreator.createTipDialog(mMainActivity,
// "恢复成功!\n注意:本功能属于实验功能,书架恢复后,书籍初次加载时可能加载失败,返回重新加载即可!");、 // "恢复成功!\n注意:本功能属于实验功能,书架恢复后,书籍初次加载时可能加载失败,返回重新加载即可!");、
@ -532,10 +557,12 @@ public class MineFragment extends BaseFragment {
} else { } else {
DialogCreator.createTipDialog(getContext(), "未找到同步文件,同步失败!"); DialogCreator.createTipDialog(getContext(), "未找到同步文件,同步失败!");
} }
dialog.dismiss();
} }
@Override @Override
public void onError(Exception e) { public void onError(Throwable e) {
DialogCreator.createTipDialog(getContext(), "未找到同步文件,同步失败!\n" + e.getLocalizedMessage());
DialogCreator.createTipDialog(getContext(), "未找到同步文件,同步失败!\n" + e.getLocalizedMessage()); DialogCreator.createTipDialog(getContext(), "未找到同步文件,同步失败!\n" + e.getLocalizedMessage());
} }
}); });
@ -547,13 +574,14 @@ public class MineFragment extends BaseFragment {
public void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) { public void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) {
if (resultCode == RESULT_OK) { if (resultCode == RESULT_OK) {
switch (requestCode) { switch (requestCode) {
/*case APPCONST.REQUEST_LOGIN: case APPCONST.REQUEST_LOGIN:
assert data != null; assert data != null;
isLogin = data.getBooleanExtra("isLogin", false); isLogin = data.getBooleanExtra("isLogin", false);
if (isLogin) { user = UserService2.INSTANCE.readConfig();
binding.tvUser.setText(UserService.readUsername()); if (isLogin && user != null) {
binding.tvUser.setText(user.getUserName());
} }
break;*/ break;
} }
} }
} }

@ -6,23 +6,19 @@ import android.app.Notification;
import android.app.PendingIntent; import android.app.PendingIntent;
import android.content.*; import android.content.*;
import android.graphics.BitmapFactory; import android.graphics.BitmapFactory;
import android.os.Build;
import android.os.Handler; import android.os.Handler;
import android.os.Message; import android.os.Message;
import android.text.TextUtils;
import android.view.Gravity; import android.view.Gravity;
import android.view.MenuItem; import android.view.MenuItem;
import android.view.View; import android.view.View;
import android.widget.PopupMenu; import android.widget.PopupMenu;
import androidx.core.app.ActivityCompat;
import androidx.recyclerview.widget.GridLayoutManager; import androidx.recyclerview.widget.GridLayoutManager;
import androidx.recyclerview.widget.ItemTouchHelper; import androidx.recyclerview.widget.ItemTouchHelper;
import androidx.recyclerview.widget.LinearLayoutManager; import androidx.recyclerview.widget.LinearLayoutManager;
import com.hjq.permissions.OnPermissionCallback; import com.hjq.permissions.OnPermissionCallback;
import com.hjq.permissions.Permission;
import com.hjq.permissions.XXPermissions; import com.hjq.permissions.XXPermissions;
import com.kongzue.dialogx.dialogs.BottomMenu; import com.kongzue.dialogx.dialogs.BottomMenu;
@ -31,7 +27,6 @@ import org.jetbrains.annotations.NotNull;
import java.text.Collator; import java.text.Collator;
import java.text.SimpleDateFormat; import java.text.SimpleDateFormat;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections; import java.util.Collections;
import java.util.Date; import java.util.Date;
import java.util.List; import java.util.List;
@ -39,7 +34,6 @@ import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors; import java.util.concurrent.Executors;
import io.reactivex.Observable; import io.reactivex.Observable;
import io.reactivex.Observer;
import io.reactivex.disposables.Disposable; import io.reactivex.disposables.Disposable;
import io.reactivex.schedulers.Schedulers; import io.reactivex.schedulers.Schedulers;
import xyz.fycz.myreader.R; import xyz.fycz.myreader.R;
@ -55,12 +49,11 @@ import xyz.fycz.myreader.webapi.ResultCallback;
import xyz.fycz.myreader.common.APPCONST; import xyz.fycz.myreader.common.APPCONST;
import xyz.fycz.myreader.greendao.entity.BookGroup; import xyz.fycz.myreader.greendao.entity.BookGroup;
import xyz.fycz.myreader.greendao.service.BookGroupService; import xyz.fycz.myreader.greendao.service.BookGroupService;
import xyz.fycz.myreader.model.backup.UserService; import xyz.fycz.myreader.model.user.UserService;
import xyz.fycz.myreader.ui.activity.*; import xyz.fycz.myreader.ui.activity.*;
import xyz.fycz.myreader.webapi.crawler.base.ReadCrawler; import xyz.fycz.myreader.webapi.crawler.base.ReadCrawler;
import xyz.fycz.myreader.webapi.crawler.ReadCrawlerUtil; import xyz.fycz.myreader.webapi.crawler.ReadCrawlerUtil;
import xyz.fycz.myreader.ui.dialog.DialogCreator; import xyz.fycz.myreader.ui.dialog.DialogCreator;
import xyz.fycz.myreader.widget.custom.DragSortGridView;
import xyz.fycz.myreader.entity.Setting; import xyz.fycz.myreader.entity.Setting;
import xyz.fycz.myreader.enums.BookcaseStyle; import xyz.fycz.myreader.enums.BookcaseStyle;
import xyz.fycz.myreader.greendao.entity.Book; import xyz.fycz.myreader.greendao.entity.Book;

@ -88,7 +88,7 @@ public class StringHelper {
//生成随机数字和字母, //生成随机数字和字母,
public static String getStringRandom(int length) { public static String getStringRandom(int length) {
String val = ""; StringBuilder val = new StringBuilder();
Random random = new Random(); Random random = new Random();
//参数length,表示生成几位随机数 //参数length,表示生成几位随机数
@ -98,12 +98,12 @@ public class StringHelper {
if( "char".equalsIgnoreCase(charOrNum) ) { if( "char".equalsIgnoreCase(charOrNum) ) {
//输出是大写字母还是小写字母 //输出是大写字母还是小写字母
int temp = random.nextInt(2) % 2 == 0 ? 65 : 97; int temp = random.nextInt(2) % 2 == 0 ? 65 : 97;
val += (char)(random.nextInt(26) + temp); val.append((char) (random.nextInt(26) + temp));
} else if( "num".equalsIgnoreCase(charOrNum) ) { } else if( "num".equalsIgnoreCase(charOrNum) ) {
val += String.valueOf(random.nextInt(10)); val.append(String.valueOf(random.nextInt(10)));
} }
} }
return val; return val.toString();
} }
public static String jidToUsername(String jid){ public static String jidToUsername(String jid){

@ -13,7 +13,7 @@ import okhttp3.MediaType;
import okhttp3.RequestBody; import okhttp3.RequestBody;
import xyz.fycz.myreader.base.observer.MySingleObserver; import xyz.fycz.myreader.base.observer.MySingleObserver;
import xyz.fycz.myreader.common.URLCONST; import xyz.fycz.myreader.common.URLCONST;
import xyz.fycz.myreader.model.backup.UserService; import xyz.fycz.myreader.model.user.UserService;
import xyz.fycz.myreader.util.SharedPreUtils; import xyz.fycz.myreader.util.SharedPreUtils;
import xyz.fycz.myreader.util.help.DateHelper; import xyz.fycz.myreader.util.help.DateHelper;

@ -316,12 +316,10 @@ public class FileUtils {
public static void write(Context context, String fileName, String content) { public static void write(Context context, String fileName, String content) {
if (content == null) if (content == null)
content = ""; content = "";
try { try {
FileOutputStream fos = context.openFileOutput(fileName, FileOutputStream fos = context.openFileOutput(fileName,
Context.MODE_PRIVATE); Context.MODE_PRIVATE);
fos.write(content.getBytes()); fos.write(content.getBytes());
fos.close(); fos.close();
} catch (Exception e) { } catch (Exception e) {
e.printStackTrace(); e.printStackTrace();

@ -0,0 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:color="@color/textSecondary" android:state_enabled="false" />
<item android:color="@color/sys_color"/>
</selector>

Binary file not shown.

Before

Width:  |  Height:  |  Size: 134 KiB

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

@ -0,0 +1,125 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:fitsSystemWindows="true"
android:orientation="vertical">
<include layout="@layout/toolbar" />
<!--添加标题和输入框-->
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_margin="10dp"
android:orientation="vertical"
android:padding="10dp">
<!--标题-->
<TextView
android:id="@+id/tv_title"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="@string/text_register"
android:textAlignment="center"
android:textColor="@color/textPrimary"
android:textSize="@dimen/text_senior_size" />
<TextView
android:id="@+id/tv_register_tip"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="10dp"
android:text=""
android:textColor="@color/textError"
android:visibility="gone" />
<com.google.android.material.textfield.TextInputLayout
android:id="@+id/et_email"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:drawablePadding="10dp"
app:counterEnabled="true"
app:counterMaxLength="100">
<com.google.android.material.textfield.TextInputEditText
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:hint="@string/et_email"
android:inputType="text" />
</com.google.android.material.textfield.TextInputLayout>
<com.google.android.material.textfield.TextInputLayout
android:id="@+id/et_password"
android:visibility="gone"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:drawablePadding="10dp"
app:counterEnabled="true"
app:counterMaxLength="16"
app:passwordToggleEnabled="true"
app:passwordToggleTintMode="src_in">
<com.google.android.material.textfield.TextInputEditText
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:hint="@string/et_new_password_tip"
android:inputType="textPassword" />
</com.google.android.material.textfield.TextInputLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal">
<com.google.android.material.textfield.TextInputLayout
android:id="@+id/et_email_code"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_weight="1"
android:drawablePadding="10dp"
app:counterEnabled="true"
app:counterMaxLength="6">
<com.google.android.material.textfield.TextInputEditText
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:hint="@string/et_email_captcha"
android:inputType="text" />
</com.google.android.material.textfield.TextInputLayout>
<TextView
android:id="@+id/tv_get_email_code"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_weight="2.5"
android:gravity="center"
android:text="@string/get_email_code"
android:textColor="@color/selector_get_emali_code"
android:textSize="@dimen/text_small_size" />
</LinearLayout>
<!--登录按钮-->
<Button
android:id="@+id/bt_submit"
android:layout_width="match_parent"
android:layout_height="50dp"
android:layout_marginTop="10dp"
android:background="@drawable/login_btn_selector"
android:enabled="false"
android:text="@string/text_register"
android:textAlignment="center"
android:textColor="#ffffff"
android:textSize="@dimen/text_large_size" />
</LinearLayout>
</LinearLayout>

@ -1,113 +1,22 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="match_parent" android:layout_height="match_parent"
android:background="@color/colorBackground"
android:fitsSystemWindows="true" android:fitsSystemWindows="true"
android:orientation="vertical"> android:orientation="vertical">
<include layout="@layout/toolbar" /> <include layout="@layout/toolbar" />
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="match_parent">
<!--背景图片-->
<ImageView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:scaleType="fitXY"
app:srcCompat="@drawable/bg_login" />
<!--添加虚化层-->
<io.alterac.blurkit.BlurLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
app:blk_blurRadius="5"
app:blk_fps="0" />
<!-- 猫头鹰-->
<!-- <RelativeLayout-->
<!-- android:layout_width="300dp"-->
<!-- android:layout_height="200dp"-->
<!-- android:layout_centerHorizontal="true"-->
<!-- android:layout_alignTop="@+id/bg"-->
<!-- android:layout_marginTop="-75dp">-->
<!-- &lt;!&ndash;头像&ndash;&gt;-->
<!-- <ImageView-->
<!-- android:id="@+id/iv_head"-->
<!-- android:layout_width="wrap_content"-->
<!-- android:layout_height="wrap_content"-->
<!-- android:src="@drawable/owl_head"-->
<!-- android:layout_centerHorizontal="true"-->
<!-- />-->
<!-- &lt;!&ndash;手掌&ndash;&gt;-->
<!-- <ImageView-->
<!-- android:id="@+id/iv_left_hand"-->
<!-- android:layout_width="50dp"-->
<!-- android:layout_height="60dp"-->
<!-- android:src="@drawable/icon_hand"-->
<!-- android:layout_alignParentLeft="true"-->
<!-- android:layout_alignBottom="@+id/iv_head"-->
<!-- android:layout_marginBottom="-25dp"-->
<!-- android:layout_marginLeft="10dp"/>-->
<!-- <ImageView-->
<!-- android:id="@+id/iv_right_hand"-->
<!-- android:layout_width="50dp"-->
<!-- android:layout_height="60dp"-->
<!-- android:src="@drawable/icon_hand"-->
<!-- android:layout_alignParentRight="true"-->
<!-- android:layout_alignBottom="@+id/iv_head"-->
<!-- android:layout_marginBottom="-25dp"-->
<!-- android:layout_marginRight="10dp"/>-->
<!-- &lt;!&ndash;翅膀&ndash;&gt;-->
<!-- <ImageView-->
<!-- android:id="@+id/iv_left_arm"-->
<!-- android:layout_width="65dp"-->
<!-- android:layout_height="40dp"-->
<!-- android:src="@drawable/arm_left"-->
<!-- android:layout_below="@+id/iv_head"-->
<!-- android:layout_alignParentLeft="true"-->
<!-- android:layout_marginLeft="20dp"/>-->
<!-- <ImageView-->
<!-- android:id="@+id/iv_right_arm"-->
<!-- android:layout_width="65dp"-->
<!-- android:layout_height="40dp"-->
<!-- android:src="@drawable/arm_right"-->
<!-- android:layout_below="@+id/iv_head"-->
<!-- android:layout_alignParentRight="true"-->
<!-- android:layout_marginRight="20dp"/>-->
<!-- </RelativeLayout>-->
<View
android:id="@+id/bg"
android:layout_width="match_parent"
android:layout_height="280dp"
android:layout_centerInParent="true"
android:layout_marginLeft="20dp"
android:layout_marginRight="20dp"
android:background="@drawable/input_bg_shape" />
<io.alterac.blurkit.BlurLayout
android:layout_width="match_parent"
android:layout_height="280dp"
android:layout_centerInParent="true"
android:layout_marginLeft="20dp"
android:layout_marginRight="20dp"
app:blk_blurRadius="20"
app:blk_fps="0" />
<!--添加标题和输入框--> <!--添加标题和输入框-->
<LinearLayout <LinearLayout
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_centerInParent="true" android:layout_margin="10dp"
android:layout_marginLeft="20dp"
android:layout_marginRight="20dp"
android:orientation="vertical" android:orientation="vertical"
android:padding="20dp"> android:padding="10dp">
<!--标题--> <!--标题-->
<TextView <TextView
@ -115,22 +24,8 @@
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:text="@string/text_login" android:text="@string/text_login"
android:textAlignment="center" android:textAlignment="center"
android:textColor="@color/textSecondary" android:textColor="@color/textPrimary"
android:textSize="20dp" /> android:textSize="@dimen/text_senior_size" />
<!--添加输入框-->
<!--<EditText
android:id="@+id/et_user"
android:layout_width="match_parent"
android:layout_height="50dp"
android:background="@drawable/editview_shape"
android:drawableStart="@drawable/iconfont_user"
android:drawablePadding="10dp"
android:hint="@string/et_account_tip"
android:inputType="text"
android:maxLines="1"
android:paddingStart="10dp"
android:textSize="18dp" />-->
<com.google.android.material.textfield.TextInputLayout <com.google.android.material.textfield.TextInputLayout
android:id="@+id/et_user" android:id="@+id/et_user"
@ -148,14 +43,6 @@
android:inputType="text" /> android:inputType="text" />
</com.google.android.material.textfield.TextInputLayout> </com.google.android.material.textfield.TextInputLayout>
<!--<EditText
android:id="@+id/et_password"
style="@style/EditTextStyle"
android:background="@drawable/editview_shape"
android:drawableStart="@drawable/iconfont_password"
android:hint="@string/et_password_tip"
android:inputType="textPassword"
android:textSize="18dp" />-->
<com.google.android.material.textfield.TextInputLayout <com.google.android.material.textfield.TextInputLayout
android:id="@+id/et_password" android:id="@+id/et_password"
@ -174,20 +61,12 @@
android:inputType="textPassword" /> android:inputType="textPassword" />
</com.google.android.material.textfield.TextInputLayout> </com.google.android.material.textfield.TextInputLayout>
<LinearLayout <LinearLayout
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:orientation="horizontal"> android:orientation="horizontal">
<!--<EditText
android:id="@+id/et_captcha"
style="@style/EditTextStyle"
android:layout_width="match_parent"
android:layout_weight="1"
android:background="@drawable/editview_shape"
android:hint="@string/et_rp_captcha"
android:inputType="text"
android:textSize="18dp" />-->
<com.google.android.material.textfield.TextInputLayout <com.google.android.material.textfield.TextInputLayout
android:id="@+id/et_captcha" android:id="@+id/et_captcha"
android:layout_width="match_parent" android:layout_width="match_parent"
@ -209,33 +88,46 @@
android:id="@+id/iv_captcha" android:id="@+id/iv_captcha"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_weight="3"
android:layout_gravity="center_vertical" android:layout_gravity="center_vertical"
android:paddingStart="7dp" /> android:layout_weight="2"
android:paddingStart="7dp"
tools:ignore="RtlSymmetry" />
</LinearLayout> </LinearLayout>
<!--登录按钮--> <!--登录按钮-->
<Button <Button
android:id="@+id/bt_login" android:id="@+id/bt_login"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="50dp" android:layout_height="45dp"
android:layout_marginTop="20dp" android:layout_marginTop="20dp"
android:background="@drawable/login_btn_selector" android:background="@drawable/login_btn_selector"
android:enabled="false" android:enabled="false"
android:text="@string/text_login" android:text="@string/text_login"
android:textAlignment="center" android:textAlignment="center"
android:textColor="@color/textPrimaryInverted" android:textColor="@color/textPrimaryInverted"
android:textSize="25dp" /> android:textSize="@dimen/text_large_size" />
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="10dp">
<TextView <TextView
android:id="@+id/tv_register" android:id="@+id/tv_register"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_marginTop="10dp"
android:text="@string/tv_register" android:text="@string/tv_register"
android:textColor="@color/colorAccent" /> android:textColor="@color/colorAccent" />
</LinearLayout>
</RelativeLayout>
<TextView
android:id="@+id/tv_forgot_pwd"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentEnd="true"
android:text="@string/tv_forget_pwd"
android:textColor="@color/colorAccent" />
</RelativeLayout>
</LinearLayout> </LinearLayout>
</LinearLayout>

@ -1,6 +1,7 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="match_parent" android:layout_height="match_parent"
android:fitsSystemWindows="true" android:fitsSystemWindows="true"
@ -8,58 +9,24 @@
<include layout="@layout/toolbar" /> <include layout="@layout/toolbar" />
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="match_parent">
<!--背景图片-->
<ImageView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:scaleType="fitXY"
app:srcCompat="@drawable/bg_login" />
<!--添加虚化层-->
<io.alterac.blurkit.BlurLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
app:blk_blurRadius="5"
app:blk_fps="0" />
<View
android:id="@+id/bg"
android:layout_width="match_parent"
android:layout_height="280dp"
android:layout_centerInParent="true"
android:layout_marginLeft="20dp"
android:layout_marginRight="20dp"
android:background="@drawable/input_bg_shape" />
<io.alterac.blurkit.BlurLayout
android:layout_width="match_parent"
android:layout_height="400dp"
android:layout_centerInParent="true"
android:layout_marginLeft="20dp"
android:layout_marginRight="20dp"
app:blk_blurRadius="20"
app:blk_fps="0" />
<!--添加标题和输入框--> <!--添加标题和输入框-->
<LinearLayout <LinearLayout
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_centerInParent="true" android:layout_margin="10dp"
android:layout_marginLeft="20dp"
android:layout_marginRight="20dp"
android:orientation="vertical" android:orientation="vertical"
android:padding="20dp"> android:padding="10dp">
<!--标题--> <!--标题-->
<TextView <TextView
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:text="@string/text_register" android:text="@string/text_register"
android:textAlignment="center" android:textAlignment="center"
android:textColor="@color/sys_word_little" android:textColor="@color/textPrimary"
android:textSize="20dp" /> android:textSize="@dimen/text_senior_size" />
<TextView <TextView
android:id="@+id/tv_register_tip" android:id="@+id/tv_register_tip"
@ -105,25 +72,56 @@
</com.google.android.material.textfield.TextInputLayout> </com.google.android.material.textfield.TextInputLayout>
<com.google.android.material.textfield.TextInputLayout
android:id="@+id/et_email"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:drawablePadding="10dp"
app:counterEnabled="true"
app:counterMaxLength="100">
<com.google.android.material.textfield.TextInputEditText
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:hint="@string/et_email"
android:inputType="text" />
</com.google.android.material.textfield.TextInputLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal">
<com.google.android.material.textfield.TextInputLayout <com.google.android.material.textfield.TextInputLayout
android:id="@+id/et_rp_password" android:id="@+id/et_email_code"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_weight="1"
android:drawablePadding="10dp" android:drawablePadding="10dp"
app:counterEnabled="true" app:counterEnabled="true"
app:counterMaxLength="16" app:counterMaxLength="6">
app:passwordToggleEnabled="true"
app:passwordToggleTintMode="src_in">
<com.google.android.material.textfield.TextInputEditText <com.google.android.material.textfield.TextInputEditText
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:hint="@string/et_password_tip" android:hint="@string/et_email_captcha"
android:inputType="textPassword"/> android:inputType="text" />
</com.google.android.material.textfield.TextInputLayout> </com.google.android.material.textfield.TextInputLayout>
<TextView
android:id="@+id/tv_get_email_code"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:gravity="center"
android:textColor="@color/selector_get_emali_code"
android:text="@string/get_email_code"
android:textSize="@dimen/text_small_size"
android:layout_weight="2.5" />
</LinearLayout>
<LinearLayout <LinearLayout
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
@ -152,8 +150,9 @@
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_gravity="center_vertical" android:layout_gravity="center_vertical"
android:layout_weight="3" android:layout_weight="2.5"
android:paddingStart="7dp" /> android:paddingStart="7dp"
tools:ignore="RtlSymmetry" />
</LinearLayout> </LinearLayout>
@ -168,38 +167,19 @@
android:text="@string/text_register" android:text="@string/text_register"
android:textAlignment="center" android:textAlignment="center"
android:textColor="#ffffff" android:textColor="#ffffff"
android:textSize="25dp" /> android:textSize="@dimen/text_large_size" />
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="10dp"
android:orientation="horizontal">
<CheckBox <CheckBox
android:id="@+id/cb_agreement" android:id="@+id/cb_agreement"
android:layout_width="wrap_content" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_marginTop="10dp"
android:textColorLink="@color/colorAccent"
android:text="@string/text_agreement_tip" android:text="@string/text_agreement_tip"
android:textColor="@color/textSecondaryInverted" android:textColor="@color/textPrimary"
android:theme="@style/MyCheckBox" /> android:theme="@style/MyCheckBox" />
<TextView
android:id="@+id/tv_agreement"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/link_agreement"
android:textColor="@color/colorAccent"
android:textSize="14dp" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="》"
android:textColor="@color/textSecondaryInverted" />
</LinearLayout>
</LinearLayout> </LinearLayout>
</RelativeLayout>
</LinearLayout> </LinearLayout>

@ -13,7 +13,7 @@
android:layout_height="match_parent" android:layout_height="match_parent"
android:orientation="vertical"> android:orientation="vertical">
<!--<RelativeLayout <RelativeLayout
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="25dp" android:layout_height="25dp"
android:paddingLeft="5dp" android:paddingLeft="5dp"
@ -56,7 +56,7 @@
android:textSize="@dimen/text_medium_size" android:textSize="@dimen/text_medium_size"
android:text="登录/注册"/> android:text="登录/注册"/>
</RelativeLayout>--> </RelativeLayout>
<RelativeLayout <RelativeLayout
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="25dp" android:layout_height="25dp"

@ -22,6 +22,7 @@
<dimen name="text_small_size">14sp</dimen> <dimen name="text_small_size">14sp</dimen>
<dimen name="text_normal_size">16sp</dimen> <dimen name="text_normal_size">16sp</dimen>
<dimen name="text_medium_size">18sp</dimen> <dimen name="text_medium_size">18sp</dimen>
<dimen name="text_senior_size">20sp</dimen>
<dimen name="text_large_size">22sp</dimen> <dimen name="text_large_size">22sp</dimen>
<dimen name="default_padding_top">5dp</dimen> <dimen name="default_padding_top">5dp</dimen>
<dimen name="default_padding_bottom">5dp</dimen> <dimen name="default_padding_bottom">5dp</dimen>

@ -89,15 +89,16 @@
<string name="stop_download_tip">停止</string> <string name="stop_download_tip">停止</string>
<string name="text_login">登录</string> <string name="text_login">登录</string>
<string name="tv_register">新用户注册</string> <string name="tv_register">新用户注册</string>
<string name="tv_forget_pwd">忘记密码</string>
<string name="et_password_tip">请输入密码</string> <string name="et_password_tip">请输入密码</string>
<string name="et_rp_password_tip">请再次输入密码</string> <string name="et_new_password_tip">请输入新密码</string>
<string name="et_email">请输入邮箱</string>
<string name="et_rp_captcha">请输入验证码</string> <string name="et_rp_captcha">请输入验证码</string>
<string name="et_email_captcha">请输入邮箱验证码</string>
<string name="et_account_tip">请输入用户名</string> <string name="et_account_tip">请输入用户名</string>
<string name="text_register">注册</string> <string name="text_register">注册</string>
<string name="text_agreement_tip">我已阅读并同意《</string> <string name="text_agreement_tip">我已阅读并同意《<a href="https://shimo.im/docs/RgkDpd3D3Gp6t3rD">用户服务协议</a></string>
<string name="link_agreement">
<a href="https://shimo.im/docs/RgkDpd3D3Gp6t3rD">用户服务协议</a>
</string>
<string name="add_book_mark">添加书签</string> <string name="add_book_mark">添加书签</string>
<string name="share_app">分享软件</string> <string name="share_app">分享软件</string>
<string name="update_log">更新日志</string> <string name="update_log">更新日志</string>
@ -515,6 +516,8 @@
<string name="search_word">内容搜索</string> <string name="search_word">内容搜索</string>
<string name="search_word_tip">搜索书籍已缓存的内容</string> <string name="search_word_tip">搜索书籍已缓存的内容</string>
<string name="clear_result">清除搜索结果</string> <string name="clear_result">清除搜索结果</string>
<string name="get_email_code">发送验证码</string>
<string name="re_get_email_code">重新发送%s</string>
<string-array name="reset_screen_time"> <string-array name="reset_screen_time">

@ -1,3 +1,3 @@
#Fri Jun 18 21:45:31 CST 2021 #Fri Jun 18 21:45:31 CST 2021
VERSION_CODE=226 VERSION_CODE=227
NEED_CREATE_RELEASE=false NEED_CREATE_RELEASE=false

Loading…
Cancel
Save