Move setting fields into separate component
This commit is contained in:
parent
aba16cdf4b
commit
b396bb818d
|
@ -0,0 +1,146 @@
|
||||||
|
<script lang="ts">
|
||||||
|
import { createEventDispatcher } from 'svelte'
|
||||||
|
import { getProfile } from "./lib/Profiles.svelte"
|
||||||
|
import { setChatSettingValue } from "./lib/Storage.svelte"
|
||||||
|
import type { Chat, ChatSetting, ChatSettings } from "./lib/Types.svelte"
|
||||||
|
import { autoGrowInputOnEvent } from "./lib/Util.svelte"
|
||||||
|
|
||||||
|
export let setting:ChatSetting
|
||||||
|
export let chatSettings:ChatSettings
|
||||||
|
export let chat:Chat
|
||||||
|
export let chatDefaults:Record<string, any>
|
||||||
|
|
||||||
|
const chatId = chat.id
|
||||||
|
|
||||||
|
const dispatch = createEventDispatcher()
|
||||||
|
|
||||||
|
const refreshSettings = () => {
|
||||||
|
dispatch('refresh')
|
||||||
|
}
|
||||||
|
|
||||||
|
let debounce:any
|
||||||
|
|
||||||
|
const queueSettingValueChange = (event: Event, setting: ChatSetting) => {
|
||||||
|
clearTimeout(debounce)
|
||||||
|
if (event.target === null) return
|
||||||
|
const val = chatSettings[setting.key]
|
||||||
|
const el = (event.target as HTMLInputElement)
|
||||||
|
const doSet = () => {
|
||||||
|
try {
|
||||||
|
(typeof setting.beforeChange === 'function') && setting.beforeChange(chatId, setting, el.checked || el.value) &&
|
||||||
|
refreshSettings()
|
||||||
|
} catch (e) {
|
||||||
|
window.alert('Unable to change:\n' + e.message)
|
||||||
|
}
|
||||||
|
switch (setting.type) {
|
||||||
|
case 'boolean':
|
||||||
|
setChatSettingValue(chatId, setting, el.checked)
|
||||||
|
refreshSettings()
|
||||||
|
break
|
||||||
|
default:
|
||||||
|
setChatSettingValue(chatId, setting, el.value)
|
||||||
|
}
|
||||||
|
const newVal = chatSettings[setting.key]
|
||||||
|
if (val === newVal) return
|
||||||
|
try {
|
||||||
|
(typeof setting.afterChange === 'function') && setting.afterChange(chatId, setting, chatSettings[setting.key]) &&
|
||||||
|
refreshSettings()
|
||||||
|
} catch (e) {
|
||||||
|
setChatSettingValue(chatId, setting, val)
|
||||||
|
window.alert('Unable to change:\n' + e.message)
|
||||||
|
}
|
||||||
|
dispatch('change', setting)
|
||||||
|
}
|
||||||
|
if (setting.key === 'profile' && chat.sessionStarted &&
|
||||||
|
(getProfile(el.value).characterName !== chatSettings.characterName)) {
|
||||||
|
const val = chatSettings[setting.key]
|
||||||
|
if (window.confirm('Personality change will not correctly apply to existing chat session.\n Continue?')) {
|
||||||
|
doSet()
|
||||||
|
} else {
|
||||||
|
// roll-back
|
||||||
|
setChatSettingValue(chatId, setting, val)
|
||||||
|
// refresh setting modal, if open
|
||||||
|
refreshSettings()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
debounce = setTimeout(doSet, 250)
|
||||||
|
}
|
||||||
|
|
||||||
|
</script>
|
||||||
|
|
||||||
|
{#if (typeof setting.hide !== 'function') || !setting.hide(chatId)}
|
||||||
|
{#if setting.header}
|
||||||
|
<p class="notification {setting.headerClass}">
|
||||||
|
{@html setting.header}
|
||||||
|
</p>
|
||||||
|
{/if}
|
||||||
|
<div class="field is-horizontal">
|
||||||
|
{#if setting.type === 'boolean'}
|
||||||
|
<div class="field is-normal">
|
||||||
|
<label class="label" for="settings-{setting.key}" title="{setting.title}">
|
||||||
|
<input
|
||||||
|
type="checkbox"
|
||||||
|
title="{setting.title}"
|
||||||
|
class="checkbox"
|
||||||
|
id="settings-{setting.key}"
|
||||||
|
checked={!!chatSettings[setting.key]}
|
||||||
|
on:click={e => queueSettingValueChange(e, setting)}
|
||||||
|
>
|
||||||
|
{setting.name}
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
|
{:else if setting.type === 'textarea'}
|
||||||
|
<div class="field is-normal" style="width:100%">
|
||||||
|
<label class="label" for="settings-{setting.key}" title="{setting.title}">{setting.name}</label>
|
||||||
|
<textarea
|
||||||
|
class="input is-info is-focused chat-input auto-size"
|
||||||
|
placeholder={setting.placeholder || ''}
|
||||||
|
rows="1"
|
||||||
|
on:input={e => autoGrowInputOnEvent(e)}
|
||||||
|
on:change={e => { queueSettingValueChange(e, setting); autoGrowInputOnEvent(e) }}
|
||||||
|
>{chatSettings[setting.key]}</textarea>
|
||||||
|
</div>
|
||||||
|
{:else}
|
||||||
|
<div class="field-label is-normal">
|
||||||
|
<label class="label" for="settings-{setting.key}" title="{setting.title}">{setting.name}</label>
|
||||||
|
</div>
|
||||||
|
{/if}
|
||||||
|
<div class="field-body">
|
||||||
|
<div class="field">
|
||||||
|
{#if setting.type === 'number'}
|
||||||
|
<input
|
||||||
|
class="input"
|
||||||
|
inputmode="decimal"
|
||||||
|
type={setting.type}
|
||||||
|
title="{setting.title}"
|
||||||
|
id="settings-{setting.key}"
|
||||||
|
value={chatSettings[setting.key]}
|
||||||
|
min={setting.min}
|
||||||
|
max={setting.max}
|
||||||
|
step={setting.step}
|
||||||
|
placeholder={String(setting.placeholder)}
|
||||||
|
on:change={e => queueSettingValueChange(e, setting)}
|
||||||
|
/>
|
||||||
|
{:else if setting.type === 'select'}
|
||||||
|
<div class="select">
|
||||||
|
<select id="settings-{setting.key}" title="{setting.title}" on:change={e => queueSettingValueChange(e, setting) } >
|
||||||
|
{#each setting.options as option}
|
||||||
|
<option class:is-default={option.value === chatDefaults[setting.key]} value={option.value} selected={option.value === chatSettings[setting.key]}>{option.text}</option>
|
||||||
|
{/each}
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
{:else if setting.type === 'text'}
|
||||||
|
<div class="field">
|
||||||
|
<input
|
||||||
|
type="text"
|
||||||
|
title="{setting.title}"
|
||||||
|
class="input"
|
||||||
|
value={chatSettings[setting.key]}
|
||||||
|
on:change={e => { queueSettingValueChange(e, setting) }}
|
||||||
|
>
|
||||||
|
</div>
|
||||||
|
{/if}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{/if}
|
|
@ -27,6 +27,7 @@
|
||||||
} from '@fortawesome/free-solid-svg-icons/index'
|
} from '@fortawesome/free-solid-svg-icons/index'
|
||||||
import { exportProfileAsJSON } from './Export.svelte'
|
import { exportProfileAsJSON } from './Export.svelte'
|
||||||
import { afterUpdate } from 'svelte'
|
import { afterUpdate } from 'svelte'
|
||||||
|
import ChatSettingField from '../ChatSettingField.svelte';
|
||||||
|
|
||||||
export let chatId:number
|
export let chatId:number
|
||||||
export const show = () => { showSettings() }
|
export const show = () => { showSettings() }
|
||||||
|
@ -167,51 +168,6 @@
|
||||||
setTimeout(() => sizeTextElements(), 0)
|
setTimeout(() => sizeTextElements(), 0)
|
||||||
}
|
}
|
||||||
|
|
||||||
const debounce = {}
|
|
||||||
|
|
||||||
const queueSettingValueChange = (event: Event, setting: ChatSetting) => {
|
|
||||||
clearTimeout(debounce[setting.key])
|
|
||||||
if (event.target === null) return
|
|
||||||
const val = chatSettings[setting.key]
|
|
||||||
const el = (event.target as HTMLInputElement)
|
|
||||||
const doSet = () => {
|
|
||||||
try {
|
|
||||||
(typeof setting.beforeChange === 'function') && setting.beforeChange(chatId, setting, el.checked || el.value) &&
|
|
||||||
refreshSettings()
|
|
||||||
} catch (e) {
|
|
||||||
window.alert('Unable to change:\n' + e.message)
|
|
||||||
}
|
|
||||||
switch (setting.type) {
|
|
||||||
case 'boolean':
|
|
||||||
setChatSettingValue(chatId, setting, el.checked)
|
|
||||||
refreshSettings()
|
|
||||||
break
|
|
||||||
default:
|
|
||||||
setChatSettingValue(chatId, setting, el.value)
|
|
||||||
}
|
|
||||||
try {
|
|
||||||
(typeof setting.afterChange === 'function') && setting.afterChange(chatId, setting, chatSettings[setting.key]) &&
|
|
||||||
refreshSettings()
|
|
||||||
} catch (e) {
|
|
||||||
setChatSettingValue(chatId, setting, val)
|
|
||||||
window.alert('Unable to change:\n' + e.message)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (setting.key === 'profile' && chat.sessionStarted &&
|
|
||||||
(getProfile(el.value).characterName !== chatSettings.characterName)) {
|
|
||||||
const val = chatSettings[setting.key]
|
|
||||||
if (window.confirm('Personality change will not correctly apply to existing chat session.\n Continue?')) {
|
|
||||||
doSet()
|
|
||||||
} else {
|
|
||||||
// roll-back
|
|
||||||
setChatSettingValue(chatId, setting, val)
|
|
||||||
// refresh setting modal, if open
|
|
||||||
showSettingsModal && showSettingsModal++
|
|
||||||
}
|
|
||||||
}
|
|
||||||
debounce[setting.key] = setTimeout(doSet, 250)
|
|
||||||
}
|
|
||||||
|
|
||||||
const saveProfile = () => {
|
const saveProfile = () => {
|
||||||
showProfileMenu = false
|
showProfileMenu = false
|
||||||
try {
|
try {
|
||||||
|
@ -285,82 +241,7 @@
|
||||||
<!-- Below are the settings that OpenAI allows to be changed for the API calls. See the <a href="https://platform.openai.com/docs/api-reference/chat/create">OpenAI API docs</a> for more details.</p> -->
|
<!-- Below are the settings that OpenAI allows to be changed for the API calls. See the <a href="https://platform.openai.com/docs/api-reference/chat/create">OpenAI API docs</a> for more details.</p> -->
|
||||||
{#key showSettingsModal}
|
{#key showSettingsModal}
|
||||||
{#each settingsList as setting}
|
{#each settingsList as setting}
|
||||||
{#if (typeof setting.hide !== 'function') || !setting.hide(chatId)}
|
<ChatSettingField on:refresh={refreshSettings} chat={chat} chatDefaults={chatDefaults} chatSettings={chatSettings} setting={setting} />
|
||||||
{#if setting.header}
|
|
||||||
<p class="notification {setting.headerClass}">
|
|
||||||
{@html setting.header}
|
|
||||||
</p>
|
|
||||||
{/if}
|
|
||||||
<div class="field is-horizontal">
|
|
||||||
{#if setting.type === 'boolean'}
|
|
||||||
<div class="field is-normal">
|
|
||||||
<label class="label" for="settings-{setting.key}" title="{setting.title}">
|
|
||||||
<input
|
|
||||||
type="checkbox"
|
|
||||||
title="{setting.title}"
|
|
||||||
class="checkbox"
|
|
||||||
id="settings-{setting.key}"
|
|
||||||
checked={!!chatSettings[setting.key]}
|
|
||||||
on:click={e => queueSettingValueChange(e, setting)}
|
|
||||||
>
|
|
||||||
{setting.name}
|
|
||||||
</label>
|
|
||||||
</div>
|
|
||||||
{:else if setting.type === 'textarea'}
|
|
||||||
<div class="field is-normal" style="width:100%">
|
|
||||||
<label class="label" for="settings-{setting.key}" title="{setting.title}">{setting.name}</label>
|
|
||||||
<textarea
|
|
||||||
class="input is-info is-focused chat-input auto-size"
|
|
||||||
placeholder={setting.placeholder || ''}
|
|
||||||
rows="1"
|
|
||||||
on:input={e => autoGrowInputOnEvent(e)}
|
|
||||||
on:change={e => { queueSettingValueChange(e, setting); autoGrowInputOnEvent(e) }}
|
|
||||||
>{chatSettings[setting.key]}</textarea>
|
|
||||||
</div>
|
|
||||||
{:else}
|
|
||||||
<div class="field-label is-normal">
|
|
||||||
<label class="label" for="settings-{setting.key}" title="{setting.title}">{setting.name}</label>
|
|
||||||
</div>
|
|
||||||
{/if}
|
|
||||||
<div class="field-body">
|
|
||||||
<div class="field">
|
|
||||||
{#if setting.type === 'number'}
|
|
||||||
<input
|
|
||||||
class="input"
|
|
||||||
inputmode="decimal"
|
|
||||||
type={setting.type}
|
|
||||||
title="{setting.title}"
|
|
||||||
id="settings-{setting.key}"
|
|
||||||
value={chatSettings[setting.key]}
|
|
||||||
min={setting.min}
|
|
||||||
max={setting.max}
|
|
||||||
step={setting.step}
|
|
||||||
placeholder={String(setting.placeholder)}
|
|
||||||
on:change={e => queueSettingValueChange(e, setting)}
|
|
||||||
/>
|
|
||||||
{:else if setting.type === 'select'}
|
|
||||||
<div class="select">
|
|
||||||
<select id="settings-{setting.key}" title="{setting.title}" on:change={e => queueSettingValueChange(e, setting) } >
|
|
||||||
{#each setting.options as option}
|
|
||||||
<option class:is-default={option.value === chatDefaults[setting.key]} value={option.value} selected={option.value === chatSettings[setting.key]}>{option.text}</option>
|
|
||||||
{/each}
|
|
||||||
</select>
|
|
||||||
</div>
|
|
||||||
{:else if setting.type === 'text'}
|
|
||||||
<div class="field">
|
|
||||||
<input
|
|
||||||
type="text"
|
|
||||||
title="{setting.title}"
|
|
||||||
class="input"
|
|
||||||
value={chatSettings[setting.key]}
|
|
||||||
on:change={e => { queueSettingValueChange(e, setting) }}
|
|
||||||
>
|
|
||||||
</div>
|
|
||||||
{/if}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
{/if}
|
|
||||||
{/each}
|
{/each}
|
||||||
{/key}
|
{/key}
|
||||||
</section>
|
</section>
|
||||||
|
|
Loading…
Reference in New Issue