diff --git a/app/build.gradle b/app/build.gradle
index 1c6c7a570..3a59b113a 100644
--- a/app/build.gradle
+++ b/app/build.gradle
@@ -69,6 +69,11 @@ dependencies {
//协程
implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-core: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'
+
testImplementation 'junit:junit:4.12'
androidTestImplementation 'androidx.test:runner:1.1.1'
androidTestImplementation 'androidx.test.espresso:espresso-core:3.1.1'
diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml
index 10ee7aea6..7c5e32f4a 100644
--- a/app/src/main/AndroidManifest.xml
+++ b/app/src/main/AndroidManifest.xml
@@ -39,6 +39,7 @@
+
\ No newline at end of file
diff --git a/app/src/main/java/io/legado/app/App.kt b/app/src/main/java/io/legado/app/App.kt
index d94919f22..6ef0e877d 100644
--- a/app/src/main/java/io/legado/app/App.kt
+++ b/app/src/main/java/io/legado/app/App.kt
@@ -1,6 +1,7 @@
package io.legado.app
import android.app.Application
+import io.legado.app.data.AppDatabase
class App : Application() {
@@ -8,10 +9,15 @@ class App : Application() {
@JvmStatic
lateinit var INSTANCE: App
private set
+
+ @JvmStatic
+ lateinit var db: AppDatabase
+ private set
}
override fun onCreate() {
super.onCreate()
INSTANCE = this
+ db = AppDatabase.createDatabase(INSTANCE)
}
}
diff --git a/app/src/main/java/io/legado/app/constant/AppConst.kt b/app/src/main/java/io/legado/app/constant/AppConst.kt
index 6f9e7b6b9..89a1d204f 100644
--- a/app/src/main/java/io/legado/app/constant/AppConst.kt
+++ b/app/src/main/java/io/legado/app/constant/AppConst.kt
@@ -4,4 +4,8 @@ object AppConst {
const val channelIdDownload = "channel_download"
const val channelIdReadAloud = "channel_read_aloud"
const val channelIdWeb = "channel_web"
+
+ const val APP_TAG = "Legado"
+ const val RC_IMPORT_YUEDU_DATA = 100
+
}
\ No newline at end of file
diff --git a/app/src/main/java/io/legado/app/data/AppDatabase.kt b/app/src/main/java/io/legado/app/data/AppDatabase.kt
index 327651493..f5db6c908 100644
--- a/app/src/main/java/io/legado/app/data/AppDatabase.kt
+++ b/app/src/main/java/io/legado/app/data/AppDatabase.kt
@@ -7,6 +7,7 @@ import androidx.room.RoomDatabase
import androidx.room.migration.Migration
import androidx.sqlite.db.SupportSQLiteDatabase
import io.legado.app.data.dao.BookDao
+import io.legado.app.data.dao.ReplaceRuleDao
import io.legado.app.data.entities.Book
import io.legado.app.data.entities.Chapter
import io.legado.app.data.entities.ReplaceRule
@@ -51,5 +52,6 @@ abstract class AppDatabase : RoomDatabase() {
}
abstract fun bookDao(): BookDao
+ abstract fun replaceRuleDao(): ReplaceRuleDao
}
\ No newline at end of file
diff --git a/app/src/main/java/io/legado/app/data/dao/ReplaceRuleDao.kt b/app/src/main/java/io/legado/app/data/dao/ReplaceRuleDao.kt
new file mode 100644
index 000000000..9b92e4c6a
--- /dev/null
+++ b/app/src/main/java/io/legado/app/data/dao/ReplaceRuleDao.kt
@@ -0,0 +1,49 @@
+package io.legado.app.data.dao
+
+import androidx.lifecycle.LiveData
+import androidx.paging.DataSource
+import androidx.room.*
+import io.legado.app.data.entities.ReplaceRule
+
+
+@Dao
+interface ReplaceRuleDao {
+
+ @Query("SELECT * FROM replace_rules ORDER BY sortOrder ASC")
+ fun observeAll(): DataSource.Factory
+
+ @Query("SELECT id FROM replace_rules ORDER BY sortOrder ASC")
+ fun observeAllIds(): LiveData>
+
+ @get:Query("SELECT MAX(sortOrder) FROM replace_rules")
+ val maxOrder: Int
+
+ @get:Query("SELECT * FROM replace_rules ORDER BY sortOrder ASC")
+ val all: List
+
+ @get:Query("SELECT * FROM replace_rules WHERE isEnabled = 1 ORDER BY sortOrder ASC")
+ val allEnabled: List
+
+ @Query("SELECT * FROM replace_rules WHERE id = :id")
+ fun findById(id: Int): ReplaceRule?
+
+ @Query("SELECT * FROM replace_rules WHERE id in (:ids)")
+ fun findByIds(vararg ids: Int): List
+
+ @Query("SELECT * FROM replace_rules WHERE isEnabled = 1 AND scope LIKE '%' || :scope || '%'")
+ fun findEnabledByScope(scope: String): List
+
+ @Insert(onConflict = OnConflictStrategy.REPLACE)
+ fun insert(vararg replaceRules: ReplaceRule)
+
+ @Insert(onConflict = OnConflictStrategy.REPLACE)
+ fun insert(replaceRule: ReplaceRule): Long
+
+ @Update
+ fun update(vararg replaceRules: ReplaceRule)
+
+ @Delete
+ fun delete(vararg replaceRules: ReplaceRule)
+
+
+}
\ No newline at end of file
diff --git a/app/src/main/java/io/legado/app/data/entities/ReplaceRule.kt b/app/src/main/java/io/legado/app/data/entities/ReplaceRule.kt
index 2436fb641..8b5a0fda6 100644
--- a/app/src/main/java/io/legado/app/data/entities/ReplaceRule.kt
+++ b/app/src/main/java/io/legado/app/data/entities/ReplaceRule.kt
@@ -1,6 +1,7 @@
package io.legado.app.data.entities
import android.os.Parcelable
+import androidx.room.ColumnInfo
import androidx.room.Entity
import androidx.room.Index
import androidx.room.PrimaryKey
@@ -11,14 +12,15 @@ import kotlinx.android.parcel.Parcelize
indices = [(Index(value = ["id"]))])
data class ReplaceRule(
@PrimaryKey(autoGenerate = true)
- val id: Int = 0,
- val summary: String? = null,
- val pattern: String? = null,
- val replacement: String? = null,
- val scope: String? = null,
- val isEnabled: Boolean = true,
- val isRegex: Boolean = true,
- val order: Int = 0
+ var id: Int = 0,
+ var name: String? = null,
+ var pattern: String? = null,
+ var replacement: String? = null,
+ var scope: String? = null,
+ var isEnabled: Boolean = true,
+ var isRegex: Boolean = true,
+ @ColumnInfo(name = "sortOrder")
+ var order: Int = 0
) : Parcelable
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 cf4a2329d..db76d4916 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
@@ -1,7 +1,9 @@
package io.legado.app.ui.main
+import android.Manifest
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
@@ -9,18 +11,37 @@ import androidx.core.view.GravityCompat
import androidx.drawerlayout.widget.DrawerLayout
import androidx.lifecycle.ViewModelProvider
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.constant.AppConst.RC_IMPORT_YUEDU_DATA
+import io.legado.app.data.entities.ReplaceRule
+import io.legado.app.ui.replacerule.ReplaceRuleActivity
import io.legado.app.ui.search.SearchActivity
+import io.legado.app.utils.getSdPath
+import io.legado.app.utils.readBool
+import io.legado.app.utils.readInt
+import io.legado.app.utils.readString
import kotlinx.android.synthetic.main.activity_main.*
import kotlinx.android.synthetic.main.app_bar_main.*
-import kotlinx.android.synthetic.main.view_titlebar.*
+import org.jetbrains.anko.doAsync
+import org.jetbrains.anko.startActivity
+import org.jetbrains.anko.uiThread
+import pub.devrel.easypermissions.AfterPermissionGranted
+import pub.devrel.easypermissions.EasyPermissions
+import java.io.File
+import java.lang.Exception
class MainActivity : BaseActivity(), NavigationView.OnNavigationItemSelectedListener {
override val viewModel: MainViewModel
get() = ViewModelProvider.AndroidViewModelFactory.getInstance(application).create(MainViewModel::class.java)
override val layoutID: Int
get() = R.layout.activity_main
+ private val PERMISSONS = arrayOf(Manifest.permission.WRITE_EXTERNAL_STORAGE)
override fun onViewModelCreated(viewModel: MainViewModel, savedInstanceState: Bundle?) {
fab.setOnClickListener { startActivity(Intent(this, SearchActivity::class.java)) }
@@ -58,21 +79,17 @@ class MainActivity : BaseActivity(), NavigationV
override fun onNavigationItemSelected(item: MenuItem): Boolean {
// Handle navigation view item clicks here.
when (item.itemId) {
- R.id.nav_home -> {
+ R.id.nav_backup -> {
// Handle the camera action
}
- R.id.nav_gallery -> {
+ R.id.nav_import -> {
}
- R.id.nav_slideshow -> {
-
- }
- R.id.nav_tools -> {
-
- }
- R.id.nav_share -> {
+ R.id.nav_import_old -> importYueDu()
+ R.id.nav_import_github -> {
}
+ R.id.nav_replace_rule -> startActivity()
R.id.nav_send -> {
}
@@ -81,4 +98,60 @@ class MainActivity : BaseActivity(), NavigationV
drawerLayout.closeDrawer(GravityCompat.START)
return true
}
+
+ /*
+ * import from YueDu backup data
+ * */
+ @AfterPermissionGranted(RC_IMPORT_YUEDU_DATA)
+ fun importYueDu() {
+ if (!EasyPermissions.hasPermissions(this, Manifest.permission.WRITE_EXTERNAL_STORAGE)) {
+ EasyPermissions.requestPermissions(this, getString(R.string.perm_request_storage), RC_IMPORT_YUEDU_DATA, Manifest.permission.WRITE_EXTERNAL_STORAGE)
+ return
+ }
+
+ 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