Skip to content

Commit

Permalink
Merge branch 'release-1.2.0'
Browse files Browse the repository at this point in the history
  • Loading branch information
AoEiuV020 committed Nov 25, 2017
2 parents ac6ad23 + e9e3c65 commit cf7ea85
Show file tree
Hide file tree
Showing 44 changed files with 778 additions and 103 deletions.
2 changes: 1 addition & 1 deletion api/src/main/java/cc/aoeiuv020/panovel/api/piaotian.kt
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ class Piaotian : NovelContext() {
response(requester)
}
if (isDetail(response.url().toString())) {
val detail = getNovelDetail(DetailRequester(requester.url))
val detail = getNovelDetail(DetailRequester(response.url().toString()))
val sdf = SimpleDateFormat("yyyy-MM-dd HH:mm")
val info = detail.run { "更新: ${sdf.format(update)} 简介: $introduction" }
return listOf(NovelListItem(detail.novel, info))
Expand Down
5 changes: 3 additions & 2 deletions app/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,8 @@ android {
applicationId "cc.aoeiuv020.panovel"
minSdkVersion min_version
targetSdkVersion target_version
versionCode 14
versionName "1.1.11"
versionCode 15
versionName "1.2.0"
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
setProperty("archivesBaseName", "$rootProject.name-$versionName")
vectorDrawables.useSupportLibrary = true
Expand Down Expand Up @@ -60,6 +60,7 @@ dependencies {
implementation project(':RefreshRecyclerView')
implementation 'com.github.hackware1993:MagicIndicator:1.5.0'
implementation project(':api')
implementation 'com.github.didikee:AndroidDonate:0.1.0'
}


Expand Down
3 changes: 3 additions & 0 deletions app/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,9 @@
android:label="@string/title_activity_refine_search"
android:theme="@style/AppTheme.NoActionBar" />
<activity android:name=".booklist.BookListActivity" />
<activity
android:name=".donate.DonateActivity"
android:label="@string/donate" />
</application>

</manifest>
9 changes: 8 additions & 1 deletion app/src/main/assets/ChangeLog.txt
Original file line number Diff line number Diff line change
@@ -1,3 +1,11 @@
更新日志:
1.2.0:
添加捐赠界面,
离开捐赠界面五秒后回来就去广告,重启生效,
添加清除缓存功能,
解决精确搜索时飘天文学崩溃的问题,
默认小型布局,能在设置里改,

1.1.11:
试着解决阅读页无法退出全屏的问题,
并添加了返回键退出全屏的设置,
Expand All @@ -21,4 +29,3 @@
添加导出小说到.txt的功能,
在,/sdcard/Android/data/cc.aoeiuv020.panovel/files/Text/
书架中的书籍右上角长按出功能选项,

13 changes: 13 additions & 0 deletions app/src/main/assets/Donate.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
捐赠说明:
paypal会跳到浏览器打开我的paypal.me付款页面,
支付宝如果安装了会跳到转账界面,否则跳到浏览器,
微信没法直接跳到转账界面,只能自己保存二维码,跳到微信扫码选择,

捐赠只是捐赠,聊表心意,
不是应用付费功能,
无法知道是否捐赠,
无法知道是谁捐赠的,
无法记住这个捐赠行为,

事实上主要是国内支付接口对个人开发者不友好,
另外本app也没有服务器保存用户信息,
5 changes: 5 additions & 0 deletions app/src/main/assets/Explain.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
本app所有数据都保存在sd卡中应用的私有目录下,卸载时自动删除,
/sdcard/Android/data/cc.aoeiuv020.panovel/files
有点深,但想必用户也不喜欢什么app都往sd根目录建文件夹,
其中Cache可以删除,包含缓存和不在书架中的书的阅读进度,
导出的书在Text下,
5 changes: 5 additions & 0 deletions app/src/main/java/cc/aoeiuv020/panovel/Presenter.kt
Original file line number Diff line number Diff line change
Expand Up @@ -31,12 +31,17 @@ abstract class Presenter<T : IView> : AnkoLogger {
}

protected fun addDisposable(disposable: Disposable, index: Int = 0) {
debug { "$this add disposable $disposable" }
while (index >= disposableList.size) {
disposableList.add(null)
}
val old = disposableList[index]
disposableList[index] = disposable
old?.dispose()
old?.let {
debug { "old $old dispose" }
it.dispose()
}
}

override fun toString(): String = "${javaClass.simpleName}@${hashCode()}"
Expand Down
9 changes: 7 additions & 2 deletions app/src/main/java/cc/aoeiuv020/panovel/base/item/adapter.kt
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import android.content.Context
import android.view.ViewGroup
import cc.aoeiuv020.panovel.R
import cc.aoeiuv020.panovel.api.NovelItem
import cc.aoeiuv020.panovel.local.Settings
import cn.lemon.view.adapter.BaseViewHolder
import cn.lemon.view.adapter.RecyclerAdapter

Expand All @@ -16,14 +17,18 @@ abstract class BaseItemListAdapter(context: Context)

override fun onViewRecycled(holder: BaseViewHolder<NovelItem>) {
// header和footer会强转失败,
(holder as? BaseItemViewHolder<*>)?.destroy()
(holder as? SmallItemViewHolder<*>)?.destroy()
}
}

open class DefaultItemListAdapter(context: Context, private val presenter: BaseItemListPresenter<*, DefaultItemPresenter>,
private val listener: OnItemLongClickListener? = null)
: BaseItemListAdapter(context) {
override fun onCreateBaseViewHolder(parent: ViewGroup?, viewType: Int): BaseViewHolder<NovelItem>
= DefaultItemViewHolder(presenter, context, parent, R.layout.novel_item, listener)
= if (Settings.BookSmallLayout) {
DefaultItemViewHolder(presenter, context, parent, R.layout.novel_item_small, listener)
} else {
DefaultItemViewHolder(presenter, context, parent, R.layout.novel_item_big, listener)
}

}
44 changes: 25 additions & 19 deletions app/src/main/java/cc/aoeiuv020/panovel/base/item/presenter.kt
Original file line number Diff line number Diff line change
Expand Up @@ -9,13 +9,14 @@ import cc.aoeiuv020.panovel.local.Progress
import cc.aoeiuv020.panovel.local.bookId
import cc.aoeiuv020.panovel.util.async
import io.reactivex.Observable
import org.jetbrains.anko.debug
import org.jetbrains.anko.error

/**
*
* Created by AoEiuV020 on 2017.11.22-10:45:36.
*/
abstract class BaseItemListPresenter<V : BaseItemListView, out T : BaseItemPresenter<*>> : Presenter<V>() {
abstract class BaseItemListPresenter<V : BaseItemListView, out T : SmallItemPresenter<*>> : Presenter<V>() {
var refreshTime = 0L

abstract fun refresh()
Expand All @@ -35,13 +36,14 @@ abstract class DefaultItemListPresenter<V : BaseItemListView>
}

class DefaultItemPresenter(itemListPresenter: BaseItemListPresenter<*, *>)
: BaseItemPresenter<DefaultItemViewHolder>(itemListPresenter)
: BigItemPresenter<DefaultItemViewHolder<*>>(itemListPresenter)

abstract class BaseItemPresenter<T : BaseItemView>(private val itemListPresenter: BaseItemListPresenter<*, *>) : Presenter<T>() {
abstract class SmallItemPresenter<T : SmallItemView>(protected val itemListPresenter: BaseItemListPresenter<*, *>) : Presenter<T>() {
open val refreshTime: Long
get() = itemListPresenter.refreshTime

fun requestDetail(novelItem: NovelItem) {
debug { "request detail $novelItem" }
Observable.fromCallable {
Cache.detail.get(novelItem)
?: NovelContext.getNovelContextByUrl(novelItem.requester.url)
Expand All @@ -55,22 +57,6 @@ abstract class BaseItemPresenter<T : BaseItemView>(private val itemListPresenter
}).let { addDisposable(it, 0) }
}

fun requestUpdate(novelDetail: NovelDetail) {
val novelItem = novelDetail.novel
Observable.fromCallable {
val detail = Cache.detail.get(novelItem, refreshTime = refreshTime)
?: NovelContext.getNovelContextByUrl(novelItem.requester.url)
.getNovelDetail(novelItem.requester).also { Cache.detail.put(it.novel, it) }
detail.update
}.async().subscribe({ updateTime ->
view?.showUpdateTime(updateTime)
}, { e ->
val message = "读取《${novelItem.bookId}》详情失败,"
error(message, e)
itemListPresenter.view?.showError(message, e)
}).let { addDisposable(it, 0) }
}

fun requestChapters(detail: NovelDetail) {
Observable.fromCallable {
val novelItem = detail.novel
Expand All @@ -88,4 +74,24 @@ abstract class BaseItemPresenter<T : BaseItemView>(private val itemListPresenter
}).let { addDisposable(it, 1) }
}

}

abstract class BigItemPresenter<T : BigItemView>(itemListPresenter: BaseItemListPresenter<*, *>) : SmallItemPresenter<T>(itemListPresenter) {

fun requestUpdate(novelDetail: NovelDetail) {
val novelItem = novelDetail.novel
Observable.fromCallable {
val detail = Cache.detail.get(novelItem, refreshTime = refreshTime)
?: NovelContext.getNovelContextByUrl(novelItem.requester.url)
.getNovelDetail(novelItem.requester).also { Cache.detail.put(it.novel, it) }
detail.update
}.async().subscribe({ updateTime ->
view?.showUpdateTime(updateTime)
}, { e ->
val message = "读取《${novelItem.bookId}》详情失败,"
error(message, e)
itemListPresenter.view?.showError(message, e)
}).let { addDisposable(it, 2) }
}

}
7 changes: 5 additions & 2 deletions app/src/main/java/cc/aoeiuv020/panovel/base/item/view.kt
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,11 @@ interface BaseItemListView : IView {
fun showError(message: String, e: Throwable)
}

interface BaseItemView : IView {
interface SmallItemView : IView {
fun showDetail(novelDetail: NovelDetail)
fun showUpdateTime(updateTime: Date)
fun showChapter(chapters: List<NovelChapter>, progress: Int)
}

interface BigItemView : SmallItemView {
fun showUpdateTime(updateTime: Date)
}
96 changes: 57 additions & 39 deletions app/src/main/java/cc/aoeiuv020/panovel/base/item/viewHolder.kt
Original file line number Diff line number Diff line change
Expand Up @@ -3,16 +3,18 @@ package cc.aoeiuv020.panovel.base.item
import android.annotation.SuppressLint
import android.content.Context
import android.view.ViewGroup
import android.widget.TextView
import cc.aoeiuv020.panovel.api.NovelChapter
import cc.aoeiuv020.panovel.api.NovelDetail
import cc.aoeiuv020.panovel.api.NovelItem
import cc.aoeiuv020.panovel.detail.NovelDetailActivity
import cc.aoeiuv020.panovel.local.Bookshelf
import cc.aoeiuv020.panovel.search.RefineSearchActivity
import cc.aoeiuv020.panovel.text.CheckableImageView
import cc.aoeiuv020.panovel.text.NovelTextActivity
import cn.lemon.view.adapter.BaseViewHolder
import com.bumptech.glide.Glide
import kotlinx.android.synthetic.main.novel_item.view.*
import kotlinx.android.synthetic.main.novel_item_big.view.*
import org.jetbrains.anko.AnkoLogger
import org.jetbrains.anko.debug
import java.text.SimpleDateFormat
Expand All @@ -22,24 +24,21 @@ import java.util.*
*
* Created by AoEiuV020 on 2017.11.22-11:19:03.
*/
abstract class BaseItemViewHolder<out T : BaseItemPresenter<*>>(protected val itemListPresenter: BaseItemListPresenter<*, T>,
protected val ctx: Context, parent: ViewGroup?, layoutId: Int,
listener: OnItemLongClickListener? = null)
: BaseViewHolder<NovelItem>(parent, layoutId), BaseItemView, AnkoLogger {
companion object {
@SuppressLint("SimpleDateFormat")
private val sdf = SimpleDateFormat("yyyy-MM-dd HH:mm:ss")
}

abstract class SmallItemViewHolder<out T : SmallItemPresenter<*>>(protected val itemListPresenter: BaseItemListPresenter<*, T>,
protected val ctx: Context, parent: ViewGroup?, layoutId: Int,
listener: OnItemLongClickListener? = null)
: BaseViewHolder<NovelItem>(parent, layoutId), SmallItemView, AnkoLogger {
@Suppress("UNCHECKED_CAST")
protected val presenter: T = itemListPresenter.subPresenter()
private val image = itemView.imageView
private val name = itemView.tvName
private val author = itemView.tvAuthor
private val site = itemView.tvSite
private val update = itemView.tvUpdate
private val readAt = itemView.tvReadAt
private val last = itemView.tvLast
/**
* 书架页没有这个star按钮,
*/
private val star: CheckableImageView? = itemView.ivStar
protected lateinit var novelItem: NovelItem

init {
Expand All @@ -66,42 +65,45 @@ abstract class BaseItemViewHolder<out T : BaseItemPresenter<*>>(protected val it
true
}
}

star?.apply {
setOnClickListener {
toggle()
if (isChecked) {
Bookshelf.add(novelItem)
} else {
Bookshelf.remove(novelItem)
}
}
}
}

override fun setData(data: NovelItem) {
this.novelItem = data
debug {
"${this.hashCode()} $layoutPosition setData $data"
}
star?.isChecked = Bookshelf.contains(novelItem)
@Suppress("UnnecessaryVariable")
val novel = data
name.text = novel.name
author.text = novel.author
site.text = novel.site

// 清空残留数据,避免闪烁,
update.text = ""
last.text = ""
image.setImageDrawable(null)
readAt.text = ""

presenter.attach(this)
presenter.requestDetail(novel)
}

override fun showDetail(novelDetail: NovelDetail) {
showUpdateTime(novelDetail.update)
Glide.with(ctx).load(novelDetail.bigImg).into(image)
presenter.requestUpdate(novelDetail)
presenter.requestChapters(novelDetail)
}

override fun showUpdateTime(updateTime: Date) {
update.text = sdf.format(updateTime)
}

override fun showChapter(chapters: List<NovelChapter>, progress: Int) {
readAt.text = chapters[progress].name
last.text = chapters.last().name
}

Expand All @@ -110,28 +112,44 @@ abstract class BaseItemViewHolder<out T : BaseItemPresenter<*>>(protected val it
}
}

open class DefaultItemViewHolder(itemListPresenter: BaseItemListPresenter<*, DefaultItemPresenter>,
ctx: Context, parent: ViewGroup?, layoutId: Int,
listener: OnItemLongClickListener? = null)
: BaseItemViewHolder<DefaultItemPresenter>(itemListPresenter, ctx, parent, layoutId, listener) {
private val star = itemView.ivStar

init {
star.apply {
setOnClickListener {
toggle()
if (isChecked) {
Bookshelf.add(novelItem)
} else {
Bookshelf.remove(novelItem)
}
}
}
open class DefaultItemViewHolder<out T : BigItemPresenter<*>>(itemListPresenter: BaseItemListPresenter<*, T>,
ctx: Context, parent: ViewGroup?, layoutId: Int,
listener: OnItemLongClickListener? = null)
: SmallItemViewHolder<T>(itemListPresenter, ctx, parent, layoutId, listener), BigItemView {
companion object {
@SuppressLint("SimpleDateFormat")
private val sdf = SimpleDateFormat("yyyy-MM-dd HH:mm:ss")
}

/**
* 小型视图没有这两个,
*/
private val update: TextView? = itemView.tvUpdate
private val readAt: TextView? = itemView.tvReadAt

override fun setData(data: NovelItem) {
super.setData(data)
star.isChecked = Bookshelf.contains(novelItem)

// 清空残留数据,避免闪烁,
update?.text = ""
readAt?.text = ""
}

override fun showDetail(novelDetail: NovelDetail) {
super.showDetail(novelDetail)
showUpdateTime(novelDetail.update)
update?.also {
presenter.requestUpdate(novelDetail)
}
}

override fun showUpdateTime(updateTime: Date) {
update?.text = sdf.format(updateTime)
}

override fun showChapter(chapters: List<NovelChapter>, progress: Int) {
super.showChapter(chapters, progress)
readAt?.text = chapters[progress].name
}
}

Loading

0 comments on commit cf7ea85

Please sign in to comment.