Merge branch 'master' into antecer

pull/487/head
Antecer 5 years ago committed by GitHub
commit 1d6b57ed13
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 2
      README.md
  2. 4
      app/build.gradle
  3. 10
      app/src/main/assets/updateLog.md
  4. 3
      app/src/main/java/io/legado/app/App.kt
  5. 8
      app/src/main/java/io/legado/app/base/BaseActivity.kt
  6. 15
      app/src/main/java/io/legado/app/data/AppDatabase.kt
  7. 24
      app/src/main/java/io/legado/app/data/dao/CacheDao.kt
  8. 6
      app/src/main/java/io/legado/app/data/entities/BookSource.kt
  9. 13
      app/src/main/java/io/legado/app/data/entities/Cache.kt
  10. 4
      app/src/main/java/io/legado/app/data/entities/RssSource.kt
  11. 39
      app/src/main/java/io/legado/app/help/CacheManager.kt
  12. 4
      app/src/main/java/io/legado/app/help/JsExtensions.kt
  13. 22
      app/src/main/java/io/legado/app/help/http/CookieStore.kt
  14. 28
      app/src/main/java/io/legado/app/help/http/api/CookieManager.kt
  15. 25
      app/src/main/java/io/legado/app/lib/theme/ATH.kt
  16. 5
      app/src/main/java/io/legado/app/model/Debug.kt
  17. 4
      app/src/main/java/io/legado/app/model/analyzeRule/AnalyzeRule.kt
  18. 23
      app/src/main/java/io/legado/app/model/analyzeRule/AnalyzeUrl.kt
  19. 1
      app/src/main/java/io/legado/app/model/analyzeRule/QueryTTF.kt
  20. 2
      app/src/main/java/io/legado/app/model/webBook/WebBook.kt
  21. 9
      app/src/main/java/io/legado/app/ui/book/cache/CacheViewModel.kt
  22. 13
      app/src/main/java/io/legado/app/ui/book/read/ReadBookBaseActivity.kt
  23. 5
      app/src/main/java/io/legado/app/ui/book/read/ReadMenu.kt
  24. 2
      app/src/main/java/io/legado/app/ui/book/read/config/AutoReadDialog.kt
  25. 2
      app/src/main/java/io/legado/app/ui/book/read/config/BgTextConfigDialog.kt
  26. 2
      app/src/main/java/io/legado/app/ui/book/read/config/ClickActionConfigDialog.kt
  27. 2
      app/src/main/java/io/legado/app/ui/book/read/config/MoreConfigDialog.kt
  28. 2
      app/src/main/java/io/legado/app/ui/book/read/config/ReadAloudDialog.kt
  29. 2
      app/src/main/java/io/legado/app/ui/book/read/config/ReadStyleDialog.kt
  30. 70
      app/src/main/java/io/legado/app/ui/book/read/page/ContentView.kt
  31. 2
      app/src/main/java/io/legado/app/ui/book/read/page/PageView.kt
  32. 8
      app/src/main/java/io/legado/app/ui/book/source/manage/BookSourceActivity.kt
  33. 2
      app/src/main/java/io/legado/app/ui/rss/source/edit/RssSourceEditActivity.kt
  34. 1
      app/src/main/java/io/legado/app/ui/welcome/WelcomeActivity.kt
  35. 4
      app/src/main/java/io/legado/app/ui/widget/BatteryView.kt
  36. 13
      app/src/main/java/io/legado/app/utils/ActivityExtensions.kt
  37. 12
      app/src/main/res/layout/dialog_read_aloud.xml
  38. 5
      app/src/main/res/layout/view_book_page.xml
  39. 12
      app/src/main/res/layout/view_read_menu.xml
  40. 2
      build.gradle

