Skip to content

Commit

Permalink
feat(gui): mod browsing
Browse files Browse the repository at this point in the history
  • Loading branch information
V3L0C1T13S committed Feb 23, 2024
1 parent 275f209 commit 498ea5e
Show file tree
Hide file tree
Showing 16 changed files with 264 additions and 27 deletions.
12 changes: 12 additions & 0 deletions thunder_gui/src-tauri/src/commands/fetch_package.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
use thunder_manager_common::utils::thunderstore::package::{self, FetchPackageResult};

#[tauri::command]
pub async fn fetch_package(name: &str, namespace: &str) -> Result<FetchPackageResult, String> {
let data = package::fetch_package(name, namespace).await;

if let Ok(data) = data {
Ok(data)
} else {
data.map_err(|e| e.to_string())
}
}
5 changes: 4 additions & 1 deletion thunder_gui/src-tauri/src/commands/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,13 @@ use tauri::Wry;
mod install_file;
mod list_communities;
mod fetch_community;
mod fetch_package;

use install_file::*;
use list_communities::*;
use fetch_community::*;
use fetch_package::*;

pub fn build_commands(builder: tauri::Builder<Wry>) -> tauri::Builder<Wry> {
builder.invoke_handler(tauri::generate_handler![install_file, list_communities, fetch_community])
builder.invoke_handler(tauri::generate_handler![install_file, list_communities, fetch_community, fetch_package])
}
11 changes: 10 additions & 1 deletion thunder_gui/src/components/ActionAreaCard.tsx
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
import { Card, CardActionArea, CardContent, CardMedia, Typography } from '@mui/material';
import { Box, Card, CardActionArea, CardContent, CardMedia, Chip, Divider, Stack, Typography } from '@mui/material';
import { placeholderImages } from '../utils/assets';

export type ActionAreaCardProps = {
title: string,
content: string,
image?: string,
categories?: string[],
alt?: string,
height?: number,
onClick?: () => void,
Expand Down Expand Up @@ -33,6 +34,14 @@ export default function ActionAreaCard(props: ActionAreaCardProps) {
</Typography>
</CardContent>
</CardActionArea>
{props.categories ? <>
<Divider />
<Box sx={{ p: 2 }}>
<Stack direction="row" spacing={1}>
{props.categories.map((category) => <Chip color="primary" label={category} size="small" />)}
</Stack>
</Box>
</> : <></>}
</Card>
);
}
23 changes: 23 additions & 0 deletions thunder_gui/src/components/InfoRow.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
import { Paper, Table, TableBody, TableCell, TableContainer, TableRow } from "@mui/material"

export type Row = {
name: string
value?: string | number
}

export type InfoRowProps = {
rows: Row[],
}

export default function InfoRow(props: InfoRowProps) {
return <TableContainer component={Paper}>
<Table sx={{ minWidth: 345 }}>
<TableBody>
{props.rows.map((row) => <TableRow>
<TableCell>{row.name}</TableCell>
<TableCell>{row.value}</TableCell>
</TableRow>)}
</TableBody>
</Table>
</TableContainer>
}
3 changes: 2 additions & 1 deletion thunder_gui/src/main.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import { BrowserRouter, Route, Routes } from "react-router-dom";
import Browse from "./pages/Browse";
import Community from "./pages/Community";
import { ThemeProvider, createTheme } from "@mui/material";
import Package from "./pages/Package";

