From c31f1086c76335736513ab390442cf38414ef43b Mon Sep 17 00:00:00 2001 From: LynithDev <61880709+LynithDev@users.noreply.github.com> Date: Sun, 1 Sep 2024 17:05:03 +0200 Subject: [PATCH] feat: BrowserPackage version list (3/4 done) chore: Make ErrorBoundary only work during prod --- Cargo.lock | 5 +- Cargo.toml | 2 +- apps/desktop/src/api/commands/mod.rs | 3 + apps/desktop/src/api/commands/package.rs | 34 ++- .../src/ui/components/ErrorBoundary.tsx | 33 +-- .../src/ui/components/base/Button.module.scss | 4 +- .../src/ui/components/base/Button.tsx | 2 +- .../src/ui/pages/browser/BrowserPackage.tsx | 242 +++++++++++++++--- packages/core/Cargo.toml | 1 + .../core/src/api/cluster/content/package.rs | 6 +- packages/core/src/api/package/content/mod.rs | 18 +- .../core/src/api/package/content/modrinth.rs | 32 ++- packages/core/src/error.rs | 4 + 13 files changed, 322 insertions(+), 64 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index a7bda745..4e78e6dc 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4398,6 +4398,7 @@ dependencies = [ "tracing-appender", "tracing-error", "tracing-subscriber", + "url", "uuid 1.10.0", "whoami", "winreg 0.52.0", @@ -7261,9 +7262,9 @@ dependencies = [ [[package]] name = "tauri-build" -version = "2.0.0-rc.3" +version = "2.0.0-rc.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1fc103bde77870e08d5fc8765615b9615997827550b626fbc4ebbd7a1fbfe2a2" +checksum = "7d5ad5fcfaf02cf79aa6727f6c5df38567d8dce172b00b62690c6bc46c08b7ce" dependencies = [ "anyhow", "cargo_toml", diff --git a/Cargo.toml b/Cargo.toml index e78a6554..40bac067 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -43,7 +43,7 @@ tauri = { version = "=2.0.0-rc.3", features = [ ] } # tauri-build is the codegen utility for our tauri buildscript. -tauri-build = { version = "=2.0.0-rc.3" } +tauri-build = { version = "=2.0.0-rc.7" } # tauri-plugin-shell adds a bridge for opening urls and paths in the frontend. tauri-plugin-shell = { version = "=2.0.0-rc.1" } # tauri-plugin-window-state saves the window position and size to be restored. diff --git a/apps/desktop/src/api/commands/mod.rs b/apps/desktop/src/api/commands/mod.rs index 45704488..560ec8d6 100644 --- a/apps/desktop/src/api/commands/mod.rs +++ b/apps/desktop/src/api/commands/mod.rs @@ -59,6 +59,9 @@ macro_rules! collect_commands { // Provider Packages get_provider_package, get_provider_packages, + get_all_provider_package_versions, + get_provider_package_versions, + get_provider_package_version, search_provider_packages, get_provider_authors, download_provider_package, diff --git a/apps/desktop/src/api/commands/package.rs b/apps/desktop/src/api/commands/package.rs index 8c201a41..07cdb30c 100644 --- a/apps/desktop/src/api/commands/package.rs +++ b/apps/desktop/src/api/commands/package.rs @@ -1,5 +1,5 @@ use onelauncher::cluster::content::package; -use onelauncher::data::{Loader, ManagedPackage, ManagedUser, PackageType}; +use onelauncher::data::{Loader, ManagedPackage, ManagedUser, ManagedVersion, PackageType}; use onelauncher::package::content::Providers; use onelauncher::store::{Author, ClusterPath, Package, PackagePath, ProviderSearchResults}; use uuid::Uuid; @@ -22,6 +22,35 @@ pub async fn get_provider_packages( Ok(provider.get_multiple(&project_ids).await?) } +#[specta::specta] +#[tauri::command] +pub async fn get_all_provider_package_versions( + provider: Providers, + project_id: String, + game_versions: Option>, + loaders: Option>, +) -> Result, String> { + Ok(provider.get_all_versions(&project_id, game_versions, loaders).await?) +} + +#[specta::specta] +#[tauri::command] +pub async fn get_provider_package_versions( + provider: Providers, + versions: Vec, +) -> Result, String> { + Ok(provider.get_versions(versions).await?) +} + +#[specta::specta] +#[tauri::command] +pub async fn get_provider_package_version( + provider: Providers, + version: String, +) -> Result { + Ok(provider.get_version(&version).await?) +} + #[specta::specta] #[tauri::command] pub async fn search_provider_packages( @@ -75,6 +104,9 @@ pub async fn download_provider_package( Ok(()) } + + + #[specta::specta] #[tauri::command] pub async fn get_cluster_package( diff --git a/apps/frontend/src/ui/components/ErrorBoundary.tsx b/apps/frontend/src/ui/components/ErrorBoundary.tsx index c5a93a8d..19161654 100644 --- a/apps/frontend/src/ui/components/ErrorBoundary.tsx +++ b/apps/frontend/src/ui/components/ErrorBoundary.tsx @@ -1,22 +1,25 @@ import type { ParentProps } from 'solid-js'; -import { ErrorBoundary as Boundary } from 'solid-js'; -import { useDebugState } from '@onelauncher/client'; -import Button from './base/Button'; -import Popup from './overlay/Popup'; +import { ErrorBoundary as Boundary, Match, Switch } from 'solid-js'; -// TODO: Uncomment code function ErrorBoundary(props: ParentProps) { return ( - ( -
-

An unexpected error has occurred

-

{err.toString()}

-
- )} - > - {props.children} -
+ + + ( +
+

An unexpected error has occurred

+

{err.toString()}

+
+ )} + > + {props.children} +
+
+ + {props.children} + +
); } diff --git a/apps/frontend/src/ui/components/base/Button.module.scss b/apps/frontend/src/ui/components/base/Button.module.scss index 74411c71..7672b4e3 100644 --- a/apps/frontend/src/ui/components/base/Button.module.scss +++ b/apps/frontend/src/ui/components/base/Button.module.scss @@ -1,7 +1,7 @@ .button { @apply py-1.5 px-3 rounded-lg flex flex-row justify-center items-center gap-x-2.5; - &__primary { + &__primary, &__iconPrimary { @apply text-onbrand hover:text-onbrand-hover active:text-onbrand-pressed disabled:text-onbrand-disabled; @apply bg-brand hover:bg-brand-hover active:bg-brand-pressed disabled:bg-brand-disabled; } @@ -25,7 +25,7 @@ @apply hover:bg-gray-05 [&[aria-checked="true"]]:bg-gray-10 active:bg-gray-10; } - &__icon, &__iconSecondary, &__iconDanger { + &__icon, &__iconPrimary, &__iconSecondary, &__iconDanger { @apply p-1.5 aspect-square box-border w-8 h-8; &.large { diff --git a/apps/frontend/src/ui/components/base/Button.tsx b/apps/frontend/src/ui/components/base/Button.tsx index fc8d78b1..1ed8eed5 100644 --- a/apps/frontend/src/ui/components/base/Button.tsx +++ b/apps/frontend/src/ui/components/base/Button.tsx @@ -5,7 +5,7 @@ import styles from './Button.module.scss'; type ButtonProps = JSX.ButtonHTMLAttributes & ParentProps & { iconLeft?: JSX.Element; iconRight?: JSX.Element; - buttonStyle?: 'primary' | 'secondary' | 'danger' | 'icon' | 'iconSecondary' | 'iconDanger' | 'ghost'; + buttonStyle?: 'primary' | 'secondary' | 'danger' | 'icon' | 'iconPrimary' | 'iconSecondary' | 'iconDanger' | 'ghost'; large?: boolean; }; diff --git a/apps/frontend/src/ui/pages/browser/BrowserPackage.tsx b/apps/frontend/src/ui/pages/browser/BrowserPackage.tsx index f2e27875..093bd7b1 100644 --- a/apps/frontend/src/ui/pages/browser/BrowserPackage.tsx +++ b/apps/frontend/src/ui/pages/browser/BrowserPackage.tsx @@ -1,8 +1,8 @@ -import { For, type ParentProps, Show, createContext, createEffect, createSignal, useContext } from 'solid-js'; +import { For, type ParentProps, Show, createContext, createEffect, createSignal, on, useContext } from 'solid-js'; import { A, type Params, Route, useSearchParams } from '@solidjs/router'; -import { CalendarIcon, ChevronDownIcon, ClockRewindIcon, Download01Icon, File02Icon, HeartIcon, LinkExternal01Icon } from '@untitled-theme/icons-solid'; -import type { Cluster, ManagedPackage, ManagedUser, Providers } from '@onelauncher/client/bindings'; -import { getLicenseUrl, getPackageUrl } from '../../../utils'; +import { CalendarIcon, ChevronDownIcon, ChevronLeftIcon, ChevronRightIcon, ClockRewindIcon, Download01Icon, File02Icon, HeartIcon, LinkExternal01Icon } from '@untitled-theme/icons-solid'; +import type { Cluster, ManagedPackage, ManagedUser, ManagedVersion, Providers } from '@onelauncher/client/bindings'; +import { getLicenseUrl, getPackageUrl, upperFirst } from '../../../utils'; import { bridge } from '~imports'; import useCommand from '~ui/hooks/useCommand'; import { abbreviateNumber, formatAsRelative } from '~utils'; @@ -37,7 +37,7 @@ function BrowserPackageRoutes() { return ( <> - + {/* */} ); @@ -68,7 +68,7 @@ function BrowserPackage(props: ParentProps) { const links = [ ['About', '/'], - ['Gallery', '/gallery'], + // ['Gallery', '/gallery'], ['Versions', '/versions'], ]; @@ -170,24 +170,29 @@ function BrowserSidebar(props: { package: ManagedPackage; authors: ManagedUser[]

Authors

{author => ( -
promptOpen(author.url)} - > - {`${author.username}'s -
- {author.username} + <> +
promptOpen(author.url)} + > + {`${author.username}'s +
+ {author.username} - - Organization - + + Organization + - - {author.role} - + + {author.role} + +
+
- -
+ +
+ + )}
@@ -335,27 +340,190 @@ function BrowserPackageBody() { ); } -function BrowserPackageGallery() { - // const context = useContext(BrowserPackageContext); +// function BrowserPackageGallery() { +// // const context = useContext(BrowserPackageContext); - return ( -
-
Gallery
- {/* - {image => ( - {image.alt} - )} - */} -
- ); -} +// return ( +//
+//
Gallery
+// {/* +// {image => ( +// {image.alt} +// )} +// */} +//
+// ); +// } function BrowserPackageVersions() { - // const context = useContext(BrowserPackageContext); + const context = useContext(BrowserPackageContext); + const [page, setPage] = createSignal(1); + + const MAX_ITEMS_PER_PAGE = 20; + + const getVersionsForPage = (page: number) => { + if (context === null) + return []; + + const newestToOldest = context.versions.toReversed(); + const start = (page - 1) * MAX_ITEMS_PER_PAGE; + const end = start + MAX_ITEMS_PER_PAGE; + + return newestToOldest.slice(start, end); + }; + + const getMaxPage = () => { + if (context === null) + return 1; + + return Math.ceil(context.versions.length / MAX_ITEMS_PER_PAGE); + }; + + const diffFrom = (from: number = page()) => getMaxPage() - from; + + const [versions, { refetch }] = useCommand(context, async () => { + if (context === null) + return { error: 'No package context', status: 'error' }; + + const list = getVersionsForPage(page()); + + return await bridge.commands.getProviderPackageVersions(context.provider, list); + }); + + function PaginationBtn(props: { page: number }) { + return ( +
+ ); } + +function VersionRow(props: ManagedVersion) { + function colorForType(type: string) { + switch (type) { + case 'release': + return 'bg-code-trace'; + case 'snapshot': + return 'bg-code-debug'; + case 'beta': + return 'bg-code-warn'; + case 'alpha': + return 'bg-code-error'; + default: + return 'bg-gray-05'; + } + } + + return ( + + + +
+ {props.version_type.charAt(0).toUpperCase()} +
+
+ + + +
+

{props.version_id}

+

{props.name}

+
+ + + + {props.game_versions.join(', ')} + + + + {props.loaders.map(upperFirst).join(', ')} + + + + {formatAsRelative(new Date(props.published).getTime(), 'en', 'long')} + + + + {props.downloads} + + + +