feat: Add 'group' and 'groupEnd' type toggle

This commit is contained in:
enzi221
2025-05-20 01:11:21 +09:00
parent ab485543b8
commit 3f68238c9a
2 changed files with 59 additions and 15 deletions

View File

@@ -1,10 +1,10 @@
<script lang="ts"> <script lang="ts">
import { getModuleToggles } from "src/ts/process/modules"; import { getModuleToggles } from "src/ts/process/modules";
import { DBState, MobileGUI } from "src/ts/stores.svelte"; import { DBState, MobileGUI } from "src/ts/stores.svelte";
import { parseToggleSyntax } from "src/ts/util"; import { parseToggleSyntax, type sidebarToggle, type sidebarToggleGroup } from "src/ts/util";
import CheckInput from "../UI/GUI/CheckInput.svelte";
import { language } from "src/lang"; import { language } from "src/lang";
import type { character, groupChat } from "src/ts/storage/database.svelte"; import type { character, groupChat } from "src/ts/storage/database.svelte";
import CheckInput from "../UI/GUI/CheckInput.svelte";
import SelectInput from "../UI/GUI/SelectInput.svelte"; import SelectInput from "../UI/GUI/SelectInput.svelte";
import OptionInput from "../UI/GUI/OptionInput.svelte"; import OptionInput from "../UI/GUI/OptionInput.svelte";
import TextInput from "../UI/GUI/TextInput.svelte"; import TextInput from "../UI/GUI/TextInput.svelte";
@@ -16,16 +16,39 @@
let { chara = $bindable(), noContainer }: Props = $props(); let { chara = $bindable(), noContainer }: Props = $props();
let parsedKv = $derived(parseToggleSyntax(DBState.db.customPromptTemplateToggle + getModuleToggles())) let groupedToggles = $derived.by(() => {
const ungrouped = parseToggleSyntax(DBState.db.customPromptTemplateToggle + getModuleToggles())
let groupOpen = false
// group toggles together between group ... groupEnd
return ungrouped.reduce<sidebarToggle[]>((acc, toggle) => {
if (toggle.type === 'group') {
groupOpen = true
acc.push(toggle)
} else if (toggle.type === 'groupEnd') {
groupOpen = false
} else if (groupOpen) {
(acc.at(-1) as sidebarToggleGroup).children.push(toggle)
} else {
acc.push(toggle)
}
return acc
}, [])
})
</script> </script>
{#snippet toggles(reverse: boolean = false)} {#snippet toggles(items: sidebarToggle[], reverse: boolean = false)}
{#each parsedKv as toggle, index} {#each items as toggle, index}
{#if toggle.type === 'select'} {#if toggle.type === 'group' && toggle.children.length > 0}
<details class="mt-3 mb-1 w-full border border-darkborderc rounded">
<summary class="-m-px p-2 bg-darkbutton border border-darkborderc rounded text-xs cursor-pointer select-none hover:bg-selected transition-colors duration-190">{toggle.value}</summary>
<div class="flex flex-col px-2 py-4 pt-0">
{@render toggles((toggle as sidebarToggleGroup).children, reverse)}
</div>
</details>
{:else if toggle.type === 'select'}
<div class="flex gap-2 mt-2 items-center" class:flex-row-reverse={!reverse} class:justify-end={!reverse}> <div class="flex gap-2 mt-2 items-center" class:flex-row-reverse={!reverse} class:justify-end={!reverse}>
<span>{toggle.value}</span> <span>{toggle.value}</span>
<SelectInput className="w-32" bind:value={DBState.db.globalChatVariables[`toggle_${toggle.key}`]}> <SelectInput className="w-32" bind:value={DBState.db.globalChatVariables[`toggle_${toggle.key}`]}>
{#each toggle.options as option, i} {#each toggle.options as option, i}
<OptionInput value={i.toString()}>{option}</OptionInput> <OptionInput value={i.toString()}>{option}</OptionInput>
@@ -38,7 +61,7 @@
<TextInput className="w-32" bind:value={DBState.db.globalChatVariables[`toggle_${toggle.key}`]} /> <TextInput className="w-32" bind:value={DBState.db.globalChatVariables[`toggle_${toggle.key}`]} />
</div> </div>
{:else if toggle.type === 'divider'} {:else if toggle.type === 'divider'}
{@const prevToggle = parsedKv[index - 1]} {@const prevToggle = groupedToggles[index - 1]}
<!-- Prevent multiple dividers appearing in a row --> <!-- Prevent multiple dividers appearing in a row -->
{#if index === 0 || prevToggle.type !== 'divider' || prevToggle.value !== toggle.value} {#if index === 0 || prevToggle.type !== 'divider' || prevToggle.value !== toggle.value}
<div class="flex gap-2 mt-2 w-full min-h-5 items-center" class:flex-row-reverse={!reverse} class:justify-end={!reverse}> <div class="flex gap-2 mt-2 w-full min-h-5 items-center" class:flex-row-reverse={!reverse} class:justify-end={!reverse}>
@@ -58,12 +81,12 @@
{/each} {/each}
{/snippet} {/snippet}
{#if !noContainer && parsedKv.length > 4} {#if !noContainer && groupedToggles.length > 4}
<div class="h-48 border-darkborderc p-2 border rounded flex flex-col items-start mt-2 overflow-y-auto"> <div class="h-48 border-darkborderc p-2 border rounded flex flex-col items-start mt-2 overflow-y-auto">
<div class="flex mt-2 items-center w-full" class:justify-end={$MobileGUI}> <div class="flex mt-2 items-center w-full" class:justify-end={$MobileGUI}>
<CheckInput bind:check={DBState.db.jailbreakToggle} name={language.jailbreakToggle} reverse /> <CheckInput bind:check={DBState.db.jailbreakToggle} name={language.jailbreakToggle} reverse />
</div> </div>
{@render toggles(true)} {@render toggles(groupedToggles, true)}
{#if DBState.db.supaModelType !== 'none' || DBState.db.hanuraiEnable || DBState.db.hypaV3} {#if DBState.db.supaModelType !== 'none' || DBState.db.hanuraiEnable || DBState.db.hypaV3}
<div class="flex mt-2 items-center w-full" class:justify-end={$MobileGUI}> <div class="flex mt-2 items-center w-full" class:justify-end={$MobileGUI}>
<CheckInput bind:check={chara.supaMemory} reverse name={DBState.db.hypaV3 ? language.ToggleHypaMemory : DBState.db.hanuraiEnable ? language.hanuraiMemory : DBState.db.hypaMemory ? language.ToggleHypaMemory : language.ToggleSuperMemory}/> <CheckInput bind:check={chara.supaMemory} reverse name={DBState.db.hypaV3 ? language.ToggleHypaMemory : DBState.db.hanuraiEnable ? language.hanuraiMemory : DBState.db.hypaMemory ? language.ToggleHypaMemory : language.ToggleSuperMemory}/>
@@ -74,7 +97,7 @@
<div class="flex mt-2 items-center"> <div class="flex mt-2 items-center">
<CheckInput bind:check={DBState.db.jailbreakToggle} name={language.jailbreakToggle}/> <CheckInput bind:check={DBState.db.jailbreakToggle} name={language.jailbreakToggle}/>
</div> </div>
{@render toggles()} {@render toggles(groupedToggles)}
{#if DBState.db.supaModelType !== 'none' || DBState.db.hanuraiEnable || DBState.db.hypaV3} {#if DBState.db.supaModelType !== 'none' || DBState.db.hanuraiEnable || DBState.db.hypaV3}
<div class="flex mt-2 items-center"> <div class="flex mt-2 items-center">
<CheckInput bind:check={chara.supaMemory} name={DBState.db.hypaV3 ? language.ToggleHypaMemory : DBState.db.hanuraiEnable ? language.hanuraiMemory : DBState.db.hypaMemory ? language.ToggleHypaMemory : language.ToggleSuperMemory}/> <CheckInput bind:check={chara.supaMemory} name={DBState.db.hypaV3 ? language.ToggleHypaMemory : DBState.db.hanuraiEnable ? language.hanuraiMemory : DBState.db.hypaMemory ? language.ToggleHypaMemory : language.ToggleSuperMemory}/>

View File

@@ -1009,12 +1009,26 @@ export function parseKeyValue(template:string){
} }
} }
type sidebarToggle = export type sidebarToggleGroup = {
key?:string,
value?:string,
type:'group',
children:sidebarToggle[]
}
export type sidebarToggleGroupEnd = {
key?:string,
value?:string,
type:'groupEnd',
}
export type sidebarToggle =
| sidebarToggleGroup
| sidebarToggleGroupEnd
| { | {
key?:string, key?:string,
value?:string, value?:string,
type:'divider', type:'divider',
options?:string[]
} }
| { | {
key:string, key:string,
@@ -1025,7 +1039,7 @@ type sidebarToggle =
| { | {
key:string, key:string,
value:string, value:string,
type:string|undefined, type:'text'|undefined,
options?:string[] options?:string[]
} }
@@ -1041,11 +1055,18 @@ export function parseToggleSyntax(template:string){
for(const line of splited){ for(const line of splited){
const [key, value, type, option] = line.split('=') const [key, value, type, option] = line.split('=')
if((key && value) || type === 'divider'){ if(type === 'group' || type === 'groupEnd' || type === 'divider'){
keyValue.push({ keyValue.push({
key, key,
value, value,
type, type,
children: []
})
} else if((key && value)){
keyValue.push({
key,
value,
type: type === 'select' || type === 'text' ? type : undefined,
options: option?.split(',') ?? [] options: option?.split(',') ?? []
}) })
} }