const darkTheme = createTheme({
palette: {
Expand All @@ -27,8 +28,8 @@ ReactDOM.createRoot(document.getElementById("root") as HTMLElement).render(
<Routes >
<Route path="/" element={<App />} />
<Route path="/browse" element={<Browse />} />
<Route path="/browse/:cursor" element={<Browse />} />
<Route path="/community/:id" element={<Community />} />
<Route path="/package/:namespace/:name" element={<Package />} />
</Routes>
</ThemeProvider>
</BrowserRouter>
Expand Down
25 changes: 16 additions & 9 deletions thunder_gui/src/pages/Browse.tsx
Original file line number Diff line number Diff line change
@@ -1,27 +1,34 @@
import { useState } from "react";
import { useEffect, useState } from "react";
import { Box, Container, Grid, Pagination, Skeleton, Stack, Typography } from "@mui/material";
import { ListResponse } from "../utils/community";
import { ListCommunities } from "../utils";
import "../App.css";
import { useNavigate, useParams } from "react-router-dom";
import { useNavigate } from "react-router-dom";
import ActionAreaCard from "../components/ActionAreaCard";

export default function Browse() {
const [communities, setCommunities] = useState<ListResponse>({});
const [communities, setCommunities] = useState<ListResponse | null>(null);
const navigate = useNavigate();

if (!communities.results) {
ListCommunities()
.then((response) => setCommunities(response))
.catch((e) => console.error("error fetching communities:", e));
}
useEffect(() => {
async function getCommunities() {
try {
const response = await ListCommunities();
setCommunities(response);
} catch (e) {
console.error("error fetching communities:", e);
}
}

if (!communities) getCommunities();
})

return (<Container>
<Box textAlign="center" alignItems="center" alignContent="center" alignSelf="center">
<Typography variant="h4">Browse</Typography>
<br />
<Grid container spacing={2} >
{communities.results ? communities.results.map((community) => (
{communities?.results ? communities.results.map((community) => (
<ActionAreaCard
key={community.identifier}
title={community.name}
Expand Down
26 changes: 18 additions & 8 deletions thunder_gui/src/pages/Community.tsx
Original file line number Diff line number Diff line change
@@ -1,21 +1,29 @@
import { Box, Container, Grid, Skeleton, Typography } from "@mui/material";
import { useState } from "react";
import { useParams } from "react-router-dom"
import { useEffect, useState } from "react";
import { useNavigate, useParams } from "react-router-dom"
import { PackageList } from "../utils/package";
import { GetCommunityPackages } from "../utils";
import ActionAreaCard from "../components/ActionAreaCard";

export default function Community() {
const { id } = useParams();
const [packages, setPackages] = useState<PackageList | null>(null);
const navigate = useNavigate();

if (!id) return <Container>
<Typography>Awkward... You didn't choose a community.</Typography>
</Container>
useEffect(() => {
async function fetchPackages() {
try {
if (!id) return;

const response = await GetCommunityPackages(id)
setPackages(response);
} catch (e) {
console.error("error fetching packages:", e);
}
}

if (!packages) {
GetCommunityPackages(id).then((list) => setPackages(list));
}
if (!packages) fetchPackages();
});

return <Container maxWidth="sm">
<Box textAlign="center">
Expand All @@ -28,6 +36,8 @@ export default function Community() {
title={card.package_name}
content={`${card.download_count} Downloads`}
image={card.image_src}
categories={card.categories.map((category) => category.name)}
onClick={() => navigate(`/package/${card.namespace}/${card.package_name}`)}
/>
)) : <Skeleton variant="rounded" width={500} height={100} />}
</Grid>
Expand Down
62 changes: 60 additions & 2 deletions thunder_gui/src/pages/Package.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,65 @@
import { Container } from "@mui/material";
import { Box, Button, Card, CardContent, Container, Skeleton, Typography } from "@mui/material";
import { FetchPackage } from "../utils";
import { useParams } from "react-router-dom";
import { useEffect, useState } from "react";
import { ThunderstorePackage } from "../utils/package";
import { copyToClipboard } from "../utils/clipboard";
import InfoRow from "../components/InfoRow";

export default function Package() {
return <Container>
const { name, namespace } = useParams();
const [packageData, setPackageData] = useState<ThunderstorePackage | null>(null);

useEffect(() => {
async function fetchPackageData() {
try {
if (!name || !namespace) {
console.error("no name or namespace", name, namespace);
return;
}

const data = await FetchPackage(name, namespace);

console.log(data);

setPackageData(data);
} catch (e) {
console.error("couldn't fetch pacakge:", e);
}
}

if (!packageData) fetchPackageData();
});

const tableRows = [{
name: "Last updated",
value: packageData?.date_updated,
}, {
name: "Total downloads",
value: packageData?.total_downloads,
}, {
name: "Rating",
value: packageData?.rating_score,
}, {
name: "Dependency string",
value: packageData?.full_name,
}]

return <Container maxWidth="sm">
{packageData ? <Box>
<Card sx={{ minWidth: 345, maxWidth: 650 }}>
<CardContent>
<Typography gutterBottom variant="h5" component="div">{packageData.name}</Typography>
<Typography variant="body2" color="text.secondary">{packageData.latest.description}</Typography>
<Typography variant="body1">By&nbsp;</Typography>
<Typography variant="body1" color="turquoise">{packageData.owner}</Typography>
<InfoRow rows={tableRows} />
<Button>Add</Button>
{packageData.package_url ? <Button
onClick={() => copyToClipboard(packageData.package_url ?? "")}
>Copy link</Button> : <></>}
</CardContent>
</Card>
</Box> : <Skeleton variant="rectangular" height={250} width={345} />}
</Container>
}
1 change: 1 addition & 0 deletions thunder_gui/src/utils/clipboard.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export const copyToClipboard = (text: string) => navigator.clipboard.writeText(text)
13 changes: 12 additions & 1 deletion thunder_gui/src/utils/commands.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { invoke } from "@tauri-apps/api/tauri";
import { ListResponse } from "./community";
import { PackageList } from "./package";
import { ThunderstorePackage, PackageList } from "./package";

export enum Commands {
InstallFile = "install_file"
Expand All @@ -27,4 +27,15 @@ export async function GetCommunityPackages(identifier: string) {
});

return packages;
}

export async function FetchPackage(name: string, namespace: string) {
console.log(`fetching pkg ${namespace} ${name}`);

const data = await invoke<ThunderstorePackage>("fetch_package", {
name,
namespace
});

return data;
}
42 changes: 41 additions & 1 deletion thunder_gui/src/utils/package.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,4 +6,44 @@ export interface PackageList {
community_name: string,
has_more_pages: boolean,
packages: Card[],
}
}

export interface PackageVersionExperimental {
namespace?: string,
name: string,
description: string,
}

export interface ThunderstorePackage {
namespace?: string,
name: string,
full_name: string,
owner?: string,
package_url?: string,
date_created?: string,
date_updated?: string,
rating_score?: string,
is_pinned?: boolean,
is_deprecated?: boolean,
total_downloads?: string,
latest: PackageVersionExperimental,
community_listings?: never[]
}

export interface ThunderstorePackageV1 {
name?: string,
full_name?: string,
owner?: string,
package_url?: string,
donation_link?: string,
date_created?: string,
date_updated?: string,
uuid4?: string,
is_pinned?: string,
is_deprecated?: string,
has_nsfw_content?: boolean,
categories?: string,
versions?: string,
}

export type PackageListV1 = ThunderstorePackageV1[];
1 change: 1 addition & 0 deletions thunder_manager_common/src/model/thunderstore/mod.rs
Original file line number Diff line number Diff line change
@@ -1 +1,2 @@
pub mod manifest;
pub mod package;
36 changes: 36 additions & 0 deletions thunder_manager_common/src/model/thunderstore/package.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
use serde::{Deserialize, Serialize};

#[derive(Deserialize, Serialize)]
#[serde(untagged)]
pub enum StringOri32 {
String(String),
I32(i32)
}

pub type RatingScore = StringOri32;
pub type DownloadCount = StringOri32;

#[derive(Deserialize, Serialize)]
pub struct PackageVersionExperimental {
namespace: Option<String>,
name: String,
version_number: String,
full_name: Option<String>,
description: String,
}

#[derive(Deserialize, Serialize)]
pub struct ExperimentalPackage {
pub namespace: Option<String>,
pub name: String,
pub full_name: Option<String>,
pub owner: Option<String>,
pub package_url: Option<String>,
pub date_created: Option<String>,
pub date_updated: Option<String>,
pub rating_score: Option<RatingScore>,
pub is_pinned: Option<bool>,
pub is_deprecated: Option<bool>,
pub total_downloads: Option<DownloadCount>,
pub latest: PackageVersionExperimental,
}
Loading

0 comments on commit 498ea5e

Please sign in to comment.