From bdde78475ef1876f979db33744bf7a1fdd7e2b71 Mon Sep 17 00:00:00 2001 From: "[Tui]" Date: Sun, 21 Dec 2025 09:44:53 +1300 Subject: [PATCH] Added the option to directly input webp file name or character image link when creating PNG for character cards --- next-env.d.ts | 2 +- package-lock.json | 9 ++ src/app/page.tsx | 343 +++++++++++++++++++++++++--------------------- 3 files changed, 195 insertions(+), 159 deletions(-) diff --git a/next-env.d.ts b/next-env.d.ts index 9edff1c..c4b7818 100644 --- a/next-env.d.ts +++ b/next-env.d.ts @@ -1,6 +1,6 @@ /// /// -import "./.next/types/routes.d.ts"; +import "./.next/dev/types/routes.d.ts"; // NOTE: This file should not be edited // see https://nextjs.org/docs/app/api-reference/config/typescript for more information. diff --git a/package-lock.json b/package-lock.json index 6c41cc3..62a491f 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1296,6 +1296,7 @@ "resolved": "https://registry.npmjs.org/@types/react/-/react-19.2.7.tgz", "integrity": "sha512-MWtvHrGZLFttgeEj28VXHxpmwYbor/ATPYbBfSFZEIRK0ecCFLl2Qo55z52Hss+UV9CRN7trSeq1zbgx7YDWWg==", "license": "MIT", + "peer": true, "dependencies": { "csstype": "^3.2.2" } @@ -1305,6 +1306,7 @@ "resolved": "https://registry.npmjs.org/@types/react-dom/-/react-dom-19.2.3.tgz", "integrity": "sha512-jp2L/eY6fn+KgVVQAOqYItbF0VY/YApe5Mz2F0aykSO8gx31bYCZyvSeYxCHKvzHG5eZjc+zyaS5BrBWya2+kQ==", "license": "MIT", + "peer": true, "peerDependencies": { "@types/react": "^19.2.0" } @@ -1464,6 +1466,7 @@ } ], "license": "MIT", + "peer": true, "dependencies": { "baseline-browser-mapping": "^2.9.0", "caniuse-lite": "^1.0.30001759", @@ -2075,6 +2078,7 @@ "resolved": "https://registry.npmjs.org/jiti/-/jiti-1.21.7.tgz", "integrity": "sha512-/imKNG4EbWNrVjoNC/1H5/9GFy+tqjGBHCaSsN+P2RnPqjsLmv6UD3Ej+Kj8nBWaRAwyk7kK5ZUc+OEatnTR3A==", "license": "MIT", + "peer": true, "bin": { "jiti": "bin/jiti.js" } @@ -2372,6 +2376,7 @@ } ], "license": "MIT", + "peer": true, "dependencies": { "nanoid": "^3.3.11", "picocolors": "^1.1.1", @@ -2540,6 +2545,7 @@ "resolved": "https://registry.npmjs.org/react/-/react-19.2.1.tgz", "integrity": "sha512-DGrYcCWK7tvYMnWh79yrPHt+vdx9tY+1gPZa7nJQtO/p8bLTDaHp4dzwEhQB7pZ4Xe3ok4XKuEPrVuc+wlpkmw==", "license": "MIT", + "peer": true, "engines": { "node": ">=0.10.0" } @@ -2549,6 +2555,7 @@ "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-19.2.1.tgz", "integrity": "sha512-ibrK8llX2a4eOskq1mXKu/TGZj9qzomO+sNfO98M6d9zIPOEhlBkMkBUBLd1vgS0gQsLDBzA+8jJBVXDnfHmJg==", "license": "MIT", + "peer": true, "dependencies": { "scheduler": "^0.27.0" }, @@ -2844,6 +2851,7 @@ "resolved": "https://registry.npmjs.org/tailwindcss/-/tailwindcss-3.4.18.tgz", "integrity": "sha512-6A2rnmW5xZMdw11LYjhcI5846rt9pbLSabY5XPxo+XWdxwZaFEn47Go4NzFiHu9sNNmr/kXivP1vStfvMaK1GQ==", "license": "MIT", + "peer": true, "dependencies": { "@alloc/quick-lru": "^5.2.0", "arg": "^5.0.2", @@ -2953,6 +2961,7 @@ "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.3.tgz", "integrity": "sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==", "license": "MIT", + "peer": true, "engines": { "node": ">=12" }, diff --git a/src/app/page.tsx b/src/app/page.tsx index bf19ccf..45d09e8 100644 --- a/src/app/page.tsx +++ b/src/app/page.tsx @@ -258,12 +258,11 @@ export default function Home() { const cardData = JSON.stringify(pngData); const newImageData = Png.Generate(arrayBuffer, cardData); - const newFileName = `${ - (card.initialVersion?.name || card.data.name).replace( - /[^a-zA-Z0-9\-_]/g, - "_" - ) || "character" - }.png`; + const newFileName = `${(card.initialVersion?.name || card.data.name).replace( + /[^a-zA-Z0-9\-_]/g, + "_" + ) || "character" + }.png`; const newFile = new File([new Uint8Array(newImageData)], newFileName, { type: "image/png", }); @@ -290,14 +289,44 @@ export default function Home() { }; const handleOpenMetadata = () => { - const match = characterUrl.match(/characters\/([\w-]+)/); - if (match && match[1]) { - const characterId = match[1].split("_")[0]; - window.open( - `https://janitorai.com/hampter/characters/${characterId}`, - "_blank" - ); - setIsMetadataOpen(true); + // Check if the input is a character metadata URL (janitorai.com/characters/...) + const isCharacterUrl = /janitorai\.com\/characters\//.test(characterUrl); + + if (isCharacterUrl) { + // Extract character ID and open metadata page, then show second input + const match = characterUrl.match(/characters\/([\w-]+)/); + if (match && match[1]) { + const characterId = match[1].split("_")[0]; + window.open( + `https://janitorai.com/hampter/characters/${characterId}`, + "_blank" + ); + setIsMetadataOpen(true); + } + return; + } + + // Check if the input is a direct image link (webp filename or full image URL) + const isImagePath = /\.(webp|png|jpg|jpeg|gif)(\?.*)?$/i.test(characterUrl); + const isFullImageUrl = (characterUrl.startsWith("http://") || characterUrl.startsWith("https://")) && isImagePath; + const isWebpFilename = /^[\w-]+\.(webp|png|jpg|jpeg|gif)$/i.test(characterUrl); + + if (isFullImageUrl || isWebpFilename) { + // Directly set the avatar URL without opening metadata + if (selectedCardIndex === null) return; + + const avatarUrl = isFullImageUrl + ? characterUrl + : `https://ella.janitorai.com/bot-avatars/${characterUrl}`; + + const updatedCards = [...cards]; + updatedCards[selectedCardIndex] = { + ...updatedCards[selectedCardIndex], + avatarUrl, + }; + setCards(updatedCards); + setDialogOpen(false); + return; } }; @@ -588,71 +617,70 @@ export default function Home() {
{(card.initialVersion?.description || card.data?.description) && ( - - - Description - -
-
-                                      {card.initialVersion?.description ||
-                                        card.data.description}
-                                    
- -
-
-
-
- )} + ); + }} + > + + +
+ + + + )} {(card.initialVersion?.first_mes || card.data?.first_mes) && ( - - - - First Message - - -
-
-                                      {card.initialVersion?.first_mes ||
-                                        card.data.first_mes}
-                                    
- -
-
-
-
- )} + ); + }} + > + + + + + + + )} {card.alternate_greetings && card.alternate_greetings.length > 0 && (
-

{`Alternate Greetings (${ - card.alternate_greetings?.length || 0 - })`}

+

{`Alternate Greetings (${card.alternate_greetings?.length || 0 + })`}

-
- - - - )} + ); + }} + > + + +
+ + + + )} {(card.initialVersion?.mes_example || card.data?.mes_example) && ( - - - - Example Messages - - -
-
-                                      {card.initialVersion?.mes_example ||
-                                        card.data.mes_example}
-                                    
- -
-
-
-
- )} + ); + }} + > + + +
+ + + + )} {(card.initialVersion?.personality || card.data?.personality) && ( - - - Personality - -
-
-                                      {card.initialVersion?.personality ||
-                                        card.data.personality}
-                                    
- -
-
-
-
- )} + ); + }} + > + + + + + + + )} @@ -863,12 +891,12 @@ export default function Home() { - {isMetadataOpen ? "Enter Avatar Path" : "Enter Character URL"} + {isMetadataOpen ? "Enter Avatar Path" : "Fetch Avatar"} {isMetadataOpen ? "Look for the avatar field in the opened tab and paste the value here." - : "Enter the Janitor character URL (https://janitorai.com/characters/...)."} + : "Enter a character URL (janitorai.com/characters/...) to open metadata, or paste an image filename (id.webp) or full image URL directly."} @@ -888,19 +916,18 @@ export default function Home() { ) : (
) => setCharacterUrl(e.target.value) } />

- Upon clicking this button, a new tab will open with the - character's metadata. Look for the avatar field and copy the - value before returning to this page. + For character URLs, a new tab will open with metadata. For image + filenames or full image URLs, the avatar will be set directly.

)}