diff --git a/.eslintrc.cjs b/.eslintrc.cjs
index 63c9779..954f8bd 100644
--- a/.eslintrc.cjs
+++ b/.eslintrc.cjs
@@ -4,6 +4,9 @@ module.exports = {
'plugin:react/recommended',
'plugin:react/jsx-runtime',
'@electron-toolkit/eslint-config-ts/recommended',
- '@electron-toolkit/eslint-config-prettier'
- ]
+ '@electron-toolkit/eslint-config-prettier',
+ ],
+ rules: {
+ '@typescript-eslint/no-explicit-any': 'off',
+ },
}
diff --git a/bun.lockb b/bun.lockb
index dd4e005..0055699 100755
Binary files a/bun.lockb and b/bun.lockb differ
diff --git a/package.json b/package.json
index 4a4cc50..cd54fcb 100644
--- a/package.json
+++ b/package.json
@@ -28,9 +28,16 @@
"@fontsource/roboto": "^5.1.1",
"@mui/icons-material": "^6.3.1",
"@mui/material": "^6.3.1",
+ "@tailwindcss/typography": "^0.5.16",
"electron-updater": "^6.3.9",
"react-router": "^7.1.1",
- "solar-js-sdk": "^0.1.2"
+ "rehype-sanitize": "^6.0.0",
+ "rehype-stringify": "^10.0.1",
+ "remark-gfm": "^4.0.0",
+ "remark-parse": "^11.0.0",
+ "remark-rehype": "^11.1.1",
+ "solar-js-sdk": "^0.1.2",
+ "unified": "^11.0.5"
},
"devDependencies": {
"@electron-toolkit/eslint-config-prettier": "^2.0.0",
diff --git a/src/main/index.ts b/src/main/index.ts
index 7922e22..7810e5f 100644
--- a/src/main/index.ts
+++ b/src/main/index.ts
@@ -8,8 +8,8 @@ function createWindow(): void {
const mainWindow = new BrowserWindow({
width: 1280,
height: 720,
- minWidth: 480,
- minHeight: 640,
+ minWidth: 800,
+ minHeight: 600,
show: false,
autoHideMenuBar: true,
title: 'MatrixTerminal',
diff --git a/src/renderer/src/App.tsx b/src/renderer/src/App.tsx
index 3102b98..140825e 100644
--- a/src/renderer/src/App.tsx
+++ b/src/renderer/src/App.tsx
@@ -6,6 +6,8 @@ import Landing from '@renderer/pages/Landing'
import { useUserStore } from 'solar-js-sdk'
import { useEffect } from 'react'
+import ProductDetails from './pages/products/Details'
+
function App(): JSX.Element {
// const ipcHandle = (): void => window.electron.ipcRenderer.send('ping')
@@ -40,6 +42,7 @@ function App(): JSX.Element {
} />
+ } />
diff --git a/src/renderer/src/components/MaAppBar.tsx b/src/renderer/src/components/MaAppBar.tsx
index e0707f9..0c8379b 100644
--- a/src/renderer/src/components/MaAppBar.tsx
+++ b/src/renderer/src/components/MaAppBar.tsx
@@ -34,7 +34,7 @@ export function MaAppBar(): JSX.Element {
-
+
([])
async function fetchProducts(): Promise {
@@ -40,7 +43,7 @@ export default function Landing(): JSX.Element {
{products.map((p) => (
-
+ navigate('/products/' + p.id)}>
{p.previews && (
()
+ const [content, setContent] = useState()
+
+ async function fetchProduct(): Promise {
+ const { data } = await sni.get('/cgi/ma/products/' + id)
+ setProduct(data)
+ }
+
+ async function parseContent(content: string): Promise {
+ content = content.replace(
+ /!\[.*?\]\(solink:\/\/attachments\/([\w-]+)\)/g,
+ '',
+ )
+
+ const out = await unified()
+ .use(remarkParse)
+ .use(remarkRehype)
+ .use(remarkGfm)
+ .use(rehypeSanitize)
+ .use(rehypeStringify)
+ .process(content)
+
+ return String(out)
+ }
+
+ const [releases, setReleases] = useState()
+ const [selectedRelease, setSelectedRelease] = useState()
+ const [selectedReleaseContent, setSelectedReleaseContent] = useState()
+
+ const [showInstaller, setShowInstaller] = useState(false)
+
+ async function fetchReleases(): Promise {
+ const { data: resp } = await sni.get<{ data: MaRelease[] }>('/cgi/ma/products/' + id + '/releases', {
+ params: {
+ take: 10,
+ },
+ })
+ setReleases(resp.data)
+ }
+
+ useEffect(() => {
+ fetchProduct().then(() => Promise.all([fetchReleases()]))
+ }, [])
+
+ useEffect(() => {
+ if (product?.meta?.introduction == null) return
+ parseContent(product.meta.introduction).then((out) => setContent(out))
+ }, [product?.meta?.introduction])
+
+ useEffect(() => {
+ if (selectedRelease == null) return
+ parseContent(selectedRelease.meta.content).then((out) => setSelectedReleaseContent(out))
+ }, [selectedRelease])
+
+ return (
+ <>
+ {product?.previews && (
+
+ )}
+
+
+
+
+
+ } onClick={() => navigate('/')} sx={{ mb: 1 }}>
+ Back
+
+
+
+
+ {product?.icon && (
+
+ )}
+
+ {product?.name}
+
+
+ {product?.description}
+
+
+
+ {content && (
+
+ )}
+
+
+
+
+
+
+ Install
+
+
+
+ Releases
+
+
+
+ }
+ onClick={() => {
+ if (selectedRelease == null) return
+ setShowInstaller(true)
+ }}
+ >
+ Install
+
+
+
+
+
+
+
+
+ >
+ )
+}
diff --git a/tailwind.config.js b/tailwind.config.js
index ab20e63..694b742 100644
--- a/tailwind.config.js
+++ b/tailwind.config.js
@@ -4,5 +4,5 @@ module.exports = {
theme: {
extend: {},
},
- plugins: [],
+ plugins: [require('@tailwindcss/typography')],
}