搜索建议完成

This commit is contained in:
coldmint 2022-07-10 00:33:10 +08:00
parent 0d153622cb
commit 3a691b33aa
34 changed files with 661 additions and 257 deletions

Binary file not shown.

View File

@ -11,6 +11,7 @@
android:name="android.permission.MANAGE_EXTERNAL_STORAGE"
tools:ignore="ScopedStorage" />
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<application
android:name=".RustApplication"
@ -23,6 +24,10 @@
android:supportsRtl="true"
android:theme="@style/Theme.rust.Concept"
android:usesCleartextTraffic="true">
<activity
android:name=".SearchActivity"
android:exported="false" />
<provider
android:name="androidx.core.content.FileProvider"
android:authorities="${applicationId}.fileProvider"
@ -44,24 +49,24 @@
android:name="notch.config"
android:value="portrait|landscape" /> <!-- Activity注册 -->
<activity
android:screenOrientation="portrait"
android:name=".CreationWizardActivity"
android:exported="false" />
android:exported="false"
android:screenOrientation="portrait" />
<activity
android:name=".TurretDesignActivity"
android:screenOrientation="portrait"
android:exported="false" />
android:exported="false"
android:screenOrientation="portrait" />
<activity
android:name=".BrowserActivity"
android:exported="false"
android:screenOrientation="portrait"
android:label="@string/built_in_browser" /> <!-- 适配全面屏 -->
android:label="@string/built_in_browser"
android:screenOrientation="portrait" /> <!-- 适配全面屏 -->
<activity
android:name=".OrderListActivity"
android:exported="false"
android:screenOrientation="portrait" />
<activity
android:name=".SearchActivity"
android:name=".SearchResultActivity"
android:exported="false"
android:screenOrientation="portrait" />
<activity
@ -120,8 +125,6 @@
android:name=".WebModInfoActivity"
android:exported="false"
android:screenOrientation="portrait" />
<activity
android:name=".ErrorActivity"
android:exported="false"

View File

