mirror of
https://github.com/severian-dev/sucker.severian.dev.git
synced 2025-10-28 20:55:46 +00:00
formatting
This commit is contained in:
318
src/app/page.tsx
318
src/app/page.tsx
@@ -91,28 +91,30 @@ export default function Home() {
|
||||
|
||||
const downloadJson = (card: Card) => {
|
||||
// Use initial version for download, or current version if no initial version available
|
||||
const downloadData = card.initialVersion ? {
|
||||
name: card.initialVersion.name,
|
||||
first_mes: card.initialVersion.first_mes,
|
||||
description: card.initialVersion.description,
|
||||
personality: card.initialVersion.personality,
|
||||
mes_example: card.initialVersion.mes_example,
|
||||
scenario: card.initialVersion.scenario,
|
||||
} : {
|
||||
name: card.name,
|
||||
first_mes: card.first_mes,
|
||||
description: card.description,
|
||||
personality: card.personality,
|
||||
mes_example: card.mes_example,
|
||||
scenario: card.scenario,
|
||||
};
|
||||
const downloadData = card.initialVersion
|
||||
? {
|
||||
name: card.initialVersion.name,
|
||||
first_mes: card.initialVersion.first_mes,
|
||||
description: card.initialVersion.description,
|
||||
personality: card.initialVersion.personality,
|
||||
mes_example: card.initialVersion.mes_example,
|
||||
scenario: card.initialVersion.scenario,
|
||||
}
|
||||
: {
|
||||
name: card.name,
|
||||
first_mes: card.first_mes,
|
||||
description: card.description,
|
||||
personality: card.personality,
|
||||
mes_example: card.mes_example,
|
||||
scenario: card.scenario,
|
||||
};
|
||||
|
||||
const element = document.createElement("a");
|
||||
const file = new Blob([JSON.stringify(downloadData, null, 2)], {
|
||||
type: "application/json",
|
||||
});
|
||||
element.href = URL.createObjectURL(file);
|
||||
element.download = `${card.name.replace(/[^a-zA-Z0-9\-_]/g, '_')}.json`;
|
||||
element.download = `${card.name.replace(/[^a-zA-Z0-9\-_]/g, "_")}.json`;
|
||||
document.body.appendChild(element);
|
||||
element.click();
|
||||
document.body.removeChild(element);
|
||||
@@ -122,22 +124,27 @@ export default function Home() {
|
||||
try {
|
||||
const response = await fetch(`/api/proxy?changes=true&cardId=${card.id}`);
|
||||
if (!response.ok) {
|
||||
throw new Error('Failed to fetch changes');
|
||||
throw new Error("Failed to fetch changes");
|
||||
}
|
||||
|
||||
|
||||
const changesData = await response.json();
|
||||
const element = document.createElement("a");
|
||||
const file = new Blob([JSON.stringify(changesData, null, 2)], {
|
||||
type: "application/json",
|
||||
});
|
||||
element.href = URL.createObjectURL(file);
|
||||
element.download = `${card.name.replace(/[^a-zA-Z0-9\-_]/g, '_')}_changes.json`;
|
||||
element.download = `${card.name.replace(
|
||||
/[^a-zA-Z0-9\-_]/g,
|
||||
"_"
|
||||
)}_changes.json`;
|
||||
document.body.appendChild(element);
|
||||
element.click();
|
||||
document.body.removeChild(element);
|
||||
} catch (error) {
|
||||
console.error("Error downloading changes:", error);
|
||||
alert("Failed to download changes. The card may not have version history.");
|
||||
alert(
|
||||
"Failed to download changes. The card may not have version history."
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -145,9 +152,9 @@ export default function Home() {
|
||||
try {
|
||||
const response = await fetch(`/api/proxy?changes=true&cardId=${card.id}`);
|
||||
if (!response.ok) {
|
||||
throw new Error('Failed to fetch changes');
|
||||
throw new Error("Failed to fetch changes");
|
||||
}
|
||||
|
||||
|
||||
const changesData = await response.json();
|
||||
setSelectedChanges(changesData);
|
||||
setShowFullText(false); // Reset to diff view by default
|
||||
@@ -187,27 +194,29 @@ export default function Home() {
|
||||
const arrayBuffer = await pngBlob.arrayBuffer();
|
||||
|
||||
// Use initial version for PNG embedding, or current version if no initial version available
|
||||
const pngData = card.initialVersion ? {
|
||||
name: card.initialVersion.name,
|
||||
first_mes: card.initialVersion.first_mes,
|
||||
description: card.initialVersion.description,
|
||||
personality: card.initialVersion.personality,
|
||||
mes_example: card.initialVersion.mes_example,
|
||||
scenario: card.initialVersion.scenario,
|
||||
} : {
|
||||
name: card.name,
|
||||
first_mes: card.first_mes,
|
||||
description: card.description,
|
||||
personality: card.personality,
|
||||
mes_example: card.mes_example,
|
||||
scenario: card.scenario,
|
||||
};
|
||||
const pngData = card.initialVersion
|
||||
? {
|
||||
name: card.initialVersion.name,
|
||||
first_mes: card.initialVersion.first_mes,
|
||||
description: card.initialVersion.description,
|
||||
personality: card.initialVersion.personality,
|
||||
mes_example: card.initialVersion.mes_example,
|
||||
scenario: card.initialVersion.scenario,
|
||||
}
|
||||
: {
|
||||
name: card.name,
|
||||
first_mes: card.first_mes,
|
||||
description: card.description,
|
||||
personality: card.personality,
|
||||
mes_example: card.mes_example,
|
||||
scenario: card.scenario,
|
||||
};
|
||||
|
||||
const cardData = JSON.stringify(pngData);
|
||||
|
||||
const newImageData = Png.Generate(arrayBuffer, cardData);
|
||||
const newFileName = `${
|
||||
card.name.replace(/[^a-zA-Z0-9\-_]/g, '_') || "character"
|
||||
card.name.replace(/[^a-zA-Z0-9\-_]/g, "_") || "character"
|
||||
}.png`;
|
||||
const newFile = new File([newImageData], newFileName, {
|
||||
type: "image/png",
|
||||
@@ -274,7 +283,8 @@ export default function Home() {
|
||||
<div>
|
||||
<h1 className="text-3xl font-bold">Sucker v2.0</h1>
|
||||
<p className="text-sm text-muted-foreground">
|
||||
Now with multimessage support! Tracks changes to character descriptions and scenarios across multiple extractions.
|
||||
Now with multimessage support! Tracks changes to character
|
||||
descriptions and scenarios across multiple extractions.
|
||||
</p>
|
||||
</div>
|
||||
<Button
|
||||
@@ -294,7 +304,10 @@ export default function Home() {
|
||||
New: Multimessage Support
|
||||
</span>
|
||||
<p className="text-sm text-muted-foreground">
|
||||
Sucker now tracks changes to character descriptions and scenarios across multiple messages. Cards with multiple versions show a version badge and offer a "Download Changes" button to get the change history.
|
||||
Sucker now tracks changes to character descriptions and
|
||||
scenarios across multiple messages. Cards with multiple versions
|
||||
show a version badge and offer a "Download Changes" button to
|
||||
get the change history.
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
@@ -333,7 +346,9 @@ export default function Home() {
|
||||
REQUIRED: Set your custom prompt to <code><.></code>
|
||||
</li>
|
||||
<li className="mb-2">
|
||||
REQUIRED: Set your persona (or create a new one) with the name <code>{user}</code> and the description should only have <code>.</code> in it.
|
||||
REQUIRED: Set your persona (or create a new one) with the name{" "}
|
||||
<code>{user}</code> and the description should only
|
||||
have <code>.</code> in it.
|
||||
</li>
|
||||
<li className="mb-2">
|
||||
Save settings and refresh the page. Not this page. <i>That</i>{" "}
|
||||
@@ -343,7 +358,9 @@ export default function Home() {
|
||||
Start a new chat with a character or multiple.
|
||||
</li>
|
||||
<li className="mb-2">
|
||||
You can either send a dot to let sucker make a best guess about the char name, or send the char name yourself and it'll be used instead.
|
||||
You can either send a dot to let sucker make a best guess
|
||||
about the char name, or send the char name yourself and it'll
|
||||
be used instead.
|
||||
</li>
|
||||
<li className="mb-2">
|
||||
Hit the Refresh button here, and the cards should appear here.
|
||||
@@ -359,10 +376,11 @@ export default function Home() {
|
||||
I'm not storing shit.
|
||||
</p>
|
||||
<p className="mb-2">
|
||||
<strong>New:</strong> If you send multiple messages with the same character name,
|
||||
Sucker will track changes to the description and scenario fields. Cards with
|
||||
multiple versions will show a version badge and offer a "Download Changes"
|
||||
button to get a detailed change history with timestamps.
|
||||
<strong>New:</strong> If you send multiple messages with the
|
||||
same character name, Sucker will track changes to the
|
||||
description and scenario fields. Cards with multiple versions
|
||||
will show a version badge and offer a "Download Changes" button
|
||||
to get a detailed change history with timestamps.
|
||||
</p>
|
||||
</div>
|
||||
</CollapsibleContent>
|
||||
@@ -400,19 +418,26 @@ export default function Home() {
|
||||
</AccordionTrigger>
|
||||
<AccordionContent>
|
||||
<div id={`card-${index}`} className="space-y-4 mt-4">
|
||||
{(card.initialVersion?.description || card.description) && (
|
||||
{(card.initialVersion?.description ||
|
||||
card.description) && (
|
||||
<Accordion type="single" collapsible>
|
||||
<AccordionItem value="description">
|
||||
<AccordionTrigger>Description</AccordionTrigger>
|
||||
<AccordionContent>
|
||||
<div className="flex justify-between">
|
||||
<pre className="whitespace-pre-wrap font-sans text-sm">{card.initialVersion?.description || card.description}</pre>
|
||||
<Button
|
||||
variant="ghost"
|
||||
size="icon"
|
||||
onClick={(e) => {
|
||||
e.stopPropagation();
|
||||
copyToClipboard(card.initialVersion?.description || card.description);
|
||||
<pre className="whitespace-pre-wrap font-sans text-sm">
|
||||
{card.initialVersion?.description ||
|
||||
card.description}
|
||||
</pre>
|
||||
<Button
|
||||
variant="ghost"
|
||||
size="icon"
|
||||
onClick={(e) => {
|
||||
e.stopPropagation();
|
||||
copyToClipboard(
|
||||
card.initialVersion?.description ||
|
||||
card.description
|
||||
);
|
||||
}}
|
||||
>
|
||||
<Copy className="h-4 w-4" />
|
||||
@@ -422,7 +447,8 @@ export default function Home() {
|
||||
</AccordionItem>
|
||||
</Accordion>
|
||||
)}
|
||||
{(card.initialVersion?.first_mes || card.first_mes) && (
|
||||
{(card.initialVersion?.first_mes ||
|
||||
card.first_mes) && (
|
||||
<Accordion type="single" collapsible>
|
||||
<AccordionItem value="first-message">
|
||||
<AccordionTrigger>
|
||||
@@ -430,13 +456,19 @@ export default function Home() {
|
||||
</AccordionTrigger>
|
||||
<AccordionContent>
|
||||
<div className="flex justify-between">
|
||||
<pre className="whitespace-pre-wrap font-sans text-sm">{card.initialVersion?.first_mes || card.first_mes}</pre>
|
||||
<Button
|
||||
variant="ghost"
|
||||
size="icon"
|
||||
onClick={(e) => {
|
||||
e.stopPropagation();
|
||||
copyToClipboard(card.initialVersion?.first_mes || card.first_mes);
|
||||
<pre className="whitespace-pre-wrap font-sans text-sm">
|
||||
{card.initialVersion?.first_mes ||
|
||||
card.first_mes}
|
||||
</pre>
|
||||
<Button
|
||||
variant="ghost"
|
||||
size="icon"
|
||||
onClick={(e) => {
|
||||
e.stopPropagation();
|
||||
copyToClipboard(
|
||||
card.initialVersion?.first_mes ||
|
||||
card.first_mes
|
||||
);
|
||||
}}
|
||||
>
|
||||
<Copy className="h-4 w-4" />
|
||||
@@ -452,13 +484,19 @@ export default function Home() {
|
||||
<AccordionTrigger>Scenario</AccordionTrigger>
|
||||
<AccordionContent>
|
||||
<div className="flex justify-between">
|
||||
<pre className="whitespace-pre-wrap font-sans text-sm">{card.initialVersion?.scenario || card.scenario}</pre>
|
||||
<Button
|
||||
variant="ghost"
|
||||
size="icon"
|
||||
onClick={(e) => {
|
||||
e.stopPropagation();
|
||||
copyToClipboard(card.initialVersion?.scenario || card.scenario);
|
||||
<pre className="whitespace-pre-wrap font-sans text-sm">
|
||||
{card.initialVersion?.scenario ||
|
||||
card.scenario}
|
||||
</pre>
|
||||
<Button
|
||||
variant="ghost"
|
||||
size="icon"
|
||||
onClick={(e) => {
|
||||
e.stopPropagation();
|
||||
copyToClipboard(
|
||||
card.initialVersion?.scenario ||
|
||||
card.scenario
|
||||
);
|
||||
}}
|
||||
>
|
||||
<Copy className="h-4 w-4" />
|
||||
@@ -468,7 +506,8 @@ export default function Home() {
|
||||
</AccordionItem>
|
||||
</Accordion>
|
||||
)}
|
||||
{(card.initialVersion?.mes_example || card.mes_example) && (
|
||||
{(card.initialVersion?.mes_example ||
|
||||
card.mes_example) && (
|
||||
<Accordion type="single" collapsible>
|
||||
<AccordionItem value="example-messages">
|
||||
<AccordionTrigger>
|
||||
@@ -476,13 +515,19 @@ export default function Home() {
|
||||
</AccordionTrigger>
|
||||
<AccordionContent>
|
||||
<div className="flex justify-between">
|
||||
<pre className="whitespace-pre-wrap font-sans text-sm">{card.initialVersion?.mes_example || card.mes_example}</pre>
|
||||
<Button
|
||||
variant="ghost"
|
||||
size="icon"
|
||||
onClick={(e) => {
|
||||
e.stopPropagation();
|
||||
copyToClipboard(card.initialVersion?.mes_example || card.mes_example);
|
||||
<pre className="whitespace-pre-wrap font-sans text-sm">
|
||||
{card.initialVersion?.mes_example ||
|
||||
card.mes_example}
|
||||
</pre>
|
||||
<Button
|
||||
variant="ghost"
|
||||
size="icon"
|
||||
onClick={(e) => {
|
||||
e.stopPropagation();
|
||||
copyToClipboard(
|
||||
card.initialVersion?.mes_example ||
|
||||
card.mes_example
|
||||
);
|
||||
}}
|
||||
>
|
||||
<Copy className="h-4 w-4" />
|
||||
@@ -492,19 +537,26 @@ export default function Home() {
|
||||
</AccordionItem>
|
||||
</Accordion>
|
||||
)}
|
||||
{(card.initialVersion?.personality || card.personality) && (
|
||||
{(card.initialVersion?.personality ||
|
||||
card.personality) && (
|
||||
<Accordion type="single" collapsible>
|
||||
<AccordionItem value="personality">
|
||||
<AccordionTrigger>Personality</AccordionTrigger>
|
||||
<AccordionContent>
|
||||
<div className="flex justify-between">
|
||||
<pre className="whitespace-pre-wrap font-sans text-sm">{card.initialVersion?.personality || card.personality}</pre>
|
||||
<Button
|
||||
variant="ghost"
|
||||
size="icon"
|
||||
onClick={(e) => {
|
||||
e.stopPropagation();
|
||||
copyToClipboard(card.initialVersion?.personality || card.personality);
|
||||
<pre className="whitespace-pre-wrap font-sans text-sm">
|
||||
{card.initialVersion?.personality ||
|
||||
card.personality}
|
||||
</pre>
|
||||
<Button
|
||||
variant="ghost"
|
||||
size="icon"
|
||||
onClick={(e) => {
|
||||
e.stopPropagation();
|
||||
copyToClipboard(
|
||||
card.initialVersion?.personality ||
|
||||
card.personality
|
||||
);
|
||||
}}
|
||||
>
|
||||
<Copy className="h-4 w-4" />
|
||||
@@ -620,13 +672,16 @@ export default function Home() {
|
||||
Change History: {selectedChanges?.cardName}
|
||||
</DialogTitle>
|
||||
<DialogDescription className="flex items-center justify-between">
|
||||
<span>Version history showing changes to description and scenario fields</span>
|
||||
<span>
|
||||
Version history showing changes to description and scenario
|
||||
fields
|
||||
</span>
|
||||
<Button
|
||||
variant="outline"
|
||||
size="sm"
|
||||
onClick={() => setShowFullText(!showFullText)}
|
||||
>
|
||||
{showFullText ? 'Show Changes Only' : 'Show Full Text'}
|
||||
{showFullText ? "Show Changes Only" : "Show Full Text"}
|
||||
</Button>
|
||||
</DialogDescription>
|
||||
</DialogHeader>
|
||||
@@ -635,16 +690,20 @@ export default function Home() {
|
||||
<div className="space-y-4">
|
||||
<div className="grid grid-cols-2 gap-4 text-sm">
|
||||
<div>
|
||||
<strong>Total Versions:</strong> {selectedChanges.totalVersions}
|
||||
<strong>Total Versions:</strong>{" "}
|
||||
{selectedChanges.totalVersions}
|
||||
</div>
|
||||
<div>
|
||||
<strong>Current Version:</strong> {selectedChanges.currentVersion}
|
||||
<strong>Current Version:</strong>{" "}
|
||||
{selectedChanges.currentVersion}
|
||||
</div>
|
||||
<div>
|
||||
<strong>Description Changes:</strong> {selectedChanges.summary.descriptionChanges}
|
||||
<strong>Description Changes:</strong>{" "}
|
||||
{selectedChanges.summary.descriptionChanges}
|
||||
</div>
|
||||
<div>
|
||||
<strong>Scenario Changes:</strong> {selectedChanges.summary.scenarioChanges}
|
||||
<strong>Scenario Changes:</strong>{" "}
|
||||
{selectedChanges.summary.scenarioChanges}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -660,16 +719,20 @@ export default function Home() {
|
||||
</h4>
|
||||
<div className="text-sm text-muted-foreground">
|
||||
{new Date(version.timestamp).toLocaleString()}
|
||||
{version.messageCount && ` • Message ${version.messageCount}`}
|
||||
{version.messageCount &&
|
||||
` • Message ${version.messageCount}`}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
{version.changes.description && (
|
||||
<div className="mb-3">
|
||||
<h5 className="font-medium text-sm mb-1">Description Change:</h5>
|
||||
{version.changeType === 'initial' ? (
|
||||
<h5 className="font-medium text-sm mb-1">
|
||||
Description Change:
|
||||
</h5>
|
||||
{version.changeType === "initial" ? (
|
||||
<div className="bg-blue-50 dark:bg-blue-950 p-2 rounded text-sm">
|
||||
<strong>Initial Content:</strong> {version.changes.description.new}
|
||||
<strong>Initial Content:</strong>{" "}
|
||||
{version.changes.description.new}
|
||||
</div>
|
||||
) : (
|
||||
<div className="space-y-2">
|
||||
@@ -677,15 +740,18 @@ export default function Home() {
|
||||
<div className="bg-green-50 dark:bg-green-950 p-2 rounded text-sm">
|
||||
<div className="flex justify-between items-start">
|
||||
<div>
|
||||
<strong>Added:</strong> {version.addedText.description}
|
||||
<strong>Added:</strong>{" "}
|
||||
{version.addedText.description}
|
||||
</div>
|
||||
<Button
|
||||
variant="ghost"
|
||||
size="icon"
|
||||
<Button
|
||||
variant="ghost"
|
||||
size="icon"
|
||||
className="ml-2 h-6 w-6"
|
||||
onClick={(e) => {
|
||||
e.stopPropagation();
|
||||
copyToClipboard(version.addedText.description);
|
||||
onClick={(e) => {
|
||||
e.stopPropagation();
|
||||
copyToClipboard(
|
||||
version.addedText.description
|
||||
);
|
||||
}}
|
||||
>
|
||||
<Copy className="h-3 w-3" />
|
||||
@@ -695,16 +761,19 @@ export default function Home() {
|
||||
)}
|
||||
{version.removedText?.description && (
|
||||
<div className="bg-red-50 dark:bg-red-950 p-2 rounded text-sm">
|
||||
<strong>Removed:</strong> {version.removedText.description}
|
||||
<strong>Removed:</strong>{" "}
|
||||
{version.removedText.description}
|
||||
</div>
|
||||
)}
|
||||
{showFullText && (
|
||||
<div className="space-y-1 mt-2 pt-2 border-t">
|
||||
<div className="bg-gray-50 dark:bg-gray-950 p-2 rounded text-xs">
|
||||
<strong>Full Old:</strong> {version.changes.description.old}
|
||||
<strong>Full Old:</strong>{" "}
|
||||
{version.changes.description.old}
|
||||
</div>
|
||||
<div className="bg-gray-50 dark:bg-gray-950 p-2 rounded text-xs">
|
||||
<strong>Full New:</strong> {version.changes.description.new}
|
||||
<strong>Full New:</strong>{" "}
|
||||
{version.changes.description.new}
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
@@ -712,13 +781,16 @@ export default function Home() {
|
||||
)}
|
||||
</div>
|
||||
)}
|
||||
|
||||
|
||||
{version.changes.scenario && (
|
||||
<div>
|
||||
<h5 className="font-medium text-sm mb-1">Scenario Change:</h5>
|
||||
{version.changeType === 'initial' ? (
|
||||
<h5 className="font-medium text-sm mb-1">
|
||||
Scenario Change:
|
||||
</h5>
|
||||
{version.changeType === "initial" ? (
|
||||
<div className="bg-blue-50 dark:bg-blue-950 p-2 rounded text-sm">
|
||||
<strong>Initial Content:</strong> {version.changes.scenario.new}
|
||||
<strong>Initial Content:</strong>{" "}
|
||||
{version.changes.scenario.new}
|
||||
</div>
|
||||
) : (
|
||||
<div className="space-y-2">
|
||||
@@ -726,15 +798,18 @@ export default function Home() {
|
||||
<div className="bg-green-50 dark:bg-green-950 p-2 rounded text-sm">
|
||||
<div className="flex justify-between items-start">
|
||||
<div>
|
||||
<strong>Added:</strong> {version.addedText.scenario}
|
||||
<strong>Added:</strong>{" "}
|
||||
{version.addedText.scenario}
|
||||
</div>
|
||||
<Button
|
||||
variant="ghost"
|
||||
size="icon"
|
||||
<Button
|
||||
variant="ghost"
|
||||
size="icon"
|
||||
className="ml-2 h-6 w-6"
|
||||
onClick={(e) => {
|
||||
e.stopPropagation();
|
||||
copyToClipboard(version.addedText.scenario);
|
||||
onClick={(e) => {
|
||||
e.stopPropagation();
|
||||
copyToClipboard(
|
||||
version.addedText.scenario
|
||||
);
|
||||
}}
|
||||
>
|
||||
<Copy className="h-3 w-3" />
|
||||
@@ -744,16 +819,19 @@ export default function Home() {
|
||||
)}
|
||||
{version.removedText?.scenario && (
|
||||
<div className="bg-red-50 dark:bg-red-950 p-2 rounded text-sm">
|
||||
<strong>Removed:</strong> {version.removedText.scenario}
|
||||
<strong>Removed:</strong>{" "}
|
||||
{version.removedText.scenario}
|
||||
</div>
|
||||
)}
|
||||
{showFullText && (
|
||||
<div className="space-y-1 mt-2 pt-2 border-t">
|
||||
<div className="bg-gray-50 dark:bg-gray-950 p-2 rounded text-xs">
|
||||
<strong>Full Old:</strong> {version.changes.scenario.old}
|
||||
<strong>Full Old:</strong>{" "}
|
||||
{version.changes.scenario.old}
|
||||
</div>
|
||||
<div className="bg-gray-50 dark:bg-gray-950 p-2 rounded text-xs">
|
||||
<strong>Full New:</strong> {version.changes.scenario.new}
|
||||
<strong>Full New:</strong>{" "}
|
||||
{version.changes.scenario.new}
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
|
||||
Reference in New Issue
Block a user