mirror of
https://github.com/Grasscutters/Cultivation.git
synced 2025-12-12 23:24:35 +01:00
Mod browser searching
This commit is contained in:
@@ -15,6 +15,7 @@ import Menu from './components/menu/Menu'
|
|||||||
import BigButton from './components/common/BigButton'
|
import BigButton from './components/common/BigButton'
|
||||||
import Tr from '../utils/language'
|
import Tr from '../utils/language'
|
||||||
import { ModPages } from './components/mods/ModPages'
|
import { ModPages } from './components/mods/ModPages'
|
||||||
|
import TextInput from './components/common/TextInput'
|
||||||
|
|
||||||
interface IProps {
|
interface IProps {
|
||||||
downloadHandler: DownloadHandler
|
downloadHandler: DownloadHandler
|
||||||
@@ -25,6 +26,7 @@ interface IState {
|
|||||||
category: string
|
category: string
|
||||||
downloadList: { name: string; url: string; mod: ModData }[] | null
|
downloadList: { name: string; url: string; mod: ModData }[] | null
|
||||||
page: number
|
page: number
|
||||||
|
search: string
|
||||||
}
|
}
|
||||||
|
|
||||||
const pages = [
|
const pages = [
|
||||||
@@ -59,14 +61,17 @@ const headers = [
|
|||||||
* @TODO Categorizaiton/sorting (by likes, views, etc)
|
* @TODO Categorizaiton/sorting (by likes, views, etc)
|
||||||
*/
|
*/
|
||||||
export class Mods extends React.Component<IProps, IState> {
|
export class Mods extends React.Component<IProps, IState> {
|
||||||
|
timeout: number
|
||||||
constructor(props: IProps) {
|
constructor(props: IProps) {
|
||||||
super(props)
|
super(props)
|
||||||
|
this.timeout = 0
|
||||||
|
|
||||||
this.state = {
|
this.state = {
|
||||||
isDownloading: false,
|
isDownloading: false,
|
||||||
category: '',
|
category: '',
|
||||||
downloadList: null,
|
downloadList: null,
|
||||||
page: 1,
|
page: 1,
|
||||||
|
search: '',
|
||||||
}
|
}
|
||||||
|
|
||||||
this.setCategory = this.setCategory.bind(this)
|
this.setCategory = this.setCategory.bind(this)
|
||||||
@@ -137,6 +142,17 @@ export class Mods extends React.Component<IProps, IState> {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async setSearch(text: string) {
|
||||||
|
if(this.timeout) clearTimeout(this.timeout);
|
||||||
|
this.timeout = window.setTimeout(() => {
|
||||||
|
this.setState({
|
||||||
|
search: text,
|
||||||
|
},
|
||||||
|
this.forceUpdate
|
||||||
|
)
|
||||||
|
}, 300)
|
||||||
|
}
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
return (
|
return (
|
||||||
<div className="Mods">
|
<div className="Mods">
|
||||||
@@ -190,16 +206,25 @@ export class Mods extends React.Component<IProps, IState> {
|
|||||||
|
|
||||||
{this.state.category != 'installed' && (
|
{this.state.category != 'installed' && (
|
||||||
<>
|
<>
|
||||||
<p className="ModPagesPage">{this.state.page} </p>
|
<div className="ModPagesPage">
|
||||||
|
<TextInput
|
||||||
|
id="search"
|
||||||
|
key="search"
|
||||||
|
placeholder={this.state.page.toString()}
|
||||||
|
onChange={(text: string) => {this.setSearch(text)}}
|
||||||
|
initalValue={''}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
<ModPages onClick={this.setPage} headers={pages} defaultHeader={this.state.page} />
|
<ModPages onClick={this.setPage} headers={pages} defaultHeader={this.state.page} />
|
||||||
</>
|
</>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
<ModList
|
<ModList
|
||||||
key={`${this.state.category}_${this.state.page}`}
|
key={`${this.state.category}_${this.state.page}_${this.state.search}`}
|
||||||
mode={this.state.category}
|
mode={this.state.category}
|
||||||
addDownload={this.addDownload}
|
addDownload={this.addDownload}
|
||||||
page={this.state.page}
|
page={this.state.page}
|
||||||
|
search={this.state.search}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
import React from 'react'
|
import React from 'react'
|
||||||
import { getConfigOption } from '../../../utils/configuration'
|
import { getConfigOption } from '../../../utils/configuration'
|
||||||
import { getInstalledMods, getMods, ModData, PartialModData } from '../../../utils/gamebanana'
|
import { getAllMods, getInstalledMods, getMods, ModData, PartialModData } from '../../../utils/gamebanana'
|
||||||
import { LoadingCircle } from './LoadingCircle'
|
import { LoadingCircle } from './LoadingCircle'
|
||||||
|
|
||||||
import './ModList.css'
|
import './ModList.css'
|
||||||
@@ -9,6 +9,7 @@ import { ModTile } from './ModTile'
|
|||||||
interface IProps {
|
interface IProps {
|
||||||
mode: string
|
mode: string
|
||||||
page: number
|
page: number
|
||||||
|
search: string
|
||||||
addDownload: (mod: ModData) => void
|
addDownload: (mod: ModData) => void
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -16,11 +17,11 @@ interface IState {
|
|||||||
horny: boolean
|
horny: boolean
|
||||||
modList: ModData[] | null
|
modList: ModData[] | null
|
||||||
installedList:
|
installedList:
|
||||||
| {
|
| {
|
||||||
path: string
|
path: string
|
||||||
info: ModData | PartialModData
|
info: ModData | PartialModData
|
||||||
}[]
|
}[]
|
||||||
| null
|
| null
|
||||||
}
|
}
|
||||||
|
|
||||||
export class ModList extends React.Component<IProps, IState> {
|
export class ModList extends React.Component<IProps, IState> {
|
||||||
@@ -63,7 +64,15 @@ export class ModList extends React.Component<IProps, IState> {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
const mods = await getMods(this.props.mode, this.props.page)
|
let mods: ModData[]
|
||||||
|
|
||||||
|
if (!(this.props.search == '')) {
|
||||||
|
// idk the api so just filter all mods to search
|
||||||
|
mods = (await getAllMods(this.props.mode)).filter(mod => mod.name.toLowerCase().includes(this.props.search.toLowerCase()))
|
||||||
|
} else {
|
||||||
|
mods = await getMods(this.props.mode, this.props.page)
|
||||||
|
}
|
||||||
|
|
||||||
const horny = await getConfigOption('horny_mode')
|
const horny = await getConfigOption('horny_mode')
|
||||||
|
|
||||||
this.setState({
|
this.setState({
|
||||||
@@ -80,21 +89,21 @@ export class ModList extends React.Component<IProps, IState> {
|
|||||||
return (
|
return (
|
||||||
<div className="ModList">
|
<div className="ModList">
|
||||||
{(this.state.modList && this.props.mode !== 'installed') ||
|
{(this.state.modList && this.props.mode !== 'installed') ||
|
||||||
(this.state.installedList && this.props.mode === 'installed') ? (
|
(this.state.installedList && this.props.mode === 'installed') ? (
|
||||||
<div className="ModListInner">
|
<div className="ModListInner">
|
||||||
{this.props.mode === 'installed'
|
{this.props.mode === 'installed'
|
||||||
? this.state.installedList?.map((mod) => (
|
? this.state.installedList?.map((mod) => (
|
||||||
<ModTile
|
<ModTile
|
||||||
horny={this.state.horny}
|
horny={this.state.horny}
|
||||||
path={mod.path}
|
path={mod.path}
|
||||||
mod={mod.info}
|
mod={mod.info}
|
||||||
key={mod.info.name}
|
key={mod.info.name}
|
||||||
onClick={this.downloadMod}
|
onClick={this.downloadMod}
|
||||||
/>
|
/>
|
||||||
))
|
))
|
||||||
: this.state.modList?.map((mod: ModData) => (
|
: this.state.modList?.map((mod: ModData) => (
|
||||||
<ModTile horny={this.state.horny} mod={mod} key={mod.id} onClick={this.downloadMod} />
|
<ModTile horny={this.state.horny} mod={mod} key={mod.id} onClick={this.downloadMod} />
|
||||||
))}
|
))}
|
||||||
</div>
|
</div>
|
||||||
) : (
|
) : (
|
||||||
<LoadingCircle />
|
<LoadingCircle />
|
||||||
|
|||||||
@@ -47,3 +47,20 @@
|
|||||||
font-weight: bold;
|
font-weight: bold;
|
||||||
color: #fff;
|
color: #fff;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.ModPagesPage input {
|
||||||
|
text-align: center;
|
||||||
|
padding: 3px;
|
||||||
|
border-radius: 3px;
|
||||||
|
height: 18px;
|
||||||
|
font-size: 20px;
|
||||||
|
font-weight: bold;
|
||||||
|
color: #fff;
|
||||||
|
background: rgba(77, 77, 77, 0.6);
|
||||||
|
}
|
||||||
|
|
||||||
|
.ModPagesPage .TextInputWrapper {
|
||||||
|
background: rgba(77, 77, 77, 0.6);
|
||||||
|
z-index: -1;
|
||||||
|
display: inline-block;
|
||||||
|
}
|
||||||
|
|||||||
@@ -132,6 +132,28 @@ export async function getMods(mode: string, page: number) {
|
|||||||
return formatGamebananaData(modList)
|
return formatGamebananaData(modList)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export async function getAllMods(mode: string) {
|
||||||
|
let modList: GamebananaResponse[] = []
|
||||||
|
let hadMods = true
|
||||||
|
let page = 1
|
||||||
|
|
||||||
|
while (hadMods) {
|
||||||
|
const resp = JSON.parse(
|
||||||
|
await invoke('list_submissions', {
|
||||||
|
mode,
|
||||||
|
page: '' + page,
|
||||||
|
})
|
||||||
|
)
|
||||||
|
|
||||||
|
if (resp.length === 0) hadMods = false
|
||||||
|
|
||||||
|
modList = [...modList, ...resp]
|
||||||
|
page++
|
||||||
|
}
|
||||||
|
|
||||||
|
return formatGamebananaData(modList)
|
||||||
|
}
|
||||||
|
|
||||||
export async function formatGamebananaData(obj: GamebananaResponse[]) {
|
export async function formatGamebananaData(obj: GamebananaResponse[]) {
|
||||||
if (!obj) return []
|
if (!obj) return []
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user