diff --git a/app/build.gradle b/app/build.gradle index 5a4c99f24..89c0b7d53 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -3,6 +3,10 @@ apply plugin: 'kotlin-android' apply plugin: 'kotlin-android-extensions' apply plugin: 'kotlin-kapt' +androidExtensions { + experimental = true +} + android { compileSdkVersion 28 defaultConfig { @@ -19,6 +23,19 @@ android { proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro' } } + + compileOptions { + sourceCompatibility = '1.8' + targetCompatibility = '1.8' + } + +} + + +kapt { + arguments { + arg("room.schemaLocation", "$projectDir/schemas") + } } dependencies { @@ -34,15 +51,22 @@ dependencies { implementation 'androidx.cardview:cardview:1.0.0' implementation 'com.google.android.material:material:1.0.0' + implementation 'androidx.lifecycle:lifecycle-extensions:2.0.0' + kapt 'androidx.lifecycle:lifecycle-compiler:2.0.0' + + implementation 'androidx.room:room-runtime:2.0.0' + kapt 'androidx.room:room-compiler:2.0.0' + implementation 'androidx.paging:paging-runtime:2.1.0' + //anko def anko_version = '0.10.8' implementation "org.jetbrains.anko:anko-sdk27:$anko_version" implementation "org.jetbrains.anko:anko-sdk27-listeners:$anko_version" - - + //协程 + implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-core:1.2.1' testImplementation 'junit:junit:4.12' androidTestImplementation 'androidx.test:runner:1.1.1' androidTestImplementation 'androidx.test.espresso:espresso-core:3.1.1' -} \ No newline at end of file +} diff --git a/app/src/main/java/io/legado/app/base/BaseActivity.kt b/app/src/main/java/io/legado/app/base/BaseActivity.kt new file mode 100644 index 000000000..45a4679a6 --- /dev/null +++ b/app/src/main/java/io/legado/app/base/BaseActivity.kt @@ -0,0 +1,55 @@ +package io.legado.app.base + +import android.os.Bundle +import android.view.MenuItem +import androidx.annotation.LayoutRes +import androidx.appcompat.app.AppCompatActivity + +abstract class BaseActivity : AppCompatActivity() { + + @LayoutRes + abstract fun getLayoutID(): Int + + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + setContentView(getLayoutID()) + } + + override fun onOptionsItemSelected(item: MenuItem?): Boolean { + item?.let { + if (it.itemId == android.R.id.home) { + supportFinishAfterTransition() + return true + } + } + return if (item == null) true else onCompatOptionsItemSelected(item) + } + + open fun onCompatOptionsItemSelected(item: MenuItem): Boolean { + return true + } + + override fun setTitle(title: CharSequence?) { + supportActionBar?.let { + it.title = title + } + } + + override fun setTitle(titleId: Int) { + supportActionBar?.let { + it.setTitle(titleId) + } + } + + fun setSubTitle(subtitle: CharSequence?){ + supportActionBar?.let { + it.subtitle = subtitle; + } + } + + fun setSubTitle(subtitleId: Int){ + supportActionBar?.let { + it.setSubtitle(subtitleId) + } + } +} \ No newline at end of file diff --git a/app/src/main/java/io/legado/app/base/README.md b/app/src/main/java/io/legado/app/base/README.md new file mode 100644 index 000000000..d28e27909 --- /dev/null +++ b/app/src/main/java/io/legado/app/base/README.md @@ -0,0 +1 @@ +## 基类 \ 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 new file mode 100644 index 000000000..71cb9dbb1 --- /dev/null +++ b/app/src/main/java/io/legado/app/data/AppDatabase.kt @@ -0,0 +1,52 @@ +package io.legado.app.data + +import android.content.Context +import androidx.room.Database +import androidx.room.Room +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.entities.Book + + +@Database(entities = [Book::class], version = 1, exportSchema = true) +// @TypeConverters(Converters::class) +abstract class AppDatabase : RoomDatabase() { + + companion object { + private const val DATABASE_NAME = "legado.db" + + + + private val MIGRATION_1_2: Migration = object : Migration(1, 2) { + override fun migrate(database: SupportSQLiteDatabase) { + database.run { + // execSQL("ALTER TABLE parsers ADD COLUMN fulltextScript TEXT") + // execSQL("ALTER TABLE feeds ADD COLUMN lastUpdateTime INTEGER NOT NULL DEFAULT 0") + // execSQL("DELETE FROM entries WHERE rowid NOT IN (SELECT MIN(rowid) FROM entries GROUP BY link)") + // execSQL("CREATE UNIQUE INDEX index_entries_link ON entries(link)") + } + } + } + + fun createDatabase(context: Context): AppDatabase { + return Room.databaseBuilder(context.applicationContext, AppDatabase::class.java, DATABASE_NAME) + // .addMigrations(MIGRATION_1_2) + // .addMigrations(MIGRATION_2_3) + // .addMigrations(MIGRATION_3_4) + // .addMigrations(MIGRATION_4_5) + // .addMigrations(MIGRATION_5_6) + .addCallback(object : Callback() { + override fun onCreate(db: SupportSQLiteDatabase) { + super.onCreate(db) + } + }) + .build() + } + + } + + abstract fun bookDao(): BookDao + +} \ No newline at end of file diff --git a/app/src/main/java/io/legado/app/data/dao/BookDao.kt b/app/src/main/java/io/legado/app/data/dao/BookDao.kt new file mode 100644 index 000000000..b6ad0ba40 --- /dev/null +++ b/app/src/main/java/io/legado/app/data/dao/BookDao.kt @@ -0,0 +1,19 @@ +package io.legado.app.data.dao + +import androidx.lifecycle.LiveData +import androidx.paging.DataSource +import androidx.room.Dao +import androidx.room.Query +import io.legado.app.data.entities.Book + + +@Dao +interface BookDao { + + @Query("SELECT * FROM books WHERE `group` = :group") + fun observeByGroup(group: Int): DataSource.Factory + + @Query("SELECT url FROM books WHERE `group` = :group") + fun observeUrlsByGroup(group: Int): LiveData> + +} \ No newline at end of file diff --git a/app/src/main/java/io/legado/app/data/entities/Book.kt b/app/src/main/java/io/legado/app/data/entities/Book.kt new file mode 100644 index 000000000..800ea42d9 --- /dev/null +++ b/app/src/main/java/io/legado/app/data/entities/Book.kt @@ -0,0 +1,34 @@ +package io.legado.app.data.entities + +import android.annotation.SuppressLint +import android.os.Parcelable +import androidx.room.* +import kotlinx.android.parcel.Parcelize + +@Parcelize +@Entity(tableName = "books", + indices = [(Index(value = ["url"]))]) +data class Book(@PrimaryKey + var url: String = "", + var name: String = "", + var tag: String = "", + var author: String? = null, + var coverUrl: String? = null, + var customCoverUrl: String? = null, + var introduction: String? = null, + var charset: String? = null, + var type: Int = 0, // 0: text, 1: audio + var group: Int = 0, // fenqu + var latestChapterName: String? = null, + var lastUpdateTime: Long? = null, + var latestChapterTime: Long? = null, + var durChapterIndex: Int = 0, + var durChapterPage: Int = 0, + var totalChapterNum: Int = 0, + var hasNewChapter: Boolean = false, + var allowUpdate: Boolean = true + ) : Parcelable { + + fun getUnreadChapterNum() = Math.max(totalChapterNum - durChapterIndex - 1, 0) + +} \ No newline at end of file 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 5e1b735d6..c11148349 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 @@ -8,8 +8,8 @@ import androidx.appcompat.app.AppCompatActivity import androidx.core.view.GravityCompat import androidx.drawerlayout.widget.DrawerLayout import com.google.android.material.navigation.NavigationView -import com.google.android.material.snackbar.Snackbar import io.legado.app.R +import io.legado.app.utils.longSnackbar import kotlinx.android.synthetic.main.activity_main.* import kotlinx.android.synthetic.main.app_bar_main.* @@ -22,10 +22,7 @@ class MainActivity : AppCompatActivity(), NavigationView.OnNavigationItemSelecte setSupportActionBar(toolbar) - fab.setOnClickListener { view -> - Snackbar.make(view, "Replace with your own action", Snackbar.LENGTH_LONG) - .setAction("Action", null).show() - } + fab.setOnClickListener { it.longSnackbar(R.string.app_name) } val toggle = ActionBarDrawerToggle( this, drawer_layout, toolbar, 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 new file mode 100644 index 000000000..da7d6ba71 --- /dev/null +++ b/app/src/main/java/io/legado/app/ui/widget/TitleBar.kt @@ -0,0 +1,40 @@ +package io.legado.app.ui.widget + +import android.content.Context +import android.util.AttributeSet +import android.widget.FrameLayout +import androidx.appcompat.app.AppCompatActivity +import io.legado.app.R +import kotlinx.android.synthetic.main.view_titlebar.view.* + +class TitleBar(context: Context, attrs: AttributeSet?) : FrameLayout(context, attrs) { + + init { + inflate(context, R.layout.view_titlebar, this) + } + + override fun onAttachedToWindow() { + super.onAttachedToWindow() + attachToActivity() + } + + private fun attachToActivity(){ + val activity = getCompatActivity(context) + activity?.let { + activity.setSupportActionBar(toolbar) + activity.supportActionBar?.let { + it.setDisplayHomeAsUpEnabled(true) + } + } + } + + private fun getCompatActivity(context: Context?): AppCompatActivity? { + if (context == null) return null + return when (context) { + is AppCompatActivity -> context + is androidx.appcompat.view.ContextThemeWrapper -> getCompatActivity(context.baseContext) + is android.view.ContextThemeWrapper -> getCompatActivity(context.baseContext) + else -> null + } + } +} \ No newline at end of file diff --git a/app/src/main/res/layout/view_titlebar.xml b/app/src/main/res/layout/view_titlebar.xml new file mode 100644 index 000000000..6f86e663a --- /dev/null +++ b/app/src/main/res/layout/view_titlebar.xml @@ -0,0 +1,16 @@ + + + + + + \ No newline at end of file