@ -5,7 +5,7 @@
## 阅读3.0 ## 阅读3.0
* [书源规则](https://alanskycn.gitee.io/teachme/) * [书源规则](https://alanskycn.gitee.io/teachme/)
* [更新日志](/app/src/main/assets/updateLog.md) * [更新日志](/app/src/main/assets/updateLog.md)
* [帮助文档](/app/src/main/assets/help/help.md) * [帮助文档](/app/src/main/assets/help/appHelp.md)
![image](https://github.com/gedoor/gedoor.github.io/blob/master/images/%E9%98%85%E8%AF%BB%E7%AE%80%E4%BB%8B1.jpg) ![image](https://github.com/gedoor/gedoor.github.io/blob/master/images/%E9%98%85%E8%AF%BB%E7%AE%80%E4%BB%8B1.jpg)
![image](https://github.com/gedoor/gedoor.github.io/blob/master/images/%E9%98%85%E8%AF%BB%E7%AE%80%E4%BB%8B2.jpg) ![image](https://github.com/gedoor/gedoor.github.io/blob/master/images/%E9%98%85%E8%AF%BB%E7%AE%80%E4%BB%8B2.jpg)

@ -111,7 +111,7 @@ kapt {
} }
dependencies { dependencies {
coreLibraryDesugaring 'com.android.tools:desugar_jdk_libs:1.1.0' coreLibraryDesugaring 'com.android.tools:desugar_jdk_libs:1.1.1'
implementation fileTree(dir: 'libs', include: ['*.jar']) implementation fileTree(dir: 'libs', include: ['*.jar'])
testImplementation 'junit:junit:4.13.1' testImplementation 'junit:junit:4.13.1'
androidTestImplementation 'androidx.test:runner:1.3.0' androidTestImplementation 'androidx.test:runner:1.3.0'
@ -122,7 +122,7 @@ dependencies {
//fireBase //fireBase
implementation 'com.google.firebase:firebase-analytics-ktx:18.0.0' implementation 'com.google.firebase:firebase-analytics-ktx:18.0.0'
implementation 'com.google.firebase:firebase-crashlytics-ktx:17.2.2' implementation 'com.google.firebase:firebase-crashlytics-ktx:17.3.0'
//androidX //androidX
implementation 'androidx.core:core-ktx:1.3.2' implementation 'androidx.core:core-ktx:1.3.2'

@ -3,6 +3,16 @@
* 关注合作公众号 **[小说拾遗]()** 获取好看的小说。 * 关注合作公众号 **[小说拾遗]()** 获取好看的小说。
* 旧版数据导入教程:先在旧版阅读(2.x)中进行备份,然后在新版阅读(3.x)【我的】->【备份与恢复】,选择【导入旧版本数据】。 * 旧版数据导入教程:先在旧版阅读(2.x)中进行备份,然后在新版阅读(3.x)【我的】->【备份与恢复】,选择【导入旧版本数据】。
**2020/11/18**
* 优化导航栏
* js添加java.log(msg: String)用于调试时输出消息
* js添加cookie变量,方法见io.legado.app.help.http.api.CookieManager
* js添加cache变量,可以用来存储token之类的临时值,可以设置保存时间,方法见io.legado.app.help.CacheManager
* 需要token的网站可以用js来写了,比如阿里tts
**2020/11/16**
* 修复导出添加替换净化引起的bug
**2020/11/15** **2020/11/15**
* 正文规则添加字体规则,返回ByteArray * 正文规则添加字体规则,返回ByteArray
* js添加方法: * js添加方法:

@ -34,8 +34,7 @@ class App : MultiDexApplication() {
lateinit var androidId: String lateinit var androidId: String
var versionCode = 0 var versionCode = 0
var versionName = "" var versionName = ""
var navigationBarHeight = 0
} }
override fun onCreate() { override fun onCreate() {

@ -10,6 +10,7 @@ import android.view.MenuItem
import android.view.View import android.view.View
import android.widget.FrameLayout import android.widget.FrameLayout
import androidx.appcompat.app.AppCompatActivity import androidx.appcompat.app.AppCompatActivity
import io.legado.app.App
import io.legado.app.R import io.legado.app.R
import io.legado.app.constant.AppConst import io.legado.app.constant.AppConst
import io.legado.app.constant.Theme import io.legado.app.constant.Theme
@ -71,6 +72,13 @@ abstract class BaseActivity(
observeLiveBus() observeLiveBus()
} }
override fun onWindowFocusChanged(hasFocus: Boolean) {
super.onWindowFocusChanged(hasFocus)
if (hasFocus) {
App.navigationBarHeight = navigationBarHeight
}
}
override fun onMultiWindowModeChanged(isInMultiWindowMode: Boolean, newConfig: Configuration?) { override fun onMultiWindowModeChanged(isInMultiWindowMode: Boolean, newConfig: Configuration?) {
super.onMultiWindowModeChanged(isInMultiWindowMode, newConfig) super.onMultiWindowModeChanged(isInMultiWindowMode, newConfig)
findViewById<TitleBar>(R.id.title_bar) findViewById<TitleBar>(R.id.title_bar)

@ -17,8 +17,8 @@ import java.util.*
entities = [Book::class, BookGroup::class, BookSource::class, BookChapter::class, entities = [Book::class, BookGroup::class, BookSource::class, BookChapter::class,
ReplaceRule::class, SearchBook::class, SearchKeyword::class, Cookie::class, ReplaceRule::class, SearchBook::class, SearchKeyword::class, Cookie::class,
RssSource::class, Bookmark::class, RssArticle::class, RssReadRecord::class, RssSource::class, Bookmark::class, RssArticle::class, RssReadRecord::class,
RssStar::class, TxtTocRule::class, ReadRecord::class, HttpTTS::class], RssStar::class, TxtTocRule::class, ReadRecord::class, HttpTTS::class, Cache::class],
version = 23, version = 24,
exportSchema = true exportSchema = true
) )
abstract class AppDatabase : RoomDatabase() { abstract class AppDatabase : RoomDatabase() {
@ -38,6 +38,7 @@ abstract class AppDatabase : RoomDatabase() {
abstract fun txtTocRule(): TxtTocRuleDao abstract fun txtTocRule(): TxtTocRuleDao
abstract fun readRecordDao(): ReadRecordDao abstract fun readRecordDao(): ReadRecordDao
abstract fun httpTTSDao(): HttpTTSDao abstract fun httpTTSDao(): HttpTTSDao
abstract fun cacheDao(): CacheDao
companion object { companion object {
@ -58,7 +59,8 @@ abstract class AppDatabase : RoomDatabase() {
migration_19_20, migration_19_20,
migration_20_21, migration_20_21,
migration_21_22, migration_21_22,
migration_22_23 migration_22_23,
migration_23_24
) )
.allowMainThreadQueries() .allowMainThreadQueries()
.addCallback(dbCallback) .addCallback(dbCallback)
@ -201,6 +203,13 @@ abstract class AppDatabase : RoomDatabase() {
database.execSQL("ALTER TABLE chapters ADD baseUrl TEXT NOT NULL DEFAULT ''") database.execSQL("ALTER TABLE chapters ADD baseUrl TEXT NOT NULL DEFAULT ''")
} }
} }
private val migration_23_24 = object : Migration(23, 24) {
override fun migrate(database: SupportSQLiteDatabase) {
database.execSQL("CREATE TABLE IF NOT EXISTS `caches` (`key` TEXT NOT NULL, `value` TEXT, `deadline` INTEGER NOT NULL, PRIMARY KEY(`key`))")
database.execSQL("CREATE UNIQUE INDEX IF NOT EXISTS `index_caches_key` ON `caches` (`key`)")
}
}
} }
} }

@ -0,0 +1,24 @@
package io.legado.app.data.dao
import androidx.room.Dao
import androidx.room.Insert
import androidx.room.OnConflictStrategy
import androidx.room.Query
import io.legado.app.data.entities.Cache
@Dao
interface CacheDao {
@Query("select value from caches where `key` = :key and (deadline = 0 or deadline > :now)")
fun get(key: String, now: Long): String?
@Insert(onConflict = OnConflictStrategy.REPLACE)
fun insert(vararg cache: Cache)
@Query("delete from caches where `key` = :key")
fun delete(key: String)
@Query("delete from caches where deadline > 0 and deadline < :now")
fun clearDeadline(now: Long)
}

@ -8,7 +8,9 @@ import io.legado.app.constant.AppConst
import io.legado.app.constant.BookType import io.legado.app.constant.BookType
import io.legado.app.data.entities.rule.* import io.legado.app.data.entities.rule.*
import io.legado.app.help.AppConfig import io.legado.app.help.AppConfig
import io.legado.app.help.CacheManager
import io.legado.app.help.JsExtensions import io.legado.app.help.JsExtensions
import io.legado.app.help.http.CookieStore
import io.legado.app.utils.ACache import io.legado.app.utils.ACache
import io.legado.app.utils.GSON import io.legado.app.utils.GSON
import io.legado.app.utils.fromJsonObject import io.legado.app.utils.fromJsonObject
@ -109,6 +111,8 @@ data class BookSource(
val bindings = SimpleBindings() val bindings = SimpleBindings()
bindings["baseUrl"] = bookSourceUrl bindings["baseUrl"] = bookSourceUrl
bindings["java"] = this bindings["java"] = this
bindings["cookie"] = CookieStore
bindings["cache"] = CacheManager
a = AppConst.SCRIPT_ENGINE.eval( a = AppConst.SCRIPT_ENGINE.eval(
it.substring(4, it.lastIndexOf("<")), it.substring(4, it.lastIndexOf("<")),
bindings bindings
@ -136,6 +140,8 @@ data class BookSource(
private fun evalJS(jsStr: String): Any { private fun evalJS(jsStr: String): Any {
val bindings = SimpleBindings() val bindings = SimpleBindings()
bindings["java"] = this bindings["java"] = this
bindings["cookie"] = CookieStore
bindings["cache"] = CacheManager
return AppConst.SCRIPT_ENGINE.eval(jsStr, bindings) return AppConst.SCRIPT_ENGINE.eval(jsStr, bindings)
} }

@ -0,0 +1,13 @@
package io.legado.app.data.entities
import androidx.room.Entity
import androidx.room.Index
import androidx.room.PrimaryKey
@Entity(tableName = "caches", indices = [(Index(value = ["key"], unique = true))])
data class Cache(
@PrimaryKey
val key: String = "",
var value: String? = null,
var deadline: Long = 0L
)

@ -6,7 +6,9 @@ import androidx.room.Index
import androidx.room.PrimaryKey import androidx.room.PrimaryKey
import io.legado.app.constant.AppConst import io.legado.app.constant.AppConst
import io.legado.app.help.AppConfig import io.legado.app.help.AppConfig
import io.legado.app.help.CacheManager
import io.legado.app.help.JsExtensions import io.legado.app.help.JsExtensions
import io.legado.app.help.http.CookieStore
import io.legado.app.utils.GSON import io.legado.app.utils.GSON
import io.legado.app.utils.fromJsonObject import io.legado.app.utils.fromJsonObject
import kotlinx.android.parcel.Parcelize import kotlinx.android.parcel.Parcelize
@ -76,6 +78,8 @@ data class RssSource(
private fun evalJS(jsStr: String): Any? { private fun evalJS(jsStr: String): Any? {
val bindings = SimpleBindings() val bindings = SimpleBindings()
bindings["java"] = this bindings["java"] = this
bindings["cookie"] = CookieStore
bindings["cache"] = CacheManager
return AppConst.SCRIPT_ENGINE.eval(jsStr, bindings) return AppConst.SCRIPT_ENGINE.eval(jsStr, bindings)
} }

@ -0,0 +1,39 @@
package io.legado.app.help
import io.legado.app.App
import io.legado.app.data.entities.Cache
@Suppress("unused")
object CacheManager {
/**
* saveTime 单位为秒
*/
@JvmOverloads
fun put(key: String, value: Any, saveTime: Int = 0) {
val deadline = if (saveTime == 0) 0 else System.currentTimeMillis() + saveTime * 1000
val cache = Cache(key, value.toString(), deadline)
App.db.cacheDao().insert(cache)
}
fun get(key: String): String? {
return App.db.cacheDao().get(key, System.currentTimeMillis())
}
fun getInt(key: String): Int? {
return get(key)?.toIntOrNull()
}
fun getLong(key: String): Long? {
return get(key)?.toLongOrNull()
}
fun getDouble(key: String): Double? {
return get(key)?.toDoubleOrNull()
}
fun getFloat(key: String): Float? {
return get(key)?.toFloatOrNull()
}
}

@ -5,6 +5,7 @@ import androidx.annotation.Keep
import io.legado.app.constant.AppConst.dateFormat import io.legado.app.constant.AppConst.dateFormat
import io.legado.app.help.http.CookieStore import io.legado.app.help.http.CookieStore
import io.legado.app.help.http.SSLHelper import io.legado.app.help.http.SSLHelper
import io.legado.app.model.Debug
import io.legado.app.model.analyzeRule.AnalyzeUrl import io.legado.app.model.analyzeRule.AnalyzeUrl
import io.legado.app.utils.* import io.legado.app.utils.*
import org.jsoup.Connection import org.jsoup.Connection
@ -206,4 +207,7 @@ interface JsExtensions {
return Base64.decode(str, flags) return Base64.decode(str, flags)
} }
fun log(msg: String) {
Debug.log(msg)
}
} }

@ -7,19 +7,17 @@ import com.franmontiel.persistentcookiejar.persistence.CookiePersistor
import com.franmontiel.persistentcookiejar.persistence.SerializableCookie import com.franmontiel.persistentcookiejar.persistence.SerializableCookie
import io.legado.app.App import io.legado.app.App
import io.legado.app.data.entities.Cookie import io.legado.app.data.entities.Cookie
import io.legado.app.help.coroutine.Coroutine import io.legado.app.help.http.api.CookieManager
import io.legado.app.utils.NetworkUtils import io.legado.app.utils.NetworkUtils
object CookieStore : CookiePersistor { object CookieStore : CookiePersistor, CookieManager {
fun setCookie(url: String, cookie: String?) { override fun setCookie(url: String, cookie: String?) {
Coroutine.async { val cookieBean = Cookie(NetworkUtils.getSubDomain(url), cookie ?: "")
val cookieBean = Cookie(NetworkUtils.getSubDomain(url), cookie ?: "") App.db.cookieDao().insert(cookieBean)
App.db.cookieDao().insert(cookieBean)
}
} }
fun replaceCookie(url: String, cookie: String) { override fun replaceCookie(url: String, cookie: String) {
if (TextUtils.isEmpty(url) || TextUtils.isEmpty(cookie)) { if (TextUtils.isEmpty(url) || TextUtils.isEmpty(cookie)) {
return return
} }
@ -34,16 +32,16 @@ object CookieStore : CookiePersistor {
} }
} }
fun getCookie(url: String): String { override fun getCookie(url: String): String {
val cookieBean = App.db.cookieDao().get(NetworkUtils.getSubDomain(url)) val cookieBean = App.db.cookieDao().get(NetworkUtils.getSubDomain(url))
return cookieBean?.cookie ?: "" return cookieBean?.cookie ?: ""
} }
fun removeCookie(url: String) { override fun removeCookie(url: String) {
App.db.cookieDao().delete(NetworkUtils.getSubDomain(url)) App.db.cookieDao().delete(NetworkUtils.getSubDomain(url))
} }
fun cookieToMap(cookie: String): MutableMap<String, String> { override fun cookieToMap(cookie: String): MutableMap<String, String> {
val cookieMap = mutableMapOf<String, String>() val cookieMap = mutableMapOf<String, String>()
if (cookie.isBlank()) { if (cookie.isBlank()) {
return cookieMap return cookieMap
@ -63,7 +61,7 @@ object CookieStore : CookiePersistor {
return cookieMap return cookieMap
} }
fun mapToCookie(cookieMap: Map<String, String>?): String? { override fun mapToCookie(cookieMap: Map<String, String>?): String? {
if (cookieMap == null || cookieMap.isEmpty()) { if (cookieMap == null || cookieMap.isEmpty()) {
return null return null
} }

@ -0,0 +1,28 @@
package io.legado.app.help.http.api
interface CookieManager {
/**
* 保存cookie
*/
fun setCookie(url: String, cookie: String?)
/**
* 替换cookie
*/
fun replaceCookie(url: String, cookie: String)
/**
* 获取cookie
*/
fun getCookie(url: String): String
/**
* 移除cookie
*/
fun removeCookie(url: String)
fun cookieToMap(cookie: String): MutableMap<String, String>
fun mapToCookie(cookieMap: Map<String, String>?): String?
}

@ -126,10 +126,8 @@ object ATH {
activity: Activity, activity: Activity,
color: Int = ThemeStore.navigationBarColor(activity) color: Int = ThemeStore.navigationBarColor(activity)
) { ) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { activity.window.navigationBarColor = color
activity.window.navigationBarColor = color setLightNavigationBar(activity, ColorUtils.isColorLight(color))
setLightNavigationBar(activity, ColorUtils.isColorLight(color))
}
} }
fun setLightNavigationBar(activity: Activity, enabled: Boolean) { fun setLightNavigationBar(activity: Activity, enabled: Boolean) {
@ -170,18 +168,15 @@ object ATH {
} }
fun setTaskDescriptionColor(activity: Activity, @ColorInt color: Int) { fun setTaskDescriptionColor(activity: Activity, @ColorInt color: Int) {
val color1: Int val color1: Int = ColorUtils.stripAlpha(color)
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { @Suppress("DEPRECATION")
color1 = ColorUtils.stripAlpha(color) activity.setTaskDescription(
@Suppress("DEPRECATION") ActivityManager.TaskDescription(
activity.setTaskDescription( activity.title as String,
ActivityManager.TaskDescription( null,
activity.title as String, color1
null,
color1
)
) )
} )
} }
fun setTint( fun setTint(

@ -41,6 +41,11 @@ object Debug {
callback?.printLog(state, printMsg) callback?.printLog(state, printMsg)
} }
@Synchronized
fun log(msg: String?) {
log(debugSource, msg, true)
}
fun cancelDebug(destroy: Boolean = false) { fun cancelDebug(destroy: Boolean = false) {
tasks.clear() tasks.clear()

@ -6,7 +6,9 @@ import io.legado.app.constant.AppConst.SCRIPT_ENGINE
import io.legado.app.constant.AppPattern.JS_PATTERN import io.legado.app.constant.AppPattern.JS_PATTERN
import io.legado.app.data.entities.BaseBook import io.legado.app.data.entities.BaseBook
import io.legado.app.data.entities.BookChapter import io.legado.app.data.entities.BookChapter
import io.legado.app.help.CacheManager
import io.legado.app.help.JsExtensions import io.legado.app.help.JsExtensions
import io.legado.app.help.http.CookieStore
import io.legado.app.utils.* import io.legado.app.utils.*
import org.jsoup.nodes.Entities import org.jsoup.nodes.Entities
import org.mozilla.javascript.NativeObject import org.mozilla.javascript.NativeObject
@ -649,6 +651,8 @@ class AnalyzeRule(var book: BaseBook? = null) : JsExtensions {
private fun evalJS(jsStr: String, result: Any?): Any? { private fun evalJS(jsStr: String, result: Any?): Any? {
val bindings = SimpleBindings() val bindings = SimpleBindings()
bindings["java"] = this bindings["java"] = this
bindings["cookie"] = CookieStore
bindings["cache"] = CacheManager
bindings["book"] = book bindings["book"] = book
bindings["result"] = result bindings["result"] = result
bindings["baseUrl"] = baseUrl bindings["baseUrl"] = baseUrl

@ -12,6 +12,7 @@ import io.legado.app.constant.AppPattern.JS_PATTERN
import io.legado.app.data.entities.BaseBook import io.legado.app.data.entities.BaseBook
import io.legado.app.data.entities.BookChapter import io.legado.app.data.entities.BookChapter
import io.legado.app.help.AppConfig import io.legado.app.help.AppConfig
import io.legado.app.help.CacheManager
import io.legado.app.help.JsExtensions import io.legado.app.help.JsExtensions
import io.legado.app.help.http.* import io.legado.app.help.http.*
import io.legado.app.help.http.api.HttpGetApi import io.legado.app.help.http.api.HttpGetApi
@ -136,18 +137,20 @@ class AnalyzeUrl(
if (ruleUrl.contains("{{") && ruleUrl.contains("}}")) { if (ruleUrl.contains("{{") && ruleUrl.contains("}}")) {
var jsEval: Any var jsEval: Any
val sb = StringBuffer() val sb = StringBuffer()
val simpleBindings = SimpleBindings() val bindings = SimpleBindings()
simpleBindings["java"] = this bindings["java"] = this
simpleBindings["baseUrl"] = baseUrl bindings["cookie"] = CookieStore
simpleBindings["page"] = page bindings["cache"] = CacheManager
simpleBindings["key"] = key bindings["baseUrl"] = baseUrl
simpleBindings["speakText"] = speakText bindings["page"] = page
simpleBindings["speakSpeed"] = speakSpeed bindings["key"] = key
simpleBindings["book"] = book bindings["speakText"] = speakText
bindings["speakSpeed"] = speakSpeed
bindings["book"] = book
val expMatcher = EXP_PATTERN.matcher(ruleUrl) val expMatcher = EXP_PATTERN.matcher(ruleUrl)
while (expMatcher.find()) { while (expMatcher.find()) {
jsEval = expMatcher.group(1)?.let { jsEval = expMatcher.group(1)?.let {
SCRIPT_ENGINE.eval(it, simpleBindings) SCRIPT_ENGINE.eval(it, bindings)
} ?: "" } ?: ""
if (jsEval is String) { if (jsEval is String) {
expMatcher.appendReplacement(sb, jsEval) expMatcher.appendReplacement(sb, jsEval)
@ -259,6 +262,8 @@ class AnalyzeUrl(
private fun evalJS(jsStr: String, result: Any? = null): Any? { private fun evalJS(jsStr: String, result: Any? = null): Any? {
val bindings = SimpleBindings() val bindings = SimpleBindings()
bindings["java"] = this bindings["java"] = this
bindings["cookie"] = CookieStore
bindings["cache"] = CacheManager
bindings["page"] = page bindings["page"] = page
bindings["key"] = key bindings["key"] = key
bindings["speakText"] = speakText bindings["speakText"] = speakText

@ -4,7 +4,6 @@ import io.legado.app.help.JsExtensions
import java.nio.charset.Charset import java.nio.charset.Charset
import kotlin.experimental.and import kotlin.experimental.and
@ExperimentalUnsignedTypes
/** /**
* 解析TTF字体 * 解析TTF字体
* @see <a href="https://docs.microsoft.com/en-us/typography/opentype/spec/">获取详情</a> * @see <a href="https://docs.microsoft.com/en-us/typography/opentype/spec/">获取详情</a>

@ -111,7 +111,7 @@ class WebBook(val bookSource: BookSource) {
headerMapF = bookSource.getHeaderMap(), headerMapF = bookSource.getHeaderMap(),
book = book book = book
).getResponseAwait(bookSource.bookSourceUrl) ).getResponseAwait(bookSource.bookSourceUrl)
BookInfo.analyzeBookInfo(book, res.body, bookSource, res.url, canReName) BookInfo.analyzeBookInfo(book, res.body, bookSource, book.bookUrl, canReName)
} }
book book
} }

@ -92,13 +92,10 @@ class CacheViewModel(application: Application) : BaseViewModel(application) {
.append(context.getString(R.string.author_show, book.author)) .append(context.getString(R.string.author_show, book.author))
App.db.bookChapterDao().getChapterList(book.bookUrl).forEach { chapter -> App.db.bookChapterDao().getChapterList(book.bookUrl).forEach { chapter ->
BookHelp.getContent(book, chapter).let { content -> BookHelp.getContent(book, chapter).let { content ->
val content1 = content?.let { val content1 = contentProcessor
contentProcessor.getContent(book, chapter.title, it, false) .getContent(book, chapter.title, content ?: "null", false)
.joinToString("\n") .joinToString("\n")
}
stringBuilder.append("\n\n") stringBuilder.append("\n\n")
.append(chapter.title)
.append("\n")
.append(content1) .append(content1)
} }
} }

@ -5,7 +5,6 @@ import android.app.Activity
import android.content.Intent import android.content.Intent
import android.content.pm.ActivityInfo import android.content.pm.ActivityInfo
import android.graphics.Color import android.graphics.Color
import android.graphics.drawable.ColorDrawable
import android.net.Uri import android.net.Uri
import android.os.Build import android.os.Build
import android.os.Bundle import android.os.Bundle
@ -44,6 +43,9 @@ import kotlinx.android.synthetic.main.view_read_menu.*
import org.jetbrains.anko.sdk27.listeners.onClick import org.jetbrains.anko.sdk27.listeners.onClick
import org.jetbrains.anko.startActivityForResult import org.jetbrains.anko.startActivityForResult
/**
* 阅读界面
*/
abstract class ReadBookBaseActivity : abstract class ReadBookBaseActivity :
VMBaseActivity<ReadBookViewModel>(R.layout.activity_book_read) { VMBaseActivity<ReadBookViewModel>(R.layout.activity_book_read) {
@ -166,9 +168,7 @@ abstract class ReadBookBaseActivity :
if (!isInMultiWindow) { if (!isInMultiWindow) {
flag = flag or View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN flag = flag or View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
} }
if (ReadBookConfig.hideNavigationBar) { flag = flag or View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION
flag = flag or View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION
}
if (toolBarHide) { if (toolBarHide) {
if (ReadBookConfig.hideStatusBar) { if (ReadBookConfig.hideStatusBar) {
flag = flag or View.SYSTEM_UI_FLAG_FULLSCREEN flag = flag or View.SYSTEM_UI_FLAG_FULLSCREEN
@ -185,11 +185,8 @@ abstract class ReadBookBaseActivity :
read_menu == null -> return read_menu == null -> return
read_menu.isVisible -> ATH.setNavigationBarColorAuto(this) read_menu.isVisible -> ATH.setNavigationBarColorAuto(this)
bottomDialog > 0 -> ATH.setNavigationBarColorAuto(this, bottomBackground) bottomDialog > 0 -> ATH.setNavigationBarColorAuto(this, bottomBackground)
ReadBookConfig.bg is ColorDrawable -> {
ATH.setNavigationBarColorAuto(this, ReadBookConfig.bgMeanColor)
}
else -> { else -> {
ATH.setNavigationBarColorAuto(this, Color.BLACK) ATH.setNavigationBarColorAuto(this, Color.TRANSPARENT)
} }
} }
} }

@ -14,7 +14,6 @@ import io.legado.app.R
import io.legado.app.constant.PreferKey import io.legado.app.constant.PreferKey
import io.legado.app.help.AppConfig import io.legado.app.help.AppConfig
import io.legado.app.help.LocalConfig import io.legado.app.help.LocalConfig
import io.legado.app.help.ReadBookConfig
import io.legado.app.lib.theme.* import io.legado.app.lib.theme.*
import io.legado.app.service.help.ReadBook import io.legado.app.service.help.ReadBook
import io.legado.app.utils.* import io.legado.app.utils.*
@ -237,10 +236,8 @@ class ReadMenu @JvmOverloads constructor(
override fun onAnimationEnd(animation: Animation) { override fun onAnimationEnd(animation: Animation) {
vw_menu_bg.onClick { runMenuOut() } vw_menu_bg.onClick { runMenuOut() }
val hasNavigationBar = ReadBookConfig.hideNavigationBar
&& SystemUtils.isNavigationBarExist(activity)
vwNavigationBar.layoutParams = vwNavigationBar.layoutParams.apply { vwNavigationBar.layoutParams = vwNavigationBar.layoutParams.apply {
height = if (hasNavigationBar) context.navigationBarHeight else 0 height = activity!!.navigationBarHeight
} }
if (LocalConfig.isFirstReadMenuShow) { if (LocalConfig.isFirstReadMenuShow) {
callBack.showReadMenuHelp() callBack.showReadMenuHelp()

@ -21,7 +21,6 @@ class AutoReadDialog : BaseDialogFragment() {
override fun onStart() { override fun onStart() {
super.onStart() super.onStart()
(activity as ReadBookActivity).bottomDialog++
dialog?.window?.let { dialog?.window?.let {
it.clearFlags(WindowManager.LayoutParams.FLAG_DIM_BEHIND) it.clearFlags(WindowManager.LayoutParams.FLAG_DIM_BEHIND)
it.setBackgroundDrawableResource(R.color.background) it.setBackgroundDrawableResource(R.color.background)
@ -44,6 +43,7 @@ class AutoReadDialog : BaseDialogFragment() {
container: ViewGroup?, container: ViewGroup?,
savedInstanceState: Bundle? savedInstanceState: Bundle?
): View? { ): View? {
(activity as ReadBookActivity).bottomDialog++
callBack = activity as? CallBack callBack = activity as? CallBack
return inflater.inflate(R.layout.dialog_auto_read, container) return inflater.inflate(R.layout.dialog_auto_read, container)
} }

@ -50,7 +50,6 @@ class BgTextConfigDialog : BaseDialogFragment(), FilePickerDialog.CallBack {
override fun onStart() { override fun onStart() {
super.onStart() super.onStart()
(activity as ReadBookActivity).bottomDialog++
dialog?.window?.let { dialog?.window?.let {
it.clearFlags(WindowManager.LayoutParams.FLAG_DIM_BEHIND) it.clearFlags(WindowManager.LayoutParams.FLAG_DIM_BEHIND)
it.setBackgroundDrawableResource(R.color.background) it.setBackgroundDrawableResource(R.color.background)
@ -68,6 +67,7 @@ class BgTextConfigDialog : BaseDialogFragment(), FilePickerDialog.CallBack {
container: ViewGroup?, container: ViewGroup?,
savedInstanceState: Bundle? savedInstanceState: Bundle?
): View? { ): View? {
(activity as ReadBookActivity).bottomDialog++
return inflater.inflate(R.layout.dialog_read_bg_text, container) return inflater.inflate(R.layout.dialog_read_bg_text, container)
} }

@ -23,7 +23,6 @@ class ClickActionConfigDialog : BaseDialogFragment() {
override fun onStart() { override fun onStart() {
super.onStart() super.onStart()
(activity as ReadBookActivity).bottomDialog++
dialog?.window?.let { dialog?.window?.let {
it.setBackgroundDrawableResource(R.color.transparent) it.setBackgroundDrawableResource(R.color.transparent)
it.setLayout(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT) it.setLayout(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT)
@ -35,6 +34,7 @@ class ClickActionConfigDialog : BaseDialogFragment() {
container: ViewGroup?, container: ViewGroup?,
savedInstanceState: Bundle? savedInstanceState: Bundle?
): View? { ): View? {
(activity as ReadBookActivity).bottomDialog++
return inflater.inflate(R.layout.dialog_click_action_config, container) return inflater.inflate(R.layout.dialog_click_action_config, container)
} }

@ -25,7 +25,6 @@ class MoreConfigDialog : DialogFragment() {
override fun onStart() { override fun onStart() {
super.onStart() super.onStart()
(activity as ReadBookActivity).bottomDialog++
dialog?.window?.let { dialog?.window?.let {
it.clearFlags(WindowManager.LayoutParams.FLAG_DIM_BEHIND) it.clearFlags(WindowManager.LayoutParams.FLAG_DIM_BEHIND)
it.setBackgroundDrawableResource(R.color.background) it.setBackgroundDrawableResource(R.color.background)
@ -43,6 +42,7 @@ class MoreConfigDialog : DialogFragment() {
container: ViewGroup?, container: ViewGroup?,
savedInstanceState: Bundle? savedInstanceState: Bundle?
): View? { ): View? {
(activity as ReadBookActivity).bottomDialog++
val view = LinearLayout(context) val view = LinearLayout(context)
view.setBackgroundColor(requireContext().bottomBackground) view.setBackgroundColor(requireContext().bottomBackground)
view.id = R.id.tag1 view.id = R.id.tag1

@ -26,7 +26,6 @@ class ReadAloudDialog : BaseDialogFragment() {
override fun onStart() { override fun onStart() {
super.onStart() super.onStart()
(activity as ReadBookActivity).bottomDialog++
dialog?.window?.let { dialog?.window?.let {
it.clearFlags(WindowManager.LayoutParams.FLAG_DIM_BEHIND) it.clearFlags(WindowManager.LayoutParams.FLAG_DIM_BEHIND)
it.setBackgroundDrawableResource(R.color.background) it.setBackgroundDrawableResource(R.color.background)
@ -49,6 +48,7 @@ class ReadAloudDialog : BaseDialogFragment() {
container: ViewGroup?, container: ViewGroup?,
savedInstanceState: Bundle? savedInstanceState: Bundle?
): View? { ): View? {
(activity as ReadBookActivity).bottomDialog++
callBack = activity as? CallBack callBack = activity as? CallBack
return inflater.inflate(R.layout.dialog_read_aloud, container) return inflater.inflate(R.layout.dialog_read_aloud, container)
} }

@ -35,7 +35,6 @@ class ReadStyleDialog : BaseDialogFragment(), FontSelectDialog.CallBack {
override fun onStart() { override fun onStart() {
super.onStart() super.onStart()
(activity as ReadBookActivity).bottomDialog++
dialog?.window?.let { dialog?.window?.let {
it.clearFlags(WindowManager.LayoutParams.FLAG_DIM_BEHIND) it.clearFlags(WindowManager.LayoutParams.FLAG_DIM_BEHIND)
it.setBackgroundDrawableResource(R.color.background) it.setBackgroundDrawableResource(R.color.background)
@ -53,6 +52,7 @@ class ReadStyleDialog : BaseDialogFragment(), FontSelectDialog.CallBack {
container: ViewGroup?, container: ViewGroup?,
savedInstanceState: Bundle? savedInstanceState: Bundle?
): View? { ): View? {
(activity as ReadBookActivity).bottomDialog++
return inflater.inflate(R.layout.dialog_read_book_style, container) return inflater.inflate(R.layout.dialog_read_book_style, container)
} }

@ -6,6 +6,7 @@ import android.graphics.drawable.Drawable
import android.widget.FrameLayout import android.widget.FrameLayout
import androidx.core.view.isGone import androidx.core.view.isGone
import androidx.core.view.isInvisible import androidx.core.view.isInvisible
import io.legado.app.App
import io.legado.app.R import io.legado.app.R
import io.legado.app.base.BaseActivity import io.legado.app.base.BaseActivity
import io.legado.app.constant.AppConst.timeFormat import io.legado.app.constant.AppConst.timeFormat
@ -51,41 +52,42 @@ class ContentView(context: Context) : FrameLayout(context) {
} }
} }
fun upStyle() { fun upStyle() = ReadBookConfig.apply {
ReadBookConfig.apply { bv_header_left.typeface = ChapterProvider.typeface
bv_header_left.typeface = ChapterProvider.typeface tv_header_left.typeface = ChapterProvider.typeface
tv_header_left.typeface = ChapterProvider.typeface tv_header_middle.typeface = ChapterProvider.typeface
tv_header_middle.typeface = ChapterProvider.typeface tv_header_right.typeface = ChapterProvider.typeface
tv_header_right.typeface = ChapterProvider.typeface bv_footer_left.typeface = ChapterProvider.typeface
bv_footer_left.typeface = ChapterProvider.typeface tv_footer_left.typeface = ChapterProvider.typeface
tv_footer_left.typeface = ChapterProvider.typeface tv_footer_middle.typeface = ChapterProvider.typeface
tv_footer_middle.typeface = ChapterProvider.typeface tv_footer_right.typeface = ChapterProvider.typeface
tv_footer_right.typeface = ChapterProvider.typeface bv_header_left.setColor(textColor)
bv_header_left.setColor(textColor) tv_header_left.setColor(textColor)
tv_header_left.setColor(textColor) tv_header_middle.setColor(textColor)
tv_header_middle.setColor(textColor) tv_header_right.setColor(textColor)
tv_header_right.setColor(textColor) bv_footer_left.setColor(textColor)
bv_footer_left.setColor(textColor) tv_footer_left.setColor(textColor)
tv_footer_left.setColor(textColor) tv_footer_middle.setColor(textColor)
tv_footer_middle.setColor(textColor) tv_footer_right.setColor(textColor)
tv_footer_right.setColor(textColor) upStatusBar()
upStatusBar() ll_header.setPadding(
ll_header.setPadding( headerPaddingLeft.dp,
headerPaddingLeft.dp, headerPaddingTop.dp,
headerPaddingTop.dp, headerPaddingRight.dp,
headerPaddingRight.dp, headerPaddingBottom.dp
headerPaddingBottom.dp )
) ll_footer.setPadding(
ll_footer.setPadding( footerPaddingLeft.dp,
footerPaddingLeft.dp, footerPaddingTop.dp,
footerPaddingTop.dp, footerPaddingRight.dp,
footerPaddingRight.dp, footerPaddingBottom.dp
footerPaddingBottom.dp )
) vw_top_divider.visible(showHeaderLine)
vw_top_divider.visible(showHeaderLine) vw_bottom_divider.visible(showFooterLine)
vw_bottom_divider.visible(showFooterLine) page_nv_bar.layoutParams = page_nv_bar.layoutParams.apply {
content_text_view.upVisibleRect() height = if (hideNavigationBar) 0 else App.navigationBarHeight
} }
content_text_view.upVisibleRect()
upTime() upTime()
upBattery(battery) upBattery(battery)
} }

@ -112,7 +112,7 @@ class PageView(context: Context, attrs: AttributeSet) :
brRect.set(width * 0.66f, height * 0.66f, width - 10f, height - 10f) brRect.set(width * 0.66f, height * 0.66f, width - 10f, height - 10f)
prevPage.x = -w.toFloat() prevPage.x = -w.toFloat()
pageDelegate?.setViewSize(w, h) pageDelegate?.setViewSize(w, h)
if (oldw != 0 && oldh != 0) { if (w != 0 && h != 0) {
ReadBook.loadContent(resetPageOffset = false) ReadBook.loadContent(resetPageOffset = false)
} }
} }

@ -328,6 +328,8 @@ class BookSourceActivity : VMBaseActivity<BookSourceViewModel>(R.layout.activity
layoutInflater.inflate(R.layout.dialog_edit_text, null).apply { layoutInflater.inflate(R.layout.dialog_edit_text, null).apply {
editText = edit_view editText = edit_view
edit_view.setHint(R.string.group_name) edit_view.setHint(R.string.group_name)
edit_view.setFilterValues(groups.toList())
edit_view.dropDownHeight = 180.dp
} }
} }
okButton { okButton {
@ -337,7 +339,7 @@ class BookSourceActivity : VMBaseActivity<BookSourceViewModel>(R.layout.activity
} }
} }
} }
noButton() cancelButton()
}.show() }.show()
} }
@ -349,6 +351,8 @@ class BookSourceActivity : VMBaseActivity<BookSourceViewModel>(R.layout.activity
layoutInflater.inflate(R.layout.dialog_edit_text, null).apply { layoutInflater.inflate(R.layout.dialog_edit_text, null).apply {
editText = edit_view editText = edit_view
edit_view.setHint(R.string.group_name) edit_view.setHint(R.string.group_name)
edit_view.setFilterValues(groups.toList())
edit_view.dropDownHeight = 180.dp
} }
} }
okButton { okButton {
@ -358,7 +362,7 @@ class BookSourceActivity : VMBaseActivity<BookSourceViewModel>(R.layout.activity
} }
} }
} }
noButton() cancelButton()
}.show() }.show()
} }

@ -50,7 +50,7 @@ class RssSourceEditActivity :
override fun finish() { override fun finish() {
val source = getRssSource() val source = getRssSource()
if (!source.equal(viewModel.rssSource ?: RssSource())) { if (!source.equal(viewModel.rssSource)) {
alert(R.string.exit) { alert(R.string.exit) {
messageResource = R.string.exit_no_save messageResource = R.string.exit_no_save
positiveButton(R.string.yes) positiveButton(R.string.yes)

@ -33,6 +33,7 @@ open class WelcomeActivity : BaseActivity(R.layout.activity_welcome) {
private fun init() { private fun init() {
Coroutine.async { Coroutine.async {
App.db.cacheDao().clearDeadline(System.currentTimeMillis())
//清除过期数据 //清除过期数据
if (getPrefBoolean(PreferKey.autoClearExpired, true)) { if (getPrefBoolean(PreferKey.autoClearExpired, true)) {
App.db.searchBookDao() App.db.searchBookDao()

@ -26,7 +26,9 @@ class BatteryView @JvmOverloads constructor(
batteryPaint.strokeWidth = 1.dp.toFloat() batteryPaint.strokeWidth = 1.dp.toFloat()
batteryPaint.isAntiAlias = true batteryPaint.isAntiAlias = true
batteryPaint.color = paint.color batteryPaint.color = paint.color
typeface = Typeface.createFromAsset(context.assets, "font${File.separator}number.ttf") if (!isInEditMode) {
typeface = Typeface.createFromAsset(context.assets, "font${File.separator}number.ttf")
}
} }
fun setColor(@ColorInt color: Int) { fun setColor(@ColorInt color: Int) {

@ -21,3 +21,16 @@ fun Activity.getSize(): DisplayMetrics {
} }
return displayMetrics return displayMetrics
} }
/**
* 该方法需要在View完全被绘制出来之后调用否则判断不了
* 在比如 onWindowFocusChanged方法中可以得到正确的结果
*/
val Activity.navigationBarHeight: Int
get() {
if (SystemUtils.isNavigationBarExist(this)) {
val resourceId = resources.getIdentifier("navigation_bar_height", "dimen", "android")
return resources.getDimensionPixelSize(resourceId)
}
return 0
}

@ -225,7 +225,8 @@
android:layout_gravity="center_horizontal" android:layout_gravity="center_horizontal"
android:layout_marginTop="3dp" android:layout_marginTop="3dp"
android:text="@string/chapter_list" android:text="@string/chapter_list"
android:maxLines="1" android:singleLine="true"
android:ellipsize="middle"
android:textColor="@color/primaryText" android:textColor="@color/primaryText"
android:textSize="12sp" /> android:textSize="12sp" />
</LinearLayout> </LinearLayout>
@ -263,7 +264,8 @@
android:layout_gravity="center_horizontal" android:layout_gravity="center_horizontal"
android:layout_marginTop="3dp" android:layout_marginTop="3dp"
android:text="@string/main_menu" android:text="@string/main_menu"
android:maxLines="1" android:singleLine="true"
android:ellipsize="middle"
android:textColor="@color/primaryText" android:textColor="@color/primaryText"
android:textSize="12sp" /> android:textSize="12sp" />
</LinearLayout> </LinearLayout>
@ -301,7 +303,8 @@
android:layout_gravity="center_horizontal" android:layout_gravity="center_horizontal"
android:layout_marginTop="3dp" android:layout_marginTop="3dp"
android:text="@string/to_backstage" android:text="@string/to_backstage"
android:maxLines="1" android:singleLine="true"
android:ellipsize="middle"
android:textColor="@color/primaryText" android:textColor="@color/primaryText"
android:textSize="12sp" /> android:textSize="12sp" />
</LinearLayout> </LinearLayout>
@ -339,7 +342,8 @@
android:layout_gravity="center_horizontal" android:layout_gravity="center_horizontal"
android:layout_marginTop="3dp" android:layout_marginTop="3dp"
android:text="@string/setting" android:text="@string/setting"
android:maxLines="1" android:singleLine="true"
android:ellipsize="middle"
android:textColor="@color/primaryText" android:textColor="@color/primaryText"
android:textSize="12sp" /> android:textSize="12sp" />
</LinearLayout> </LinearLayout>

@ -148,4 +148,9 @@
</androidx.constraintlayout.widget.ConstraintLayout> </androidx.constraintlayout.widget.ConstraintLayout>
<View
android:id="@+id/page_nv_bar"
android:layout_width="match_parent"
android:layout_height="0dp" />
</LinearLayout> </LinearLayout>

@ -281,7 +281,8 @@
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_gravity="center_horizontal" android:layout_gravity="center_horizontal"
android:layout_marginTop="3dp" android:layout_marginTop="3dp"
android:maxLines="1" android:singleLine="true"
android:ellipsize="middle"
android:text="@string/chapter_list" android:text="@string/chapter_list"
android:textColor="@color/primaryText" android:textColor="@color/primaryText"
android:textSize="12sp" /> android:textSize="12sp" />
@ -321,7 +322,8 @@
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_gravity="center_horizontal" android:layout_gravity="center_horizontal"
android:layout_marginTop="3dp" android:layout_marginTop="3dp"
android:maxLines="1" android:singleLine="true"
android:ellipsize="middle"
android:text="@string/read_aloud" android:text="@string/read_aloud"
android:textColor="@color/primaryText" android:textColor="@color/primaryText"
android:textSize="12sp" /> android:textSize="12sp" />
@ -361,7 +363,8 @@
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_gravity="center_horizontal" android:layout_gravity="center_horizontal"
android:layout_marginTop="3dp" android:layout_marginTop="3dp"
android:maxLines="1" android:singleLine="true"
android:ellipsize="middle"
android:text="@string/interface_setting" android:text="@string/interface_setting"
android:textColor="@color/primaryText" android:textColor="@color/primaryText"
android:textSize="12sp" /> android:textSize="12sp" />
@ -401,7 +404,8 @@
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_gravity="center_horizontal" android:layout_gravity="center_horizontal"
android:layout_marginTop="3dp" android:layout_marginTop="3dp"
android:maxLines="1" android:singleLine="true"
android:ellipsize="middle"
android:text="@string/setting" android:text="@string/setting"
android:textColor="@color/primaryText" android:textColor="@color/primaryText"
android:textSize="12sp" /> android:textSize="12sp" />

@ -15,7 +15,7 @@ buildscript {
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version" classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
classpath 'de.timfreiheit.resourceplaceholders:placeholders:0.3' classpath 'de.timfreiheit.resourceplaceholders:placeholders:0.3'
classpath 'com.google.gms:google-services:4.3.4' classpath 'com.google.gms:google-services:4.3.4'
classpath 'com.google.firebase:firebase-crashlytics-gradle:2.3.0' classpath 'com.google.firebase:firebase-crashlytics-gradle:2.4.1'
} }
} }

Loading…
Cancel
Save