feat: module lorebook sort, import, export
This commit is contained in:
@@ -2,6 +2,9 @@
|
||||
import { language } from "src/lang";
|
||||
import TextInput from "src/lib/UI/GUI/TextInput.svelte";
|
||||
import LoreBookData from "src/lib/SideBars/LoreBook/LoreBookData.svelte";
|
||||
import type { loreBook } from "src/ts/storage/database.svelte";
|
||||
import LoreBookList from "src/lib/SideBars/LoreBook/LoreBookList.svelte";
|
||||
import { type CCLorebook, convertExternalLorebook } from "src/ts/process/lorebook.svelte";
|
||||
import type { RisuModule } from "src/ts/process/modules";
|
||||
import { DownloadIcon, FolderUpIcon, PlusIcon, TrashIcon } from "lucide-svelte";
|
||||
import RegexList from "src/lib/SideBars/Scripts/RegexList.svelte";
|
||||
@@ -9,7 +12,8 @@
|
||||
import Check from "src/lib/UI/GUI/CheckInput.svelte";
|
||||
import Help from "src/lib/Others/Help.svelte";
|
||||
import TextAreaInput from "src/lib/UI/GUI/TextAreaInput.svelte";
|
||||
import { getFileSrc, openURL, saveAsset } from "src/ts/globalApi.svelte";
|
||||
import { getFileSrc, openURL, saveAsset, downloadFile } from "src/ts/globalApi.svelte";
|
||||
import { alertNormal, alertError } from "src/ts/alert";
|
||||
import { exportRegex, importRegex } from "src/ts/process/scripts";
|
||||
import { selectMultipleFile } from "src/ts/util";
|
||||
|
||||
@@ -57,6 +61,48 @@
|
||||
}
|
||||
}
|
||||
|
||||
async function exportLoreBook(){
|
||||
try {
|
||||
const lore = currentModule.lorebook
|
||||
const stringl = Buffer.from(JSON.stringify({
|
||||
type: 'risu',
|
||||
ver: 1,
|
||||
data: lore
|
||||
}), 'utf-8')
|
||||
|
||||
await downloadFile(`lorebook_export.json`, stringl)
|
||||
|
||||
alertNormal(language.successExport)
|
||||
} catch (error) {
|
||||
alertError(`${error}`)
|
||||
}
|
||||
}
|
||||
|
||||
async function importLoreBook(){
|
||||
let lore = currentModule.lorebook
|
||||
const lorebook = (await selectMultipleFile(['json', 'lorebook']))
|
||||
if(!lorebook){
|
||||
return
|
||||
}
|
||||
try {
|
||||
for(const f of lorebook){
|
||||
const importedlore = JSON.parse(Buffer.from(f.data).toString('utf-8'))
|
||||
if(importedlore.type === 'risu' && importedlore.data){
|
||||
const datas:loreBook[] = importedlore.data
|
||||
for(const data of datas){
|
||||
lore.push(data)
|
||||
}
|
||||
}
|
||||
else if(importedlore.entries){
|
||||
const entries:{[key:string]:CCLorebook} = importedlore.entries
|
||||
lore.push(...convertExternalLorebook(entries))
|
||||
}
|
||||
}
|
||||
} catch (error) {
|
||||
alertError(`${error}`)
|
||||
}
|
||||
}
|
||||
|
||||
function addRegex(){
|
||||
if(Array.isArray(currentModule.regex)){
|
||||
currentModule.regex.push({
|
||||
@@ -150,17 +196,18 @@
|
||||
<TextAreaInput bind:value={currentModule.customModuleToggle}/>
|
||||
{/if}
|
||||
{#if submenu === 1 && (Array.isArray(currentModule.lorebook))}
|
||||
<div class="border border-selected p-2 flex flex-col rounded-md mt-2">
|
||||
{#each currentModule.lorebook as lore, i}
|
||||
<LoreBookData bind:value={currentModule.lorebook[i]} idx={i} onRemove={() => {
|
||||
currentModule.lorebook.splice(i, 1)
|
||||
currentModule.lorebook = currentModule.lorebook
|
||||
}}/>
|
||||
{/each}
|
||||
<LoreBookList externalLoreBooks={currentModule.lorebook} />
|
||||
<div class="text-textcolor2 mt-2 flex">
|
||||
<button onclick={() => {addLorebook()}} class="hover:text-textcolor cursor-pointer ml-1">
|
||||
<PlusIcon />
|
||||
</button>
|
||||
<button onclick={() => {exportLoreBook()}} class="hover:text-textcolor cursor-pointer ml-2">
|
||||
<DownloadIcon />
|
||||
</button>
|
||||
<button onclick={() => {importLoreBook()}} class="hover:text-textcolor cursor-pointer ml-2">
|
||||
<FolderUpIcon />
|
||||
</button>
|
||||
</div>
|
||||
<button onclick={() => {addLorebook()}} class="hover:text-textcolor cursor-pointer">
|
||||
<PlusIcon />
|
||||
</button>
|
||||
{/if}
|
||||
|
||||
{#if submenu === 2 && (Array.isArray(currentModule.regex))}
|
||||
|
||||
@@ -11,9 +11,10 @@
|
||||
globalMode?: boolean;
|
||||
submenu?: number;
|
||||
lorePlus?: boolean;
|
||||
externalLoreBooks?: loreBook[];
|
||||
}
|
||||
|
||||
let { globalMode = false, submenu = 0, lorePlus = false }: Props = $props();
|
||||
let { globalMode = false, submenu = 0, lorePlus = false, externalLoreBooks = null }: Props = $props();
|
||||
let stb: Sortable = null
|
||||
let ele: HTMLDivElement = $state()
|
||||
let sorted = $state(0)
|
||||
@@ -31,6 +32,13 @@
|
||||
})
|
||||
DBState.db.loreBook[DBState.db.loreBookPage].data = newLore
|
||||
}
|
||||
else if(externalLoreBooks){
|
||||
let newLore:loreBook[] = []
|
||||
idx.forEach((i) => {
|
||||
newLore.push(externalLoreBooks[i])
|
||||
})
|
||||
externalLoreBooks = newLore
|
||||
}
|
||||
else if(submenu === 1){
|
||||
let newLore:loreBook[] = []
|
||||
idx.forEach((i) => {
|
||||
@@ -97,6 +105,18 @@
|
||||
}} onOpen={onOpen} onClose={onClose}/>
|
||||
{/each}
|
||||
{/if}
|
||||
{:else if externalLoreBooks}
|
||||
{#if externalLoreBooks.length === 0}
|
||||
<span class="text-textcolor2">No Lorebook</span>
|
||||
{:else}
|
||||
{#each externalLoreBooks as book, i}
|
||||
<LoreBookData bind:value={externalLoreBooks[i]} idx={i} onRemove={() => {
|
||||
let lore = externalLoreBooks
|
||||
lore.splice(i, 1)
|
||||
externalLoreBooks = lore
|
||||
}} onOpen={onOpen} onClose={onClose}/>
|
||||
{/each}
|
||||
{/if}
|
||||
{:else if submenu === 0}
|
||||
{#if DBState.db.characters[$selectedCharID].globalLore.length === 0}
|
||||
<span class="text-textcolor2">No Lorebook</span>
|
||||
|
||||
@@ -510,7 +510,7 @@ export async function importLoreBook(mode:'global'|'local'|'sglobal'){
|
||||
}
|
||||
}
|
||||
|
||||
interface CCLorebook{
|
||||
export interface CCLorebook{
|
||||
key:string[]
|
||||
comment:string
|
||||
content:string
|
||||
|
||||
Reference in New Issue
Block a user