feat: 吧内搜索筛选、排序、历史记录
This commit is contained in:
parent
b94d638928
commit
867d47fa59
|
|
@ -1,7 +1,7 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<litepal>
|
||||
<dbname value="tblite" />
|
||||
<version value="23" />
|
||||
<version value="24" />
|
||||
<list>
|
||||
<mapping class="com.huanchengfly.tieba.post.models.database.Account" />
|
||||
<mapping class="com.huanchengfly.tieba.post.models.database.Draft" />
|
||||
|
|
@ -9,5 +9,6 @@
|
|||
<mapping class="com.huanchengfly.tieba.post.models.database.Block" />
|
||||
<mapping class="com.huanchengfly.tieba.post.models.database.TopForum" />
|
||||
<mapping class="com.huanchengfly.tieba.post.models.database.SearchHistory" />
|
||||
<mapping class="com.huanchengfly.tieba.post.models.database.SearchPostHistory" />
|
||||
</list>
|
||||
</litepal>
|
||||
|
|
@ -17,7 +17,6 @@ import android.net.Uri
|
|||
import android.os.Build
|
||||
import android.os.Bundle
|
||||
import android.text.TextUtils
|
||||
import android.util.Log
|
||||
import android.view.Menu
|
||||
import android.view.MenuItem
|
||||
import android.view.View
|
||||
|
|
@ -280,7 +279,6 @@ class ForumActivity : BaseActivity(), View.OnClickListener, OnRefreshedListener,
|
|||
} else {
|
||||
1f
|
||||
}
|
||||
Log.i("OffsetChange", "changed")
|
||||
if (titleVisible != isTitleVisible) {
|
||||
title = if (isTitleVisible) getString(R.string.title_forum, forumName) else null
|
||||
titleVisible = isTitleVisible
|
||||
|
|
|
|||
|
|
@ -2,28 +2,52 @@ package com.huanchengfly.tieba.post.activities
|
|||
|
||||
import android.graphics.Color
|
||||
import android.os.Bundle
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import android.view.animation.LinearInterpolator
|
||||
import android.view.inputmethod.EditorInfo
|
||||
import android.widget.EditText
|
||||
import android.widget.ImageView
|
||||
import android.widget.TextView
|
||||
import androidx.appcompat.widget.ListPopupWindow
|
||||
import androidx.core.widget.TextViewCompat
|
||||
import androidx.recyclerview.widget.RecyclerView
|
||||
import butterknife.BindView
|
||||
import cn.dreamtobe.kpswitch.util.KeyboardUtil
|
||||
import com.google.android.material.textfield.TextInputLayout
|
||||
import com.huanchengfly.tieba.post.R
|
||||
import com.huanchengfly.tieba.post.adapters.SearchPostAdapter
|
||||
import com.huanchengfly.tieba.post.adapters.SearchPostHistoryAdapter
|
||||
import com.huanchengfly.tieba.post.adapters.SingleChooseAdapter
|
||||
import com.huanchengfly.tieba.post.adapters.SingleLayoutAdapter
|
||||
import com.huanchengfly.tieba.post.api.TiebaApi.getInstance
|
||||
import com.huanchengfly.tieba.post.api.models.SearchPostBean
|
||||
import com.huanchengfly.tieba.post.api.retrofit.doIfFailure
|
||||
import com.huanchengfly.tieba.post.api.retrofit.doIfSuccess
|
||||
import com.huanchengfly.tieba.post.components.AutoLineFeedLayoutManager
|
||||
import com.huanchengfly.tieba.post.components.MyLinearLayoutManager
|
||||
import com.huanchengfly.tieba.post.components.MyViewHolder
|
||||
import com.huanchengfly.tieba.post.components.dividers.SpacesItemDecoration
|
||||
import com.huanchengfly.tieba.post.dpToPx
|
||||
import com.huanchengfly.tieba.post.models.database.SearchPostHistory
|
||||
import com.huanchengfly.tieba.post.toastShort
|
||||
import com.huanchengfly.tieba.post.utils.PopupUtil
|
||||
import com.huanchengfly.tieba.post.utils.ThemeUtil
|
||||
import com.huanchengfly.tieba.post.utils.Util
|
||||
import com.huanchengfly.tieba.post.utils.anim.animSet
|
||||
import com.scwang.smart.refresh.layout.SmartRefreshLayout
|
||||
import org.litepal.LitePal
|
||||
import retrofit2.Call
|
||||
import retrofit2.Callback
|
||||
import retrofit2.Response
|
||||
|
||||
class SearchPostActivity : BaseActivity() {
|
||||
private var state: State = State.INPUT
|
||||
set(value) {
|
||||
field = value
|
||||
invalidateState()
|
||||
}
|
||||
|
||||
@BindView(R.id.search_post_refresh_layout)
|
||||
lateinit var refreshLayout: SmartRefreshLayout
|
||||
|
||||
|
|
@ -36,14 +60,47 @@ class SearchPostActivity : BaseActivity() {
|
|||
@BindView(R.id.search_edit_text)
|
||||
lateinit var editText: EditText
|
||||
|
||||
lateinit var searchPostAdapter: SearchPostAdapter
|
||||
private var headerView: View? = null
|
||||
|
||||
private val searchPostAdapter: SearchPostAdapter by lazy { SearchPostAdapter(this) }
|
||||
private var forumName: String? = null
|
||||
private var keyword: String? = null
|
||||
set(value) {
|
||||
field = value
|
||||
if (value != null) refreshLayout.autoRefresh()
|
||||
state = if (value == null) {
|
||||
State.INPUT
|
||||
} else {
|
||||
State.SEARCH
|
||||
}
|
||||
if (value != null) {
|
||||
refreshLayout.autoRefresh()
|
||||
SearchPostHistory(value, forumName)
|
||||
.saveOrUpdate("content = ?", value)
|
||||
}
|
||||
}
|
||||
private var page = 1
|
||||
private var sortMode = 1
|
||||
set(value) {
|
||||
val changed = field != value
|
||||
field = value
|
||||
if (changed) {
|
||||
refreshHeader()
|
||||
if (keyword != null) {
|
||||
refreshLayout.autoRefresh()
|
||||
}
|
||||
}
|
||||
}
|
||||
private var onlyThread = false
|
||||
set(value) {
|
||||
val changed = field != value
|
||||
field = value
|
||||
if (changed) {
|
||||
refreshHeader()
|
||||
if (keyword != null) {
|
||||
refreshLayout.autoRefresh()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun getLayoutId(): Int = R.layout.activity_search_post
|
||||
|
||||
|
|
@ -69,13 +126,120 @@ class SearchPostActivity : BaseActivity() {
|
|||
}
|
||||
}
|
||||
|
||||
private fun invalidateState() {
|
||||
when (state) {
|
||||
State.INPUT -> {
|
||||
refreshLayout.setEnableRefresh(false)
|
||||
refreshLayout.setEnableLoadMore(false)
|
||||
recyclerView.adapter = null
|
||||
loadHistory()
|
||||
}
|
||||
State.SEARCH -> {
|
||||
refreshLayout.setEnableRefresh(true)
|
||||
refreshLayout.setEnableLoadMore(true)
|
||||
recyclerView.adapter = searchPostAdapter
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun refreshHeader() {
|
||||
headerView?.apply {
|
||||
val allBtn: TextView = findViewById(R.id.search_post_header_btn_all)
|
||||
val onlyThreadBtn: TextView = findViewById(R.id.search_post_header_btn_only_thread)
|
||||
val sortModeText: TextView = findViewById(R.id.search_post_header_sort_mode_title)
|
||||
if (onlyThread) {
|
||||
TextViewCompat.setTextAppearance(allBtn, R.style.TextAppearance_Normal)
|
||||
TextViewCompat.setTextAppearance(onlyThreadBtn, R.style.TextAppearance_Bold)
|
||||
} else {
|
||||
TextViewCompat.setTextAppearance(allBtn, R.style.TextAppearance_Bold)
|
||||
TextViewCompat.setTextAppearance(onlyThreadBtn, R.style.TextAppearance_Normal)
|
||||
}
|
||||
sortModeText.text = when (sortMode) {
|
||||
1 -> getString(R.string.title_search_post_sort_by_time)
|
||||
2 -> getString(R.string.title_search_post_sort_by_relevant)
|
||||
else -> null
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun onBackPressed() {
|
||||
if (state == State.SEARCH) {
|
||||
state = State.INPUT
|
||||
KeyboardUtil.showKeyboard(editText)
|
||||
} else {
|
||||
finish()
|
||||
}
|
||||
}
|
||||
|
||||
private fun showSortModeMenu(view: View) {
|
||||
val arrow: ImageView = view.findViewById(R.id.search_post_header_sort_mode_arrow)
|
||||
val animSet = animSet {
|
||||
anim {
|
||||
values = floatArrayOf(180f, 0f)
|
||||
action = { value -> arrow.rotation = value as Float }
|
||||
duration = 150
|
||||
interpolator = LinearInterpolator()
|
||||
}
|
||||
start()
|
||||
}
|
||||
val adapter = SingleChooseAdapter(
|
||||
this,
|
||||
listOf(
|
||||
getString(R.string.title_search_post_sort_by_time),
|
||||
getString(R.string.title_search_post_sort_by_relevant)
|
||||
),
|
||||
sortMode - 1
|
||||
)
|
||||
ListPopupWindow(this).apply {
|
||||
PopupUtil.replaceBackground(this)
|
||||
anchorView = view
|
||||
width = ViewGroup.LayoutParams.WRAP_CONTENT
|
||||
height = ViewGroup.LayoutParams.WRAP_CONTENT
|
||||
isModal = true
|
||||
setAdapter(adapter)
|
||||
setOnItemClickListener { _, _, position: Int, _ ->
|
||||
dismiss()
|
||||
sortMode = position + 1
|
||||
}
|
||||
setOnDismissListener {
|
||||
animSet.reverse()
|
||||
}
|
||||
show()
|
||||
}
|
||||
}
|
||||
|
||||
private fun loadHistory() {
|
||||
LitePal.order("timestamp DESC").findAsync(SearchPostHistory::class.java)
|
||||
.listen { histories ->
|
||||
if (state == State.INPUT) {
|
||||
recyclerView.post {
|
||||
recyclerView.adapter = SearchHistoryDelegateAdapter(histories)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun initView() {
|
||||
refreshLayout.apply {
|
||||
ThemeUtil.setThemeForSmartRefreshLayout(this)
|
||||
setOnLoadMoreListener { loadMore() }
|
||||
setOnRefreshListener { refresh() }
|
||||
}
|
||||
searchPostAdapter = SearchPostAdapter(this)
|
||||
searchPostAdapter.addHeaderView(R.layout.layout_search_post_header) {
|
||||
headerView = this
|
||||
findViewById<View>(R.id.search_post_header_sort_mode).setOnClickListener {
|
||||
showSortModeMenu(
|
||||
it
|
||||
)
|
||||
}
|
||||
findViewById<View>(R.id.search_post_header_btn_all).setOnClickListener {
|
||||
onlyThread = false
|
||||
}
|
||||
findViewById<View>(R.id.search_post_header_btn_only_thread).setOnClickListener {
|
||||
onlyThread = true
|
||||
}
|
||||
refreshHeader()
|
||||
}
|
||||
searchPostAdapter.setOnItemClickListener { _, item, _ ->
|
||||
ThreadActivity.launch(this, item.tid!!, item.pid)
|
||||
}
|
||||
|
|
@ -101,22 +265,22 @@ class SearchPostActivity : BaseActivity() {
|
|||
return
|
||||
}
|
||||
page = 1
|
||||
getInstance().searchPost(keyword!!, forumName!!, false, page, 30)
|
||||
.enqueue(object : Callback<SearchPostBean> {
|
||||
override fun onResponse(
|
||||
call: Call<SearchPostBean>,
|
||||
response: Response<SearchPostBean>
|
||||
) {
|
||||
val data = response.body()
|
||||
searchPostAdapter.setData(data!!.postList)
|
||||
launchIO {
|
||||
getInstance().searchPostAsync(
|
||||
keyword!!,
|
||||
forumName!!,
|
||||
onlyThread = onlyThread,
|
||||
sortMode = sortMode,
|
||||
page = page,
|
||||
pageSize = 30
|
||||
)
|
||||
.doIfSuccess {
|
||||
searchPostAdapter.setData(it.postList)
|
||||
refreshLayout.finishRefresh()
|
||||
refreshLayout.setNoMoreData("1" != data.page!!.hasMore)
|
||||
refreshLayout.setNoMoreData("1" != it.page!!.hasMore)
|
||||
}
|
||||
|
||||
override fun onFailure(call: Call<SearchPostBean?>, t: Throwable) {
|
||||
refreshLayout.finishRefresh(false)
|
||||
}
|
||||
})
|
||||
.doIfFailure { refreshLayout.finishRefresh(false) }
|
||||
}
|
||||
}
|
||||
|
||||
private fun loadMore() {
|
||||
|
|
@ -124,7 +288,14 @@ class SearchPostActivity : BaseActivity() {
|
|||
refreshLayout.finishLoadMore(false)
|
||||
return
|
||||
}
|
||||
getInstance().searchPost(keyword!!, forumName!!, false, page + 1, 30)
|
||||
getInstance().searchPost(
|
||||
keyword!!,
|
||||
forumName!!,
|
||||
onlyThread = onlyThread,
|
||||
sortMode = sortMode,
|
||||
page = page + 1,
|
||||
pageSize = 30
|
||||
)
|
||||
.enqueue(object : Callback<SearchPostBean> {
|
||||
override fun onResponse(
|
||||
call: Call<SearchPostBean>,
|
||||
|
|
@ -143,6 +314,64 @@ class SearchPostActivity : BaseActivity() {
|
|||
})
|
||||
}
|
||||
|
||||
enum class State {
|
||||
INPUT,
|
||||
SEARCH;
|
||||
}
|
||||
|
||||
inner class SearchHistoryDelegateAdapter(
|
||||
val data: List<SearchPostHistory>? = null
|
||||
) : SingleLayoutAdapter(
|
||||
this,
|
||||
R.layout.layout_search_post_history
|
||||
) {
|
||||
val adapter: SearchPostHistoryAdapter = SearchPostHistoryAdapter(context).apply {
|
||||
setData(data)
|
||||
setOnItemClickListener { _, item, _ ->
|
||||
editText.apply {
|
||||
setText(item.content)
|
||||
clearFocus()
|
||||
KeyboardUtil.hideKeyboard(this)
|
||||
}
|
||||
keyword = item.content
|
||||
}
|
||||
}
|
||||
val layoutManager: AutoLineFeedLayoutManager = AutoLineFeedLayoutManager()
|
||||
|
||||
override fun initView(view: View) {
|
||||
view.findViewById<RecyclerView>(R.id.recyclerview)
|
||||
.addItemDecoration(SpacesItemDecoration(0, 0, 8.dpToPx(), 8.dpToPx()))
|
||||
view.findViewById<View>(R.id.end_icon).setOnClickListener {
|
||||
LitePal.deleteAllAsync(SearchPostHistory::class.java).listen {
|
||||
toastShort(R.string.toast_delete_success)
|
||||
recyclerView.post {
|
||||
loadHistory()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun convert(viewHolder: MyViewHolder, itemView: View) {
|
||||
if (data.isNullOrEmpty()) {
|
||||
viewHolder.getView<RecyclerView>(R.id.recyclerview).apply {
|
||||
visibility = View.GONE
|
||||
}
|
||||
viewHolder.getView<View>(R.id.no_data).apply {
|
||||
visibility = View.VISIBLE
|
||||
}
|
||||
} else {
|
||||
viewHolder.getView<RecyclerView>(R.id.recyclerview).apply {
|
||||
visibility = View.VISIBLE
|
||||
layoutManager = this@SearchHistoryDelegateAdapter.layoutManager
|
||||
adapter = this@SearchHistoryDelegateAdapter.adapter
|
||||
}
|
||||
viewHolder.getView<View>(R.id.no_data).apply {
|
||||
visibility = View.GONE
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
companion object {
|
||||
val TAG = SearchPostActivity::class.java.simpleName
|
||||
const val PARAM_FORUM = "forum_name"
|
||||
|
|
|
|||
|
|
@ -0,0 +1,16 @@
|
|||
package com.huanchengfly.tieba.post.adapters
|
||||
|
||||
import android.content.Context
|
||||
import com.huanchengfly.tieba.post.R
|
||||
import com.huanchengfly.tieba.post.adapters.base.BaseSingleTypeAdapter
|
||||
import com.huanchengfly.tieba.post.components.MyViewHolder
|
||||
import com.huanchengfly.tieba.post.models.database.SearchPostHistory
|
||||
|
||||
class SearchPostHistoryAdapter(context: Context) :
|
||||
BaseSingleTypeAdapter<SearchPostHistory>(context) {
|
||||
override fun getItemLayoutId(): Int = R.layout.item_search_history_chip
|
||||
|
||||
override fun convert(viewHolder: MyViewHolder, item: SearchPostHistory, position: Int) {
|
||||
viewHolder.setText(R.id.text, item.content)
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,43 @@
|
|||
package com.huanchengfly.tieba.post.adapters
|
||||
|
||||
import android.content.Context
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import androidx.annotation.LayoutRes
|
||||
import androidx.recyclerview.widget.RecyclerView
|
||||
import com.huanchengfly.tieba.post.components.MyViewHolder
|
||||
|
||||
open class SingleLayoutAdapter(
|
||||
val context: Context,
|
||||
val itemView: View
|
||||
) : RecyclerView.Adapter<MyViewHolder>() {
|
||||
constructor(
|
||||
context: Context,
|
||||
@LayoutRes
|
||||
layoutResId: Int
|
||||
) : this(
|
||||
context,
|
||||
View.inflate(context, layoutResId, null)
|
||||
)
|
||||
|
||||
constructor(
|
||||
context: Context,
|
||||
createViewFunction: () -> View
|
||||
) : this(
|
||||
context,
|
||||
createViewFunction()
|
||||
)
|
||||
|
||||
final override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): MyViewHolder =
|
||||
MyViewHolder(itemView.apply { initView(itemView) })
|
||||
|
||||
final override fun onBindViewHolder(viewHolder: MyViewHolder, position: Int) {
|
||||
convert(viewHolder, itemView)
|
||||
}
|
||||
|
||||
final override fun getItemCount(): Int = 1
|
||||
|
||||
open fun initView(view: View) {}
|
||||
|
||||
open fun convert(viewHolder: MyViewHolder, itemView: View) {}
|
||||
}
|
||||
|
|
@ -654,13 +654,6 @@ class ThreadReplyAdapter(context: Context) :
|
|||
context.getString(R.string.btn_agree_post_default)
|
||||
}
|
||||
)
|
||||
viewHolder.setText(
|
||||
R.id.thread_list_item_reply_btn, if (item.subPostNumber != "0") {
|
||||
context.getString(R.string.btn_reply_post, item.subPostNumber)
|
||||
} else {
|
||||
context.getString(R.string.btn_reply_post_default)
|
||||
}
|
||||
)
|
||||
viewHolder.itemView.background = getItemBackgroundDrawable(
|
||||
context,
|
||||
position,
|
||||
|
|
|
|||
|
|
@ -20,7 +20,7 @@ abstract class BaseAdapter<Item>(
|
|||
|
||||
val onItemChildClickListeners: MutableMap<Int, OnItemChildClickListener<Item>?> = mutableMapOf()
|
||||
|
||||
val headers: MutableList<View> = mutableListOf()
|
||||
val headers: MutableList<Layout> = mutableListOf()
|
||||
|
||||
val footers: MutableList<View> = mutableListOf()
|
||||
|
||||
|
|
@ -71,15 +71,19 @@ abstract class BaseAdapter<Item>(
|
|||
}
|
||||
|
||||
fun addHeaderView(view: View) {
|
||||
headers.add(view)
|
||||
headers.add(Layout(view = view))
|
||||
notifyItemInserted(headers.size - 1)
|
||||
}
|
||||
|
||||
fun removeHeaderView(view: View) {
|
||||
val index = headers.indexOf(view)
|
||||
if (index >= 0) {
|
||||
headers.removeAt(index)
|
||||
notifyItemRemoved(index)
|
||||
fun addHeaderView(layoutRes: Int, viewInitializer: (View.() -> Unit)?) {
|
||||
headers.add(Layout(layoutRes = layoutRes, viewInitializer = viewInitializer))
|
||||
notifyItemInserted(headers.size - 1)
|
||||
}
|
||||
|
||||
fun removeHeaderViewAt(position: Int) {
|
||||
if (position >= 0) {
|
||||
headers.removeAt(position)
|
||||
notifyItemRemoved(position)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -140,7 +144,16 @@ abstract class BaseAdapter<Item>(
|
|||
|
||||
final override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): MyViewHolder {
|
||||
return if (viewType <= ITEM_TYPE_HEADER) {
|
||||
MyViewHolder(headers[ITEM_TYPE_HEADER - viewType])
|
||||
val headerLayout = headers[ITEM_TYPE_HEADER - viewType]
|
||||
if (headerLayout.layoutRes != -1) {
|
||||
MyViewHolder(context, headerLayout.layoutRes, parent).apply {
|
||||
headerLayout.viewInitializer?.invoke(itemView)
|
||||
}
|
||||
} else if (headerLayout.view != null) {
|
||||
MyViewHolder(headerLayout.view)
|
||||
} else {
|
||||
throw IllegalArgumentException("Layout is empty!")
|
||||
}
|
||||
} else if (viewType >= ITEM_TYPE_FOOTER) {
|
||||
MyViewHolder(footers[viewType - ITEM_TYPE_FOOTER])
|
||||
} else {
|
||||
|
|
@ -205,4 +218,10 @@ abstract class BaseAdapter<Item>(
|
|||
itemList.clear()
|
||||
notifyDataSetChanged()
|
||||
}
|
||||
|
||||
class Layout(
|
||||
val layoutRes: Int = -1,
|
||||
val view: View? = null,
|
||||
val viewInitializer: (View.() -> Unit)? = null
|
||||
)
|
||||
}
|
||||
|
|
@ -282,6 +282,7 @@ interface ITiebaApi {
|
|||
* @param keyword 搜索关键词
|
||||
* @param forumName 搜索吧名
|
||||
* @param onlyThread 是否仅搜索主题贴
|
||||
* @param sortMode 排序模式(1 = 时间倒序,2 = 相关性排序)
|
||||
* @param page 分页页码(从 1 开始)
|
||||
* @param pageSize 每页贴数(默认 30)
|
||||
*/
|
||||
|
|
@ -289,10 +290,30 @@ interface ITiebaApi {
|
|||
keyword: String,
|
||||
forumName: String,
|
||||
onlyThread: Boolean = false,
|
||||
sortMode: Int = 1,
|
||||
page: Int = 1,
|
||||
pageSize: Int = 30
|
||||
): Call<SearchPostBean>
|
||||
|
||||
/**
|
||||
* 吧内搜索(异步)
|
||||
*
|
||||
* @param keyword 搜索关键词
|
||||
* @param forumName 搜索吧名
|
||||
* @param onlyThread 是否仅搜索主题贴
|
||||
* @param sortMode 排序模式(1 = 时间倒序,2 = 相关性排序)
|
||||
* @param page 分页页码(从 1 开始)
|
||||
* @param pageSize 每页贴数(默认 30)
|
||||
*/
|
||||
fun searchPostAsync(
|
||||
keyword: String,
|
||||
forumName: String,
|
||||
onlyThread: Boolean = false,
|
||||
sortMode: Int = 1,
|
||||
page: Int = 1,
|
||||
pageSize: Int = 30
|
||||
): Deferred<ApiResult<SearchPostBean>>
|
||||
|
||||
/**
|
||||
* 搜索用户
|
||||
*
|
||||
|
|
|
|||
|
|
@ -172,13 +172,35 @@ object MixedTiebaApiImpl : ITiebaApi {
|
|||
)
|
||||
|
||||
override fun searchPost(
|
||||
keyword: String, forumName: String, onlyThread: Boolean, page: Int, pageSize: Int
|
||||
keyword: String,
|
||||
forumName: String,
|
||||
onlyThread: Boolean,
|
||||
sortMode: Int,
|
||||
page: Int,
|
||||
pageSize: Int
|
||||
): Call<SearchPostBean> = RetrofitTiebaApi.MINI_TIEBA_API.searchPost(
|
||||
keyword,
|
||||
forumName,
|
||||
page,
|
||||
pageSize,
|
||||
only_thread = if (onlyThread) 1 else 0
|
||||
only_thread = if (onlyThread) 1 else 0,
|
||||
sortMode = sortMode
|
||||
)
|
||||
|
||||
override fun searchPostAsync(
|
||||
keyword: String,
|
||||
forumName: String,
|
||||
onlyThread: Boolean,
|
||||
sortMode: Int,
|
||||
page: Int,
|
||||
pageSize: Int
|
||||
): Deferred<ApiResult<SearchPostBean>> = RetrofitTiebaApi.MINI_TIEBA_API.searchPostAsync(
|
||||
keyword,
|
||||
forumName,
|
||||
page,
|
||||
pageSize,
|
||||
only_thread = if (onlyThread) 1 else 0,
|
||||
sortMode = sortMode
|
||||
)
|
||||
|
||||
override fun searchUser(keyword: String): Call<SearchUserBean> =
|
||||
|
|
|
|||
|
|
@ -277,9 +277,21 @@ interface MiniTiebaApi {
|
|||
@Field("kw") forumName: String,
|
||||
@Field("pn") page: Int = 1,
|
||||
@Field("rn") pageSize: Int = 30,
|
||||
@Field("only_thread") only_thread: Int = 0
|
||||
@Field("only_thread") only_thread: Int = 0,
|
||||
@Field("sm") sortMode: Int = 1
|
||||
): Call<SearchPostBean>
|
||||
|
||||
@POST("/c/s/searchpost")
|
||||
@FormUrlEncoded
|
||||
fun searchPostAsync(
|
||||
@Field("word") keyword: String,
|
||||
@Field("kw") forumName: String,
|
||||
@Field("pn") page: Int = 1,
|
||||
@Field("rn") pageSize: Int = 30,
|
||||
@Field("only_thread") only_thread: Int = 0,
|
||||
@Field("sm") sortMode: Int = 1
|
||||
): Deferred<ApiResult<SearchPostBean>>
|
||||
|
||||
@GET("/mo/q/search/user")
|
||||
fun searchUser(
|
||||
@Query("word") keyword: String,
|
||||
|
|
|
|||
|
|
@ -0,0 +1,44 @@
|
|||
package com.huanchengfly.tieba.post.models.database;
|
||||
|
||||
import org.litepal.crud.LitePalSupport;
|
||||
|
||||
public class SearchPostHistory extends LitePalSupport {
|
||||
private int id;
|
||||
private long timestamp;
|
||||
private String content;
|
||||
private String forumName;
|
||||
|
||||
public SearchPostHistory(String content, String forumName) {
|
||||
this.timestamp = System.currentTimeMillis();
|
||||
this.content = content;
|
||||
this.forumName = forumName;
|
||||
}
|
||||
|
||||
public int getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public long getTimestamp() {
|
||||
return timestamp;
|
||||
}
|
||||
|
||||
public void setTimestamp(long timestamp) {
|
||||
this.timestamp = timestamp;
|
||||
}
|
||||
|
||||
public String getContent() {
|
||||
return content;
|
||||
}
|
||||
|
||||
public void setContent(String content) {
|
||||
this.content = content;
|
||||
}
|
||||
|
||||
public String getForumName() {
|
||||
return forumName;
|
||||
}
|
||||
|
||||
public void setForumName(String forumName) {
|
||||
this.forumName = forumName;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,69 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="vertical">
|
||||
|
||||
<com.huanchengfly.tieba.post.widgets.theme.TintLinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:background="@drawable/bg_radius_16dp"
|
||||
android:orientation="horizontal"
|
||||
android:padding="16dp"
|
||||
app:backgroundTint="@color/default_color_card">
|
||||
|
||||
<LinearLayout
|
||||
android:id="@+id/search_post_header_sort_mode"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginEnd="16dp"
|
||||
android:layout_weight="1"
|
||||
android:orientation="horizontal">
|
||||
|
||||
<com.huanchengfly.tieba.post.widgets.theme.TintTextView
|
||||
android:id="@+id/search_post_header_sort_mode_title"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="center_vertical"
|
||||
android:textStyle="bold"
|
||||
app:tint="@color/default_color_text"
|
||||
tools:text="时间倒序" />
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/search_post_header_sort_mode_arrow"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:rotation="180"
|
||||
app:srcCompat="@drawable/ic_round_arrow_drop_up" />
|
||||
</LinearLayout>
|
||||
|
||||
<com.huanchengfly.tieba.post.widgets.theme.TintTextView
|
||||
android:id="@+id/search_post_header_btn_all"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="center_vertical"
|
||||
android:text="@string/title_all_reply"
|
||||
app:tint="@color/default_color_text"
|
||||
tools:textStyle="bold" />
|
||||
|
||||
<com.huanchengfly.tieba.post.widgets.theme.TintView
|
||||
android:layout_width="0.75dp"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_gravity="center_vertical"
|
||||
android:layout_marginStart="8dp"
|
||||
android:layout_marginTop="4dp"
|
||||
android:layout_marginEnd="8dp"
|
||||
android:layout_marginBottom="4dp"
|
||||
app:backgroundTint="@color/default_color_text_disabled" />
|
||||
|
||||
<com.huanchengfly.tieba.post.widgets.theme.TintTextView
|
||||
android:id="@+id/search_post_header_btn_only_thread"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="center_vertical"
|
||||
android:text="@string/title_search_filter_only_thread"
|
||||
app:tint="@color/default_color_text" />
|
||||
</com.huanchengfly.tieba.post.widgets.theme.TintLinearLayout>
|
||||
</LinearLayout>
|
||||
|
|
@ -0,0 +1,62 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<com.huanchengfly.tieba.post.widgets.theme.TintLinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:background="@drawable/bg_radius_8dp"
|
||||
android:orientation="vertical"
|
||||
android:paddingStart="8dp"
|
||||
android:paddingEnd="8dp"
|
||||
android:paddingBottom="12dp"
|
||||
app:backgroundTint="@color/default_color_card">
|
||||
|
||||
<RelativeLayout
|
||||
android:id="@+id/header_root_view"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="12dp"
|
||||
android:layout_marginBottom="8dp"
|
||||
android:paddingStart="8dp"
|
||||
android:paddingEnd="8dp">
|
||||
|
||||
<com.huanchengfly.tieba.post.widgets.theme.TintImageView
|
||||
android:id="@+id/icon"
|
||||
android:layout_width="24dp"
|
||||
android:layout_height="24dp"
|
||||
android:layout_alignParentStart="true"
|
||||
android:layout_centerVertical="true"
|
||||
app:srcCompat="@drawable/ic_round_watch_later_blue"
|
||||
app:tint="@color/default_color_primary" />
|
||||
|
||||
<com.huanchengfly.tieba.post.widgets.theme.TintTextView
|
||||
android:id="@+id/title"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_alignParentEnd="true"
|
||||
android:layout_centerVertical="true"
|
||||
android:layout_marginStart="8dp"
|
||||
android:layout_toStartOf="@id/end_icon"
|
||||
android:layout_toEndOf="@id/icon"
|
||||
android:text="@string/title_search_history"
|
||||
android:textStyle="bold"
|
||||
app:tint="@color/default_color_primary" />
|
||||
|
||||
<com.huanchengfly.tieba.post.widgets.theme.TintImageView
|
||||
android:id="@+id/end_icon"
|
||||
android:layout_width="24dp"
|
||||
android:layout_height="24dp"
|
||||
android:layout_alignParentEnd="true"
|
||||
android:layout_centerVertical="true"
|
||||
app:srcCompat="@drawable/ic_round_delete"
|
||||
app:tint="@color/default_color_primary" />
|
||||
</RelativeLayout>
|
||||
|
||||
<androidx.recyclerview.widget.RecyclerView
|
||||
android:id="@id/recyclerview"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content" />
|
||||
|
||||
<include
|
||||
android:id="@id/no_data"
|
||||
layout="@layout/layout_no_data" />
|
||||
</com.huanchengfly.tieba.post.widgets.theme.TintLinearLayout>
|
||||
|
|
@ -378,7 +378,7 @@
|
|||
<string name="text_no_data">这里什么都没有</string>
|
||||
<string name="title_exact_match">推荐结果</string>
|
||||
<string name="title_fuzzy_match">查询结果</string>
|
||||
<string name="title_search_filter_only_thread">仅看主题贴</string>
|
||||
<string name="title_search_filter_only_thread">只看主题贴</string>
|
||||
<string name="title_search_order_new">新贴在前</string>
|
||||
<string name="title_search_order_old">旧贴在前</string>
|
||||
<string name="title_search_order_relevant">相关度</string>
|
||||
|
|
@ -523,4 +523,6 @@
|
|||
<string name="title_hide_forum_intro_and_stat">精简吧页面</string>
|
||||
<string name="summary_hide_forum_intro_and_stat">开启后将隐藏吧页面的吧简介和数据(仍然可以通过“关于本吧”查看这些内容)</string>
|
||||
<string name="relative_date_today">今天 %1$s</string>
|
||||
<string name="title_search_post_sort_by_time">时间倒序</string>
|
||||
<string name="title_search_post_sort_by_relevant">相关性排序</string>
|
||||
</resources>
|
||||
|
|
|
|||
|
|
@ -1,4 +1,23 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<data-extraction-rules>
|
||||
<cloud-backup></cloud-backup>
|
||||
<cloud-backup>
|
||||
<exclude
|
||||
domain="sharedpref"
|
||||
path="crash.xml" />
|
||||
<exclude
|
||||
domain="sharedpref"
|
||||
path="AppCenter.xml" />
|
||||
<exclude
|
||||
domain="database"
|
||||
path="com.microsoft.appcenter.persistence" />
|
||||
<exclude
|
||||
domain="database"
|
||||
path="com.microsoft.appcenter.persistence-journal" />
|
||||
<exclude
|
||||
domain="file"
|
||||
path="error" />
|
||||
<exclude
|
||||
domain="file"
|
||||
path="appcenter" />
|
||||
</cloud-backup>
|
||||
</data-extraction-rules>
|
||||
Loading…
Reference in New Issue