show installed mods

This commit is contained in:
SpikeHD
2022-07-24 19:28:05 -07:00
parent 36c2302f1b
commit 5077c19fdc
5 changed files with 63 additions and 14 deletions

View File

@@ -9,8 +9,8 @@ static API_URL: &str = "https://api.gamebanana.com";
static SITE_URL: &str = "https://gamebanana.com"; static SITE_URL: &str = "https://gamebanana.com";
#[tauri::command] #[tauri::command]
pub async fn get_download_links(modId: String) -> String { pub async fn get_download_links(mod_id: String) -> String {
let res = web::query(format!("{}/apiv9/Mod/{}/DownloadPage", SITE_URL, modId).as_str()).await; let res = web::query(format!("{}/apiv9/Mod/{}/DownloadPage", SITE_URL, mod_id).as_str()).await;
res res
} }
@@ -65,7 +65,7 @@ pub async fn list_mods(path: String) -> HashMap<String, String> {
mod_info_strings.insert( mod_info_strings.insert(
path.to_str().unwrap().to_string(), path.to_str().unwrap().to_string(),
format!( format!(
"{{ name: \"{}\" }}", "{{ \"name\": \"{}\" }}",
path.file_name().unwrap().to_str().unwrap() path.file_name().unwrap().to_str().unwrap()
), ),
); );

View File

@@ -1,5 +1,5 @@
import React from 'react' import React from 'react'
import { getInstalledMods, getMods, ModData } from '../../../utils/gamebanana' import { getInstalledMods, getMods, ModData, PartialModData } from '../../../utils/gamebanana'
import { LoadingCircle } from './LoadingCircle' import { LoadingCircle } from './LoadingCircle'
import './ModList.css' import './ModList.css'
@@ -15,7 +15,7 @@ interface IState {
installedList: installedList:
| { | {
path: string path: string
info: unknown info: ModData | PartialModData
}[] }[]
| null | null
} }
@@ -34,9 +34,23 @@ export class ModList extends React.Component<IProps, IState> {
async componentDidMount() { async componentDidMount() {
if (this.props.mode === 'installed') { if (this.props.mode === 'installed') {
const installedMods = await getInstalledMods() const installedMods = (await getInstalledMods()).map((mod) => {
// Check if it's a partial mod, and if so, fill in some pseudo-data
if (!('id' in mod.info)) {
const newInfo = mod.info as PartialModData
console.log(installedMods) newInfo.images = []
newInfo.submitter = { name: 'Unknown' }
newInfo.likes = 0
newInfo.views = 0
mod.info = newInfo
return mod
}
return mod
})
this.setState({ this.setState({
installedList: installedMods, installedList: installedMods,
@@ -63,7 +77,9 @@ export class ModList extends React.Component<IProps, IState> {
(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 path={mod.path} mod={mod.info} key={mod.info.name} onClick={this.downloadMod} />
))
: this.state.modList?.map((mod: ModData) => ( : this.state.modList?.map((mod: ModData) => (
<ModTile mod={mod} key={mod.id} onClick={this.downloadMod} /> <ModTile mod={mod} key={mod.id} onClick={this.downloadMod} />
))} ))}

View File

@@ -36,6 +36,7 @@
padding: 0 0 0 10px; padding: 0 0 0 10px;
} }
.ModTileOpen,
.ModTileDownload { .ModTileDownload {
position: absolute; position: absolute;
object-fit: contain; object-fit: contain;

View File

@@ -1,13 +1,16 @@
import React from 'react' import React from 'react'
import { ModData } from '../../../utils/gamebanana' import { ModData, PartialModData } from '../../../utils/gamebanana'
import './ModTile.css' import './ModTile.css'
import Like from '../../../resources/icons/like.svg' import Like from '../../../resources/icons/like.svg'
import Eye from '../../../resources/icons/eye.svg' import Eye from '../../../resources/icons/eye.svg'
import Download from '../../../resources/icons/download.svg' import Download from '../../../resources/icons/download.svg'
import Folder from '../../../resources/icons/folder.svg'
import { shell } from '@tauri-apps/api'
interface IProps { interface IProps {
mod: ModData mod: ModData | PartialModData
path?: string
onClick: (mod: ModData) => void onClick: (mod: ModData) => void
} }
@@ -24,6 +27,10 @@ export class ModTile extends React.Component<IProps, IState> {
} }
} }
async openInExplorer() {
if (this.props.path) shell.open(this.props.path)
}
render() { render() {
const { mod } = this.props const { mod } = this.props
@@ -32,13 +39,26 @@ export class ModTile extends React.Component<IProps, IState> {
className="ModListItem" className="ModListItem"
onMouseEnter={() => this.setState({ hover: true })} onMouseEnter={() => this.setState({ hover: true })}
onMouseLeave={() => this.setState({ hover: false })} onMouseLeave={() => this.setState({ hover: false })}
onClick={() => this.props.onClick(mod)} onClick={() => {
// Disable downloading installed mods
if (!('id' in mod)) return this.openInExplorer()
this.props.onClick(mod)
}}
> >
<span className="ModName">{mod.name}</span> <span className="ModName">{mod.name}</span>
<span className="ModAuthor">{mod.submitter.name}</span> <span className="ModAuthor">{mod.submitter.name}</span>
<div className="ModImage"> <div className="ModImage">
{this.state.hover && <img src={Download} className="ModTileDownload" alt="Download" />} {this.state.hover &&
<img src={mod.images[0]} className={`${mod.nsfw ? 'nsfw' : ''} ${this.state.hover ? 'blur' : ''}`} /> (!this.props.path ? (
<img src={Download} className="ModTileDownload" alt="Download" />
) : (
<img src={Folder} className="ModTileOpen" alt="Open" />
))}
<img
src={mod.images[0]}
className={`${'id' in mod && mod.nsfw ? 'nsfw' : ''} ${this.state.hover ? 'blur' : ''}`}
/>
</div> </div>
<div className="ModInner"> <div className="ModInner">
<div className="likes"> <div className="likes">

View File

@@ -78,6 +78,16 @@ export interface ModData {
type: string type: string
} }
export interface PartialModData {
name: string
images: string[]
submitter: {
name: string
}
likes: number
views: number
}
interface GamebananaDownloads { interface GamebananaDownloads {
_bIsTrashed: boolean _bIsTrashed: boolean
_bIsWithheld: boolean _bIsWithheld: boolean
@@ -157,9 +167,11 @@ export async function getInstalledMods() {
// These are returned as JSON strings, so we have to parse them // These are returned as JSON strings, so we have to parse them
return Object.keys(mods).map((path) => { return Object.keys(mods).map((path) => {
const info = JSON.parse(mods[path]) as ModData | PartialModData
return { return {
path, path,
info: JSON.parse(mods[path]), info,
} }
}) })
} }