diff --git a/pkgs/clan-cli/clan_cli/clan/show.py b/pkgs/clan-cli/clan_cli/clan/show.py index 5029d17b..e4d1bc62 100644 --- a/pkgs/clan-cli/clan_cli/clan/show.py +++ b/pkgs/clan-cli/clan_cli/clan/show.py @@ -2,6 +2,7 @@ import argparse import json import logging from pathlib import Path +from urllib.parse import urlparse from clan_cli.api import API from clan_cli.clan.create import ClanMetaInfo @@ -22,6 +23,7 @@ def show_clan_meta(uri: str | Path) -> ClanMetaInfo: ] ) res = "{}" + try: proc = run_no_stdout(cmd) res = proc.stdout.strip() @@ -33,10 +35,36 @@ def show_clan_meta(uri: str | Path) -> ClanMetaInfo: ) clan_meta = json.loads(res) + + # Check if icon is a URL such as http:// or https:// + # Check if icon is an relative path + # All other schemas such as file://, ftp:// are not yet supported. + icon_path: str | None = None + if meta_icon := clan_meta.get("icon"): + scheme = urlparse(meta_icon).scheme + if scheme in ["http", "https"]: + icon_path = meta_icon + elif scheme in [""]: + if Path(meta_icon).is_absolute(): + raise ClanError( + "Invalid absolute path", + location=f"show_clan {uri}", + description="Icon path must be a URL or a relative path.", + ) + + else: + icon_path = str((Path(uri) / meta_icon).resolve()) + else: + raise ClanError( + "Invalid schema", + location=f"show_clan {uri}", + description="Icon path must be a URL or a relative path.", + ) + return ClanMetaInfo( name=clan_meta.get("name"), description=clan_meta.get("description", None), - icon=clan_meta.get("icon", None), + icon=icon_path, ) diff --git a/pkgs/webview-ui/app/gtk.webview.js b/pkgs/webview-ui/app/gtk.webview.js index a7d67c00..522d93cc 100644 --- a/pkgs/webview-ui/app/gtk.webview.js +++ b/pkgs/webview-ui/app/gtk.webview.js @@ -1,13 +1,12 @@ -const fs = require("fs"); -const path = require("path"); +import fs from "node:fs"; +import postcss from "postcss"; +import path from "node:path"; +import css_url from "postcss-url"; -const distPath = path.resolve(__dirname, "dist"); +const distPath = path.resolve("dist"); const manifestPath = path.join(distPath, ".vite/manifest.json"); const outputPath = path.join(distPath, "index.html"); -const postcss = require("postcss"); -const css_url = require("postcss-url"); - fs.readFile(manifestPath, { encoding: "utf8" }, (err, data) => { if (err) { return console.error("Failed to read manifest:", err); diff --git a/pkgs/webview-ui/app/package.json b/pkgs/webview-ui/app/package.json index 9bf4f256..0d0f8797 100644 --- a/pkgs/webview-ui/app/package.json +++ b/pkgs/webview-ui/app/package.json @@ -2,6 +2,7 @@ "name": "@clan/webview-ui", "version": "0.0.1", "description": "", + "type": "module", "scripts": { "start": "vite", "dev": "vite", diff --git a/pkgs/webview-ui/app/postcss.config.js b/pkgs/webview-ui/app/postcss.config.js index 12a703d9..a982c641 100644 --- a/pkgs/webview-ui/app/postcss.config.js +++ b/pkgs/webview-ui/app/postcss.config.js @@ -1,6 +1,8 @@ -module.exports = { +const config = { plugins: { tailwindcss: {}, autoprefixer: {}, }, }; + +export default config; diff --git a/pkgs/webview-ui/app/src/index.tsx b/pkgs/webview-ui/app/src/index.tsx index 71b79467..0d011c3f 100644 --- a/pkgs/webview-ui/app/src/index.tsx +++ b/pkgs/webview-ui/app/src/index.tsx @@ -17,6 +17,8 @@ if (import.meta.env.DEV && !(root instanceof HTMLElement)) { console.log(import.meta.env); if (import.meta.env.DEV) { console.log("Development mode"); + // Load the debugger in development mode + await import("solid-devtools"); window.webkit = window.webkit || { messageHandlers: { gtk: { @@ -28,12 +30,11 @@ if (import.meta.env.DEV) { console.log("mock", { mock }); window.clan[method](JSON.stringify(mock)); - }, 1000); + }, 200); }, }, }, }; } -postMessage; // eslint-disable-next-line @typescript-eslint/no-non-null-assertion render(() => , root!); diff --git a/pkgs/webview-ui/app/src/routes/clan/clanDetails.tsx b/pkgs/webview-ui/app/src/routes/clan/clanDetails.tsx index beac427b..74eb6ee3 100644 --- a/pkgs/webview-ui/app/src/routes/clan/clanDetails.tsx +++ b/pkgs/webview-ui/app/src/routes/clan/clanDetails.tsx @@ -19,21 +19,17 @@ interface ClanDetailsProps { directory: string; } -interface MetaFieldsProps { +interface ClanFormProps { + directory?: string; meta: ClanMeta; actions: JSX.Element; editable?: boolean; - directory?: string; } -const fn = (e: SubmitEvent) => { - e.preventDefault(); - console.log("form submit", e.currentTarget); -}; - -export default function Login() { - const [, { Form, Field }] = createForm({ - initialValues: { name: "MyClan" }, +export const ClanForm = (props: ClanFormProps) => { + const { meta, actions, editable = true, directory } = props; + const [formStore, { Form, Field }] = createForm({ + initialValues: meta, }); const handleSubmit: SubmitHandler = (values, event) => { @@ -52,156 +48,120 @@ export default function Login() { console.log("submit", values); }; return ( -
+
- - {(field, props) => ( - - )} - - - {(field, props) => ( - - )} - {(field, props) => ( - + <> +
+ + group + + } + > + {(icon) => ( + Clan Logo + )} + +
+ + )}
-
- +
+
+ + {(field, props) => ( + + )} + + + {(field, props) => ( + + )} + + {actions} +
); -} - -export const EditMetaFields = (props: MetaFieldsProps) => { - const { meta, editable, actions, directory } = props; - - const [editing, setEditing] = createSignal< - keyof MetaFieldsProps["meta"] | null - >(null); - return ( -
-
- Clan Logo -
-
- - {/*
*/} - {/*

- setEditing(null)} - type="text" - value={meta?.name} - onInput={(e) => { - console.log(e.currentTarget.value); - }} - /> - - - -

-
- description - {meta?.description || "No description"} -
- -
- folder - {directory} -
-
- {actions} */} - {/*
*/} -
-
- ); }; +// export const EditMetaFields = (props: MetaFieldsProps) => { +// const { meta, editable, actions, directory } = props; + +// const [editing, setEditing] = createSignal< +// keyof MetaFieldsProps["meta"] | null +// >(null); +// return ( + +// ); +// }; + type ClanMeta = Extract< OperationResponse<"show_clan_meta">, { status: "success" } @@ -209,7 +169,7 @@ type ClanMeta = Extract< export const ClanDetails = (props: ClanDetailsProps) => { const { directory } = props; - const [, setLoading] = createSignal(false); + const [loading, setLoading] = createSignal(false); const [errors, setErrors] = createSignal< | Extract< OperationResponse<"show_clan_meta">, @@ -237,23 +197,30 @@ export const ClanDetails = (props: ClanDetailsProps) => { }); return ( + +
Loading
+
- - - -
- } - /> + {(data) => { + const meta = data(); + return ( + + + +
+ } + /> + ); + }} - diff --git a/pkgs/webview-ui/app/src/routes/clan/view.tsx b/pkgs/webview-ui/app/src/routes/clan/view.tsx index e703e4c7..d1ced973 100644 --- a/pkgs/webview-ui/app/src/routes/clan/view.tsx +++ b/pkgs/webview-ui/app/src/routes/clan/view.tsx @@ -1,7 +1,7 @@ import { pyApi } from "@/src/api"; import { Match, Switch, createEffect, createSignal } from "solid-js"; import toast from "solid-toast"; -import { ClanDetails, EditMetaFields } from "./clanDetails"; +import { ClanDetails, ClanForm } from "./clanDetails"; export const clan = () => { const [mode, setMode] = createSignal<"init" | "open" | "create">("init"); @@ -53,16 +53,16 @@ export const clan = () => { - diff --git a/pkgs/webview-ui/app/vite.config.ts b/pkgs/webview-ui/app/vite.config.ts index 3df04e34..e5a58885 100644 --- a/pkgs/webview-ui/app/vite.config.ts +++ b/pkgs/webview-ui/app/vite.config.ts @@ -1,6 +1,6 @@ import { defineConfig } from "vite"; import solidPlugin from "vite-plugin-solid"; -// import devtools from "solid-devtools/vite"; +import devtools from "solid-devtools/vite"; import path from "node:path"; export default defineConfig({ @@ -14,7 +14,7 @@ export default defineConfig({ Uncomment the following line to enable solid-devtools. For more info see https://github.com/thetarnav/solid-devtools/tree/main/packages/extension#readme */ - // devtools(), + devtools(), solidPlugin(), ], server: {