1
0
mirror of https://github.com/fumiama/copymanga.git synced 2026-06-12 19:58:35 +08:00
新增
1. shelf, history 未登录提示 (fix #57)
2. 我的下载以KB显示小于1MB漫画
修复
1. 加入书架后立即取消则失败
2. 浅色模式下打开深色阅读背景闪退
3. 主页多次下拉刷新可能闪退
4. 搜索返回后按钮重叠
优化
1. 详情页加载可能的动画卡顿(我的下载)
2. 我的下载只在最前显示前往旧版
3. CardList加载流程
4. 主页加载流程
This commit is contained in:
源文雨
2024-03-15 01:11:32 +09:00
parent 4465759164
commit f0e7802eb2
17 changed files with 327 additions and 299 deletions

View File

@@ -3,20 +3,7 @@
<component name="deploymentTargetDropDown"> <component name="deploymentTargetDropDown">
<value> <value>
<entry key="app"> <entry key="app">
<State> <State />
<targetSelectedWithDropDown>
<Target>
<type value="QUICK_BOOT_TARGET" />
<deviceKey>
<Key>
<type value="VIRTUAL_DEVICE_PATH" />
<value value="$USER_HOME$/.android/avd/Pixel_3a_API_33_arm64-v8a.avd" />
</Key>
</deviceKey>
</Target>
</targetSelectedWithDropDown>
<timeTargetWasSelectedWithDropDown value="2024-03-08T06:58:21.703472Z" />
</State>
</entry> </entry>
</value> </value>
</component> </component>

View File

@@ -8,8 +8,8 @@ android {
applicationId 'top.fumiama.copymanga' applicationId 'top.fumiama.copymanga'
minSdkVersion 23 minSdkVersion 23
targetSdkVersion 34 targetSdkVersion 34
versionCode 52 versionCode 53
versionName '2.2.4' versionName '2.2.5'
resourceConfigurations += ['zh', 'zh-rCN'] resourceConfigurations += ['zh', 'zh-rCN']
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"

View File

@@ -127,7 +127,6 @@ class MainActivity : AppCompatActivity() {
isDrawerClosed = false isDrawerClosed = false
lifecycleScope.launch { lifecycleScope.launch {
withContext(Dispatchers.IO) { withContext(Dispatchers.IO) {
DownloadFragment.currentDir = getExternalFilesDir("")
refreshUserInfo() refreshUserInfo()
} }
} }

View File

@@ -5,6 +5,7 @@ import android.net.Uri
import android.util.Log import android.util.Log
import android.view.View import android.view.View
import androidx.fragment.app.Fragment import androidx.fragment.app.Fragment
import com.airbnb.lottie.LottieAnimationView
import com.bumptech.glide.Glide import com.bumptech.glide.Glide
import com.bumptech.glide.load.model.GlideUrl import com.bumptech.glide.load.model.GlideUrl
import kotlinx.android.synthetic.main.card_book.view.* import kotlinx.android.synthetic.main.card_book.view.*
@@ -26,89 +27,103 @@ class CardList(
private val cardPerRow: Int private val cardPerRow: Int
) { ) {
private val that get() = fragment.get() private val that get() = fragment.get()
private var rows:Array<View?> = arrayOfNulls(20) private var mRows: Array<View?> = arrayOfNulls(20)
private var index = 0 private var mIndex = 0
private var count = 0 private var mCount = 0
private var cardLoadingWaits = AtomicInteger() private var cardLoadingWaits = AtomicInteger()
var initClickListeners: InitClickListeners? = null var initClickListeners: InitClickListeners? = null
var exitCardList = false var exitCardList = false
fun reset() { fun reset() {
rows = arrayOfNulls(20) mRows = arrayOfNulls(20)
index = 0 mIndex = 0
count = 0 mCount = 0
cardLoadingWaits.set(0) cardLoadingWaits.set(0)
exitCardList = false exitCardList = false
} }
private suspend fun manageRow() { private suspend fun manageRow(whenFinish: suspend (index: Int) -> Unit) = withContext(Dispatchers.IO) {
if(!exitCardList && count++ % cardPerRow == 0) inflateRow() if (exitCardList) return@withContext
Log.d("MyCL", "index: $index, cardPR: $cardPerRow") if(mCount++ % cardPerRow == 0) {
inflateRow(++mIndex-1, whenFinish)
} else whenFinish(mIndex-1)
} }
private suspend fun inflateRow() = withContext(Dispatchers.IO) { private suspend fun inflateRow(index: Int, whenFinish: suspend (index: Int)->Unit) = withContext(Dispatchers.IO) {
Log.d("MyCL", "inflateRow: $index, cardPR: $cardPerRow")
that?.apply { that?.apply {
layoutInflater.inflate(R.layout.line_horizonal_empty, mydll, false)?.let { layoutInflater.inflate(R.layout.line_horizonal_empty, mydll, false)?.let {
if(exitCardList) return@withContext if(exitCardList) return@withContext
it.layoutParams.height = cardHeight + 16 it.layoutParams.height = cardHeight + 16
withContext(Dispatchers.Main) withMainContext@ { mydll?.apply { post { addView(it) } }
if(exitCardList) return@withMainContext recycleOneRow(it, index)
mydll?.addView(it) whenFinish(index)
}
recycleOneRow(it)
index++
} }
} }
} }
private suspend fun recycleOneRow(v:View?) = withContext(Dispatchers.IO) { private suspend fun recycleOneRow(v:View?, i: Int) = withContext(Dispatchers.IO) {
val relativeIndex = index % 20 val relativeIndex = i % 20
if(rows[relativeIndex] == null) rows[relativeIndex] = v if(mRows[relativeIndex] == null) mRows[relativeIndex] = v
else { else {
val victim = rows[relativeIndex] val victim = mRows[relativeIndex]
that?.apply { that?.apply {
withContext(Dispatchers.Main) withMainContext@ { if(exitCardList) return@withContext
if(exitCardList) return@withMainContext mydll?.apply { post { removeView(victim) } }
mydll?.removeView(victim) mys?.apply { post { scrollY -= cardHeight + 16 } }
mys?.scrollY = mys?.scrollY?.minus(cardHeight + 16)?:0 }
} mRows[relativeIndex] = v
}
}
private fun postPauseLottie(v: LottieAnimationView) {
v.apply {
post {
pauseAnimation()
visibility = View.GONE
} }
rows[relativeIndex] = v
} }
} }
@ExperimentalStdlibApi @ExperimentalStdlibApi
suspend fun addCard(name: String, append: String? = null, head: String? = null, path: String? = null, chapterUUID: String? = null, pn: Int? = null, isFinish: Boolean = false, isNew: Boolean = false) = suspend fun addCard(
withContext(Dispatchers.IO) { name: String, append: String? = null, head: String? = null,
if (exitCardList) return@withContext path: String? = null, chapterUUID: String? = null, pn: Int? = null,
manageRow() isFinish: Boolean = false, isNew: Boolean = false
that?.apply { ) {
layoutInflater.inflate(R.layout.card_book, mydll?.ltbtn, false)?.let { if (exitCardList) return
val card = it.cic manageRow { i ->
card.name = name withContext(Dispatchers.IO) {
card.append = append that?.apply {
card.headImageUrl = head layoutInflater.inflate(R.layout.card_book, mydll?.ltbtn, false)?.let {
card.path = path val card = it.cic
card.index = index - 1 card.name = name
card.chapterUUID = chapterUUID card.append = append
card.pageNumber = pn card.headImageUrl = head
card.isFinish = isFinish card.path = path
card.isNew = isNew card.index = i
addCard(it) card.chapterUUID = chapterUUID
card.pageNumber = pn
card.isFinish = isFinish
card.isNew = isNew
addCard(it)
}
}
} }
} }
} }
@SuppressLint("SetTextI18n") @SuppressLint("SetTextI18n")
@ExperimentalStdlibApi @ExperimentalStdlibApi
private suspend fun addCard(cardFrame: View) = withContext(Dispatchers.IO) withIO@ { private suspend fun addCard(cardFrame: View) = withContext(Dispatchers.IO) {
val card = cardFrame.cic val card = cardFrame.cic
if (card.index < 0) return@withIO if (card.index < 0) throw Exception("minus card index")
val name = card.name + (card.append?:"") Log.d("MyCL", "addCard: into index ${card.index}")
val appendedName = card.name + (card.append?:"")
val head = card.headImageUrl val head = card.headImageUrl
val file = File(that?.context?.getExternalFilesDir(""), card.name) val file = File(that?.context?.getExternalFilesDir(""), card.name)
if(exitCardList) return@withIO if(exitCardList) return@withContext
cardFrame.let { cardFrame.let {
it.tic.apply { post { text = name } } it.tic.apply { post { text = appendedName } }
if(!file.exists()) { if(!file.exists()) {
if(head != null) { if(head != null) {
that?.context?.let { context -> that?.context?.let { context ->
@@ -125,22 +140,12 @@ class CardList(
}, waitMillis) else it.imic.post { g.into(it.imic) } }, waitMillis) else it.imic.post { g.into(it.imic) }
} }
} else { } else {
it.laic.apply { postPauseLottie(it.laic)
post {
pauseAnimation()
visibility = View.GONE
}
}
it.imic.apply { post { setImageResource(R.drawable.img_defmask) } } it.imic.apply { post { setImageResource(R.drawable.img_defmask) } }
} }
} else { } else {
val img = File(file, "head.jpg") val img = File(file, "head.jpg")
it.laic.apply { postPauseLottie(it.laic)
post {
pauseAnimation()
visibility = View.GONE
}
}
if(img.exists()) { if(img.exists()) {
it.imic.apply { it.imic.apply {
post { post {
@@ -149,13 +154,19 @@ class CardList(
} }
} else it.imic.apply { post { setImageResource(R.drawable.img_defmask) } } } else it.imic.apply { post { setImageResource(R.drawable.img_defmask) } }
} }
withContext(Dispatchers.Main) { card.apply {
if(card.isFinish) it.sgnic.visibility = View.VISIBLE if(isFinish) it.sgnic.visibility = View.VISIBLE
if(card.isNew) it.sgnnew.visibility = View.VISIBLE if(isNew) it.sgnnew.visibility = View.VISIBLE
initClickListeners?.prepareListeners(card, card.name, card.path, card.chapterUUID, card.pageNumber) initClickListeners?.prepareListeners(this, name, path, chapterUUID, pageNumber)
rows[card.index % 20]?.ltbtn?.addView(it) mRows[index % 20]?.ltbtn?.apply {
it.layoutParams?.height = cardHeight withContext(Dispatchers.Main) {
it.layoutParams?.width = cardWidth if(!exitCardList) {
addView(it)
it.layoutParams?.height = cardHeight
it.layoutParams?.width = cardWidth
}
}
}
} }
} }
} }

View File

@@ -12,7 +12,10 @@ import kotlinx.android.synthetic.main.app_bar_main.*
import kotlinx.android.synthetic.main.card_book.* import kotlinx.android.synthetic.main.card_book.*
import kotlinx.android.synthetic.main.fragment_book.* import kotlinx.android.synthetic.main.fragment_book.*
import kotlinx.android.synthetic.main.line_booktandb.* import kotlinx.android.synthetic.main.line_booktandb.*
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.delay
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext
import top.fumiama.copymanga.MainActivity import top.fumiama.copymanga.MainActivity
import top.fumiama.copymanga.manga.Book import top.fumiama.copymanga.manga.Book
import top.fumiama.copymanga.manga.Reader import top.fumiama.copymanga.manga.Reader
@@ -36,34 +39,8 @@ class BookFragment: NoBackRefreshFragment(R.layout.fragment_book) {
fbvp?.setPadding(0, 0, 0, navBarHeight) fbvp?.setPadding(0, 0, 0, navBarHeight)
if(isFirstInflate) { if(isFirstInflate) {
arguments?.apply {
if (getBoolean("loadJson")) {
getString("name")?.let { name ->
try {
book = Book(name, {
return@Book getString(it)
}, activity?.getExternalFilesDir("")!!)
} catch (e: Exception) {
e.printStackTrace()
Toast.makeText(context, R.string.null_book, Toast.LENGTH_SHORT).show()
findNavController().popBackStack()
return
}
}
} else getString("path").let {
if (it != null) book = Book(it, { id ->
return@Book getString(id)
}, activity?.getExternalFilesDir("")!!, false)
else {
findNavController().popBackStack()
return
}
}
}
mBookHandler = BookHandler(WeakReference(this))
bookHandler.set(mBookHandler)
lifecycleScope.launch { lifecycleScope.launch {
prepareHandler()
try { try {
book?.updateInfo() book?.updateInfo()
} catch (e: Exception) { } catch (e: Exception) {
@@ -75,10 +52,11 @@ class BookFragment: NoBackRefreshFragment(R.layout.fragment_book) {
} }
Log.d("MyBF", "read path: ${book?.path}") Log.d("MyBF", "read path: ${book?.path}")
for (i in 1..3) { for (i in 1..3) {
mBookHandler?.sendEmptyMessage(i) mBookHandler?.sendEmptyMessageDelayed(i, (i*100).toLong())
} }
try { try {
book?.updateVolumes { book?.updateVolumes {
delay(300)
mBookHandler?.sendEmptyMessage(10) mBookHandler?.sendEmptyMessage(10)
} }
} catch (e: Exception) { } catch (e: Exception) {
@@ -137,6 +115,41 @@ class BookFragment: NoBackRefreshFragment(R.layout.fragment_book) {
} }
} }
private suspend fun prepareHandler() = withContext(Dispatchers.IO) {
arguments?.apply {
if (getBoolean("loadJson")) {
getString("name")?.let { name ->
try {
book = Book(name, {
return@Book getString(it)
}, activity?.getExternalFilesDir("")!!)
} catch (e: Exception) {
e.printStackTrace()
withContext(Dispatchers.Main) {
Toast.makeText(context, R.string.null_book, Toast.LENGTH_SHORT).show()
findNavController().popBackStack()
}
return@withContext
}
}
} else getString("path").let {
if (it != null) book = Book(it, { id ->
return@Book getString(id)
}, activity?.getExternalFilesDir("")!!, false)
else {
withContext(Dispatchers.Main) {
findNavController().popBackStack()
}
return@withContext
}
}
}
withContext(Dispatchers.Main) {
mBookHandler = BookHandler(WeakReference(this@BookFragment))
bookHandler.set(mBookHandler)
}
}
private suspend fun queryCollect() { private suspend fun queryCollect() {
MainActivity.shelf?.query(book?.path!!)?.let { b -> MainActivity.shelf?.query(book?.path!!)?.let { b ->
mBookHandler?.collect = b.results?.collect?:-2 mBookHandler?.collect = b.results?.collect?:-2

View File

@@ -1,9 +1,8 @@
package top.fumiama.copymanga.ui.cardflow.history package top.fumiama.copymanga.ui.cardflow.history
import android.os.Bundle import android.os.Bundle
import android.view.View import android.widget.Toast
import androidx.navigation.fragment.findNavController import androidx.navigation.fragment.findNavController
import kotlinx.android.synthetic.main.line_lazybooklines.*
import top.fumiama.copymanga.MainActivity import top.fumiama.copymanga.MainActivity
import top.fumiama.copymanga.template.ui.InfoCardLoader import top.fumiama.copymanga.template.ui.InfoCardLoader
import top.fumiama.copymanga.tools.api.CMApi import top.fumiama.copymanga.tools.api.CMApi
@@ -15,7 +14,10 @@ class HistoryFragment : InfoCardLoader(R.layout.fragment_history, R.id.action_na
getString(R.string.historyApiUrl).format(CMApi.myHostApiUrl, page * 21) getString(R.string.historyApiUrl).format(CMApi.myHostApiUrl, page * 21)
override fun onCreate(savedInstanceState: Bundle?) { override fun onCreate(savedInstanceState: Bundle?) {
if (MainActivity.member?.hasLogin != true) findNavController().popBackStack() if (MainActivity.member?.hasLogin != true) {
Toast.makeText(context, R.string.noLogin, Toast.LENGTH_SHORT).show()
findNavController().popBackStack()
}
super.onCreate(savedInstanceState) super.onCreate(savedInstanceState)
} }
} }

View File

@@ -3,11 +3,10 @@ package top.fumiama.copymanga.ui.cardflow.shelf
import android.animation.ObjectAnimator import android.animation.ObjectAnimator
import android.os.Bundle import android.os.Bundle
import android.view.View import android.view.View
import android.widget.Toast
import androidx.navigation.fragment.findNavController import androidx.navigation.fragment.findNavController
import kotlinx.android.synthetic.main.anchor_popular.view.* import kotlinx.android.synthetic.main.anchor_popular.view.*
import kotlinx.android.synthetic.main.line_shelf.* import kotlinx.android.synthetic.main.line_shelf.*
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.withContext
import top.fumiama.copymanga.MainActivity import top.fumiama.copymanga.MainActivity
import top.fumiama.copymanga.template.ui.InfoCardLoader import top.fumiama.copymanga.template.ui.InfoCardLoader
import top.fumiama.copymanga.tools.api.CMApi import top.fumiama.copymanga.tools.api.CMApi
@@ -33,7 +32,10 @@ class ShelfFragment : InfoCardLoader(R.layout.fragment_shelf, R.id.action_nav_su
) )
override fun onCreate(savedInstanceState: Bundle?) { override fun onCreate(savedInstanceState: Bundle?) {
if (MainActivity.member?.hasLogin != true) findNavController().popBackStack() if (MainActivity.member?.hasLogin != true) {
Toast.makeText(context, R.string.noLogin, Toast.LENGTH_SHORT).show()
findNavController().popBackStack()
}
super.onCreate(savedInstanceState) super.onCreate(savedInstanceState)
} }

View File

@@ -41,6 +41,7 @@ class SortFragment : StatusCardFlow(0, R.id.action_nav_sort_to_nav_book, R.layou
override fun setListeners() { override fun setListeners() {
super.setListeners() super.setListeners()
lifecycleScope.launch { lifecycleScope.launch {
setProgress(5)
PausableDownloader(getString(R.string.filterApiUrl).format(CMApi.myHostApiUrl)) { PausableDownloader(getString(R.string.filterApiUrl).format(CMApi.myHostApiUrl)) {
if(ad?.exit == true) return@PausableDownloader if(ad?.exit == true) return@PausableDownloader
it.let { it.let {
@@ -57,11 +58,13 @@ class SortFragment : StatusCardFlow(0, R.id.action_nav_sort_to_nav_book, R.layou
} }
private fun setClasses() { private fun setClasses() {
setProgress(10)
filter?.results?.top?.let { items -> filter?.results?.top?.let { items ->
setMenu(items, line_sort_region) { setMenu(items, line_sort_region) {
region = it region = it
} }
} }
setProgress(15)
filter?.results?.theme?.let { items -> filter?.results?.theme?.let { items ->
setMenu(items, line_sort_class) { setMenu(items, line_sort_class) {
theme = it theme = it

View File

@@ -23,7 +23,9 @@ class TopicFragment : InfoCardLoader(R.layout.fragment_topic, R.id.action_nav_to
override fun onCreate(savedInstanceState: Bundle?) { override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState) super.onCreate(savedInstanceState)
lifecycleScope.launch { lifecycleScope.launch {
setProgress(5)
PausableDownloader(getString(R.string.topicApiUrl).format(CMApi.myHostApiUrl, arguments?.getString("path"))) { data -> PausableDownloader(getString(R.string.topicApiUrl).format(CMApi.myHostApiUrl, arguments?.getString("path"))) { data ->
setProgress(10)
withContext(Dispatchers.IO) { withContext(Dispatchers.IO) {
if(ad?.exit == true) return@withContext if(ad?.exit == true) return@withContext
data.inputStream().use { i -> data.inputStream().use { i ->
@@ -31,6 +33,7 @@ class TopicFragment : InfoCardLoader(R.layout.fragment_topic, R.id.action_nav_to
Gson().fromJson(r, TopicStructure::class.java)?.apply { Gson().fromJson(r, TopicStructure::class.java)?.apply {
if(ad?.exit == true) return@withContext if(ad?.exit == true) return@withContext
withContext(Dispatchers.Main) withMain@ { withContext(Dispatchers.Main) withMain@ {
setProgress(15)
if(ad?.exit == true) return@withMain if(ad?.exit == true) return@withMain
activity?.toolbar?.title = results.title activity?.toolbar?.title = results.title
ftttime.text = results.datetime_created ftttime.text = results.datetime_created

View File

@@ -7,14 +7,17 @@ import android.util.Log
import android.view.View import android.view.View
import android.widget.ArrayAdapter import android.widget.ArrayAdapter
import android.widget.Toast import android.widget.Toast
import androidx.lifecycle.lifecycleScope
import androidx.navigation.fragment.findNavController import androidx.navigation.fragment.findNavController
import kotlinx.android.synthetic.main.app_bar_main.* import kotlinx.android.synthetic.main.app_bar_main.*
import kotlinx.android.synthetic.main.fragment_download.* import kotlinx.android.synthetic.main.fragment_download.*
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext
import top.fumiama.copymanga.MainActivity.Companion.mainWeakReference import top.fumiama.copymanga.MainActivity.Companion.mainWeakReference
import top.fumiama.copymanga.template.general.NoBackRefreshFragment import top.fumiama.copymanga.template.general.NoBackRefreshFragment
import top.fumiama.copymanga.tools.file.FileUtils import top.fumiama.copymanga.tools.file.FileUtils
import top.fumiama.copymanga.tools.ui.Navigate import top.fumiama.copymanga.tools.ui.Navigate
import top.fumiama.copymanga.ui.comicdl.ComicDlFragment
import top.fumiama.copymanga.ui.vm.ViewMangaActivity import top.fumiama.copymanga.ui.vm.ViewMangaActivity
import top.fumiama.dmzj.copymanga.R import top.fumiama.dmzj.copymanga.R
import java.io.File import java.io.File
@@ -27,21 +30,27 @@ class DownloadFragment: NoBackRefreshFragment(R.layout.fragment_download) {
arguments?.getString("title")?.let { arguments?.getString("title")?.let {
mainWeakReference?.get()?.toolbar?.title = it mainWeakReference?.get()?.toolbar?.title = it
} }
scanFile(currentDir) lifecycleScope.launch {
scanFile(arguments?.getString("file")?.let { File(it) }?:context?.getExternalFilesDir("")?:run {
findNavController().popBackStack()
return@launch
})
}
} }
} }
private fun scanFile(cd: File?) { private suspend fun scanFile(cd: File): Unit = withContext(Dispatchers.IO) {
val isRoot = cd == context?.getExternalFilesDir("") val isRoot = cd == context?.getExternalFilesDir("")
val jsonFile = File(cd, "info.bin") val jsonFile = File(cd, "info.bin")
if(isRoot || !jsonFile.exists()) cd?.list()?.sortedArrayWith { o1, o2 -> if(isRoot || !jsonFile.exists()) cd.listFiles()?.filter { f -> return@filter f.isDirectory }?.map { f -> return@map f.name }?.sortedWith { o1, o2 ->
if(o1.endsWith(".zip") && o2.endsWith(".zip")) (10000*getFloat(o1) - 10000*getFloat(o2) + 0.5).toInt() if(o1.endsWith(".zip") && o2.endsWith(".zip")) (10000*getFloat(o1) - 10000*getFloat(o2) + 0.5).toInt()
else o1[0] - o2[0] else o1[0] - o2[0]
}?.let { }?.let {
mylv?.apply { mylv?.apply {
setPadding(0, 0, 0, navBarHeight) val ad = ArrayAdapter(context, android.R.layout.simple_list_item_1, it)
context.let { c -> post {
adapter = ArrayAdapter(c, android.R.layout.simple_list_item_1, it) setPadding(0, 0, 0, navBarHeight)
adapter = ad
setOnItemClickListener { _, _, position, _ -> setOnItemClickListener { _, _, position, _ ->
val chosenFile = File(cd, it[position]) val chosenFile = File(cd, it[position])
val chosenJson = File(chosenFile, "info.bin") val chosenJson = File(chosenFile, "info.bin")
@@ -51,8 +60,7 @@ class DownloadFragment: NoBackRefreshFragment(R.layout.fragment_download) {
chosenJson.exists() -> callDownloadFragment(chosenJson) chosenJson.exists() -> callDownloadFragment(chosenJson)
newJson.exists() -> callDownloadFragment(newJson, true) newJson.exists() -> callDownloadFragment(newJson, true)
chosenFile.isDirectory -> { chosenFile.isDirectory -> {
currentDir = chosenFile callSelf(it[position], chosenFile)
callSelf(it[position])
} }
chosenFile.name.endsWith(".zip") -> { chosenFile.name.endsWith(".zip") -> {
Toast.makeText(context, "加载中...", Toast.LENGTH_SHORT).show() Toast.makeText(context, "加载中...", Toast.LENGTH_SHORT).show()
@@ -67,11 +75,18 @@ class DownloadFragment: NoBackRefreshFragment(R.layout.fragment_download) {
} }
setOnItemLongClickListener { _, _, position, _ -> setOnItemLongClickListener { _, _, position, _ ->
val chosenFile = File(cd, it[position]) val chosenFile = File(cd, it[position])
Log.d("MyDF", "y: ${getChildAt(0).scrollY}")
AlertDialog.Builder(context) AlertDialog.Builder(context)
.setIcon(R.drawable.ic_launcher_foreground).setMessage("删除?") .setIcon(R.drawable.ic_launcher_foreground).setMessage("删除?")
.setTitle("提示").setPositiveButton(android.R.string.ok) { _, _ -> .setTitle("提示").setPositiveButton(android.R.string.ok) { _, _ ->
if (chosenFile.exists()) FileUtils.recursiveRemove(chosenFile) lifecycleScope.launch {
scanFile(cd) withContext(Dispatchers.IO) {
if (chosenFile.exists()) {
FileUtils.recursiveRemove(chosenFile)
scanFile(cd)
}
}
}
}.setNegativeButton(android.R.string.cancel) { _, _ -> } }.setNegativeButton(android.R.string.cancel) { _, _ -> }
.show() .show()
true true
@@ -95,9 +110,10 @@ class DownloadFragment: NoBackRefreshFragment(R.layout.fragment_download) {
Navigate.safeNavigateTo(findNavController(), R.id.action_nav_download_to_nav_group, bundle) Navigate.safeNavigateTo(findNavController(), R.id.action_nav_download_to_nav_group, bundle)
} }
private fun callSelf(title: String){ private fun callSelf(title: String, file: File){
val bundle = Bundle() val bundle = Bundle()
bundle.putString("title", title) bundle.putString("title", title)
bundle.putString("file", file.absolutePath)
Log.d("MyDF", "Call self to $title") Log.d("MyDF", "Call self to $title")
Log.d("MyDF", "root view: $rootView") Log.d("MyDF", "root view: $rootView")
Log.d("MyDF", "action_nav_download_self") Log.d("MyDF", "action_nav_download_self")
@@ -116,8 +132,4 @@ class DownloadFragment: NoBackRefreshFragment(R.layout.fragment_download) {
//Log.d("MyDLL2", newString.toString().toFloat().toString()) //Log.d("MyDLL2", newString.toString().toFloat().toString())
return if(newString.isEmpty()) 0f else newString.toString().toFloat() return if(newString.isEmpty()) 0f else newString.toString().toFloat()
} }
companion object{
var currentDir: File? = null
}
} }

View File

@@ -57,7 +57,7 @@ class NewDownloadFragment: MangaPagesFragmentTemplate(R.layout.fragment_newdownl
override suspend fun addPage(): Unit = withContext(Dispatchers.IO) { override suspend fun addPage(): Unit = withContext(Dispatchers.IO) {
super.addPage() super.addPage()
if(isRefresh){ if(isRefresh) {
page = 0 page = 0
isRefresh = false isRefresh = false
} }
@@ -111,8 +111,11 @@ class NewDownloadFragment: MangaPagesFragmentTemplate(R.layout.fragment_newdownl
isContentChanged = false isContentChanged = false
} }
Log.d("MyNDF", "Start drawing cards") Log.d("MyNDF", "Start drawing cards")
cardList?.addCard(oldDlCardName, path = oldDlCardName) var cnt = 0
var cnt = 1 if(page == 0) {
cardList?.addCard(oldDlCardName, path = oldDlCardName)
cnt = 1
}
val size = sortedBookList?.size?:0 val size = sortedBookList?.size?:0
sortedBookList?.let { sortedBookList?.let {
for(i in it.listIterator(page)) { for(i in it.listIterator(page)) {
@@ -120,12 +123,16 @@ class NewDownloadFragment: MangaPagesFragmentTemplate(R.layout.fragment_newdownl
page++ // page is actually count page++ // page is actually count
val chosenJson = File(i, "info.bin") val chosenJson = File(i, "info.bin")
val newJson = File(i, "info.json") val newJson = File(i, "info.json")
val bookSize = (FileUtils.sizeOf(i)/1048576).toInt() val bookSize = FileUtils.sizeOf(i).let { sz ->
(sz/1048576).toInt().let { m ->
if (m > 0) "\n${m}MB" else "\n${(sz/1024).toInt()}KB"
}
}
when { when {
chosenJson.exists() -> continue // unsupported old folder chosenJson.exists() -> continue // unsupported old folder
newJson.exists() -> { newJson.exists() -> {
if(cardList?.exitCardList != false) return@withContext if(cardList?.exitCardList != false) return@withContext
cardList?.addCard(i.name, "\n${bookSize}MB") cardList?.addCard(i.name, bookSize)
cnt++ cnt++
} }
} }

View File

@@ -90,9 +90,9 @@ class HomeFragment : NoBackRefreshFragment(R.layout.fragment_home) {
}) })
setTextHint(android.R.string.search_go) setTextHint(android.R.string.search_go)
var lastSearch = ""
setOnQueryTextListener(object : SearchLayout.OnQueryTextListener { setOnQueryTextListener(object : SearchLayout.OnQueryTextListener {
var lastChangeTime = 0L var lastChangeTime = 0L
var lastSearch: String = ""
override fun onQueryTextChange(newText: CharSequence): Boolean { override fun onQueryTextChange(newText: CharSequence): Boolean {
if (newText.contentEquals("__notice_focus_change__") || newText.contentEquals(lastSearch)) return true if (newText.contentEquals("__notice_focus_change__") || newText.contentEquals(lastSearch)) return true
postDelayed({ postDelayed({
@@ -121,6 +121,7 @@ class HomeFragment : NoBackRefreshFragment(R.layout.fragment_home) {
return true return true
} }
}) })
setOnMicClickListener(object : SearchLayout.OnMicClickListener { setOnMicClickListener(object : SearchLayout.OnMicClickListener {
val types = arrayOf("", "name", "author", "local") val types = arrayOf("", "name", "author", "local")
var i = 0 var i = 0
@@ -137,17 +138,25 @@ class HomeFragment : NoBackRefreshFragment(R.layout.fragment_home) {
} }
}) })
var isInFocusWaiting = false
setOnFocusChangeListener(object : SearchLayout.OnFocusChangeListener { setOnFocusChangeListener(object : SearchLayout.OnFocusChangeListener {
override fun onFocusChange(hasFocus: Boolean) { override fun onFocusChange(hasFocus: Boolean) {
Log.d("MyHF", "fhs onFocusChange: $hasFocus") Log.d("MyHF", "fhs onFocusChange: $hasFocus")
navigationIconSupport = if (hasFocus) { if (isInFocusWaiting) return
setTextQuery("__notice_focus_change__", true) isInFocusWaiting = true
SearchLayout.NavigationIconSupport.ARROW postDelayed({
} navigationIconSupport = if (hasFocus) {
else { setTextQuery("__notice_focus_change__", true)
micView.postDelayed({ micView?.visibility = View.VISIBLE }, 233) SearchLayout.NavigationIconSupport.ARROW
SearchLayout.NavigationIconSupport.SEARCH }
} else {
if (lastSearch.isNotEmpty()) {
micView?.visibility = View.VISIBLE
}
SearchLayout.NavigationIconSupport.SEARCH
}
isInFocusWaiting = false
}, 300)
} }
}) })
@@ -165,8 +174,8 @@ class HomeFragment : NoBackRefreshFragment(R.layout.fragment_home) {
homeHandler.obtainMessage(-1, true).sendToTarget() homeHandler.obtainMessage(-1, true).sendToTarget()
while(!MainActivity.isDrawerClosed) delay(233) while(!MainActivity.isDrawerClosed) delay(233)
//homeHandler.sendEmptyMessage(6) //removeAllViews //homeHandler.sendEmptyMessage(6) //removeAllViews
homeHandler.fhib = null //homeHandler.fhib = null
delay(600) delay(300)
homeHandler.startLoad() homeHandler.startLoad()
} }
} }
@@ -228,42 +237,53 @@ class HomeFragment : NoBackRefreshFragment(R.layout.fragment_home) {
override fun onBindViewHolder(holder: ListViewHolder, position: Int) { override fun onBindViewHolder(holder: ListViewHolder, position: Int) {
Log.d("MyMain", "Bind open at $position") Log.d("MyMain", "Bind open at $position")
if (position == itemCount-1) { if (position == itemCount-1) {
holder.itemView.tn.setText(R.string.button_more) holder.itemView.apply { post {
holder.itemView.ta.text = "搜索 \"$query\"" tn.setText(R.string.button_more)
holder.itemView.tb.text = "$count 条结果" ta.text = "搜索 \"$query\""
holder.itemView.lwi.visibility = View.INVISIBLE tb.text = "$count 条结果"
holder.itemView.lwc.setOnClickListener { context?.let {
if (query?.isNotEmpty() != true) return@setOnClickListener Glide.with(it).load(R.drawable.img_defmask)
val bundle = Bundle() .addListener(GlideHideLottieViewListener(WeakReference(laic)))
bundle.putCharSequence("query", query) .into(imic)
bundle.putString("type", type) }
Navigate.safeNavigateTo(findNavController(), R.id.action_nav_home_to_nav_search, bundle) cic.isClickable = false
} lwc.setOnClickListener {
if (query?.isNotEmpty() != true) return@setOnClickListener
val bundle = Bundle()
bundle.putCharSequence("query", query)
bundle.putString("type", type)
Navigate.safeNavigateTo(findNavController(), R.id.action_nav_home_to_nav_search, bundle)
}
lwc.layoutParams.height = fhs.width / 4
} }
return return
} }
results?.results?.list?.get(position)?.apply { results?.results?.list?.get(position)?.apply {
holder.itemView.lwi.visibility = View.VISIBLE holder.itemView.apply { post {
holder.itemView.tn.text = name lwi.visibility = View.VISIBLE
holder.itemView.ta.text = author.let { tn.text = name
var t = "" ta.text = author.let {
it.forEach { ts -> var t = ""
t += ts.name + " " it.forEach { ts ->
t += ts.name + " "
}
return@let t
} }
return@let t tb.text = popular.toString()
} cic.isClickable = false
holder.itemView.tb.text = popular.toString() context?.let {
context?.let { Glide.with(it)
Glide.with(it) .load(GlideUrl(CMApi.imageProxy?.wrap(cover)?:cover, CMApi.myGlideHeaders))
.load(GlideUrl(CMApi.imageProxy?.wrap(cover)?:cover, CMApi.myGlideHeaders)) .addListener(GlideHideLottieViewListener(WeakReference(laic)))
.addListener(GlideHideLottieViewListener(WeakReference(holder.itemView.laic))) .into(imic)
.into(holder.itemView.imic) }
} lwc.setOnClickListener {
holder.itemView.lwc.setOnClickListener { val bundle = Bundle()
val bundle = Bundle() bundle.putString("path", path_word)
bundle.putString("path", path_word) Navigate.safeNavigateTo(findNavController(), R.id.action_nav_home_to_nav_book, bundle)
Navigate.safeNavigateTo(findNavController(), R.id.action_nav_home_to_nav_book, bundle) }
} lwc.layoutParams.height = fhs.width / 4
holder.itemView.lwc.layoutParams.height = fhs.width / 4 } }
} }
} }

View File

@@ -1,6 +1,7 @@
package top.fumiama.copymanga.ui.home package top.fumiama.copymanga.ui.home
import android.animation.ObjectAnimator import android.animation.ObjectAnimator
import android.annotation.SuppressLint
import android.graphics.Color import android.graphics.Color
import android.os.Bundle import android.os.Bundle
import android.os.Message import android.os.Message
@@ -45,11 +46,11 @@ class HomeHandler(private val that: WeakReference<HomeFragment>) : AutoDownloadH
) { ) {
private val homeF get() = that.get() private val homeF get() = that.get()
var index: IndexStructure? = null var index: IndexStructure? = null
var fhib: View? = null var fhib: Banner? = null
get() { get() {
Log.d("MyHH", "Get fhib.") Log.d("MyHH", "Get fhib.")
if (field == null) { if (field == null) {
field = homeF?.layoutInflater?.inflate(R.layout.viewpage_banner, homeF?.fhl, false) field = homeF?.layoutInflater?.inflate(R.layout.viewpage_banner, homeF?.fhl, false) as Banner
homeF?.homeHandler?.sendEmptyMessage(3) homeF?.homeHandler?.sendEmptyMessage(3)
} }
return field return field
@@ -63,7 +64,7 @@ class HomeHandler(private val that: WeakReference<HomeFragment>) : AutoDownloadH
//0 -> setLayouts() //0 -> setLayouts()
1 -> inflateCardLines() 1 -> inflateCardLines()
2 -> homeF?.swiperefresh?.let { setSwipe(it) } 2 -> homeF?.swiperefresh?.let { setSwipe(it) }
3 -> setBanner(fhib as Banner) 3 -> setBanner(fhib!!)
5 -> setBannerInfo(msg.obj as Banner) 5 -> setBannerInfo(msg.obj as Banner)
6 -> { 6 -> {
homeF?.fhl?.let { homeF?.fhl?.let {
@@ -76,15 +77,6 @@ class HomeHandler(private val that: WeakReference<HomeFragment>) : AutoDownloadH
} }
} }
7 -> inflateBanner() 7 -> inflateBanner()
8 -> {
try {
homeF?.fhl?.addView(indexLines[msg.arg1])
} catch (e: Exception) {
e.printStackTrace()
(indexLines[msg.arg1].parent as LinearLayout).removeAllViews()
homeF?.fhl?.addView(indexLines[msg.arg1])
}
}
} }
} }
@@ -226,11 +218,22 @@ class HomeHandler(private val that: WeakReference<HomeFragment>) : AutoDownloadH
inflateNew() inflateNew()
inflateFinish() inflateFinish()
inflateRank() inflateRank()
for(i in indexLines.indices) { homeF?.fhl?.apply { post {
obtainMessage(8, i, 0).sendToTarget() for (i in indexLines.indices) {
delay(512) try {
} addView(indexLines[i])
obtainMessage(-1, false).sendToTarget() //closeLoad } catch (e: Exception) {
e.printStackTrace()
(indexLines[i].parent as LinearLayout).apply {
post {
removeAllViews()
homeF?.fhl?.addView(indexLines[i])
}
}
}
}
obtainMessage(-1, false).sendToTarget() //closeLoad
} }
} }
} }
} }
@@ -264,14 +267,17 @@ class HomeHandler(private val that: WeakReference<HomeFragment>) : AutoDownloadH
v.invalidate() v.invalidate()
} }
@SuppressLint("NotifyDataSetChanged")
private fun setSwipe(sw: SwipeRefreshLayout) { private fun setSwipe(sw: SwipeRefreshLayout) {
homeF?.fhov?.swipeRefreshLayout = sw homeF?.fhov?.swipeRefreshLayout = sw
sw.setOnRefreshListener { sw.setOnRefreshListener {
Log.d("MyHFH", "Refresh items.") Log.d("MyHFH", "Refresh items.")
homeF?.lifecycleScope?.launch { homeF?.lifecycleScope?.launch {
withContext(Dispatchers.IO) { withContext(Dispatchers.IO) {
fhib?.isAutoPlay = false
fhib?.adapter?.notifyDataSetChanged()
index = null index = null
//fhib = null fhib = null
indexLines = arrayOf() indexLines = arrayOf()
this@HomeHandler.sendEmptyMessage(6) //removeAllViews this@HomeHandler.sendEmptyMessage(6) //removeAllViews
delay(300) delay(300)
@@ -293,13 +299,15 @@ class HomeHandler(private val that: WeakReference<HomeFragment>) : AutoDownloadH
2 -> R.layout.line_2bookline 2 -> R.layout.line_2bookline
3 -> R.layout.line_3bookline 3 -> R.layout.line_3bookline
else -> return@withContext -1 else -> return@withContext -1
}, homeF!!.fhl, false)?.apply { }, null, false)?.apply {
withContext(Dispatchers.Main) { withContext(Dispatchers.Main) {
scanCards(this@apply, comics, finish, isTopic) scanCards(this@apply, comics, finish, isTopic)
rttitle.text = title post {
ir.setImageResource(iconResId) rttitle.text = title
setLineHeight(this@apply, c) ir.setImageResource(iconResId)
if(onClick != null) setOnClickListener { onClick() } setLineHeight(this@apply, c)
if(onClick != null) setOnClickListener { onClick() }
}
} }
indexLines += this indexLines += this
} }
@@ -324,8 +332,8 @@ class HomeHandler(private val that: WeakReference<HomeFragment>) : AutoDownloadH
private var cardLoadingWaits = AtomicInteger() private var cardLoadingWaits = AtomicInteger()
private suspend fun setCards(cv: CardView, pw: String, name: String, img: String, isFinal: Boolean, isTopic: Boolean) = withContext(Dispatchers.Main) { private fun setCards(cv: CardView, pw: String, name: String, img: String, isFinal: Boolean, isTopic: Boolean) {
cv.tic.text = name cv.tic.apply { post { text = name } }
homeF?.let { homeF?.let {
if(img.startsWith("http")) { if(img.startsWith("http")) {
Log.d("MyHH", "load card image: $img") Log.d("MyHH", "load card image: $img")
@@ -336,15 +344,17 @@ class HomeHandler(private val that: WeakReference<HomeFragment>) : AutoDownloadH
}) })
if (waitMillis > 0) cv.imic.postDelayed({ if (waitMillis > 0) cv.imic.postDelayed({
g.into(cv.imic) g.into(cv.imic)
}, waitMillis) else g.into(cv.imic) }, waitMillis) else cv.imic.post { g.into(cv.imic) }
} }
} }
if (isFinal) cv.sgnic.visibility = View.VISIBLE if (isFinal) cv.sgnic.apply { post { visibility = View.VISIBLE } }
cv.setOnClickListener { cv.post {
val bundle = Bundle() cv.setOnClickListener {
bundle.putString("path", pw) val bundle = Bundle()
homeF?.findNavController()?.let { nav -> bundle.putString("path", pw)
Navigate.safeNavigateTo(nav, if(isTopic) R.id.action_nav_home_to_nav_topic else R.id.action_nav_home_to_nav_book, bundle) homeF?.findNavController()?.let { nav ->
Navigate.safeNavigateTo(nav, if(isTopic) R.id.action_nav_home_to_nav_topic else R.id.action_nav_home_to_nav_book, bundle)
}
} }
} }
} }

View File

@@ -133,56 +133,52 @@ class ViewMangaActivity : TitleActivityTemplate() {
@SuppressLint("SetTextI18n") @SuppressLint("SetTextI18n")
override fun onCreate(savedInstanceState: Bundle?) { override fun onCreate(savedInstanceState: Bundle?) {
val settingsPref = MainActivity.mainWeakReference?.get()?.let { PreferenceManager.getDefaultSharedPreferences(it) }
settingsPref?.getBoolean("settings_cat_vm_sw_always_dark_bg", false)?.let {
if (it) {
Log.d("MyVM", "force dark")
delegate.localNightMode = AppCompatDelegate.MODE_NIGHT_YES
} else {
delegate.localNightMode = AppCompatDelegate.MODE_NIGHT_FOLLOW_SYSTEM
}
}
postponeEnterTransition() postponeEnterTransition()
setContentView(R.layout.activity_viewmanga) setContentView(R.layout.activity_viewmanga)
super.onCreate(null) super.onCreate(null)
va = WeakReference(this@ViewMangaActivity)
//dlZip2View = intent.getStringExtra("callFrom") == "Dl" || p["dlZip2View"] == "true"
//zipFirst = intent.getStringExtra("callFrom") == "zipFirst"
intent.getStringArrayExtra("urlArray")?.let { urlArray = it }
cut = pb["useCut"]
r2l = pb["r2l"]
verticalLoadMaxCount = settingsPref?.getInt("settings_cat_vm_sb_vertical_max", 20)?.let { if(it > 0) it else 20 }?:20
isVertical = pb["vertical"]
notUseVP = pb["noVP"] || isVertical
//url = intent.getStringExtra("url")
handler = VMHandler(this@ViewMangaActivity, if(urlArray.isNotEmpty()) urlArray[position] else "", resources.getStringArray(R.array.weeks))
lifecycleScope.launch { lifecycleScope.launch {
withContext(Dispatchers.IO) { withContext(Dispatchers.IO) {
val settingsPref = MainActivity.mainWeakReference?.get()?.let { PreferenceManager.getDefaultSharedPreferences(it) } settingsPref?.getInt("settings_cat_vm_sb_quality", 100)?.let { q = if (it > 0) it else 100 }
settingsPref?.getBoolean("settings_cat_vm_sw_always_dark_bg", false)?.let { tt = TimeThread(handler, VMHandler.SET_NET_INFO, 10000)
if (it) { tt.canDo = true
Log.d("MyVM", "force dark") tt.start()
delegate.localNightMode = AppCompatDelegate.MODE_NIGHT_YES volTurnPage = settingsPref?.getBoolean("settings_cat_vm_sw_vol_turn", false)?:false
} else { am = getSystemService(Service.AUDIO_SERVICE) as AudioManager
delegate.localNightMode = AppCompatDelegate.MODE_NIGHT_FOLLOW_SYSTEM if (!noCellarAlert) noCellarAlert = settingsPref?.getBoolean("settings_cat_net_sw_use_cellar", false) == true
} fullyHideInfo = settingsPref?.getBoolean("settings_cat_vm_sw_hide_info", false) == true
}
va = WeakReference(this@ViewMangaActivity)
//dlZip2View = intent.getStringExtra("callFrom") == "Dl" || p["dlZip2View"] == "true"
//zipFirst = intent.getStringExtra("callFrom") == "zipFirst"
intent.getStringArrayExtra("urlArray")?.let { urlArray = it }
cut = pb["useCut"]
r2l = pb["r2l"]
verticalLoadMaxCount = settingsPref?.getInt("settings_cat_vm_sb_vertical_max", 20)?.let { if(it > 0) it else 20 }?:20
isVertical = pb["vertical"]
notUseVP = pb["noVP"] || isVertical
//url = intent.getStringExtra("url")
withContext(Dispatchers.Main) {
handler = VMHandler(this@ViewMangaActivity, if(urlArray.isNotEmpty()) urlArray[position] else "", resources.getStringArray(R.array.weeks))
withContext(Dispatchers.IO) {
settingsPref?.getInt("settings_cat_vm_sb_quality", 100)?.let { q = if (it > 0) it else 100 }
tt = TimeThread(handler, VMHandler.SET_NET_INFO, 10000)
tt.canDo = true
tt.start()
volTurnPage = settingsPref?.getBoolean("settings_cat_vm_sw_vol_turn", false)?:false
am = getSystemService(Service.AUDIO_SERVICE) as AudioManager
if (!noCellarAlert) noCellarAlert = settingsPref?.getBoolean("settings_cat_net_sw_use_cellar", false) == true
fullyHideInfo = settingsPref?.getBoolean("settings_cat_vm_sw_hide_info", false) == true
Log.d("MyVM", "Now ZipFile is $zipFile") Log.d("MyVM", "Now ZipFile is $zipFile")
try { try {
if (zipFile != null && zipFile?.exists() == true) { if (zipFile != null && zipFile?.exists() == true) {
if (!handler.loadFromFile(zipFile!!)) prepareImgFromWeb() if (!handler.loadFromFile(zipFile!!)) prepareImgFromWeb()
} else prepareImgFromWeb() } else prepareImgFromWeb()
} catch (e: Exception) { } catch (e: Exception) {
e.printStackTrace() e.printStackTrace()
toolsBox.toastError(R.string.load_manga_error) toolsBox.toastError(R.string.load_manga_error)
} }
withContext(Dispatchers.Main) { withContext(Dispatchers.Main) {
startPostponedEnterTransition() startPostponedEnterTransition()
ObjectAnimator.ofFloat(vcp, "alpha", 0.1f, 1f).setDuration(1000).start() ObjectAnimator.ofFloat(vcp, "alpha", 0.1f, 1f).setDuration(1000).start()
}
}
} }
} }
} }

View File

@@ -1,10 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="32dp"
android:height="32dp"
android:viewportHeight="1024"
android:viewportWidth="1024">
<path
android:fillColor="@android:color/holo_red_light"
android:pathData="M668 117C833 117 939 250 939 428c0 138-125 291-372 462a97 97 0 0 1-110 0C210 718 85 566 85 428 85 250 191 117 356 117c60 0 100 21 156 68C568 138 608 117 668 117z m0 63c-41 0-70 15-117 55-2 2-14 12-18 15a32 32 0 0 1-42 0c-4-3-16-14-18-15-47-40-76-55-117-55C230 180 149 281 149 427 149 538 263 675 494 835a32 32 0 0 0 37 0C761 675 875 538 875 427c0-145-81-246-207-246z"/>
</vector>

View File

@@ -1,10 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="32dp"
android:height="32dp"
android:viewportHeight="1024"
android:viewportWidth="1024">
<path
android:fillColor="@android:color/holo_red_light"
android:pathData="M668 117C833 117 939 250 939 428c0 138-125 291-372 462a97 97 0 0 1-110 0C210 718 85 566 85 428 85 250 191 117 356 117c60 0 100 21 156 68C568 138 608 117 668 117z"/>
</vector>

View File

@@ -14,7 +14,6 @@
layout="@layout/card_book_plain" layout="@layout/card_book_plain"
android:layout_width="0dp" android:layout_width="0dp"
android:layout_height="0dp" android:layout_height="0dp"
android:layout_marginStart="16dp"
app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toStartOf="@id/lwl" app:layout_constraintEnd_toStartOf="@id/lwl"
app:layout_constraintHorizontal_weight="1" app:layout_constraintHorizontal_weight="1"
@@ -25,7 +24,7 @@
android:id="@+id/lwl" android:id="@+id/lwl"
android:layout_width="0dp" android:layout_width="0dp"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_marginStart="8dp" android:layout_marginEnd="16dp"
android:orientation="vertical" android:orientation="vertical"
app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent" app:layout_constraintEnd_toEndOf="parent"
@@ -37,38 +36,22 @@
android:id="@+id/tn" android:id="@+id/tn"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_marginTop="10dp"
android:layout_marginEnd="16dp"
android:textColor="?attr/colorOnSurface" android:textColor="?attr/colorOnSurface"
android:textSize="24sp" android:textSize="20sp"
android:textStyle="bold" /> android:textStyle="bold" />
<TextView <TextView
android:id="@+id/ta" android:id="@+id/ta"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_marginEnd="16dp"
android:fontFamily="@font/gotham" android:fontFamily="@font/gotham"
android:textColor="?attr/colorOnSurface" android:textColor="?attr/colorOnSurface"
android:textSize="18sp" /> android:textSize="16sp" />
<TextView <TextView
android:id="@+id/tb" android:id="@+id/tb"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content" />
android:layout_marginEnd="16dp"
android:layout_marginBottom="10dp" />
</LinearLayout> </LinearLayout>
<View
android:id="@+id/vl"
android:layout_width="32dp"
android:layout_height="32dp"
android:layout_marginEnd="16dp"
android:clickable="true"
android:focusable="true"
android:foreground="?android:attr/selectableItemBackground"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toTopOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout> </androidx.constraintlayout.widget.ConstraintLayout>