diff --git a/app/build.gradle b/app/build.gradle index 966ba8516..215af4020 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -76,7 +76,6 @@ dependencies { implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-core:1.2.1' implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-android:1.2.1' //规则相关 - implementation 'pub.devrel:easypermissions:3.0.0' implementation 'com.google.code.gson:gson:2.8.5' implementation 'com.jayway.jsonpath:json-path:2.4.0' implementation 'org.jsoup:jsoup:1.12.1' diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index 7c5e32f4a..3bef8cc80 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -40,6 +40,9 @@ + + \ No newline at end of file diff --git a/app/src/main/java/io/legado/app/help/permission/ActivitySource.kt b/app/src/main/java/io/legado/app/help/permission/ActivitySource.kt new file mode 100644 index 000000000..e0618067a --- /dev/null +++ b/app/src/main/java/io/legado/app/help/permission/ActivitySource.kt @@ -0,0 +1,20 @@ +package io.legado.app.help.permission + +import android.content.Context +import android.content.Intent +import androidx.appcompat.app.AppCompatActivity + +import java.lang.ref.WeakReference + +internal class ActivitySource(activity: AppCompatActivity) : RequestSource { + + private val actRef: WeakReference = WeakReference(activity) + + override val context: Context? + get() = actRef.get() + + override fun startActivity(intent: Intent) { + actRef.get()?.startActivity(intent) + } + +} diff --git a/app/src/main/java/io/legado/app/help/permission/FragmentSource.kt b/app/src/main/java/io/legado/app/help/permission/FragmentSource.kt new file mode 100644 index 000000000..b66e11b98 --- /dev/null +++ b/app/src/main/java/io/legado/app/help/permission/FragmentSource.kt @@ -0,0 +1,19 @@ +package io.legado.app.help.permission + +import android.content.Context +import android.content.Intent +import androidx.fragment.app.Fragment + +import java.lang.ref.WeakReference + +internal class FragmentSource(fragment: Fragment) : RequestSource { + + private val fragRef: WeakReference = WeakReference(fragment) + + override val context: Context? + get() = fragRef.get()?.requireContext() + + override fun startActivity(intent: Intent) { + fragRef.get()?.startActivity(intent) + } +} diff --git a/app/src/main/java/io/legado/app/help/permission/OnPermissionsDeniedCallback.kt b/app/src/main/java/io/legado/app/help/permission/OnPermissionsDeniedCallback.kt new file mode 100644 index 000000000..d6e81a68f --- /dev/null +++ b/app/src/main/java/io/legado/app/help/permission/OnPermissionsDeniedCallback.kt @@ -0,0 +1,5 @@ +package io.legado.app.help.permission + +interface OnPermissionsDeniedCallback { + fun onPermissionsDenied(requestCode: Int, deniedPermissions: Array) +} diff --git a/app/src/main/java/io/legado/app/help/permission/OnPermissionsGrantedCallback.kt b/app/src/main/java/io/legado/app/help/permission/OnPermissionsGrantedCallback.kt new file mode 100644 index 000000000..59f6977d4 --- /dev/null +++ b/app/src/main/java/io/legado/app/help/permission/OnPermissionsGrantedCallback.kt @@ -0,0 +1,7 @@ +package io.legado.app.help.permission + +interface OnPermissionsGrantedCallback { + + fun onPermissionsGranted(requestCode: Int) + +} diff --git a/app/src/main/java/io/legado/app/help/permission/OnPermissionsResultCallback.kt b/app/src/main/java/io/legado/app/help/permission/OnPermissionsResultCallback.kt new file mode 100644 index 000000000..3d7afa600 --- /dev/null +++ b/app/src/main/java/io/legado/app/help/permission/OnPermissionsResultCallback.kt @@ -0,0 +1,9 @@ +package io.legado.app.help.permission + +interface OnPermissionsResultCallback { + + fun onPermissionsGranted(requestCode: Int) + + fun onPermissionsDenied(requestCode: Int, deniedPermissions: Array) + +} \ No newline at end of file diff --git a/app/src/main/java/io/legado/app/help/permission/OnRequestPermissionsResultCallback.kt b/app/src/main/java/io/legado/app/help/permission/OnRequestPermissionsResultCallback.kt new file mode 100644 index 000000000..b86983fd9 --- /dev/null +++ b/app/src/main/java/io/legado/app/help/permission/OnRequestPermissionsResultCallback.kt @@ -0,0 +1,11 @@ +package io.legado.app.help.permission + +import android.content.Intent + +interface OnRequestPermissionsResultCallback { + + fun onRequestPermissionsResult(requestCode: Int, permissions: Array, grantResults: IntArray) + + + fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) +} diff --git a/app/src/main/java/io/legado/app/help/permission/PermissionActivity.kt b/app/src/main/java/io/legado/app/help/permission/PermissionActivity.kt new file mode 100644 index 000000000..98ecf5b67 --- /dev/null +++ b/app/src/main/java/io/legado/app/help/permission/PermissionActivity.kt @@ -0,0 +1,77 @@ +package io.legado.app.help.permission + +import android.content.Intent +import android.net.Uri +import android.os.Bundle +import android.provider.Settings +import android.view.KeyEvent +import androidx.appcompat.app.AppCompatActivity +import androidx.core.app.ActivityCompat +import io.legado.app.R +import org.jetbrains.anko.toast + +class PermissionActivity : AppCompatActivity() { + + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + val intent = intent + + when (intent.getIntExtra(KEY_INPUT_REQUEST_TYPE, Request.TYPE_REQUEST_PERMISSION)) { + Request.TYPE_REQUEST_PERMISSION//权限请求 + -> { + val requestCode = intent.getIntExtra(KEY_INPUT_PERMISSIONS_CODE, 1000) + val permissions = intent.getStringArrayExtra(KEY_INPUT_PERMISSIONS) + if (permissions != null) { + ActivityCompat.requestPermissions(this, permissions, requestCode) + } else { + finish() + } + } + Request.TYPE_REQUEST_SETTING//跳转到设置界面 + -> try { + val settingIntent = Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS) + settingIntent.data = Uri.fromParts("package", packageName, null) + startActivityForResult(settingIntent, Request.TYPE_REQUEST_SETTING) + } catch (e: Exception) { + toast(R.string.tip_cannot_jump_setting_page) + finish() + } + + } + } + + override fun onRequestPermissionsResult(requestCode: Int, permissions: Array, grantResults: IntArray) { + super.onRequestPermissionsResult(requestCode, permissions, grantResults) + RequestPlugins.sRequestCallback?.onRequestPermissionsResult(requestCode, permissions, grantResults) + finish() + } + + override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) { + super.onActivityResult(requestCode, resultCode, data) + RequestPlugins.sRequestCallback?.onActivityResult(requestCode, resultCode, data) + finish() + } + + override fun startActivity(intent: Intent) { + super.startActivity(intent) + overridePendingTransition(0, 0) + } + + override fun finish() { + super.finish() + overridePendingTransition(0, 0) + } + + override fun onKeyDown(keyCode: Int, event: KeyEvent): Boolean { + return if (keyCode == KeyEvent.KEYCODE_BACK) { + true + } else super.onKeyDown(keyCode, event) + } + + companion object { + + const val KEY_INPUT_REQUEST_TYPE = "KEY_INPUT_REQUEST_TYPE" + const val KEY_INPUT_PERMISSIONS_CODE = "KEY_INPUT_PERMISSIONS_CODE" + const val KEY_INPUT_PERMISSIONS = "KEY_INPUT_PERMISSIONS" + } +} diff --git a/app/src/main/java/io/legado/app/help/permission/Permissions.kt b/app/src/main/java/io/legado/app/help/permission/Permissions.kt new file mode 100644 index 000000000..e1c0893e3 --- /dev/null +++ b/app/src/main/java/io/legado/app/help/permission/Permissions.kt @@ -0,0 +1,72 @@ +package io.legado.app.help.permission + +object Permissions { + + const val READ_CALENDAR = "android.permission.READ_CALENDAR" + const val WRITE_CALENDAR = "android.permission.WRITE_CALENDAR" + + const val CAMERA = "android.permission.CAMERA" + + const val READ_CONTACTS = "android.permission.READ_CONTACTS" + const val WRITE_CONTACTS = "android.permission.WRITE_CONTACTS" + const val GET_ACCOUNTS = "android.permission.GET_ACCOUNTS" + + const val ACCESS_FINE_LOCATION = "android.permission.ACCESS_FINE_LOCATION" + const val ACCESS_COARSE_LOCATION = "android.permission.ACCESS_COARSE_LOCATION" + + const val RECORD_AUDIO = "android.permission.RECORD_AUDIO" + + const val READ_PHONE_STATE = "android.permission.READ_PHONE_STATE" + const val CALL_PHONE = "android.permission.CALL_PHONE" + const val READ_CALL_LOG = "android.permission.READ_CALL_LOG" + const val WRITE_CALL_LOG = "android.permission.WRITE_CALL_LOG" + const val ADD_VOICEMAIL = "com.android.voicemail.permission.ADD_VOICEMAIL" + const val USE_SIP = "android.permission.USE_SIP" + const val PROCESS_OUTGOING_CALLS = "android.permission.PROCESS_OUTGOING_CALLS" + + const val BODY_SENSORS = "android.permission.BODY_SENSORS" + + const val SEND_SMS = "android.permission.SEND_SMS" + const val RECEIVE_SMS = "android.permission.RECEIVE_SMS" + const val READ_SMS = "android.permission.READ_SMS" + const val RECEIVE_WAP_PUSH = "android.permission.RECEIVE_WAP_PUSH" + const val RECEIVE_MMS = "android.permission.RECEIVE_MMS" + + const val READ_EXTERNAL_STORAGE = "android.permission.READ_EXTERNAL_STORAGE" + const val WRITE_EXTERNAL_STORAGE = "android.permission.WRITE_EXTERNAL_STORAGE" + + object Group { + val CALENDAR = arrayOf(READ_CALENDAR, WRITE_CALENDAR) + + val CAMERA = arrayOf(Permissions.CAMERA) + + val CONTACTS = arrayOf(READ_CONTACTS, WRITE_CONTACTS, GET_ACCOUNTS) + + val LOCATION = arrayOf(ACCESS_FINE_LOCATION, ACCESS_COARSE_LOCATION) + + val MICROPHONE = arrayOf(RECORD_AUDIO) + + val PHONE = arrayOf( + READ_PHONE_STATE, + CALL_PHONE, + READ_CALL_LOG, + WRITE_CALL_LOG, + ADD_VOICEMAIL, + USE_SIP, + PROCESS_OUTGOING_CALLS + ) + + val SENSORS = arrayOf(BODY_SENSORS) + + val SMS = arrayOf( + SEND_SMS, + RECEIVE_SMS, + READ_SMS, + RECEIVE_WAP_PUSH, + RECEIVE_MMS + ) + + val STORAGE = arrayOf(READ_EXTERNAL_STORAGE, WRITE_EXTERNAL_STORAGE) + } + +} diff --git a/app/src/main/java/io/legado/app/help/permission/PermissionsCompat.kt b/app/src/main/java/io/legado/app/help/permission/PermissionsCompat.kt new file mode 100644 index 000000000..45ef0f885 --- /dev/null +++ b/app/src/main/java/io/legado/app/help/permission/PermissionsCompat.kt @@ -0,0 +1,78 @@ +package io.legado.app.help.permission + +import androidx.annotation.StringRes +import androidx.appcompat.app.AppCompatActivity +import androidx.fragment.app.Fragment + +class PermissionsCompat private constructor() { + + private var mRequest: Request? = null + + fun request() { + RequestManager.pushRequest(mRequest) + } + + class Builder { + private val mRequest: Request + + constructor(activity: AppCompatActivity) { + mRequest = Request(activity) + } + + constructor(fragment: Fragment) { + mRequest = Request(fragment) + } + + fun addPermissions(vararg permissions: String): Builder { + mRequest.addPermissions(*permissions) + return this + } + + fun requestCode(requestCode: Int): Builder { + mRequest.setRequestCode(requestCode) + return this + } + + fun onGranted(callback: (requestCode: Int) -> Unit): Builder { + mRequest.setOnGrantedCallback(object : OnPermissionsGrantedCallback { + override fun onPermissionsGranted(requestCode: Int) { + callback(requestCode) + } + }) + return this + } + + fun onDenied(callback: (requestCode: Int, deniedPermissions: Array) -> Unit): Builder { + mRequest.setOnDeniedCallback(object : OnPermissionsDeniedCallback { + override fun onPermissionsDenied(requestCode: Int, deniedPermissions: Array) { + callback(requestCode, deniedPermissions) + } + }) + return this + } + + fun rationale(rationale: CharSequence): Builder { + mRequest.setRationale(rationale) + return this + } + + fun rationale(@StringRes resId: Int): Builder { + mRequest.setRationale(resId) + return this + } + + fun build(): PermissionsCompat { + val compat = PermissionsCompat() + compat.mRequest = mRequest + return compat + } + + fun request(): PermissionsCompat { + val compat = build() + compat.mRequest = mRequest + compat.request() + return compat + } + } + +} diff --git a/app/src/main/java/io/legado/app/help/permission/Request.kt b/app/src/main/java/io/legado/app/help/permission/Request.kt new file mode 100644 index 000000000..c5d389fa6 --- /dev/null +++ b/app/src/main/java/io/legado/app/help/permission/Request.kt @@ -0,0 +1,199 @@ +package io.legado.app.help.permission + +import android.content.Intent +import android.content.pm.PackageManager +import android.os.Build +import androidx.annotation.StringRes +import androidx.appcompat.app.AlertDialog +import androidx.appcompat.app.AppCompatActivity +import androidx.core.content.ContextCompat +import androidx.fragment.app.Fragment +import io.legado.app.R +import org.jetbrains.anko.startActivity +import java.util.* + +internal class Request : OnRequestPermissionsResultCallback { + + var startTime: Long = 0 + private set + private var requestCode: Int = 0 + private var source: RequestSource? = null + private var permissions: ArrayList? = null + private var grantedCallback: OnPermissionsGrantedCallback? = null + private var deniedCallback: OnPermissionsDeniedCallback? = null + private var rationaleResId: Int = 0 + private var rationale: CharSequence? = null + + private var rationaleDialog: AlertDialog? = null + + private val deniedPermissions: Array? + get() { + val permissions: Array? + val size = this.permissions?.size ?: 0 + if (size > 0) { + permissions = this.permissions?.toTypedArray() + } else { + permissions = null + } + return getDeniedPermissions(permissions) + } + + constructor(activity: AppCompatActivity) { + source = ActivitySource(activity) + permissions = ArrayList() + } + + constructor(fragment: Fragment) { + source = FragmentSource(fragment) + permissions = ArrayList() + } + + fun addPermissions(vararg permissions: String) { + this.permissions?.addAll(Arrays.asList(*permissions)) + } + + fun setRequestCode(requestCode: Int) { + this.requestCode = requestCode + } + + fun setOnGrantedCallback(callback: OnPermissionsGrantedCallback) { + grantedCallback = callback + } + + fun setOnDeniedCallback(callback: OnPermissionsDeniedCallback) { + deniedCallback = callback + } + + fun setRationale(@StringRes resId: Int) { + rationaleResId = resId + rationale = null + } + + fun setRationale(rationale: CharSequence) { + this.rationale = rationale + rationaleResId = 0 + } + + fun start() { + RequestPlugins.setOnRequestPermissionsCallback(this) + + val deniedPermissions = deniedPermissions + + if (Build.VERSION.SDK_INT < Build.VERSION_CODES.M) { + if (deniedPermissions == null) { + onPermissionsGranted(requestCode) + } else { + val rationale = if (rationaleResId != 0) source?.context?.getText(rationaleResId) else rationale + if (rationale != null) { + showSettingDialog(rationale) { onPermissionsDenied(requestCode, deniedPermissions) } + } else { + onPermissionsDenied(requestCode, deniedPermissions) + } + } + } else { + if (deniedPermissions != null) { + source?.context?.startActivity( + Pair(PermissionActivity.KEY_INPUT_REQUEST_TYPE, TYPE_REQUEST_PERMISSION), + Pair(PermissionActivity.KEY_INPUT_PERMISSIONS_CODE, requestCode), + Pair(PermissionActivity.KEY_INPUT_PERMISSIONS, deniedPermissions) + ) + } else { + onPermissionsGranted(requestCode) + } + } + + startTime = System.currentTimeMillis() + } + + fun clear() { + grantedCallback = null + deniedCallback = null + } + + private fun getDeniedPermissions(permissions: Array?): Array? { + if (permissions != null) { + val deniedPermissionList = ArrayList() + for (permission in permissions) { + if (source?.context?.let { + ContextCompat.checkSelfPermission( + it, + permission + ) + } != PackageManager.PERMISSION_GRANTED + ) { + deniedPermissionList.add(permission) + } + } + val size = deniedPermissionList.size + if (size > 0) { + return deniedPermissionList.toTypedArray() + } + } + return null + } + + private fun showSettingDialog(rationale: CharSequence, cancel: () -> Unit) { + rationaleDialog?.dismiss() + source?.context?.let { + rationaleDialog = AlertDialog.Builder(it) + .setTitle(R.string.dialog_title) + .setMessage(rationale) + .setPositiveButton(R.string.dialog_setting) { _, _ -> + it.startActivity( + Pair( + PermissionActivity.KEY_INPUT_REQUEST_TYPE, + TYPE_REQUEST_SETTING + ) + ) + } + .setNegativeButton(R.string.dialog_cancel) { _, _ -> cancel() } + .show() + } + } + + private fun onPermissionsGranted(requestCode: Int) { + try { + grantedCallback?.onPermissionsGranted(requestCode) + } catch (ignore: Exception) { + } + + RequestPlugins.sResultCallback?.onPermissionsGranted(requestCode) + } + + private fun onPermissionsDenied(requestCode: Int, deniedPermissions: Array) { + try { + deniedCallback?.onPermissionsDenied(requestCode, deniedPermissions) + } catch (ignore: Exception) { + } + + RequestPlugins.sResultCallback?.onPermissionsDenied(requestCode, deniedPermissions) + } + + override fun onRequestPermissionsResult(requestCode: Int, permissions: Array, grantResults: IntArray) { + val deniedPermissions = getDeniedPermissions(permissions) + if (deniedPermissions != null) { + val rationale = if (rationaleResId != 0) source?.context?.getText(rationaleResId) else rationale + if (rationale != null) { + showSettingDialog(rationale) { onPermissionsDenied(requestCode, deniedPermissions) } + } else { + onPermissionsDenied(requestCode, deniedPermissions) + } + } else { + onPermissionsGranted(requestCode) + } + } + + override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) { + val deniedPermissions = deniedPermissions + if (deniedPermissions == null) { + onPermissionsGranted(this.requestCode) + } else { + onPermissionsDenied(this.requestCode, deniedPermissions) + } + } + + companion object { + const val TYPE_REQUEST_PERMISSION = 1 + const val TYPE_REQUEST_SETTING = 2 + } +} \ No newline at end of file diff --git a/app/src/main/java/io/legado/app/help/permission/RequestManager.kt b/app/src/main/java/io/legado/app/help/permission/RequestManager.kt new file mode 100644 index 000000000..e7f0eca52 --- /dev/null +++ b/app/src/main/java/io/legado/app/help/permission/RequestManager.kt @@ -0,0 +1,67 @@ +package io.legado.app.help.permission + +import android.os.Handler +import java.util.* + +internal object RequestManager : OnPermissionsResultCallback { + + private var requests: Stack? = null + private var request: Request? = null + + private val handler = Handler() + + private val requestRunnable = Runnable { + request?.start() + } + + private val isCurrentRequestInvalid: Boolean + get() = request?.let { System.currentTimeMillis() - it.startTime > 5 * 1000L } ?: true + + init { + RequestPlugins.setOnPermissionsResultCallback(this) + } + + fun pushRequest(request: Request?) { + if (request == null) return + + if (requests == null) { + requests = Stack() + } + + requests?.let { + val index = it.indexOf(request) + if (index >= 0) { + val to = it.size - 1 + if (index != to) { + Collections.swap(requests, index, to) + } + } else { + it.push(request) + } + + if (isCurrentRequestInvalid) { + this.request = it.pop() + handler.post(requestRunnable) + } + } + } + + private fun startNextRequest() { + request?.clear() + request = null + + requests?.let { + request = if (it.empty()) null else it.pop() + request?.let { handler.post(requestRunnable) } + } + } + + override fun onPermissionsGranted(requestCode: Int) { + startNextRequest() + } + + override fun onPermissionsDenied(requestCode: Int, deniedPermissions: Array) { + startNextRequest() + } + +} diff --git a/app/src/main/java/io/legado/app/help/permission/RequestPlugins.kt b/app/src/main/java/io/legado/app/help/permission/RequestPlugins.kt new file mode 100644 index 000000000..16370193f --- /dev/null +++ b/app/src/main/java/io/legado/app/help/permission/RequestPlugins.kt @@ -0,0 +1,20 @@ +package io.legado.app.help.permission + +internal object RequestPlugins { + + @Volatile + var sRequestCallback: OnRequestPermissionsResultCallback? = null + + @Volatile + var sResultCallback: OnPermissionsResultCallback? = null + + fun setOnRequestPermissionsCallback(callback: OnRequestPermissionsResultCallback) { + sRequestCallback = callback + } + + fun setOnPermissionsResultCallback(callback: OnPermissionsResultCallback) { + sResultCallback = callback + } + + +} diff --git a/app/src/main/java/io/legado/app/help/permission/RequestSource.kt b/app/src/main/java/io/legado/app/help/permission/RequestSource.kt new file mode 100644 index 000000000..73c89df43 --- /dev/null +++ b/app/src/main/java/io/legado/app/help/permission/RequestSource.kt @@ -0,0 +1,13 @@ +package io.legado.app.help.permission + +import android.content.Context +import android.content.Intent +import androidx.fragment.app.FragmentManager + +interface RequestSource { + + val context: Context? + + fun startActivity(intent: Intent) + +} diff --git a/app/src/main/java/io/legado/app/ui/main/MainActivity.kt b/app/src/main/java/io/legado/app/ui/main/MainActivity.kt index ce40a7e33..10bfe53c3 100644 --- a/app/src/main/java/io/legado/app/ui/main/MainActivity.kt +++ b/app/src/main/java/io/legado/app/ui/main/MainActivity.kt @@ -2,18 +2,32 @@ package io.legado.app.ui.main import android.content.Intent import android.os.Bundle +import android.util.Log import android.view.Menu import android.view.MenuItem import androidx.appcompat.app.ActionBarDrawerToggle import androidx.core.view.GravityCompat import androidx.drawerlayout.widget.DrawerLayout import com.google.android.material.navigation.NavigationView +import com.jayway.jsonpath.Configuration +import com.jayway.jsonpath.JsonPath +import com.jayway.jsonpath.Option +import io.legado.app.App import io.legado.app.R import io.legado.app.base.BaseActivity +import io.legado.app.constant.AppConst.APP_TAG +import io.legado.app.data.entities.ReplaceRule +import io.legado.app.help.permission.Permissions +import io.legado.app.help.permission.PermissionsCompat +import io.legado.app.ui.replacerule.ReplaceRuleActivity import io.legado.app.ui.search.SearchActivity -import io.legado.app.utils.getViewModel +import io.legado.app.utils.* import kotlinx.android.synthetic.main.activity_main.* import kotlinx.android.synthetic.main.app_bar_main.* +import org.jetbrains.anko.doAsync +import org.jetbrains.anko.startActivity +import org.jetbrains.anko.uiThread +import java.io.File class MainActivity : BaseActivity(), NavigationView.OnNavigationItemSelectedListener { override val viewModel: MainViewModel @@ -26,7 +40,7 @@ class MainActivity : BaseActivity(), NavigationV fab.setOnClickListener { startActivity(Intent(this, SearchActivity::class.java)) } val toggle = ActionBarDrawerToggle( - this, drawer_layout, titleBar.toolbar, + this, drawer_layout, title_bar.toolbar, R.string.navigation_drawer_open, R.string.navigation_drawer_close ) @@ -58,6 +72,20 @@ class MainActivity : BaseActivity(), NavigationV override fun onNavigationItemSelected(item: MenuItem): Boolean { // Handle navigation view item clicks here. when (item.itemId) { + R.id.nav_backup -> { + // Handle the camera action + } + R.id.nav_import -> { + + } + R.id.nav_import_old -> PermissionsCompat.Builder(this) + .addPermissions(*Permissions.Group.STORAGE) + .rationale(R.string.tip_perm_request_storage) + .onGranted { importYueDu() }.request() + R.id.nav_import_github -> { + + } + R.id.nav_replace_rule -> startActivity() R.id.nav_send -> { } @@ -66,4 +94,50 @@ class MainActivity : BaseActivity(), NavigationV drawerLayout.closeDrawer(GravityCompat.START) return true } + + /* + * import from YueDu backup data + * */ + fun importYueDu() { + val yuedu = File(getSdPath(), "YueDu") + val jsonPath = JsonPath.using( + Configuration.builder() + .options(Option.SUPPRESS_EXCEPTIONS) + .build() + ) + + // Replace rules + val rFile = File(yuedu, "myBookReplaceRule.json") + val replaceRules = mutableListOf() + if (rFile.exists()) try { + val items: List> = jsonPath.parse(rFile.readText()).read("$.*") + for (item in items) { + val jsonItem = jsonPath.parse(item) + val rRule = ReplaceRule() + rRule.name = jsonItem.readString("$.replaceSummary") + rRule.pattern = jsonItem.readString("$.regex") + rRule.replacement = jsonItem.readString("$.replacement") + rRule.isRegex = jsonItem.readBool("$.isRegex") + rRule.scope = jsonItem.readString("$.useTo") + rRule.isEnabled = jsonItem.readBool("$.enable") + rRule.order = jsonItem.readInt("$.serialNumber") + replaceRules.add(rRule) + // Log.e(APP_TAG, rRule.toString()) + } + + doAsync { + App.db.replaceRuleDao().insert(*replaceRules.toTypedArray()) + val count = App.db.replaceRuleDao().all.size + val maxId = App.db.replaceRuleDao().maxOrder + uiThread { + Log.e(APP_TAG, "$count records were inserted to database, and max id is $maxId.") + } + } + + } catch (e: Exception) { + Log.e(APP_TAG, e.localizedMessage) + } + } + + } diff --git a/app/src/main/java/io/legado/app/ui/widget/TitleBar.kt b/app/src/main/java/io/legado/app/ui/widget/TitleBar.kt index 548c22ec5..74226b58c 100644 --- a/app/src/main/java/io/legado/app/ui/widget/TitleBar.kt +++ b/app/src/main/java/io/legado/app/ui/widget/TitleBar.kt @@ -37,7 +37,6 @@ class TitleBar(context: Context, attrs: AttributeSet?) : AppBarLayout(context, a val attachToActivity = a.getBoolean(R.styleable.TitleBar_attachToActivity, true) val titleText = a.getString(R.styleable.TitleBar_title) val subtitleText = a.getString(R.styleable.TitleBar_subtitle) - a.recycle() toolbar.apply { if(showNavigationIcon){ @@ -71,6 +70,7 @@ class TitleBar(context: Context, attrs: AttributeSet?) : AppBarLayout(context, a } } + a.recycle() if (attachToActivity) { attachToActivity(context) diff --git a/app/src/main/res/layout/activity_search.xml b/app/src/main/res/layout/activity_search.xml index 9e2a9e07c..4b23ca3d4 100644 --- a/app/src/main/res/layout/activity_search.xml +++ b/app/src/main/res/layout/activity_search.xml @@ -12,7 +12,7 @@ tools:context="io.legado.app.ui.search.SearchActivity"> + app:layout_constraintTop_toBottomOf="@id/title_bar"> diff --git a/app/src/main/res/layout/app_bar_main.xml b/app/src/main/res/layout/app_bar_main.xml index ae86cf117..5eb482eab 100644 --- a/app/src/main/res/layout/app_bar_main.xml +++ b/app/src/main/res/layout/app_bar_main.xml @@ -8,7 +8,7 @@ tools:context=".ui.main.MainActivity"> diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 05315f8a9..29f6c8036 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -15,9 +15,17 @@ Send + 提示 + 取消 + 确定 + 去设置 + + 无法跳转至设置界面 + 阅读需要访问存储卡权限,请前往“设置”—”应用权限“—打开所需权限 + 点击重试 正在加载 - 阅读需要访问存储卡权限: + 编辑 删除 diff --git a/app/src/main/res/values/styles.xml b/app/src/main/res/values/styles.xml index 09ffdee29..5e0976fa8 100644 --- a/app/src/main/res/values/styles.xml +++ b/app/src/main/res/values/styles.xml @@ -1,4 +1,4 @@ - + + +