feat: links and gfm support
This commit is contained in:
parent
6b42f77ce0
commit
c0b6443432
5 changed files with 68 additions and 15 deletions
|
|
@ -35,6 +35,7 @@
|
|||
"react-dom": "catalog:",
|
||||
"react-markdown": "^10.1.0",
|
||||
"rehype-raw": "^7.0.0",
|
||||
"remark-gfm": "^4.0.1",
|
||||
"tailwind-merge": "catalog:",
|
||||
"tailwind-variants": "catalog:",
|
||||
"tailwindcss": "catalog:",
|
||||
|
|
|
|||
|
|
@ -1,10 +1,10 @@
|
|||
import type { ClusterModel, ManagedPackage, ManagedUser, ManagedVersion, Paginated, Provider } from '@/bindings.gen';
|
||||
import type { JSX } from 'react';
|
||||
import type { ClusterModel, ManagedPackage, ManagedUser, ManagedVersion, PackageDonationUrl, Paginated, Provider } from '@/bindings.gen';
|
||||
import type { HTMLProps, JSX } from 'react';
|
||||
import Modal from '@/components/overlay/Modal';
|
||||
import { useBrowserContext, usePackageData, usePackageVersions } from '@/hooks/useBrowser';
|
||||
import { useClusters } from '@/hooks/useCluster';
|
||||
import { bindings } from '@/main';
|
||||
import { abbreviateNumber, formatAsRelative, PROVIDERS } from '@/utils';
|
||||
import { abbreviateNumber, formatAsRelative, PROVIDERS, upperFirst } from '@/utils';
|
||||
import { useCommand } from '@onelauncher/common';
|
||||
import { Button, Popup, Show, Tooltip } from '@onelauncher/common/components';
|
||||
import { createFileRoute, Link } from '@tanstack/react-router';
|
||||
|
|
@ -14,6 +14,8 @@ import { createContext, useContext, useEffect, useMemo, useRef, useState } from
|
|||
import { Collection, ListBox, ListBoxItem, Popover, Pressable, Select, Tab, TabList, TabPanel, Tabs } from 'react-aria-components';
|
||||
import Markdown from 'react-markdown';
|
||||
import rehypeRaw from 'rehype-raw';
|
||||
import remarkGfm from 'remark-gfm';
|
||||
import { twMerge } from 'tailwind-merge';
|
||||
|
||||
export const Route = createFileRoute('/app/browser/package/$provider/$slug')({
|
||||
component: RouteComponent,
|
||||
|
|
@ -23,17 +25,19 @@ function includes<T, TArray extends T>(list: { includes: (arg0: TArray) => boole
|
|||
return list.includes(element as unknown as TArray);
|
||||
}
|
||||
|
||||
function CustomA({ href, children }: { href: string; children: any }) {
|
||||
function CustomA({ href, children, includeIcon, className, ...rest }: { href: string; children: any, includeIcon?: boolean } & HTMLProps<HTMLAnchorElement>) {
|
||||
return (
|
||||
<a
|
||||
className="text-fg-primary underline"
|
||||
className={twMerge("text-fg-primary underline", className)}
|
||||
href={href}
|
||||
onClick={(e) => {
|
||||
e.preventDefault();
|
||||
openUrl(href);
|
||||
}}
|
||||
{...rest}
|
||||
>
|
||||
{children}
|
||||
{includeIcon && <LinkExternal01Icon className='inline w-4 ml-1'/>}
|
||||
</a>
|
||||
);
|
||||
}
|
||||
|
|
@ -73,11 +77,13 @@ function RouteComponent() {
|
|||
<Tab className="uppercase p-2.5 text-trim rounded-md selected:bg-component-bg-pressed disabled:hidden" id="gallery" isDisabled={packageData.data?.gallery.length === 0}>Gallery</Tab>
|
||||
</TabList>
|
||||
<div className="h-full min-h-full flex-1 w-full rounded-lg bg-component-bg p-3">
|
||||
<TabPanel className="prose prose-invert prose-sm max-w-none" id="about">
|
||||
<TabPanel className="prose prose-invert prose-sm max-w-none prose-code:before:content-none prose-code:after:content-none prose-code:bg-component-bg-disabled prose-code:rounded-sm prose-code:p-1! prose-code:text-trim" id="about">
|
||||
<Markdown
|
||||
components={{
|
||||
a: ({ node, children, ...props }) => <CustomA children={children} href={props.href as string} />,
|
||||
}} rehypePlugins={[rehypeRaw]}
|
||||
}}
|
||||
rehypePlugins={[rehypeRaw]}
|
||||
remarkPlugins={[remarkGfm]}
|
||||
>
|
||||
{packageData.data?.body}
|
||||
</Markdown>
|
||||
|
|
@ -111,6 +117,14 @@ function RouteComponent() {
|
|||
);
|
||||
}
|
||||
|
||||
function getPackageUrl(pkg: ManagedPackage): string {
|
||||
switch (pkg.provider){
|
||||
case 'Modrinth': return `https://modrinth.com/project/${pkg.slug}`
|
||||
case 'Curseforge': return `https://www.curseforge.com/minecraft/${pkg.package_type}s/${pkg.slug}`
|
||||
case 'SkyClient': return ``
|
||||
}
|
||||
}
|
||||
|
||||
function BrowserSidebar({ package: pkg }: { package: ManagedPackage }) {
|
||||
const { provider } = Route.useParams();
|
||||
|
||||
|
|
@ -120,7 +134,7 @@ function BrowserSidebar({ package: pkg }: { package: ManagedPackage }) {
|
|||
const authors = useCommand('getUsersFromAuthor', () => bindings.core.getUsersFromAuthor(provider as Provider, pkg.author));
|
||||
|
||||
return (
|
||||
<div className="sticky top-0 z-1 max-w-60 min-w-54 flex flex-col gap-y-4">
|
||||
<div className="z-1 max-w-60 min-w-54 flex flex-col gap-y-4 mb-6">
|
||||
<div className="flex flex-col overflow-hidden rounded-lg bg-component-bg">
|
||||
<div className="relative h-28 flex items-center justify-center overflow-hidden">
|
||||
<img alt={`Icon for ${pkg.name}`} className="absolute z-0 max-w-none w-7/6 blur-xl" src={pkg.icon_url || ''} />
|
||||
|
|
@ -153,14 +167,23 @@ function BrowserSidebar({ package: pkg }: { package: ManagedPackage }) {
|
|||
|
||||
<InstallButton />
|
||||
|
||||
{/* <div className="flex flex-col gap-2 rounded-lg bg-component-bg p-3">
|
||||
<div className="flex flex-col rounded-lg bg-component-bg p-3">
|
||||
<h4 className="text-fg-primary font-bold">Links</h4>
|
||||
<Link href={getPackageUrl(contentPackage)} includeIcon>
|
||||
{contentPackage.provider}
|
||||
{' '}
|
||||
Page
|
||||
</Link>
|
||||
</div> */}
|
||||
<div className='flex flex-col'>
|
||||
<CustomA href={getPackageUrl(pkg)} includeIcon className='text-link hover:text-link-hover'>
|
||||
{provider}
|
||||
{' '}
|
||||
Page
|
||||
</CustomA>
|
||||
{(Object.entries(pkg.links) as [keyof typeof pkg.links, typeof pkg.links[keyof typeof pkg.links]][]).filter(a=>a[1]).map(link=>
|
||||
typeof link[1] == "string"
|
||||
? <CustomA href={link[1]} children={upperFirst(link[0])} className='text-link hover:text-link-hover' includeIcon/>
|
||||
: <div>
|
||||
{(link[1] as PackageDonationUrl[]).map(donationLink=><CustomA href={donationLink.url} className='text-link hover:text-link-hover' children={upperFirst(donationLink.id)} includeIcon/>)}
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="flex flex-col gap-2 rounded-lg bg-component-bg p-3">
|
||||
<h4 className="text-fg-primary font-bold">Authors</h4>
|
||||
|
|
|
|||
|
|
@ -77,6 +77,7 @@ pub struct SearchResult {
|
|||
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
|
||||
pub struct ManagedPackage {
|
||||
pub id: String,
|
||||
pub slug: String,
|
||||
pub provider: Provider,
|
||||
pub package_type: PackageType,
|
||||
pub name: String,
|
||||
|
|
|
|||
|
|
@ -346,6 +346,7 @@ struct ModrinthPackage {
|
|||
pub icon_url: Option<String>,
|
||||
#[serde(alias = "project_id")]
|
||||
pub id: String,
|
||||
pub slug: String,
|
||||
pub team: String,
|
||||
#[serde(default)]
|
||||
pub organization: Option<String>,
|
||||
|
|
@ -373,6 +374,7 @@ impl From<ModrinthPackage> for ManagedPackage {
|
|||
Self {
|
||||
provider: Provider::Modrinth,
|
||||
id: value.id,
|
||||
slug: value.slug,
|
||||
package_type: value.project_type,
|
||||
name: value.title,
|
||||
short_desc: value.description,
|
||||
|
|
|
|||
26
pnpm-lock.yaml
generated
26
pnpm-lock.yaml
generated
|
|
@ -399,6 +399,9 @@ importers:
|
|||
rehype-raw:
|
||||
specifier: ^7.0.0
|
||||
version: 7.0.0
|
||||
remark-gfm:
|
||||
specifier: ^4.0.1
|
||||
version: 4.0.1
|
||||
tailwind-merge:
|
||||
specifier: 'catalog:'
|
||||
version: 3.2.0
|
||||
|
|
@ -5051,12 +5054,18 @@ packages:
|
|||
rehype-raw@7.0.0:
|
||||
resolution: {integrity: sha512-/aE8hCfKlQeA8LmyeyQvQF3eBiLRGNlfBJEvWH7ivp9sBqs7TNqBL5X3v157rM4IFETqDnIOO+z5M/biZbo9Ww==}
|
||||
|
||||
remark-gfm@4.0.1:
|
||||
resolution: {integrity: sha512-1quofZ2RQ9EWdeN34S79+KExV1764+wCUGop5CPL1WGdD0ocPpu91lzPGbwWMECpEpd42kJGQwzRfyov9j4yNg==}
|
||||
|
||||
remark-parse@11.0.0:
|
||||
resolution: {integrity: sha512-FCxlKLNGknS5ba/1lmpYijMUzX2esxW5xQqjWxw2eHFfS2MSdaHVINFmhjo+qN1WhZhNimq0dZATN9pH0IDrpA==}
|
||||
|
||||
remark-rehype@11.1.2:
|
||||
resolution: {integrity: sha512-Dh7l57ianaEoIpzbp0PC9UKAdCSVklD8E5Rpw7ETfbTl3FqcOOgq5q2LVDhgGCkaBv7p24JXikPdvhhmHvKMsw==}
|
||||
|
||||
remark-stringify@11.0.0:
|
||||
resolution: {integrity: sha512-1OSmLd3awB/t8qdoEOMazZkNsfVTeY4fTsgzcQFdXNq8ToTN4ZGwrMnlda4K6smTFKD+GRV6O48i6Z4iKgPPpw==}
|
||||
|
||||
remove-accents@0.5.0:
|
||||
resolution: {integrity: sha512-8g3/Otx1eJaVD12e31UbJj1YzdtVvzH85HV7t+9MJYk/u3XmkOUJ5Ys9wQrf9PCPK8+xn4ymzqYCiZl6QWKn+A==}
|
||||
|
||||
|
|
@ -11304,6 +11313,17 @@ snapshots:
|
|||
hast-util-raw: 9.1.0
|
||||
vfile: 6.0.3
|
||||
|
||||
remark-gfm@4.0.1:
|
||||
dependencies:
|
||||
'@types/mdast': 4.0.4
|
||||
mdast-util-gfm: 3.1.0
|
||||
micromark-extension-gfm: 3.0.0
|
||||
remark-parse: 11.0.0
|
||||
remark-stringify: 11.0.0
|
||||
unified: 11.0.5
|
||||
transitivePeerDependencies:
|
||||
- supports-color
|
||||
|
||||
remark-parse@11.0.0:
|
||||
dependencies:
|
||||
'@types/mdast': 4.0.4
|
||||
|
|
@ -11321,6 +11341,12 @@ snapshots:
|
|||
unified: 11.0.5
|
||||
vfile: 6.0.3
|
||||
|
||||
remark-stringify@11.0.0:
|
||||
dependencies:
|
||||
'@types/mdast': 4.0.4
|
||||
mdast-util-to-markdown: 2.1.2
|
||||
unified: 11.0.5
|
||||
|
||||
remove-accents@0.5.0: {}
|
||||
|
||||
require-from-string@2.0.2: {}
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue