diff --git a/app/src/main/assets/litepal.xml b/app/src/main/assets/litepal.xml
index d4c6908d..5474a50a 100644
--- a/app/src/main/assets/litepal.xml
+++ b/app/src/main/assets/litepal.xml
@@ -1,7 +1,7 @@
-
+
@@ -9,5 +9,6 @@
+
\ No newline at end of file
diff --git a/app/src/main/java/com/huanchengfly/tieba/post/activities/ForumActivity.kt b/app/src/main/java/com/huanchengfly/tieba/post/activities/ForumActivity.kt
index 12aa75be..c7a8e451 100644
--- a/app/src/main/java/com/huanchengfly/tieba/post/activities/ForumActivity.kt
+++ b/app/src/main/java/com/huanchengfly/tieba/post/activities/ForumActivity.kt
@@ -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
diff --git a/app/src/main/java/com/huanchengfly/tieba/post/activities/SearchPostActivity.kt b/app/src/main/java/com/huanchengfly/tieba/post/activities/SearchPostActivity.kt
index 6beba2da..ea9a088e 100644
--- a/app/src/main/java/com/huanchengfly/tieba/post/activities/SearchPostActivity.kt
+++ b/app/src/main/java/com/huanchengfly/tieba/post/activities/SearchPostActivity.kt
@@ -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(R.id.search_post_header_sort_mode).setOnClickListener {
+ showSortModeMenu(
+ it
+ )
+ }
+ findViewById(R.id.search_post_header_btn_all).setOnClickListener {
+ onlyThread = false
+ }
+ findViewById(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 {
- override fun onResponse(
- call: Call,
- response: Response
- ) {
- 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, 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 {
override fun onResponse(
call: Call,
@@ -143,6 +314,64 @@ class SearchPostActivity : BaseActivity() {
})
}
+ enum class State {
+ INPUT,
+ SEARCH;
+ }
+
+ inner class SearchHistoryDelegateAdapter(
+ val data: List? = 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(R.id.recyclerview)
+ .addItemDecoration(SpacesItemDecoration(0, 0, 8.dpToPx(), 8.dpToPx()))
+ view.findViewById(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(R.id.recyclerview).apply {
+ visibility = View.GONE
+ }
+ viewHolder.getView(R.id.no_data).apply {
+ visibility = View.VISIBLE
+ }
+ } else {
+ viewHolder.getView(R.id.recyclerview).apply {
+ visibility = View.VISIBLE
+ layoutManager = this@SearchHistoryDelegateAdapter.layoutManager
+ adapter = this@SearchHistoryDelegateAdapter.adapter
+ }
+ viewHolder.getView(R.id.no_data).apply {
+ visibility = View.GONE
+ }
+ }
+ }
+ }
+
companion object {
val TAG = SearchPostActivity::class.java.simpleName
const val PARAM_FORUM = "forum_name"
diff --git a/app/src/main/java/com/huanchengfly/tieba/post/adapters/SearchPostHistoryAdapter.kt b/app/src/main/java/com/huanchengfly/tieba/post/adapters/SearchPostHistoryAdapter.kt
new file mode 100644
index 00000000..85eda731
--- /dev/null
+++ b/app/src/main/java/com/huanchengfly/tieba/post/adapters/SearchPostHistoryAdapter.kt
@@ -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(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)
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/huanchengfly/tieba/post/adapters/SingleLayoutAdapter.kt b/app/src/main/java/com/huanchengfly/tieba/post/adapters/SingleLayoutAdapter.kt
new file mode 100644
index 00000000..8316f101
--- /dev/null
+++ b/app/src/main/java/com/huanchengfly/tieba/post/adapters/SingleLayoutAdapter.kt
@@ -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() {
+ 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) {}
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/huanchengfly/tieba/post/adapters/ThreadReplyAdapter.kt b/app/src/main/java/com/huanchengfly/tieba/post/adapters/ThreadReplyAdapter.kt
index d138319d..8ec1bfa2 100644
--- a/app/src/main/java/com/huanchengfly/tieba/post/adapters/ThreadReplyAdapter.kt
+++ b/app/src/main/java/com/huanchengfly/tieba/post/adapters/ThreadReplyAdapter.kt
@@ -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,
diff --git a/app/src/main/java/com/huanchengfly/tieba/post/adapters/base/BaseAdapter.kt b/app/src/main/java/com/huanchengfly/tieba/post/adapters/base/BaseAdapter.kt
index 543fc35a..b0c2e390 100644
--- a/app/src/main/java/com/huanchengfly/tieba/post/adapters/base/BaseAdapter.kt
+++ b/app/src/main/java/com/huanchengfly/tieba/post/adapters/base/BaseAdapter.kt
@@ -20,7 +20,7 @@ abstract class BaseAdapter- (
val onItemChildClickListeners: MutableMap?> = mutableMapOf()
- val headers: MutableList = mutableListOf()
+ val headers: MutableList = mutableListOf()
val footers: MutableList = mutableListOf()
@@ -71,15 +71,19 @@ abstract class BaseAdapter
- (
}
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
- (
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
- (
itemList.clear()
notifyDataSetChanged()
}
+
+ class Layout(
+ val layoutRes: Int = -1,
+ val view: View? = null,
+ val viewInitializer: (View.() -> Unit)? = null
+ )
}
\ No newline at end of file
diff --git a/app/src/main/java/com/huanchengfly/tieba/post/api/interfaces/ITiebaApi.kt b/app/src/main/java/com/huanchengfly/tieba/post/api/interfaces/ITiebaApi.kt
index 59415491..90d655e8 100644
--- a/app/src/main/java/com/huanchengfly/tieba/post/api/interfaces/ITiebaApi.kt
+++ b/app/src/main/java/com/huanchengfly/tieba/post/api/interfaces/ITiebaApi.kt
@@ -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
+ /**
+ * 吧内搜索(异步)
+ *
+ * @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>
+
/**
* 搜索用户
*
diff --git a/app/src/main/java/com/huanchengfly/tieba/post/api/interfaces/impls/MixedTiebaApiImpl.kt b/app/src/main/java/com/huanchengfly/tieba/post/api/interfaces/impls/MixedTiebaApiImpl.kt
index 4ce07a72..60c1888a 100644
--- a/app/src/main/java/com/huanchengfly/tieba/post/api/interfaces/impls/MixedTiebaApiImpl.kt
+++ b/app/src/main/java/com/huanchengfly/tieba/post/api/interfaces/impls/MixedTiebaApiImpl.kt
@@ -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 = 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> = RetrofitTiebaApi.MINI_TIEBA_API.searchPostAsync(
+ keyword,
+ forumName,
+ page,
+ pageSize,
+ only_thread = if (onlyThread) 1 else 0,
+ sortMode = sortMode
)
override fun searchUser(keyword: String): Call =
diff --git a/app/src/main/java/com/huanchengfly/tieba/post/api/retrofit/interfaces/MiniTiebaApi.kt b/app/src/main/java/com/huanchengfly/tieba/post/api/retrofit/interfaces/MiniTiebaApi.kt
index 9ea25e63..75394653 100644
--- a/app/src/main/java/com/huanchengfly/tieba/post/api/retrofit/interfaces/MiniTiebaApi.kt
+++ b/app/src/main/java/com/huanchengfly/tieba/post/api/retrofit/interfaces/MiniTiebaApi.kt
@@ -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
+ @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>
+
@GET("/mo/q/search/user")
fun searchUser(
@Query("word") keyword: String,
diff --git a/app/src/main/java/com/huanchengfly/tieba/post/models/database/SearchPostHistory.java b/app/src/main/java/com/huanchengfly/tieba/post/models/database/SearchPostHistory.java
new file mode 100644
index 00000000..2b77d4da
--- /dev/null
+++ b/app/src/main/java/com/huanchengfly/tieba/post/models/database/SearchPostHistory.java
@@ -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;
+ }
+}
diff --git a/app/src/main/res/layout/layout_search_post_header.xml b/app/src/main/res/layout/layout_search_post_header.xml
new file mode 100644
index 00000000..1e271622
--- /dev/null
+++ b/app/src/main/res/layout/layout_search_post_header.xml
@@ -0,0 +1,69 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/layout/layout_search_post_history.xml b/app/src/main/res/layout/layout_search_post_history.xml
new file mode 100644
index 00000000..0ff64215
--- /dev/null
+++ b/app/src/main/res/layout/layout_search_post_history.xml
@@ -0,0 +1,62 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml
index 3832fa4b..296309f7 100644
--- a/app/src/main/res/values/strings.xml
+++ b/app/src/main/res/values/strings.xml
@@ -378,7 +378,7 @@
这里什么都没有
推荐结果
查询结果
- 仅看主题贴
+ 只看主题贴
新贴在前
旧贴在前
相关度
@@ -523,4 +523,6 @@
精简吧页面
开启后将隐藏吧页面的吧简介和数据(仍然可以通过“关于本吧”查看这些内容)
今天 %1$s
+ 时间倒序
+ 相关性排序
diff --git a/app/src/main/res/xml/data_extraction_rules.xml b/app/src/main/res/xml/data_extraction_rules.xml
index e46addba..d342cefa 100644
--- a/app/src/main/res/xml/data_extraction_rules.xml
+++ b/app/src/main/res/xml/data_extraction_rules.xml
@@ -1,4 +1,23 @@
-
+
+
+
+
+
+
+
+
\ No newline at end of file