@ -21,7 +21,6 @@ import androidx.navigation.ui.*
import com.afollestad.materialdialogs.MaterialDialog
import com.bumptech.glide.Glide
import com.coldmint.dialog.CoreDialog
import com.coldmint.dialog.InputDialog
import com.coldmint.rust.core.CompressionManager
import com.coldmint.rust.core.TemplatePackage
import com.coldmint.rust.core.dataBean.AppUpdateData
@ -452,46 +451,46 @@ class MainActivity : BaseActivity<ActivityMainBinding>() {
/**
* 初始化搜索项目事件
*/
private fun initSearchItem(newSearchView: SearchView) {
val navigationIcon = viewBinding.toolbar.navigationIcon
var oldTile: CharSequence = viewBinding.toolbar.title
val hideView: (collapsed: Boolean) -> Unit = {
if (it) {
newSearchView.onActionViewCollapsed()
}
viewBinding.toolbar.navigationIcon = navigationIcon
viewBinding.toolbar.title = oldTile
}
newSearchView.queryHint = getString(R.string.search_hint)
newSearchView.setOnCloseListener {
hideView.invoke(false)
return@setOnCloseListener false
}
newSearchView.setOnSearchClickListener {
oldTile = viewBinding.toolbar.title
viewBinding.toolbar.navigationIcon = null
viewBinding.toolbar.title = getString(R.string.search)
}
newSearchView.setOnQueryTextListener(object : SearchView.OnQueryTextListener {
override fun onQueryTextSubmit(query: String?): Boolean {
hideView.invoke(true)
val key = query
if (key != null) {
val goIntent = Intent(this@MainActivity, SearchActivity::class.java)
goIntent.putExtra("key", key)
startActivity(goIntent)
}
return false
}
override fun onQueryTextChange(newText: String?): Boolean {
return false
}
})
searchView = newSearchView
}
// private fun initSearchItem(newSearchView: SearchView) {
// val navigationIcon = viewBinding.toolbar.navigationIcon
// var oldTile: CharSequence = viewBinding.toolbar.title
// val hideView: (collapsed: Boolean) -> Unit = {
// if (it) {
// newSearchView.onActionViewCollapsed()
// }
// viewBinding.toolbar.navigationIcon = navigationIcon
// viewBinding.toolbar.title = oldTile
// }
// newSearchView.queryHint = getString(R.string.search_hint)
// newSearchView.setOnCloseListener {
// hideView.invoke(false)
// return@setOnCloseListener false
// }
// newSearchView.setOnSearchClickListener {
// oldTile = viewBinding.toolbar.title
// viewBinding.toolbar.navigationIcon = null
// viewBinding.toolbar.title = getString(R.string.search)
// }
//
// newSearchView.setOnQueryTextListener(object : SearchView.OnQueryTextListener {
// override fun onQueryTextSubmit(query: String?): Boolean {
// hideView.invoke(true)
// val key = query
// if (key != null) {
// val goIntent = Intent(this@MainActivity, SearchResultActivity::class.java)
// goIntent.putExtra("key", key)
// startActivity(goIntent)
// }
// return false
// }
//
// override fun onQueryTextChange(newText: String?): Boolean {
// return false
// }
//
// })
// searchView = newSearchView
// }
/**
* 导入模板
@ -643,8 +642,8 @@ class MainActivity : BaseActivity<ActivityMainBinding>() {
override fun onCreateOptionsMenu(menu: Menu): Boolean {
val inflater = menuInflater
inflater.inflate(R.menu.menu_main, menu)
val searchView = menu.findItem(R.id.app_bar_search).actionView as SearchView
initSearchItem(searchView)
// val searchView = menu.findItem(R.id.app_bar_search).actionView as SearchView
// initSearchItem(searchView)
return true
}
@ -655,6 +654,9 @@ class MainActivity : BaseActivity<ActivityMainBinding>() {
}
override fun onOptionsItemSelected(item: MenuItem): Boolean {
if (item.itemId == R.id.search) {
startActivity(Intent(this, SearchActivity::class.java))
}
return false
}

View File

@ -866,7 +866,7 @@ class ReleaseModActivity : BaseActivity<ActivityReleaseModBinding>() {
.positiveButton(R.string.dialog_ok).cancelable(false)
}
WebMod.instance.releaseMod(appSettings.getValue(AppSettings.Setting.AppID, ""), modId,
account,
appSettings.getValue(AppSettings.Setting.Token, ""),
modName,
modDescribe,
tagsBuilder.toString(),

View File

@ -22,15 +22,15 @@ import com.google.android.material.snackbar.Snackbar
* @date 2022/1/9 16:50
*/
class ReviewModActivity : BaseActivity<ActivityReviewModBinding>() {
val account: String by lazy {
appSettings.getValue(AppSettings.Setting.Account, "")
val token by lazy {
AppSettings.getInstance(this).getValue(AppSettings.Setting.Token, "")
}
override fun whenCreateActivity(savedInstanceState: Bundle?, canUseView: Boolean) {
if (canUseView) {
viewBinding.toolbar.title = getText(R.string.review_mod)
setReturnButton()
if (account.isBlank()) {
if (token.isBlank()) {
showInfoToView(resId = R.string.please_login_first)
return
}
@ -65,7 +65,7 @@ class ReviewModActivity : BaseActivity<ActivityReviewModBinding>() {
}
itemAuditModBinding.consentView.setOnClickListener {
WebMod.instance.auditMod(
account,
token,
data.id,
true,
object : ApiCallBack<ApiResponse> {
@ -93,8 +93,9 @@ class ReviewModActivity : BaseActivity<ActivityReviewModBinding>() {
})
}
itemAuditModBinding.refusedView.setOnClickListener {
WebMod.instance.auditMod(
account,
token,
data.id,
false,
object : ApiCallBack<ApiResponse> {

View File

@ -1,85 +1,84 @@
package com.coldmint.rust.pro
import android.content.Intent
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import androidx.appcompat.widget.SearchView
import androidx.core.view.isVisible
import androidx.recyclerview.widget.LinearLayoutManager
import com.coldmint.rust.core.dataBean.SearchResultDataBean
import com.coldmint.rust.core.dataBean.SearchSuggestionsData
import com.coldmint.rust.core.interfaces.ApiCallBack
import com.coldmint.rust.core.web.Search
import com.coldmint.rust.core.web.ServerConfiguration
import com.coldmint.rust.pro.adapters.SearchResultAdapter
import com.coldmint.rust.pro.adapters.SearchSuggestionsAdapter
import com.coldmint.rust.pro.base.BaseActivity
import com.coldmint.rust.pro.databinding.ActivitySearchBinding
/**
* 搜索activity
* 搜索界面
*/
class SearchActivity : BaseActivity<ActivitySearchBinding>() {
lateinit var keyWord: String
override fun whenCreateActivity(savedInstanceState: Bundle?, canUseView: Boolean) {
if (canUseView) {
title = getString(R.string.search)
setReturnButton()
loadData(keyWord)
title = String.format(getString(R.string.search_mod_key), keyWord)
viewBinding.recyclerView.layoutManager = LinearLayoutManager(this)
} else {
val thisIntent = intent
val key = thisIntent.getStringExtra("key")
if (key == null) {
showError("key为null")
return
}
keyWord = key
viewBinding.searchView.setOnQueryTextListener(object : SearchView.OnQueryTextListener,
android.widget.SearchView.OnQueryTextListener {
override fun onQueryTextSubmit(query: String?): Boolean {
if (query != null && query.isNotBlank()) {
val intent = Intent(this@SearchActivity, SearchResultActivity::class.java)
intent.putExtra("key", query)
startActivity(intent)
}
return true
}
/**
* 加载数据
* @param keyWord String
*/
fun loadData(keyWord: String) {
Search.instance.searchAll(keyWord, object : ApiCallBack<SearchResultDataBean> {
override fun onResponse(t: SearchResultDataBean) {
if (t.code == ServerConfiguration.Success_Code) {
val list = t.data
if (list != null && list.isNotEmpty()) {
val adapter = SearchResultAdapter(this@SearchActivity, keyWord, list)
viewBinding.progressBar.isVisible = false
viewBinding.tipView.isVisible = false
viewBinding.recyclerView.isVisible = true
viewBinding.recyclerView.adapter = adapter
title = String.format(
getString(R.string.search_mod_key),
keyWord
) + "(" + list.size + ")"
override fun onQueryTextChange(newText: String?): Boolean {
if (newText != null && newText.isNotBlank()) {
Search.instance.suggestions(newText,
object : ApiCallBack<SearchSuggestionsData> {
override fun onResponse(t: SearchSuggestionsData) {
val dataList = t.data
if (dataList.isNullOrEmpty()) {
viewBinding.recyclerView.isVisible = false
} else {
showInfoToView(t.message)
val adapter =
SearchSuggestionsAdapter(
this@SearchActivity,
newText,
dataList
)
adapter.setItemEvent { i, itemSearchSuggestionsBinding, viewHolder, s ->
itemSearchSuggestionsBinding.root.setOnClickListener {
val intent = Intent(
this@SearchActivity,
SearchResultActivity::class.java
)
intent.putExtra("key", s)
startActivity(intent)
}
} else {
showInfoToView(t.message)
}
viewBinding.recyclerView.adapter = adapter
viewBinding.recyclerView.isVisible = true
}
}
override fun onFailure(e: Exception) {
showInfoToView(this@SearchActivity.getString(R.string.network_error))
viewBinding.recyclerView.isVisible = false
}
})
} else {
viewBinding.recyclerView.isVisible = false
}
return true
}
})
}
/**
* 显示信息到视图
* @param text String
*/
fun showInfoToView(text: String) {
viewBinding.tipView.isVisible = true
viewBinding.tipView.text = text
viewBinding.progressBar.isVisible = false
viewBinding.recyclerView.isVisible = false
}
override fun getViewBindingObject(): ActivitySearchBinding {
return ActivitySearchBinding.inflate(layoutInflater)
}
}

View File

@ -0,0 +1,109 @@
package com.coldmint.rust.pro
import android.os.Bundle
import androidx.core.view.isVisible
import com.coldmint.rust.core.dataBean.user.SearchResultDataBean
import com.coldmint.rust.core.interfaces.ApiCallBack
import com.coldmint.rust.core.web.Search
import com.coldmint.rust.core.web.ServerConfiguration
import com.coldmint.rust.pro.adapters.SearchPageAdapter
import com.coldmint.rust.pro.base.BaseActivity
import com.coldmint.rust.pro.databinding.ActivitySearchResultBinding
import com.google.android.material.tabs.TabLayoutMediator
/**
* 搜索activity
*/
class SearchResultActivity : BaseActivity<ActivitySearchResultBinding>() {
lateinit var keyWord: String
val typeMap by lazy {
val map = HashMap<String, Int>()
map["mod"] = R.string.search_type_mod
map["user"] = R.string.search_type_user
map["dynamic"] = R.string.search_type_dynamic
map["mod_comments"] = R.string.search_type_mod_comments
map["mod_versions"] = R.string.search_type_mod_versions
map["purchase_plan"] = R.string.search_type_purchase_plan
map
}
override fun whenCreateActivity(savedInstanceState: Bundle?, canUseView: Boolean) {
if (canUseView) {
setReturnButton()
loadData(keyWord)
title = String.format(getString(R.string.search_mod_key), keyWord)
} else {
val thisIntent = intent
val key = thisIntent.getStringExtra("key")
if (key == null) {
showError("key为null")
return
}
keyWord = key
}
}
/**
* 加载数据
* @param keyWord String
*/
fun loadData(keyWord: String) {
Search.instance.searchAll(keyWord, object : ApiCallBack<SearchResultDataBean> {
override fun onResponse(t: SearchResultDataBean) {
if (t.code == ServerConfiguration.Success_Code) {
val list = t.data.total
if (list.isNotEmpty()) {
val adapter = SearchPageAdapter(this@SearchResultActivity, keyWord, t.data)
viewBinding.viewPager2.adapter = adapter
TabLayoutMediator(viewBinding.tabLayout, viewBinding.viewPager2) { tab, i ->
tab.text = if (i == 0) {
getString(R.string.search_type_mod_all) + "(" + t.data.total.size + ")"
} else {
val typeData = t.data.type[i - 1]
val id = typeMap[typeData.typeName] ?: -1
val name = if (id == -1) {
typeData.typeName
} else {
getString(id)
}
name + "(" + typeData.num + ")"
}
}.attach()
viewBinding.progressBar.isVisible = false
viewBinding.tipView.isVisible = false
viewBinding.contentLayout.isVisible = true
title = String.format(
getString(R.string.search_mod_key),
keyWord
)
} else {
showInfoToView(t.message)
}
} else {
showInfoToView(t.message)
}
}
override fun onFailure(e: Exception) {
showInfoToView(this@SearchResultActivity.getString(R.string.network_error))
}
})
}
/**
* 显示信息到视图
* @param text String
*/
fun showInfoToView(text: String) {
viewBinding.tipView.isVisible = true
viewBinding.tipView.text = text
viewBinding.progressBar.isVisible = false
viewBinding.contentLayout.isVisible = false
}
override fun getViewBindingObject(): ActivitySearchResultBinding {
return ActivitySearchResultBinding.inflate(layoutInflater)
}
}

View File

@ -68,8 +68,8 @@ class WebModInfoActivity : BaseActivity<ActivityWebModInfoBinding>() {
val modFilePath = "$modFolderPath$modId.rwmod"
File(modFilePath)
}
val account by lazy {
appSettings.getValue(AppSettings.Setting.Account, "")
val token by lazy {
appSettings.getValue(AppSettings.Setting.Token, "")
}
var developer: String? = null
@ -105,7 +105,7 @@ class WebModInfoActivity : BaseActivity<ActivityWebModInfoBinding>() {
private fun initData() {
if (account.isBlank()) {
if (token.isBlank()) {
viewBinding.progressBar.isVisible = false
viewBinding.tipView.isVisible = true
viewBinding.tipView.setText(R.string.please_login_first)
@ -115,7 +115,7 @@ class WebModInfoActivity : BaseActivity<ActivityWebModInfoBinding>() {
loadModCommentList(modId)
WebMod.instance.getInfo(account, modId, object : ApiCallBack<WebModInfoData> {
WebMod.instance.getInfo(token, modId, object : ApiCallBack<WebModInfoData> {
override fun onResponse(t: WebModInfoData) {
if (t.code == ServerConfiguration.Success_Code) {
developer = t.data.developer
@ -287,18 +287,6 @@ class WebModInfoActivity : BaseActivity<ActivityWebModInfoBinding>() {
when (item.itemId) {
R.id.report_item -> {
if (isOpen) {
//不能举报自己的模组
if (developer != null && developer == account) {
Snackbar.make(
viewBinding.button,
R.string.unable_to_report2,
Snackbar.LENGTH_SHORT
).setAction(R.string.open) {
val gotoIntent =
Intent(this, WorkManagementActivity::class.java)
startActivity(gotoIntent)
}.show()
} else {
val thisIntent = Intent(this, ReportActivity::class.java)
val bundle = Bundle()
bundle.putString("target", modId)
@ -306,7 +294,6 @@ class WebModInfoActivity : BaseActivity<ActivityWebModInfoBinding>() {
bundle.putString("name", viewBinding.titleView.text.toString())
thisIntent.putExtra("data", bundle)
startActivity(thisIntent)
}
} else {
//不能举报未公开的模组
Snackbar.make(
@ -492,8 +479,7 @@ class WebModInfoActivity : BaseActivity<ActivityWebModInfoBinding>() {
val text = inputField.text.toString()
if (!text.isBlank()) {
WebMod.instance.sendComment(
account,
appSettings.getValue(AppSettings.Setting.AppID, ""),
appSettings.getValue(AppSettings.Setting.Token, ""),
modId,
text,
object : ApiCallBack<ApiResponse> {

View File

@ -175,7 +175,11 @@ class WorkManagementActivity : BaseActivity<ActivityWorkmangementBinding>() {
.positiveButton(R.string.dialog_ok)
.positiveButton {
WebMod.instance.afreshAuditMod(
data.developer,
AppSettings.getInstance(this@WorkManagementActivity)
.getValue(
AppSettings.Setting.Token,
""
),
data.id,
object :
ApiCallBack<ApiResponse> {

View File

@ -0,0 +1,29 @@
package com.coldmint.rust.pro.adapters
import androidx.fragment.app.Fragment
import androidx.fragment.app.FragmentActivity
import androidx.viewpager2.adapter.FragmentStateAdapter
import com.coldmint.rust.core.dataBean.user.SearchResultDataBean
import com.coldmint.rust.pro.fragments.SearchResultFragment
class SearchPageAdapter(
fragmentActivity: FragmentActivity, val keyword: String,
val data: SearchResultDataBean.Data
) : FragmentStateAdapter(fragmentActivity) {
override fun getItemCount(): Int {
return data.type.size + 1
}
override fun createFragment(position: Int): Fragment {
val typeName = if (position == 0) {
"all"
} else {
data.type[position - 1].typeName
}
return SearchResultFragment(keyword, data, typeName)
}
}

View File

@ -2,26 +2,17 @@ package com.coldmint.rust.pro.adapters
import android.content.Context
import android.content.Intent
import android.graphics.Color
import android.graphics.Typeface
import android.os.Bundle
import android.text.SpannableStringBuilder
import android.text.Spanned
import android.text.style.ForegroundColorSpan
import android.text.style.StyleSpan
import android.view.LayoutInflater
import android.view.ViewGroup
import android.widget.Toast
import androidx.core.view.isVisible
import com.bumptech.glide.Glide
import com.bumptech.glide.request.RequestOptions
import com.coldmint.rust.core.dataBean.SearchResultDataBean
import com.coldmint.rust.core.dataBean.user.SearchResultDataBean
import com.coldmint.rust.core.web.ServerConfiguration
import com.coldmint.rust.pro.UserHomePageActivity
import com.coldmint.rust.pro.WebModInfoActivity
import com.coldmint.rust.pro.base.BaseAdapter
import com.coldmint.rust.pro.databinding.ItemSearchResultBinding
import com.coldmint.rust.pro.edit.RustAutoComplete2
import com.coldmint.rust.pro.tool.GlobalMethod
import com.coldmint.rust.pro.tool.TextStyleMaker
import java.util.*
@ -35,9 +26,9 @@ import java.util.*
class SearchResultAdapter(
val context: Context,
val keyWord: String,
dataList: MutableList<SearchResultDataBean.Data>
dataList: MutableList<SearchResultDataBean.Data.Total>
) :
BaseAdapter<ItemSearchResultBinding, SearchResultDataBean.Data>(context, dataList) {
BaseAdapter<ItemSearchResultBinding, SearchResultDataBean.Data.Total>(context, dataList) {
override fun getViewBindingObject(
@ -49,7 +40,7 @@ class SearchResultAdapter(
}
override fun onBingView(
data: SearchResultDataBean.Data,
data: SearchResultDataBean.Data.Total,
viewBinding: ItemSearchResultBinding,
viewHolder: ViewHolder<ItemSearchResultBinding>,
position: Int

View File

@ -0,0 +1,35 @@
package com.coldmint.rust.pro.adapters
import android.content.Context
import android.view.LayoutInflater
import android.view.ViewGroup
import com.coldmint.rust.pro.base.BaseAdapter
import com.coldmint.rust.pro.databinding.ItemSearchSuggestionsBinding
/**
* 搜索建议适配器
* @constructor
*/
class SearchSuggestionsAdapter(
context: Context,
val keyword: String,
dataList: MutableList<String>
) :
BaseAdapter<ItemSearchSuggestionsBinding, String>(context, dataList) {
override fun getViewBindingObject(
layoutInflater: LayoutInflater,
parent: ViewGroup,
viewType: Int
): ItemSearchSuggestionsBinding {
return ItemSearchSuggestionsBinding.inflate(layoutInflater, parent, false)
}
override fun onBingView(
data: String,
viewBinding: ItemSearchSuggestionsBinding,
viewHolder: ViewHolder<ItemSearchSuggestionsBinding>,
position: Int
) {
viewBinding.titleView.text = createSpannableString(data,keyword)
}
}

View File

@ -37,7 +37,7 @@ abstract class BaseAdapter<ViewBindingType : ViewBinding, DataType>(
Handler(Looper.getMainLooper())
}
private val spannableStringBuilder: SpannableStringBuilder = SpannableStringBuilder()
private val colorSpan: ForegroundColorSpan = ForegroundColorSpan(Color.parseColor("#2196F3"))
private val colorSpan: ForegroundColorSpan = ForegroundColorSpan(Color.parseColor("#e91e63"))
private val bold = StyleSpan(Typeface.BOLD)

View File

@ -0,0 +1,50 @@
package com.coldmint.rust.pro.fragments
import android.os.Bundle
import android.view.LayoutInflater
import androidx.recyclerview.widget.LinearLayoutManager
import com.coldmint.rust.core.dataBean.user.SearchResultDataBean
import com.coldmint.rust.pro.adapters.SearchResultAdapter
import com.coldmint.rust.pro.base.BaseFragment
import com.coldmint.rust.pro.databinding.FragmentSearchResultBinding
/**
* 搜索结果碎片
* @property keyword String
* @property dataList MutableList<Data>
* @constructor
*/
class SearchResultFragment(
val keyword: String,
val data: SearchResultDataBean.Data,
val typeName: String
) :
BaseFragment<FragmentSearchResultBinding>() {
override fun whenViewCreated(inflater: LayoutInflater, savedInstanceState: Bundle?) {
val adapter = SearchResultAdapter(requireContext(), keyword, filterList())
viewBinding.recyclerView.adapter = adapter
viewBinding.recyclerView.layoutManager = LinearLayoutManager(requireContext())
}
/**
* 过滤列表(为all返回所有)
* @return MutableList<SearchResultDataBean.Data.Total>
*/
fun filterList(): MutableList<SearchResultDataBean.Data.Total> {
if (typeName == "all") {
return data.total
}
val list = ArrayList<SearchResultDataBean.Data.Total>()
data.total.forEach {
if (it.type == typeName) {
list.add(it)
}
}
return list
}
override fun getViewBindingObject(): FragmentSearchResultBinding {
return FragmentSearchResultBinding.inflate(layoutInflater)
}
}

View File

@ -21,6 +21,7 @@ import com.coldmint.rust.pro.tool.AppSettings
import com.coldmint.rust.pro.tool.GlobalMethod
class UserInfoFragment : BaseFragment<FragmentUserInfoBinding>() {
lateinit var token: String
lateinit var account: String
/**
@ -103,8 +104,8 @@ class UserInfoFragment : BaseFragment<FragmentUserInfoBinding>() {
override fun onResume() {
super.onResume()
if (account.isNotBlank()) {
User.getUserActivationInfo(account, object : ApiCallBack<ActivationInfo> {
if (token.isNotBlank()) {
User.getUserActivationInfo(token, object : ApiCallBack<ActivationInfo> {
override fun onFailure(e: Exception) {
@ -127,9 +128,8 @@ class UserInfoFragment : BaseFragment<FragmentUserInfoBinding>() {
}
loadRecyclerView(t.data.permission)
} else {
viewBinding.nameView.text = account
viewBinding.nameView.text = t.data.userName
loadRecyclerView(3)
// viewBinding.expirationTimeView.text = t.message
}
}
@ -138,6 +138,7 @@ class UserInfoFragment : BaseFragment<FragmentUserInfoBinding>() {
}
override fun whenViewCreated(inflater: LayoutInflater, savedInstanceState: Bundle?) {
token = appSettings.getValue(AppSettings.Setting.Token, "")
account = appSettings.getValue(AppSettings.Setting.Account, "")
viewBinding.myHomeView.setOnClickListener {
val intent = Intent(

View File

@ -6,7 +6,7 @@
android:layout_width="match_parent"
android:layout_height="match_parent"
android:fitsSystemWindows="true"
tools:context=".OrderListActivity">
tools:context=".ActivateActivity">
<com.google.android.material.appbar.AppBarLayout
android:layout_width="match_parent"
@ -21,35 +21,48 @@
</com.google.android.material.appbar.AppBarLayout>
<LinearLayout
<androidx.core.widget.NestedScrollView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_marginLeft="16dp"
android:layout_marginRight="16dp"
android:gravity="center"
android:orientation="vertical"
android:layout_marginLeft="8dp"
android:layout_marginTop="8dp"
android:layout_marginRight="8dp"
app:layout_behavior="com.google.android.material.appbar.AppBarLayout$ScrollingViewBehavior">
<ProgressBar
android:id="@+id/progressBar"
android:layout_width="wrap_content"
<com.google.android.material.card.MaterialCardView
style="@style/Widget.Material3.CardView.Elevated"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:indeterminate="true" />
android:layout_margin="8dp">
<TextView
android:id="@+id/tipView"
android:layout_width="wrap_content"
<LinearLayout
android:animateLayoutChanges="true"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="@string/loading_data"
android:visibility="gone" />
android:layout_margin="8dp"
android:orientation="vertical">
<SearchView
android:id="@+id/searchView"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:iconifiedByDefault="false"
android:queryBackground="@null"
android:queryHint="@string/search" />
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/recyclerView"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="16dp"
android:visibility="gone" />
</LinearLayout>
</com.google.android.material.card.MaterialCardView>
</androidx.core.widget.NestedScrollView>
</androidx.coordinatorlayout.widget.CoordinatorLayout>

View File

@ -0,0 +1,73 @@
<?xml version="1.0" encoding="utf-8"?>
<androidx.coordinatorlayout.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:card_view="http://schemas.android.com/tools"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:fitsSystemWindows="true"
tools:context=".OrderListActivity">
<com.google.android.material.appbar.AppBarLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:fitsSystemWindows="true">
<com.google.android.material.appbar.MaterialToolbar
android:id="@+id/toolbar"
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize" />
</com.google.android.material.appbar.AppBarLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_marginLeft="16dp"
android:layout_marginRight="16dp"
android:gravity="center"
android:orientation="vertical"
app:layout_behavior="com.google.android.material.appbar.AppBarLayout$ScrollingViewBehavior">
<ProgressBar
android:id="@+id/progressBar"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:indeterminate="true" />
<TextView
android:id="@+id/tipView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/loading_data"
android:visibility="gone" />
<LinearLayout
android:visibility="gone"
android:id="@+id/contentLayout"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<com.google.android.material.tabs.TabLayout
android:id="@+id/tabLayout"
app:tabMode="scrollable"
android:layout_width="match_parent"
android:layout_height="wrap_content"/>
<androidx.viewpager2.widget.ViewPager2
android:id="@+id/viewPager2"
android:layout_width="match_parent"
android:layout_height="match_parent"/>
</LinearLayout>
</LinearLayout>
</androidx.coordinatorlayout.widget.CoordinatorLayout>

View File

@ -0,0 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<androidx.recyclerview.widget.RecyclerView xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/recyclerView"
android:layout_width="match_parent"
android:layout_height="match_parent" />

View File

@ -1,18 +1,17 @@
<?xml version="1.0" encoding="utf-8"?>
<androidx.cardview.widget.CardView xmlns:android="http://schemas.android.com/apk/res/android"
<com.google.android.material.card.MaterialCardView xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:card_view="http://schemas.android.com/apk/res-auto"
style="@style/Widget.Material3.CardView.Elevated"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="8dp"
app:cardElevation="2dp"
card_view:cardCornerRadius="2dp">
android:layout_margin="8dp">
<RelativeLayout
android:id="@+id/rootLayout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:padding="8dp">
android:padding="16dp">
<ImageView
android:id="@+id/imageView"
@ -22,24 +21,25 @@
<TextView
android:id="@+id/titleView"
style="@style/TextAppearance.Material3.BodyLarge"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignTop="@id/imageView"
android:layout_marginLeft="8dp"
android:layout_toRightOf="@id/imageView"
android:text="@string/mod_title"
android:textSize="18sp" />
android:layout_marginStart="8dp"
android:layout_toEndOf="@id/imageView"
android:text="@string/mod_title" />
<TextView
android:id="@+id/contentView"
style="@style/TextAppearance.Material3.BodyMedium"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="@id/titleView"
android:layout_marginLeft="8dp"
android:layout_marginTop="8dp"
android:layout_toRightOf="@id/imageView"
android:layout_marginStart="8dp"
android:layout_marginTop="16dp"
android:layout_toEndOf="@id/imageView"
android:text="@string/no_content" />
</RelativeLayout>
</androidx.cardview.widget.CardView>
</com.google.android.material.card.MaterialCardView>

View File

@ -0,0 +1,27 @@
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:padding="8dp">
<TextView
android:layout_centerVertical="true"
android:id="@+id/titleView"
style="@style/TextAppearance.Material3.BodyMedium"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentStart="true"
android:layout_marginStart="8dp"
android:layout_toStartOf="@id/imageView"
android:text="@string/title" />
<ImageView
android:layout_centerVertical="true"
android:id="@+id/imageView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentEnd="true"
android:layout_marginEnd="8dp"
android:src="@drawable/ic_baseline_chevron_right_24" />
</RelativeLayout>

View File

@ -4,8 +4,7 @@
<item
app:showAsAction="always"
android:id="@+id/app_bar_search"
android:id="@+id/search"
android:icon="@drawable/ic_search_black_24dp"
android:title="Search"
app:actionViewClass="android.widget.SearchView" />
android:title="@string/search" />
</menu>

View File

@ -846,4 +846,12 @@
<string name="dynamic_color_tip">跟随设备壁纸更换主题色。</string>
<string name="dynamic_color_disabled">此设备不支持动态颜色。</string>
<string name="title">标题</string>
<string name="search_type_mod">模组</string>
<string name="search_type_user">用户</string>
<string name="search_type_dynamic">动态</string>
<string name="search_type_mod_comments">模组评论</string>
<string name="search_type_mod_versions">模组更新日志</string>
<string name="search_type_purchase_plan">套餐</string>
<string name="search_type_mod_all">全部</string>
</resources>

View File

@ -1,33 +0,0 @@
package com.coldmint.rust.core.dataBean
import com.google.gson.annotations.SerializedName
/**
* 搜索记录
* @property code Int
* @property `data` List<Data>
* @property message String
* @constructor
*/
data class SearchResultDataBean(
@SerializedName("code")
val code: Int,
@SerializedName("data")
val `data`: MutableList<Data>?,
@SerializedName("message")
val message: String
) {
data class Data(
@SerializedName("content")
val content: String,
@SerializedName("icon")
val icon: String?,
@SerializedName("id")
val id: String,
@SerializedName("title")
val title: String,
@SerializedName("type")
val type: String
)
}

View File

@ -0,0 +1,20 @@
package com.coldmint.rust.core.dataBean
import com.google.gson.annotations.SerializedName
/**
* 搜索建议
* @property code Int
* @property `data` List<String>
* @property message String
* @constructor
*/
data class SearchSuggestionsData(
@SerializedName("code")
val code: Int,
@SerializedName("data")
val `data`: MutableList<String>,
@SerializedName("message")
val message: String
)

View File

@ -0,0 +1,40 @@
package com.coldmint.rust.core.dataBean.user
import com.google.gson.annotations.SerializedName
data class SearchResultDataBean(
@SerializedName("code")
val code: Int,
@SerializedName("data")
val `data`: Data,
@SerializedName("message")
val message: String
) {
data class Data(
@SerializedName("total")
val total: MutableList<Total>,
@SerializedName("type")
val type: List<Type>
) {
data class Total(
@SerializedName("content")
val content: String,
@SerializedName("icon")
val icon: String?,
@SerializedName("id")
val id: String,
@SerializedName("title")
val title: String,
@SerializedName("type")
val type: String
)
data class Type(
@SerializedName("num")
val num: Int,
@SerializedName("typeName")
val typeName: String
)
}
}

View File

@ -2,8 +2,8 @@ package com.coldmint.rust.core.web
import android.os.Handler
import android.os.Looper
import com.coldmint.rust.core.dataBean.SearchResultDataBean
import com.coldmint.rust.core.dataBean.mod.WebModListData
import com.coldmint.rust.core.dataBean.SearchSuggestionsData
import com.coldmint.rust.core.dataBean.user.SearchResultDataBean
import com.coldmint.rust.core.interfaces.ApiCallBack
import com.google.gson.Gson
import okhttp3.*
@ -59,4 +59,46 @@ class Search private constructor() {
})
}
/**
* 搜索建议
* @param key String 关键字
* @param apiCallBack ApiCallBack<SearchResultDataBean>
*/
fun suggestions(key: String, apiCallBack: ApiCallBack<SearchSuggestionsData>) {
val okHttpClient = ServerConfiguration.initOkHttpClient()
val requestBodyBuilder: FormBody.Builder =
FormBody.Builder().add("key", key)
val requestBody = requestBodyBuilder.build()
val request =
Request.Builder()
.url(ServerConfiguration.website + "php/search.php?action=suggestions")
.post(requestBody).build()
val call = okHttpClient.newCall(request)
val handler = Handler(Looper.getMainLooper())
val gson = Gson()
call.enqueue(object : Callback {
override fun onFailure(call: Call, e: IOException) {
e.printStackTrace()
handler.post { apiCallBack.onFailure(e) }
}
override fun onResponse(call: Call, response: Response) {
try {
val data = response.body!!.string()
val finalSearchSuggestionsData =
gson.fromJson(data, SearchSuggestionsData::class.java)
handler.post {
apiCallBack.onResponse(finalSearchSuggestionsData)
}
} catch (e: Exception) {
e.printStackTrace()
handler.post {
apiCallBack.onFailure(e)
}
}
}
})
}
}

View File

@ -190,20 +190,20 @@ class WebMod private constructor() {
//audit
/**
* 审核模组
* @param account String 账号管理员
* @param token String 令牌管理员
* @param modId String 模组id
* @param state Boolean 通过状态
* @param apiCallBack ApiCallBack<ApiResponse> 回调接口
*/
fun auditMod(
account: String,
token: String,
modId: String,
state: Boolean,
apiCallBack: ApiCallBack<ApiResponse>
) {
val okHttpClient = ServerConfiguration.initOkHttpClient()
val requestBodyBuilder: FormBody.Builder =
FormBody.Builder().add("account", account).add("modId", modId)
FormBody.Builder().add("token", token).add("modId", modId)
.add("state", state.toString())
val requestBody = requestBodyBuilder.build()
val request =
@ -239,14 +239,14 @@ class WebMod private constructor() {
/**
* 重新审核模组
* @param account String 账号
* @param token String 令牌
* @param modId String 模组id
* @param apiCallBack ApiCallBack<ApiResponse> 回调接口
*/
fun afreshAuditMod(account: String, modId: String, apiCallBack: ApiCallBack<ApiResponse>) {
fun afreshAuditMod(token: String, modId: String, apiCallBack: ApiCallBack<ApiResponse>) {
val okHttpClient = ServerConfiguration.initOkHttpClient()
val requestBodyBuilder: FormBody.Builder =
FormBody.Builder().add("account", account).add("modId", modId)
FormBody.Builder().add("token", token).add("modId", modId)
val requestBody = requestBodyBuilder.build()
val request =
Request.Builder()
@ -515,22 +515,20 @@ class WebMod private constructor() {
/**
* 发布评论
* @param account String 账号
* @param appId String appid
* @param token String token
* @param modId String 模组id
* @param content String 评论内容
* @param apiCallBack ApiCallBack<ApiResponse> 结果
*/
fun sendComment(
account: String,
appId: String,
token: String,
modId: String,
content: String,
apiCallBack: ApiCallBack<ApiResponse>
) {
val okHttpClient = ServerConfiguration.initOkHttpClient()
val requestBody: FormBody =
FormBody.Builder().add("account", account).add("appId", appId).add("modId", modId)
FormBody.Builder().add("token", token).add("modId", modId)
.add("content", content).build()
val request =
Request.Builder().url(ServerConfiguration.website + "php/mod.php?action=comments")
@ -565,13 +563,13 @@ class WebMod private constructor() {
/**
* 查看模组信息
* @param account String 账号
* @param token String 令牌
* @param modId String 模组Id
*/
fun getInfo(account: String, modId: String, apiCallBack: ApiCallBack<WebModInfoData>) {
fun getInfo(token: String, modId: String, apiCallBack: ApiCallBack<WebModInfoData>) {
val okHttpClient = ServerConfiguration.initOkHttpClient()
val requestBody: FormBody =
FormBody.Builder().add("account", account).add("modId", modId).build()
FormBody.Builder().add("token", token).add("modId", modId).build()
val request =
Request.Builder().url(ServerConfiguration.website + "php/mod.php?action=getInfo")
.post(requestBody).build()
@ -587,6 +585,7 @@ class WebMod private constructor() {
override fun onResponse(call: Call, response: Response) {
try {
val data = response.body!!.string()
Log.d("模组信息",data)
val finalWebModInfoData =
gson.fromJson(data, WebModInfoData::class.java)
handler.post {
@ -871,7 +870,7 @@ class WebMod private constructor() {
/**
* 发布模组
* @param account String 账号
* @param token String 账号
* @param modName String 模组名称
* @param describe String 描述
* @param tags String 标签
@ -881,7 +880,7 @@ class WebMod private constructor() {
fun releaseMod(
appId: String,
modId: String,
account: String,
token: String,
modName: String,
describe: String,
tags: String,
@ -896,7 +895,7 @@ class WebMod private constructor() {
val builder =
MultipartBody.Builder().setType(MultipartBody.FORM).addFormDataPart("appID", appId)
.addFormDataPart("modId", modId)
.addFormDataPart("account", account).addFormDataPart("modName", modName)
.addFormDataPart("token", token).addFormDataPart("modName", modName)
.addFormDataPart("describe", describe).addFormDataPart("tags", tags)
.addFormDataPart("versionName", versionName)
.addFormDataPart("unitNumber", unitNum.toString())
@ -958,6 +957,7 @@ class WebMod private constructor() {
val body = response.body
if (body != null) {
val data = body.string()
Log.d("发布模组响应",data)
val finalApiResponse = gson.fromJson(data, ApiResponse::class.java)
handler.post {
apiCallBack.onResponse(finalApiResponse)