1
0
mirror of https://github.com/fumiama/copymanga.git synced 2026-06-23 11:00:24 +08:00
新增
1. 启动时尝试登陆失败提示
2. 热切换阅览模式
3. 拉进度条连续翻页超过3后松手时再更新进度
4. 更高清晰度支持 (可在设置调节)
修复
1. 大屏设备下用户头像过大
2. 阅览漫画时加载图片过快导致触发访问限制
3. 白色背景下无法显示页码标号
4. 闪退重新拉起时继续闪退
5. 非ViewPager阅读漫画异常CPU占用
优化
1. 默认api地址更改为api.copymanga.tv
2. 字符串与常量定义
3. 首页下拉刷新行为
4. 竖向、单页模式下漫画加载速度
5. 封面加载速度
This commit is contained in:
源文雨
2024-01-17 20:41:38 +09:00
parent 2257e977d1
commit 40574ba9a6
30 changed files with 356 additions and 174 deletions

View File

@@ -8,8 +8,8 @@ android {
applicationId 'top.fumiama.copymanga' applicationId 'top.fumiama.copymanga'
minSdkVersion 23 minSdkVersion 23
targetSdkVersion 34 targetSdkVersion 34
versionCode 42 versionCode 44
versionName '2.0.6' versionName '2.1.1'
resConfigs 'zh', 'zh-rCN' resConfigs 'zh', 'zh-rCN'
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"

View File

@@ -14,7 +14,7 @@
android:usesCleartextTraffic="true"> android:usesCleartextTraffic="true">
<provider <provider
android:name="androidx.core.content.FileProvider" android:name="androidx.core.content.FileProvider"
android:authorities="@string/file_provider_authority" android:authorities="${applicationId}.fileprovider"
android:exported="false" android:exported="false"
android:grantUriPermissions="true"> android:grantUriPermissions="true">
<meta-data <meta-data
@@ -22,25 +22,25 @@
android:resource="@xml/provider_paths" /> android:resource="@xml/provider_paths" />
</provider> </provider>
<activity <activity
android:name="top.fumiama.copymanga.MainActivity" android:name="${applicationId}.MainActivity"
android:theme="@style/AppTheme.NoActionBar" android:theme="@style/AppTheme.NoActionBar"
android:exported="true"> android:exported="true">
<intent-filter> <intent-filter>
<action android:name="android.intent.action.MAIN" /> <action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" /> <category android:name="android.intent.category.LAUNCHER" />
<action android:name="top.fumiama.copymanga.SHARE"/> <action android:name="${applicationId}.SHARE"/>
<category android:name="android.intent.category.DEFAULT"/> <category android:name="android.intent.category.DEFAULT"/>
</intent-filter> </intent-filter>
</activity> </activity>
<activity <activity
android:name="top.fumiama.copymanga.LoginActivity" android:name="${applicationId}.LoginActivity"
android:theme="@style/AppTheme.NoActionBar"/> android:theme="@style/AppTheme.NoActionBar"/>
<activity <activity
android:name="com.yalantis.ucrop.UCropActivity" android:name="com.yalantis.ucrop.UCropActivity"
android:screenOrientation="fullSensor" android:screenOrientation="fullSensor"
android:theme="@style/Theme.AppCompat.Light.NoActionBar"/> android:theme="@style/Theme.AppCompat.Light.NoActionBar"/>
<activity <activity
android:name="top.fumiama.copymanga.ui.vm.ViewMangaActivity" android:name="${applicationId}.ui.vm.ViewMangaActivity"
android:theme="@style/AppTheme.NoActionBar"/> android:theme="@style/AppTheme.NoActionBar"/>
</application> </application>

View File

@@ -69,8 +69,9 @@ class MainActivity : AppCompatActivity() {
private var isMenuWaiting = false private var isMenuWaiting = false
override fun onCreate(savedInstanceState: Bundle?) { override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState) super.onCreate(null)
// must init before setContentView because HomeF need them to init
mainWeakReference = WeakReference(this) mainWeakReference = WeakReference(this)
toolsBox = UITools(this) toolsBox = UITools(this)

View File

@@ -31,7 +31,7 @@ object Reader {
} }
if (zipf.exists()) { if (zipf.exists()) {
ViewMangaActivity.zipFile = zipf ViewMangaActivity.zipFile = zipf
intent.putExtra("callFrom", "zipFirst") //intent.putExtra("callFrom", "zipFirst")
startActivity(intent) startActivity(intent)
} else { } else {
ViewMangaActivity.zipFile = null ViewMangaActivity.zipFile = null

View File

@@ -1,17 +1,12 @@
package top.fumiama.copymanga.template.ui package top.fumiama.copymanga.template.ui
import android.annotation.SuppressLint import android.annotation.SuppressLint
import android.graphics.drawable.Drawable
import android.net.Uri 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.bumptech.glide.Glide import com.bumptech.glide.Glide
import com.bumptech.glide.load.DataSource
import com.bumptech.glide.load.engine.GlideException
import com.bumptech.glide.load.model.GlideUrl import com.bumptech.glide.load.model.GlideUrl
import com.bumptech.glide.request.RequestListener
import com.bumptech.glide.request.target.Target
import kotlinx.android.synthetic.main.card_book.* import kotlinx.android.synthetic.main.card_book.*
import kotlinx.android.synthetic.main.card_book.view.* import kotlinx.android.synthetic.main.card_book.view.*
import kotlinx.android.synthetic.main.line_horizonal_empty.view.* import kotlinx.android.synthetic.main.line_horizonal_empty.view.*
@@ -21,6 +16,7 @@ import top.fumiama.copymanga.tools.ui.GlideHideLottieViewListener
import top.fumiama.dmzj.copymanga.R import top.fumiama.dmzj.copymanga.R
import java.io.File import java.io.File
import java.lang.ref.WeakReference import java.lang.ref.WeakReference
import java.util.concurrent.atomic.AtomicInteger
class CardList( class CardList(
private val fragment: WeakReference<Fragment>, private val fragment: WeakReference<Fragment>,
@@ -32,6 +28,7 @@ class CardList(
private var rows:Array<View?> = arrayOfNulls(20) private var rows:Array<View?> = arrayOfNulls(20)
private var index = 0 private var index = 0
private var count = 0 private var count = 0
private var cardLoadingWaits = AtomicInteger()
var initClickListeners: InitClickListeners? = null var initClickListeners: InitClickListeners? = null
var exitCardList = false var exitCardList = false
@@ -115,9 +112,17 @@ class CardList(
if(!file.exists()){ if(!file.exists()){
if(head != null) { if(head != null) {
that?.context?.let { context -> that?.context?.let { context ->
Glide.with(context).load( val waitMillis = cardLoadingWaits.getAndIncrement().toLong()*200
val g = Glide.with(context).load(
GlideUrl(CMApi.proxy?.wrap(head)?:head, CMApi.myGlideHeaders) GlideUrl(CMApi.proxy?.wrap(head)?:head, CMApi.myGlideHeaders)
).addListener(GlideHideLottieViewListener(WeakReference(it.laic))).into(it.imic) ).addListener(GlideHideLottieViewListener(WeakReference(it.laic)) {
if (exitCardList) return@GlideHideLottieViewListener
cardLoadingWaits.decrementAndGet()
})
if (waitMillis > 0) it.imic.postDelayed({
if (exitCardList) return@postDelayed
g.into(it.imic)
}, waitMillis) else g.into(it.imic)
} }
} else { } else {
it.laic.pauseAnimation() it.laic.pauseAnimation()

View File

@@ -7,11 +7,13 @@ import top.fumiama.dmzj.copymanga.R
import top.fumiama.copymanga.MainActivity import top.fumiama.copymanga.MainActivity
import top.fumiama.copymanga.tools.http.DownloadTools import top.fumiama.copymanga.tools.http.DownloadTools
import top.fumiama.copymanga.tools.http.Proxy import top.fumiama.copymanga.tools.http.Proxy
import top.fumiama.copymanga.tools.http.Resolution
import java.io.File import java.io.File
import java.net.URLEncoder import java.net.URLEncoder
object CMApi { object CMApi {
var proxy = if(Proxy.useImageProxy) Proxy(R.string.imgProxyApiUrl, R.string.imgProxyApiPrefix, R.string.imgProxyKeyID) else null var proxy = if(Proxy.useImageProxy) Proxy(R.string.imgProxyApiUrl, R.string.imgProxyApiPrefix, R.string.imgProxyKeyID) else null
var resolution = Resolution(Regex("\\.c\\d+x\\."))
var myGlideHeaders: LazyHeaders? = null var myGlideHeaders: LazyHeaders? = null
get() { get() {
MainActivity.mainWeakReference?.get()?.let { MainActivity.mainWeakReference?.get()?.let {

View File

@@ -87,7 +87,7 @@ class DownloadPool(folder: String) {
var s = false var s = false
while (!s && tryTimes-- > 0) { while (!s && tryTimes-- > 0) {
val u = imgUrls[index] val u = imgUrls[index]
s = (DownloadTools.getHttpContent(CMApi.proxy?.wrap(u)?:u, -1))?.let { s = (DownloadTools.getHttpContent(CMApi.resolution.wrap(CMApi.proxy?.wrap(u)?:u), -1))?.let {
zip.putNextEntry(ZipEntry("$index.${if(imgUrls[index].contains(".webp")) "webp" else "jpg"}")) zip.putNextEntry(ZipEntry("$index.${if(imgUrls[index].contains(".webp")) "webp" else "jpg"}"))
zip.write(it) zip.write(it)
zip.closeEntry() zip.closeEntry()

View File

@@ -124,6 +124,26 @@ object DownloadTools {
task task
} }
fun prepare(url: String?): FutureTask<ByteArray?>? =
url?.let {
Log.d("Mydl", "prepareHttp: $it")
var ret: ByteArray? = null
val task = FutureTask(Callable {
try {
val connection = getNormalConnection(it, "GET")
val ci = connection?.inputStream
ret = ci?.readBytes()
ci?.close()
connection?.disconnect()
} catch (ex: Exception) {
ex.printStackTrace()
}
return@Callable ret
})
task
}
/*private fun replaceChineseCharacters(string: String?) : String? { /*private fun replaceChineseCharacters(string: String?) : String? {
if (android.os.Build.VERSION.SDK_INT > android.os.Build.VERSION_CODES.M) return string if (android.os.Build.VERSION.SDK_INT > android.os.Build.VERSION_CODES.M) return string
else return string?.replace(Regex("(?<=/)[\\w\\s\\d\\u4e00-\\u9fa5.-]+(?=/?)")) { match -> else return string?.replace(Regex("(?<=/)[\\w\\s\\d\\u4e00-\\u9fa5.-]+(?=/?)")) { match ->

View File

@@ -35,7 +35,7 @@ class Proxy(id: Int, apiPrefixID: Int, keyID: Int? = null) {
} }
return false return false
} }
val useApiProxy: Boolean /*val useApiProxy: Boolean
get() { get() {
MainActivity.mainWeakReference?.get()?.let { MainActivity.mainWeakReference?.get()?.let {
PreferenceManager.getDefaultSharedPreferences(it).apply { PreferenceManager.getDefaultSharedPreferences(it).apply {
@@ -45,6 +45,6 @@ class Proxy(id: Int, apiPrefixID: Int, keyID: Int? = null) {
} }
} }
return false return false
} }*/
} }
} }

View File

@@ -0,0 +1,20 @@
package top.fumiama.copymanga.tools.http
import androidx.preference.PreferenceManager
import top.fumiama.copymanga.MainActivity
import top.fumiama.dmzj.copymanga.R
class Resolution(private val original: Regex) {
private val imageResolution: Int
get() {
MainActivity.mainWeakReference?.get()?.apply {
PreferenceManager.getDefaultSharedPreferences(this).apply {
val b = getString(getString(R.string.imgResolutionKeyID), null)
//Log.d("MyResolution", "use image resolution: $b")
return b?.toInt()?:1500
}
}
return 1500
}
fun wrap(u: String) : String = u.replace(original, ".c${imageResolution}x.")
}

View File

@@ -9,7 +9,7 @@ import com.bumptech.glide.request.RequestListener
import com.bumptech.glide.request.target.Target import com.bumptech.glide.request.target.Target
import java.lang.ref.WeakReference import java.lang.ref.WeakReference
class GlideHideLottieViewListener(private val wla: WeakReference<LottieAnimationView>): RequestListener<Drawable> { class GlideHideLottieViewListener(private val wla: WeakReference<LottieAnimationView>, private val runAfterLoad: (() -> Unit)? = null): RequestListener<Drawable> {
override fun onLoadFailed( override fun onLoadFailed(
e: GlideException?, e: GlideException?,
model: Any?, model: Any?,
@@ -29,6 +29,7 @@ class GlideHideLottieViewListener(private val wla: WeakReference<LottieAnimation
wla.get()?.apply { wla.get()?.apply {
pauseAnimation() pauseAnimation()
visibility = View.GONE visibility = View.GONE
runAfterLoad?.let { it() }
} }
return false return false
} }

View File

@@ -24,8 +24,6 @@ import java.lang.Thread.sleep
import java.lang.ref.WeakReference import java.lang.ref.WeakReference
class BookFragment: NoBackRefreshFragment(R.layout.fragment_book) { class BookFragment: NoBackRefreshFragment(R.layout.fragment_book) {
var fbibinfo: View? = null
var fbtinfo: View? = null
var isOnPause = false var isOnPause = false
override fun onViewCreated(view: View, savedInstanceState: Bundle?) { override fun onViewCreated(view: View, savedInstanceState: Bundle?) {

View File

@@ -73,9 +73,8 @@ class BookHandler(private val th: WeakReference<BookFragment>, val path: String)
//0 -> setLayouts() //0 -> setLayouts()
1 -> setCover() 1 -> setCover()
2 -> setTexts() 2 -> setTexts()
3 -> that?.fbibinfo?.let { setInfoHeight(it) } 3 -> setAuthorsAndTags()
4 -> setAuthorsAndTags() 4 -> setOverScale()
5 -> setOverScale()
6 -> if(complete) that?.navigate2dl() 6 -> if(complete) that?.navigate2dl()
7 -> setVolumes() 7 -> setVolumes()
8 -> that?.apply { fbl?.addView(msg.obj as View) } 8 -> that?.apply { fbl?.addView(msg.obj as View) }
@@ -102,7 +101,6 @@ class BookHandler(private val th: WeakReference<BookFragment>, val path: String)
override fun doWhenFinishDownload() { override fun doWhenFinishDownload() {
super.doWhenFinishDownload() super.doWhenFinishDownload()
if(exit) return if(exit) return
inflateComponents()
if(keys.isEmpty()) book?.results?.groups?.values?.forEach{ if(keys.isEmpty()) book?.results?.groups?.values?.forEach{
keys += it.name keys += it.name
gpws += it.path_word gpws += it.path_word
@@ -112,7 +110,7 @@ class BookHandler(private val th: WeakReference<BookFragment>, val path: String)
cnts += it.count cnts += it.count
Log.d("MyBFH", "Add caption: ${it.name} @ ${it.path_word} of ${it.count}") Log.d("MyBFH", "Add caption: ${it.name} @ ${it.path_word} of ${it.count}")
} }
for (i in 1..5) { for (i in 1..4) {
sendEmptyMessageDelayed(i, (100*i).toLong()) sendEmptyMessageDelayed(i, (100*i).toLong())
} }
if(vols?.isEmpty() != false) initComicData() if(vols?.isEmpty() != false) initComicData()
@@ -126,24 +124,15 @@ class BookHandler(private val th: WeakReference<BookFragment>, val path: String)
that?.setAddToShelf() that?.setAddToShelf()
Log.d("MyBH", "Set complete: true") Log.d("MyBH", "Set complete: true")
} }
private fun inflateComponents(){
if(that?.fbibinfo == null) that?.fbibinfo = that?.layoutInflater?.inflate(R.layout.line_bookinfo, that?.fbl, false)
if(that?.fbtinfo == null) that?.fbtinfo = that?.layoutInflater?.inflate(R.layout.line_text_info, that?.fbl, false)
}
private fun setOverScale(){ private fun setOverScale(){
that?.fbov?.setScaleView(that!!.lbibg) that?.fbov?.setScaleView(that!!.lbibg)
} }
private fun setCover(){ private fun setCover() {
that?.apply { that?.apply {
try { that?.layoutInflater?.inflate(R.layout.line_bookinfo, that?.fbl, false)?.let {
fbl.addView(fbibinfo) fbl.addView(it)
} catch (e: Exception) { setInfoHeight(it)
e.printStackTrace()
(fbibinfo?.parent as LinearLayout?)?.removeAllViews()
fbl?.addView(fbibinfo)
} }
book?.results?.comic?.cover?.let { cover -> book?.results?.comic?.cover?.let { cover ->
val load = Glide.with(this).load( val load = Glide.with(this).load(
@@ -180,8 +169,9 @@ class BookHandler(private val th: WeakReference<BookFragment>, val path: String)
book?.results?.comic?.status?.display book?.results?.comic?.status?.display
) }?:"" ) }?:""
that?.bttime?.text = book?.results?.comic?.datetime_updated that?.bttime?.text = book?.results?.comic?.datetime_updated
(that?.fbtinfo as TextView).text = book?.results?.comic?.brief val v = that?.layoutInflater?.inflate(R.layout.line_text_info, that?.fbl, false)
that?.fbl?.addView(that?.fbtinfo) (v as TextView).text = book?.results?.comic?.brief
that?.fbl?.addView(v)
that?.fbl?.addView(divider) that?.fbl?.addView(divider)
} }

View File

@@ -352,7 +352,7 @@ class ComicDlHandler(looper: Looper, private val th: WeakReference<ComicDlFragme
it.tbtn.setBackgroundResource(R.drawable.rndbg_checked) it.tbtn.setBackgroundResource(R.drawable.rndbg_checked)
it.tbtn.isChecked = false it.tbtn.isChecked = false
ViewMangaActivity.zipFile = zipf ViewMangaActivity.zipFile = zipf
ViewMangaActivity.dlhandler = this ViewMangaActivity.dlHandler = this
ViewMangaActivity.position = it.tbtn.index ViewMangaActivity.position = it.tbtn.index
dl?.show() dl?.show()
val intent = Intent(that?.context, ViewMangaActivity::class.java) val intent = Intent(that?.context, ViewMangaActivity::class.java)
@@ -380,7 +380,7 @@ class ComicDlHandler(looper: Looper, private val th: WeakReference<ComicDlFragme
toolsBox.buildInfo("直接观看", "不下载而进行观看", "确定", toolsBox.buildInfo("直接观看", "不下载而进行观看", "确定",
null, "取消", { null, "取消", {
ViewMangaActivity.zipFile = null ViewMangaActivity.zipFile = null
ViewMangaActivity.dlhandler = this ViewMangaActivity.dlHandler = this
ViewMangaActivity.position = it.tbtn.index ViewMangaActivity.position = it.tbtn.index
dl?.show() dl?.show()

View File

@@ -10,6 +10,7 @@ import android.view.View
import android.view.ViewGroup import android.view.ViewGroup
import android.widget.ArrayAdapter import android.widget.ArrayAdapter
import android.widget.ImageButton import android.widget.ImageButton
import android.widget.Toast
import androidx.navigation.fragment.findNavController import androidx.navigation.fragment.findNavController
import androidx.recyclerview.widget.LinearLayoutManager import androidx.recyclerview.widget.LinearLayoutManager
import androidx.recyclerview.widget.RecyclerView import androidx.recyclerview.widget.RecyclerView
@@ -41,6 +42,19 @@ class HomeFragment : NoBackRefreshFragment(R.layout.fragment_home) {
override fun onViewCreated(view: View, savedInstanceState: Bundle?) { override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState) super.onViewCreated(view, savedInstanceState)
if(isFirstInflate) { if(isFirstInflate) {
val tb = mainWeakReference?.get()?.toolsBox
val netInfo = tb?.netInfo
if(netInfo != null && netInfo != tb.transportStringNull && netInfo != tb.transportStringError) Thread {
val l = MainActivity.member?.refreshAvatar()
if (l?.code != 200) {
mainWeakReference?.get()?.runOnUiThread {
Toast.makeText(context, "${getString(R.string.login_get_avatar_failed)}: 代码${l?.code}, 信息: ${l?.message}", Toast.LENGTH_SHORT).show()
}
MainActivity.member?.logout()
}
}.start()
homeHandler = HomeHandler(WeakReference(this))
val theme = resources.newTheme() val theme = resources.newTheme()
swiperefresh?.setColorSchemeColors( swiperefresh?.setColorSchemeColors(
resources.getColor(R.color.colorAccent, theme), resources.getColor(R.color.colorAccent, theme),
@@ -150,20 +164,6 @@ class HomeFragment : NoBackRefreshFragment(R.layout.fragment_home) {
}.start() }.start()
} }
} }
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
val tb = mainWeakReference?.get()?.toolsBox
val netInfo = tb?.netInfo
if(netInfo != null && netInfo != tb.transportStringNull && netInfo != tb.transportStringError) Thread {
val l = MainActivity.member?.refreshAvatar()
if (l?.code != 200) {
MainActivity.member?.logout()
}
}.start()
homeHandler = HomeHandler(WeakReference(this))
}
override fun onDestroy() { override fun onDestroy() {
super.onDestroy() super.onDestroy()
homeHandler.destroy() homeHandler.destroy()

View File

@@ -12,6 +12,7 @@ import android.widget.LinearLayout
import android.widget.Toast import android.widget.Toast
import androidx.cardview.widget.CardView import androidx.cardview.widget.CardView
import androidx.constraintlayout.widget.ConstraintLayout import androidx.constraintlayout.widget.ConstraintLayout
import androidx.core.animation.doOnEnd
import androidx.navigation.fragment.findNavController import androidx.navigation.fragment.findNavController
import com.bumptech.glide.Glide import com.bumptech.glide.Glide
import com.bumptech.glide.load.model.GlideUrl import com.bumptech.glide.load.model.GlideUrl
@@ -43,9 +44,9 @@ class HomeHandler(private val that: WeakReference<HomeFragment>) : AutoDownloadH
var fhib: View? = null var fhib: View? = 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)
Thread{homeF?.homeHandler?.sendEmptyMessage(3)}.start() Thread{ homeF?.homeHandler?.sendEmptyMessage(3) }.start()
} }
return field return field
} }
@@ -57,17 +58,16 @@ class HomeHandler(private val that: WeakReference<HomeFragment>) : AutoDownloadH
-1 -> homeF?.swiperefresh?.isRefreshing = msg.obj as Boolean -1 -> homeF?.swiperefresh?.isRefreshing = msg.obj as Boolean
//0 -> setLayouts() //0 -> setLayouts()
1 -> inflateCardLines() 1 -> inflateCardLines()
3 -> setBanner(fhib as Banner) 3 -> setBanner(fhib as Banner)
5 -> setBannerInfo(msg.obj as Banner) 5 -> setBannerInfo(msg.obj as Banner)
6 -> { 6 -> {
homeF?.fhl?.let { homeF?.fhl?.let {
ObjectAnimator.ofFloat(it, "alpha", 1f, 0f).setDuration(233).start() val oa = ObjectAnimator.ofFloat(it, "alpha", 1f, 0f).setDuration(233)
it.postDelayed({ oa.doOnEnd { _ ->
it.removeAllViews() it.removeAllViews()
ObjectAnimator.ofFloat(it, "alpha", 0f, 1f).setDuration(233).start() it.alpha = 1f
}, 233) }
oa.start()
} }
} }
7 -> inflateBanner() 7 -> inflateBanner()
@@ -213,7 +213,7 @@ class HomeHandler(private val that: WeakReference<HomeFragment>) : AutoDownloadH
} }
} }
private fun inflateCardLines() = Thread{ private fun inflateCardLines() = Thread {
if (indexLines.isNotEmpty()) indexLines = arrayOf() if (indexLines.isNotEmpty()) indexLines = arrayOf()
inflateRec() inflateRec()
inflateTopics() inflateTopics()

View File

@@ -84,9 +84,9 @@ class VMHandler(activity: ViewMangaActivity, url: String) : AutoDownloadHandler(
PREPARE_LAST_PAGE -> wv.get()?.prepareLastPage(msg.arg1, msg.arg2) PREPARE_LAST_PAGE -> wv.get()?.prepareLastPage(msg.arg1, msg.arg2)
DIALOG_SHOW -> dl.show() DIALOG_SHOW -> dl.show()
LOAD_ITEM_SCROLL_MODE -> loadScrollMode(msg.arg1) LOAD_ITEM_SCROLL_MODE -> loadScrollMode(msg.arg1, msg.obj as? Runnable?)
LOAD_SCROLL_MODE -> loadScrollMode() LOAD_SCROLL_MODE -> loadScrollMode()
LOAD_ITEM_IMAGES_INTO_LINE -> loadImagesIntoLine(msg.arg1) LOAD_ITEM_IMAGES_INTO_LINE -> loadImagesIntoLine(msg.arg1, msg.obj as? Runnable?)
LOAD_IMAGES_INTO_LINE -> loadImagesIntoLine() LOAD_IMAGES_INTO_LINE -> loadImagesIntoLine()
RESTORE_PAGE_NUMBER -> { RESTORE_PAGE_NUMBER -> {
sendEmptyMessage(DIALOG_HIDE) sendEmptyMessage(DIALOG_HIDE)
@@ -121,6 +121,7 @@ class VMHandler(activity: ViewMangaActivity, url: String) : AutoDownloadHandler(
} }
Log.d("MyVMH", "remainingImageCount = $remainingImageCount") Log.d("MyVMH", "remainingImageCount = $remainingImageCount")
} }
DO_LAMBDA -> (msg.obj as? Runnable?)?.run()
SET_NET_INFO -> wv.get()?.idtime?.text = SimpleDateFormat("HH:mm").format(Date()) + week + wv.get()?.toolsBox?.netInfo SET_NET_INFO -> wv.get()?.idtime?.text = SimpleDateFormat("HH:mm").format(Date()) + week + wv.get()?.toolsBox?.netInfo
} }
} }
@@ -187,7 +188,8 @@ class VMHandler(activity: ViewMangaActivity, url: String) : AutoDownloadHandler(
wv.get()?.initManga() wv.get()?.initManga()
wv.get()?.vprog?.visibility = View.GONE wv.get()?.vprog?.visibility = View.GONE
} }
private fun loadImagesIntoLine(item: Int = (wv.get()?.currentItem?:0), maxCount: Int = (wv.get()?.verticalLoadMaxCount?:20)) = Thread{ private fun loadImagesIntoLine(item: Int = (wv.get()?.currentItem?:0), doAfter: Runnable? = null) = Thread{
val maxCount: Int = (wv.get()?.verticalLoadMaxCount?:20)
Log.d("MyVMH", "Fun: loadImagesIntoLine($item, $maxCount)") Log.d("MyVMH", "Fun: loadImagesIntoLine($item, $maxCount)")
wv.get()?.realCount?.let { count -> wv.get()?.realCount?.let { count ->
if(count > 0){ if(count > 0){
@@ -195,10 +197,15 @@ class VMHandler(activity: ViewMangaActivity, url: String) : AutoDownloadHandler(
val loadCount = (if(notFull) count - item else maxCount) - 1 val loadCount = (if(notFull) count - item else maxCount) - 1
obtainMessage(INIT_IMAGE_COUNT, loadCount+1, 0).sendToTarget() obtainMessage(INIT_IMAGE_COUNT, loadCount+1, 0).sendToTarget()
Log.d("MyVMH", "count: $count, loadCount: $loadCount, notFull: $notFull") Log.d("MyVMH", "count: $count, loadCount: $loadCount, notFull: $notFull")
if(loadCount >= 0) for(i in 0..loadCount) obtainMessage(LOAD_IMG_ON,item + i, if(i == loadCount - 1) 1 else 0, wv.get()?.scrollImages?.get(i)).sendToTarget() if(loadCount >= 0) for(i in 0..loadCount) {
obtainMessage(LOAD_IMG_ON,item + i, if(i == loadCount - 1) 1 else 0, wv.get()?.scrollImages?.get(i)).sendToTarget()
}
//else sendEmptyMessageDelayed(RESTORE_PAGE_NUMBER, 233) //else sendEmptyMessageDelayed(RESTORE_PAGE_NUMBER, 233)
if(notFull) obtainMessage(PREPARE_LAST_PAGE, loadCount + 1, maxCount).sendToTarget() if(notFull) obtainMessage(PREPARE_LAST_PAGE, loadCount + 1, maxCount).sendToTarget()
wv.get()?.let { it.runOnUiThread { it.updateSeekBar() } } obtainMessage(DO_LAMBDA, Runnable{
doAfter?.run()
wv.get()?.let { it.updateSeekBar(0) }
}).sendToTarget()
} }
} }
}.start() }.start()
@@ -209,11 +216,11 @@ class VMHandler(activity: ViewMangaActivity, url: String) : AutoDownloadHandler(
sendEmptyMessage(LOAD_IMAGES_INTO_LINE) sendEmptyMessage(LOAD_IMAGES_INTO_LINE)
} }
private fun loadScrollMode(item: Int) { private fun loadScrollMode(item: Int, doAfter: Runnable? = null) {
sendEmptyMessage(DIALOG_SHOW) sendEmptyMessage(DIALOG_SHOW)
//sleep(233) //sleep(233)
Log.d("MyVMH", "loadImgsIntoLine($item)") Log.d("MyVMH", "loadImgsIntoLine($item)")
obtainMessage(LOAD_ITEM_IMAGES_INTO_LINE, item, 0).sendToTarget() obtainMessage(LOAD_ITEM_IMAGES_INTO_LINE, item, 0, doAfter).sendToTarget()
} }
private fun showInfCard() { private fun showInfCard() {
@@ -258,7 +265,7 @@ class VMHandler(activity: ViewMangaActivity, url: String) : AutoDownloadHandler(
const val TRIGGER_INFO_CARD_FULL = 18 const val TRIGGER_INFO_CARD_FULL = 18
const val INIT_IMAGE_COUNT = 19 const val INIT_IMAGE_COUNT = 19
const val DECREASE_IMAGE_COUNT_AND_RESTORE_PAGE_NUMBER_AT_ZERO = 20 const val DECREASE_IMAGE_COUNT_AND_RESTORE_PAGE_NUMBER_AT_ZERO = 20
const val DO_LAMBDA = 21
const val SET_NET_INFO = 22 const val SET_NET_INFO = 22
} }
} }

View File

@@ -13,9 +13,11 @@ import android.media.AudioManager
import android.os.Bundle import android.os.Bundle
import android.os.Handler import android.os.Handler
import android.util.Log import android.util.Log
import android.util.TypedValue
import android.view.* import android.view.*
import android.widget.SeekBar import android.widget.SeekBar
import android.widget.Toast import android.widget.Toast
import androidx.core.animation.doOnEnd
import androidx.core.content.ContextCompat import androidx.core.content.ContextCompat
import androidx.core.content.edit import androidx.core.content.edit
import androidx.preference.PreferenceManager import androidx.preference.PreferenceManager
@@ -50,6 +52,7 @@ import java.io.File
import java.io.InputStream import java.io.InputStream
import java.lang.ref.WeakReference import java.lang.ref.WeakReference
import java.util.concurrent.FutureTask import java.util.concurrent.FutureTask
import java.util.concurrent.atomic.AtomicInteger
import java.util.zip.ZipFile import java.util.zip.ZipFile
import kotlin.math.abs import kotlin.math.abs
@@ -78,16 +81,23 @@ class ViewMangaActivity : TitleActivityTemplate() {
set(value) = setPageNumber(value) set(value) = setPageNumber(value)
//var pn = 0 //var pn = 0
private val isPnValid: Boolean get() { private val isPnValid: Boolean get() {
val re = if(pn == -2) { val re = forceLetPNValid || if(pn == -2) {
pn = 0 pn = 0
true true
} else { } else {
intent.getStringExtra("function") == "log" && pn > 0 intent.getStringExtra("function") == "log" && pn > 0
} }
Log.d("MyVM", "isPnValid: $re") Log.d("MyVM", "isPnValid: $re")
return re return re && pn <= realCount
} }
private var forceLetPNValid: Boolean = false
get() {
if(!field) return false
field = false
return true
}
private var tasks: Array<FutureTask<ByteArray?>?>? = null private var tasks: Array<FutureTask<ByteArray?>?>? = null
private var tasksRunStatus: Array<Boolean>? = null
private var destroy = false private var destroy = false
private var cut = false private var cut = false
private var isCut = booleanArrayOf() private var isCut = booleanArrayOf()
@@ -100,10 +110,26 @@ class ViewMangaActivity : TitleActivityTemplate() {
var urlArray = arrayOf<String>() var urlArray = arrayOf<String>()
private val loadImgOnWait = AtomicInteger()
private var colorOnSurface: Int = 0
get() {
if (field != 0) return field
val tv = TypedValue()
field = if (theme.resolveAttribute(R.attr.colorOnSurface, tv, true)) {
Log.d("MyVM", "resolve R.attr.colorOnSurface: ${tv.data}")
tv.data
} else {
ContextCompat.getColor(applicationContext, R.color.material_on_surface_stroke)
}
return field
}
@SuppressLint("SetTextI18n") @SuppressLint("SetTextI18n")
override fun onCreate(savedInstanceState: Bundle?) { override fun onCreate(savedInstanceState: Bundle?) {
postponeEnterTransition()
setContentView(R.layout.activity_viewmanga) setContentView(R.layout.activity_viewmanga)
super.onCreate(savedInstanceState) super.onCreate(null)
val settingsPref = MainActivity.mainWeakReference?.get()?.let { PreferenceManager.getDefaultSharedPreferences(it) } val settingsPref = MainActivity.mainWeakReference?.get()?.let { PreferenceManager.getDefaultSharedPreferences(it) }
va = WeakReference(this) va = WeakReference(this)
//dlZip2View = intent.getStringExtra("callFrom") == "Dl" || p["dlZip2View"] == "true" //dlZip2View = intent.getStringExtra("callFrom") == "Dl" || p["dlZip2View"] == "true"
@@ -134,6 +160,8 @@ class ViewMangaActivity : TitleActivityTemplate() {
e.printStackTrace() e.printStackTrace()
toolsBox.toastError(R.string.load_manga_error) toolsBox.toastError(R.string.load_manga_error)
} }
startPostponedEnterTransition()
ObjectAnimator.ofFloat(vcp, "alpha", 0.1f, 1f).setDuration(1000).start()
} }
@Suppress("DEPRECATION") @Suppress("DEPRECATION")
@@ -183,35 +211,13 @@ class ViewMangaActivity : TitleActivityTemplate() {
setProgress() setProgress()
} }
private fun preDownloadChapterPages() { private fun prepareDownloadTasks() {
getImgUrlArray()?.let { getImgUrlArray()?.let {
val mid = (if(pn in 1 until realCount) (if(cut) abs(indexMap[pn]) else pn) else if(pn == -2 || pn >= realCount) it.size else 1) - 1 tasks = Array(it.size) { i ->
val left = if(isVertical && mid > verticalLoadMaxCount) (mid / verticalLoadMaxCount) * verticalLoadMaxCount else (mid-1) val u = it[i]?:return@Array null
val right = if(isVertical) (mid / verticalLoadMaxCount + 1) * verticalLoadMaxCount else mid return@Array DownloadTools.prepare(CMApi.resolution.wrap(CMApi.proxy?.wrap(u)?:u))
tasks = arrayOfNulls(it.size) }
Thread{ tasksRunStatus = Array(it.size) { return@Array false }
for (i in right until it.size) {
if(destroy) break
tasks?.let { tasks ->
it[i]?.let { u ->
tasks[i] = DownloadTools.touch(CMApi.proxy?.wrap(u)?:u)
Thread.sleep(1000)
}
}
}
}.start()
Thread.sleep(500)
Thread{
for (i in left downTo 0) {
if(destroy) break
tasks?.let { tasks ->
it[i]?.let { u ->
tasks[i] = DownloadTools.touch(CMApi.proxy?.wrap(u)?:u)
Thread.sleep(1000)
}
}
}
}.start()
} }
} }
@@ -226,7 +232,7 @@ class ViewMangaActivity : TitleActivityTemplate() {
forEachIndexed{ i, it -> forEachIndexed{ i, it ->
if(it != null) { if(it != null) {
Thread{ Thread{
DownloadTools.getHttpContent(CMApi.proxy?.wrap(it)?:it, 1024)?.inputStream()?.let { DownloadTools.getHttpContent(CMApi.resolution.wrap(CMApi.proxy?.wrap(it)?:it), 1024)?.inputStream()?.let {
isCut[i] = canCut(it) isCut[i] = canCut(it)
analyzedCnt[i] = true analyzedCnt[i] = true
} }
@@ -245,7 +251,7 @@ class ViewMangaActivity : TitleActivityTemplate() {
} }
count = size count = size
runOnUiThread { prepareItems() } runOnUiThread { prepareItems() }
preDownloadChapterPages() if (notUseVP) prepareDownloadTasks()
} }
} }
@@ -379,7 +385,7 @@ class ViewMangaActivity : TitleActivityTemplate() {
private fun loadImgUrlInto(imgView: ScaleImageView, url: String, useCut: Boolean, isLeft: Boolean){ private fun loadImgUrlInto(imgView: ScaleImageView, url: String, useCut: Boolean, isLeft: Boolean){
Log.d("MyVM", "Load from adt: $url") Log.d("MyVM", "Load from adt: $url")
AutoDownloadThread(CMApi.proxy?.wrap(url)?:url, 1000) { AutoDownloadThread(CMApi.resolution.wrap(CMApi.proxy?.wrap(url)?:url), 1000) {
it?.let { loadImg(imgView, BitmapFactory.decodeByteArray(it, 0, it.size), useCut, isLeft, false) } it?.let { loadImg(imgView, BitmapFactory.decodeByteArray(it, 0, it.size), useCut, isLeft, false) }
}.start() }.start()
} }
@@ -388,7 +394,7 @@ class ViewMangaActivity : TitleActivityTemplate() {
val loading = Bitmap.createBitmap(1024, 256, Bitmap.Config.ARGB_8888) val loading = Bitmap.createBitmap(1024, 256, Bitmap.Config.ARGB_8888)
val canvas = Canvas(loading) val canvas = Canvas(loading)
val paint = Paint() val paint = Paint()
paint.color = ContextCompat.getColor(applicationContext, R.color.design_default_color_surface) paint.color = colorOnSurface
paint.textSize = 100.0f paint.textSize = 100.0f
paint.typeface = Font.nisiTypeFace!! paint.typeface = Font.nisiTypeFace!!
val text = "${position+1}" val text = "${position+1}"
@@ -398,8 +404,9 @@ class ViewMangaActivity : TitleActivityTemplate() {
return loading return loading
} }
fun loadImgOn(imgView: ScaleImageView, position: Int){ fun loadImgOn(imgView: ScaleImageView, position: Int) {
Log.d("MyVM", "Load img: $position") Log.d("MyVM", "Load img: $position")
if (position < 0 || position > realCount) return
val index2load = if(cut) abs(indexMap[position]) -1 else position val index2load = if(cut) abs(indexMap[position]) -1 else position
val useCut = cut && isCut[index2load] val useCut = cut && isCut[index2load]
val isLeft = cut && indexMap[position] > 0 val isLeft = cut && indexMap[position] > 0
@@ -408,18 +415,53 @@ class ViewMangaActivity : TitleActivityTemplate() {
} }
else { else {
loadImg(imgView, getLoadingBitmap(position), useCut, isLeft, true) loadImg(imgView, getLoadingBitmap(position), useCut, isLeft, true)
val re = tasks?.get(index2load) val sleepTime = loadImgOnWait.getAndIncrement().toLong()*200
if (re != null) Thread{ Log.d("MyVM", "loadImgOn sleep: $sleepTime ms")
val data = re.get() Thread {
if(data != null && data.isNotEmpty()) { val re = tasks?.get(index2load)
BitmapFactory.decodeByteArray(data, 0, data.size)?.let { if (sleepTime > 0 && re?.isDone != true) Thread.sleep(sleepTime)
loadImg(imgView, it, useCut, isLeft, false) if (re != null) {
Log.d("MyVM", "Load position $position from task") if(!re.isDone) re.run()
}?:Log.d("MyVM", "null bitmap at $position") val data = re.get()
if(data != null && data.isNotEmpty()) {
BitmapFactory.decodeByteArray(data, 0, data.size)?.let {
loadImg(imgView, it, useCut, isLeft, false)
runOnUiThread { Log.d("MyVM", "Load position $position from task") }
}?:runOnUiThread { Log.d("MyVM", "null bitmap at $position") }
}
else getImgUrl(index2load)?.let { loadImgUrlInto(imgView, it, useCut, isLeft) }
} }
else getImgUrl(index2load)?.let { loadImgUrlInto(imgView, it, useCut, isLeft) } else getImgUrl(index2load)?.let { loadImgUrlInto(imgView, it, useCut, isLeft) }
loadImgOnWait.decrementAndGet()
tasks?.apply {
if (index2load >= size) return@apply
val p = if (index2load == size-1) index2load-1 else index2load+1
var delta = 1
var isMinus = false
var pos = p
var maxCount = size
while (pos in indices && get(pos)?.isDone != false && tasksRunStatus?.get(pos) != false && maxCount-- > 0) {
runOnUiThread { Log.d("MyVM", "search $pos") }
pos = p + if (isMinus) -delta else delta
if (pos !in indices) {
isMinus = !isMinus
if (!isMinus) delta++
pos = p + if (isMinus) -delta else delta
if (pos !in indices) return@apply
}
isMinus = !isMinus
if (!isMinus) delta++
}
if (pos !in indices || tasksRunStatus?.get(pos) != false) return@apply
runOnUiThread { Log.d("MyVM", "Preload position $pos from task") }
get(pos)?.apply {
if(!isDone) {
tasksRunStatus?.set(pos, true)
run()
}
}
}
}.start() }.start()
else getImgUrl(index2load)?.let { loadImgUrlInto(imgView, it, useCut, isLeft) }
} }
imgView.visibility = View.VISIBLE imgView.visibility = View.VISIBLE
} }
@@ -516,23 +558,43 @@ class ViewMangaActivity : TitleActivityTemplate() {
idtbcut.isChecked = cut idtbcut.isChecked = cut
idtbcut.setOnClickListener { idtbcut.setOnClickListener {
pb["useCut"] = idtbcut.isChecked pb["useCut"] = idtbcut.isChecked
Toast.makeText(this, R.string.take_effect_on_reload, Toast.LENGTH_SHORT).show() val oa = ObjectAnimator.ofFloat(vcp, "alpha", 1f, 0.1f).setDuration(1000)
oa.doOnEnd {
recreate()
}
oa.start()
} }
} }
private fun prepareIdBtLR() { private fun prepareIdBtLR() {
idtblr.isChecked = r2l idtblr.isChecked = r2l
idtblr.setOnClickListener { idtblr.setOnClickListener {
if (isVertical) {
Toast.makeText(this, R.string.unsupported_mode_switching, Toast.LENGTH_SHORT).show()
return@setOnClickListener
}
pb["r2l"] = idtblr.isChecked pb["r2l"] = idtblr.isChecked
Toast.makeText(this, R.string.take_effect_on_reload, Toast.LENGTH_SHORT).show() val oa = ObjectAnimator.ofFloat(vcp, "alpha", 1f, 0.1f).setDuration(1000)
oa.doOnEnd {
recreate()
}
oa.start()
} }
} }
private fun prepareIdBtVP() { private fun prepareIdBtVP() {
idtbvp.isChecked = notUseVP idtbvp.isChecked = notUseVP
idtbvp.setOnClickListener { idtbvp.setOnClickListener {
if (isVertical) {
Toast.makeText(this, R.string.unsupported_mode_switching, Toast.LENGTH_SHORT).show()
return@setOnClickListener
}
pb["noVP"] = idtbvp.isChecked pb["noVP"] = idtbvp.isChecked
Toast.makeText(this, R.string.take_effect_on_reload, Toast.LENGTH_SHORT).show() val oa = ObjectAnimator.ofFloat(vcp, "alpha", 1f, 0.1f).setDuration(1000)
oa.doOnEnd {
recreate()
}
oa.start()
} }
} }
@@ -554,7 +616,11 @@ class ViewMangaActivity : TitleActivityTemplate() {
} }
} }
fun updateSeekBar() { fun updateSeekBar(p: Int = 0) {
if (p > 0) {
updateSeekText(p)
return
}
if (!isInSeek) hideDrawer() if (!isInSeek) hideDrawer()
updateSeekText() updateSeekText()
updateSeekProgress() updateSeekProgress()
@@ -569,19 +635,53 @@ class ViewMangaActivity : TitleActivityTemplate() {
inftitle.ttitle.text = handler.manga?.results?.chapter?.name inftitle.ttitle.text = handler.manga?.results?.chapter?.name
inftxtprogress.text = "$pageNum/$realCount" inftxtprogress.text = "$pageNum/$realCount"
infseek.setOnSeekBarChangeListener(object : SeekBar.OnSeekBarChangeListener { infseek.setOnSeekBarChangeListener(object : SeekBar.OnSeekBarChangeListener {
var p = 0
var manualCount = 0
var startP = 0
override fun onProgressChanged(p0: SeekBar?, p1: Int, isHuman: Boolean) { override fun onProgressChanged(p0: SeekBar?, p1: Int, isHuman: Boolean) {
Log.d("MyVM", "seek to ${p1 * realCount / 100}")
if (isHuman) { if (isHuman) {
if (p1 >= (pageNum + 1) * 100 / realCount) scrollForward() var np = p1 * realCount / 100
else if (p1 < (pageNum - 1) * 100 / realCount) scrollBack() if (np <= 0) np = 1
else if (np > realCount) np = realCount
Log.d("MyVM", "seek to $np")
if (p1 >= (pageNum + 1) * 100 / realCount) {
if(manualCount < 3) scrollForward() else p = np
after()
}
else if (p1 < (pageNum - 1) * 100 / realCount) {
if(manualCount < 3) scrollBack() else p = np
after()
}
} }
} }
override fun onStartTrackingTouch(p0: SeekBar?) { override fun onStartTrackingTouch(p0: SeekBar?) {
isInSeek = true isInSeek = true
p = pageNum
startP = p
manualCount = 0
} }
override fun onStopTrackingTouch(p0: SeekBar?) { override fun onStopTrackingTouch(p0: SeekBar?) {
isInSeek = false if(manualCount >= 3) {
val pS = p
Log.d("MyVM", "stop seek at $pS")
if (isVertical && startP/verticalLoadMaxCount != p/verticalLoadMaxCount) {
handler.obtainMessage(
VMHandler.LOAD_ITEM_SCROLL_MODE,
p / verticalLoadMaxCount * verticalLoadMaxCount,
0,
Runnable {
isInScroll = false
forceLetPNValid = true
pn = pS
Log.d("MyVM", "set stopped seek to $pS = $pageNum")
isInSeek = false
}
).sendToTarget()
} else pageNum = pS
} else isInSeek = false
}
private fun after() {
if(manualCount++ < 3) p = pageNum else updateSeekBar(p)
} }
}) })
isearch.setImageResource(R.drawable.ic_author) isearch.setImageResource(R.drawable.ic_author)
@@ -617,7 +717,7 @@ class ViewMangaActivity : TitleActivityTemplate() {
handler.sendEmptyMessage(if(isPnValid) VMHandler.LOAD_PAGE_FROM_ITEM else VMHandler.LOAD_SCROLL_MODE) handler.sendEmptyMessage(if(isPnValid) VMHandler.LOAD_PAGE_FROM_ITEM else VMHandler.LOAD_SCROLL_MODE)
psivs.setOnScrollChangeListener { _, _, scrollY, _, _ -> psivs.setOnScrollChangeListener { _, _, scrollY, _, _ ->
isInScroll = true isInScroll = true
if(!isInSeek){ if(!isInSeek) {
val delta = (scrollY.toFloat() * size.toFloat() / psivl.height.toFloat() + 0.5).toInt() - currentItem % verticalLoadMaxCount val delta = (scrollY.toFloat() * size.toFloat() / psivl.height.toFloat() + 0.5).toInt() - currentItem % verticalLoadMaxCount
if(delta != 0 && !(delta > 0 && pageNum == size)) { if(delta != 0 && !(delta > 0 && pageNum == size)) {
pageNum += delta pageNum += delta
@@ -628,28 +728,48 @@ class ViewMangaActivity : TitleActivityTemplate() {
} }
idtbvh.setOnClickListener { idtbvh.setOnClickListener {
pb["vertical"] = idtbvh.isChecked pb["vertical"] = idtbvh.isChecked
Toast.makeText(this, R.string.take_effect_on_reload, Toast.LENGTH_SHORT).show() val oa = ObjectAnimator.ofFloat(vcp, "alpha", 1f, 0.1f).setDuration(1000)
oa.doOnEnd {
recreate()
}
oa.start()
} }
} }
fun scrollBack() { fun scrollBack() {
isInScroll = false isInScroll = false
if(isVertical && (pageNum-1) % verticalLoadMaxCount == 0){ if(isVertical && (pageNum-1) % verticalLoadMaxCount == 0) {
Log.d("MyVM", "Do scroll back, isVertical: $isVertical, pageNum: $pageNum") Log.d("MyVM", "Do scroll back, isVertical: $isVertical, pageNum: $pageNum")
handler.obtainMessage(VMHandler.LOAD_ITEM_SCROLL_MODE, currentItem - verticalLoadMaxCount, 0).sendToTarget() //loadImgsIntoLine(currentItem - verticalLoadMaxCount) if (isInSeek) {
psivl.postDelayed({ pageNum-- }, 233) updateSeekBar(pageNum-1)
return
}
handler.obtainMessage(
VMHandler.LOAD_ITEM_SCROLL_MODE,
currentItem - verticalLoadMaxCount, 0,
Runnable{
forceLetPNValid = true
pn = pageNum-1
}
).sendToTarget() //loadImgsIntoLine(currentItem - verticalLoadMaxCount)
} else pageNum-- } else pageNum--
} }
fun scrollForward() { fun scrollForward() {
isInScroll = false isInScroll = false
pageNum++ pageNum++
if(isVertical && (pageNum-1) % verticalLoadMaxCount == 0) handler.sendEmptyMessage(VMHandler.LOAD_SCROLL_MODE) if(isVertical && (pageNum-1) % verticalLoadMaxCount == 0) {
if (isInSeek) {
updateSeekBar(pageNum+1)
return
}
handler.sendEmptyMessage(VMHandler.LOAD_SCROLL_MODE)
}
} }
@SuppressLint("SetTextI18n") @SuppressLint("SetTextI18n")
private fun updateSeekText() { private fun updateSeekText(p: Int = 0) {
inftxtprogress.text = "$pageNum/$realCount" inftxtprogress.text = "${if(p == 0) pageNum else p}/$realCount"
} }
private fun updateSeekProgress() { private fun updateSeekProgress() {
@@ -657,10 +777,10 @@ class ViewMangaActivity : TitleActivityTemplate() {
} }
override fun onDestroy() { override fun onDestroy() {
dlhandler?.sendEmptyMessage(0) dlHandler?.sendEmptyMessage(0)
tt.canDo = false tt.canDo = false
destroy = true destroy = true
dlhandler = null dlHandler = null
handler.dl.dismiss() handler.dl.dismiss()
handler.destroy() handler.destroy()
super.onDestroy() super.onDestroy()
@@ -691,7 +811,7 @@ class ViewMangaActivity : TitleActivityTemplate() {
val thisOneI = holder.itemView.onei val thisOneI = holder.itemView.onei
Glide.with(this@ViewMangaActivity.applicationContext) Glide.with(this@ViewMangaActivity.applicationContext)
.asBitmap() .asBitmap()
.load(GlideUrl(CMApi.proxy?.wrap(it)?:it, CMApi.myGlideHeaders)) .load(GlideUrl(CMApi.resolution.wrap(CMApi.proxy?.wrap(it)?:it), CMApi.myGlideHeaders))
.placeholder(BitmapDrawable(resources, getLoadingBitmap(pos))) .placeholder(BitmapDrawable(resources, getLoadingBitmap(pos)))
.into(object : CustomTarget<Bitmap>() { .into(object : CustomTarget<Bitmap>() {
override fun onResourceReady(resource: Bitmap, transition: Transition<in Bitmap>?) { override fun onResourceReady(resource: Bitmap, transition: Transition<in Bitmap>?) {
@@ -700,7 +820,7 @@ class ViewMangaActivity : TitleActivityTemplate() {
override fun onLoadCleared(placeholder: Drawable?) { } override fun onLoadCleared(placeholder: Drawable?) { }
}) })
} else Glide.with(this@ViewMangaActivity.applicationContext) } else Glide.with(this@ViewMangaActivity.applicationContext)
.load(GlideUrl(CMApi.proxy?.wrap(it)?:it, CMApi.myGlideHeaders)) .load(GlideUrl(CMApi.resolution.wrap(CMApi.proxy?.wrap(it)?:it), CMApi.myGlideHeaders))
.placeholder(BitmapDrawable(resources, getLoadingBitmap(pos))) .placeholder(BitmapDrawable(resources, getLoadingBitmap(pos)))
.into(holder.itemView.onei) .into(holder.itemView.onei)
} }
@@ -745,7 +865,7 @@ class ViewMangaActivity : TitleActivityTemplate() {
var fileArray = arrayOf<File>() var fileArray = arrayOf<File>()
var position = 0 var position = 0
var zipFile: File? = null var zipFile: File? = null
var dlhandler: Handler? = null var dlHandler: Handler? = null
var va: WeakReference<ViewMangaActivity>? = null var va: WeakReference<ViewMangaActivity>? = null
var pn = 0 var pn = 0
var noCellarAlert = false var noCellarAlert = false

View File

@@ -20,7 +20,8 @@ class ScrollRefreshView : NestedScrollView {
override fun onScrollChanged(l: Int, t: Int, oldl: Int, oldt: Int) { override fun onScrollChanged(l: Int, t: Int, oldl: Int, oldt: Int) {
super.onScrollChanged(l, t, oldl, oldt) super.onScrollChanged(l, t, oldl, oldt)
//Log.d("MyOSV", "$l, $t, $oldl, $oldt") if(swipeRefreshLayout?.isRefreshing == false) {
swipeRefreshLayout?.isEnabled = t == 0 swipeRefreshLayout?.isEnabled = t == 0
}
} }
} }

View File

@@ -3,7 +3,8 @@
xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:app="http://schemas.android.com/apk/res-auto"
android:id="@+id/vcp" android:id="@+id/vcp"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="match_parent"> android:layout_height="match_parent"
android:alpha="0.1">
<include <include
android:id="@+id/vone" android:id="@+id/vone"
@@ -35,7 +36,7 @@
app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent" app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent" app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" > app:layout_constraintTop_toTopOf="parent">
</androidx.viewpager2.widget.ViewPager2> </androidx.viewpager2.widget.ViewPager2>

View File

@@ -16,8 +16,8 @@
android:clickable="true" android:clickable="true"
android:focusable="true" android:focusable="true"
android:foreground="?android:attr/selectableItemBackground" android:foreground="?android:attr/selectableItemBackground"
app:cardCornerRadius="@dimen/global_radius" app:cardCornerRadius="@dimen/book_card_radius"
app:cardElevation="@dimen/global_card_elevation" app:cardElevation="@dimen/book_card_elevation"
app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent" app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent" app:layout_constraintStart_toStartOf="parent"

View File

@@ -15,8 +15,8 @@
android:clickable="true" android:clickable="true"
android:focusable="true" android:focusable="true"
android:foreground="?android:attr/selectableItemBackground" android:foreground="?android:attr/selectableItemBackground"
app:cardCornerRadius="@dimen/global_radius" app:cardCornerRadius="@dimen/book_card_radius"
app:cardElevation="@dimen/global_card_elevation" app:cardElevation="@dimen/book_card_elevation"
app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent" app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent" app:layout_constraintStart_toStartOf="parent"

View File

@@ -1,6 +1,6 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android" <FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools" xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent" android:layout_width="match_parent"
@@ -12,7 +12,8 @@
android:id="@+id/swiperefresh" android:id="@+id/swiperefresh"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="match_parent" android:layout_height="match_parent"
android:layout_marginTop="64dp"> android:isScrollContainer="true"
android:layout_marginTop="@dimen/search_layout_padding">
<top.fumiama.copymanga.views.ScrollRefreshView <top.fumiama.copymanga.views.ScrollRefreshView
android:id="@+id/fhov" android:id="@+id/fhov"

View File

@@ -8,7 +8,7 @@
<ImageView <ImageView
android:id="@+id/navhbg" android:id="@+id/navhbg"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="0dp" android:layout_height="match_parent"
android:foreground="@drawable/mask_blackbottom" android:foreground="@drawable/mask_blackbottom"
android:onClick="onNavHBgClicked" android:onClick="onNavHBgClicked"
android:scaleType="centerCrop" android:scaleType="centerCrop"
@@ -41,10 +41,10 @@
<ImageView <ImageView
android:id="@+id/navhicon" android:id="@+id/navhicon"
android:layout_width="wrap_content" android:layout_width="@dimen/user_icon_size"
android:layout_height="wrap_content" android:layout_height="@dimen/user_icon_size"
android:layout_marginBottom="@dimen/nav_header_vertical_spacing" android:layout_marginBottom="@dimen/nav_header_vertical_spacing"
android:alpha="@dimen/global_alpha" android:alpha="@dimen/user_icon_alpha"
android:onClick="startLoginActivity" android:onClick="startLoginActivity"
app:layout_constraintBottom_toTopOf="@+id/navttitle" app:layout_constraintBottom_toTopOf="@+id/navttitle"
app:layout_constraintEnd_toEndOf="parent" app:layout_constraintEnd_toEndOf="parent"

View File

@@ -15,8 +15,8 @@
android:clickable="true" android:clickable="true"
android:focusable="true" android:focusable="true"
android:foreground="?android:attr/selectableItemBackground" android:foreground="?android:attr/selectableItemBackground"
app:cardCornerRadius="@dimen/global_radius" app:cardCornerRadius="@dimen/book_card_radius"
app:cardElevation="@dimen/global_card_elevation" app:cardElevation="@dimen/book_card_elevation"
app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent" app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent" app:layout_constraintStart_toStartOf="parent"

View File

@@ -1,5 +1,11 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<resources> <resources>
<string-array name="search_types">
<item>全部</item>
<item>名称</item>
<item>作者</item>
<item>汉化组</item>
</string-array>
<string-array name="weeks"> <string-array name="weeks">
<item>周日</item> <item>周日</item>
<item>周一</item> <item>周一</item>
@@ -9,4 +15,9 @@
<item>周五</item> <item>周五</item>
<item>周六</item> <item>周六</item>
</string-array> </string-array>
<string-array name="resolutions">
<item>1500</item>
<item>1200</item>
<item>800</item>
</string-array>
</resources> </resources>

View File

@@ -7,10 +7,11 @@
<dimen name="icon_size">32dp</dimen> <dimen name="icon_size">32dp</dimen>
<dimen name="icon_size_middle">24dp</dimen> <dimen name="icon_size_middle">24dp</dimen>
<dimen name="icon_size_small">16dp</dimen> <dimen name="icon_size_small">16dp</dimen>
<dimen name="user_icon_size">64dp</dimen>
<dimen name="user_icon_alpha">0.8</dimen>
<dimen name="global_alpha">0.8</dimen> <dimen name="book_card_radius">16dp</dimen>
<dimen name="global_radius">16dp</dimen> <dimen name="book_card_elevation">4dp</dimen>
<dimen name="global_card_elevation">4dp</dimen>
<dimen name="global_content_padding_bottom">48dp</dimen> <dimen name="search_layout_padding">64dp</dimen>
</resources> </resources>

View File

@@ -1,9 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<string-array name="search_types">
<item>全部</item>
<item>名称</item>
<item>作者</item>
<item>汉化组</item>
</string-array>
</resources>

View File

@@ -1,10 +1,9 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE resources [ <!DOCTYPE resources [
<!ENTITY hosturl "api.mangacopy.com"> <!ENTITY hosturl "api.copymanga.tv">
]> ]>
<resources> <resources>
<string name="app_name">拷贝漫画</string> <string name="app_name">拷贝漫画</string>
<string name="file_provider_authority">top.fumiama.copymanga.fileprovider</string>
<string name="action_settings">设定</string> <string name="action_settings">设定</string>
<string name="action_info">关于</string> <string name="action_info">关于</string>
@@ -42,7 +41,7 @@
<string name="web_error">网络错误</string> <string name="web_error">网络错误</string>
<string name="download_cover_failed">保存封面失败</string> <string name="download_cover_failed">保存封面失败</string>
<string name="download_cover_timeout">保存封面超时</string> <string name="download_cover_timeout">保存封面超时</string>
<string name="take_effect_on_reload">下次浏览生效</string> <string name="unsupported_mode_switching">不支持在此模式下切换</string>
<string name="end_of_chapter">已经到头了~</string> <string name="end_of_chapter">已经到头了~</string>
<string name="press_again_to_load_previous_chapter">再次按下加载上一章</string> <string name="press_again_to_load_previous_chapter">再次按下加载上一章</string>
<string name="press_again_to_load_next_chapter">再次按下加载下一章</string> <string name="press_again_to_load_next_chapter">再次按下加载下一章</string>
@@ -85,6 +84,7 @@
<string name="apiProxyApiUrl">https://copymanga.azurewebsites.net/api/api?url=%1$s</string> <string name="apiProxyApiUrl">https://copymanga.azurewebsites.net/api/api?url=%1$s</string>
<string name="apiProxyApiPrefix">https://api.mangacopy.com/api/</string> <string name="apiProxyApiPrefix">https://api.mangacopy.com/api/</string>
--> -->
<string name="imgResolutionKeyID">settings_cat_net_sb_image_resolution</string>
<string name="complete">已完结</string> <string name="complete">已完结</string>
@@ -129,6 +129,8 @@
<string name="caption">标签</string> <string name="caption">标签</string>
<string name="settings_cat_net">网络</string> <string name="settings_cat_net">网络</string>
<string name="settings_cat_net_sb_title_image_resolution">图片分辨率</string>
<string name="settings_cat_net_sb_summary_image_resolution">默认1500</string>
<string name="settings_cat_net_sw_use_cellar">总是使用流量观看</string> <string name="settings_cat_net_sw_use_cellar">总是使用流量观看</string>
<string name="settings_cat_net_sm_use_cellar">打开后不再在开始阅读时提示</string> <string name="settings_cat_net_sm_use_cellar">打开后不再在开始阅读时提示</string>
<string name="settings_cat_net_sw_use_foreign">使用海外线路</string> <string name="settings_cat_net_sw_use_foreign">使用海外线路</string>

View File

@@ -4,6 +4,16 @@
<PreferenceCategory <PreferenceCategory
app:iconSpaceReserved="false" app:iconSpaceReserved="false"
app:title="@string/settings_cat_net"> app:title="@string/settings_cat_net">
<ListPreference
android:max="1500"
app:iconSpaceReserved="false"
app:key="settings_cat_net_sb_image_resolution"
app:selectable="true"
app:summary="@string/settings_cat_net_sb_summary_image_resolution"
app:title="@string/settings_cat_net_sb_title_image_resolution"
app:entries="@array/resolutions"
app:entryValues="@array/resolutions"
android:defaultValue="1500"/>
<SwitchPreferenceCompat <SwitchPreferenceCompat
app:iconSpaceReserved="false" app:iconSpaceReserved="false"
app:key="settings_cat_net_sw_use_cellar" app:key="settings_cat_net_sw_use_cellar"