Use modal for setting field change confirmations

This commit is contained in:
Webifi 2023-06-05 08:51:40 -05:00
parent f1dbf5d74d
commit 939d69fe46
8 changed files with 109 additions and 23 deletions

View File

@ -545,6 +545,7 @@
on:keydown={e => {
// Only send if Enter is pressed, not Shift+Enter
if (e.key === 'Enter' && !e.shiftKey) {
e.stopPropagation()
submitForm()
e.preventDefault()
}

View File

@ -143,6 +143,7 @@
<svelte:window
on:keydown={(event) => {
if (event.key === 'Escape') {
event.stopPropagation()
showChatMenu = false
}
}}

View File

@ -6,6 +6,8 @@
import { autoGrowInputOnEvent } from './Util.svelte'
// import { replace } from 'svelte-spa-router'
import Fa from 'svelte-fa/src/fa.svelte'
import { openModal } from 'svelte-modals'
import PromptConfirm from './PromptConfirm.svelte'
export let setting:ChatSetting
export let chatSettings:ChatSettings
@ -32,7 +34,8 @@
const settingChecks:Record<string, SettingPrompt[]> = {
profile: [
{
prompt: 'Unsaved changes to the current profile will be lost.\n Continue?',
title: 'Unsaved Profile Changes',
message: 'Unsaved changes to the current profile will be lost.\n Continue?',
checkPrompt: (setting, newVal, oldVal) => {
return !!chatSettings.isDirty && newVal !== oldVal
},
@ -113,31 +116,37 @@
const c = checks[i]
if (c.passed) continue
if (c.checkPrompt(setting, newVal, val)) {
// eventually this needs to be an async call to a confirmation modal where
// "passed", not really being used here, will be reworked to some other
// state to deal with inevitable issues once a non-blocking modal is used.
if (window.confirm(c.prompt)) {
openModal(PromptConfirm, {
title: c.title,
message: c.message,
class: c.class || 'is-warning',
onConfirm: () => {
c.passed = true
if (c.onYes && c.onYes(setting, newVal, val)) {
resetSettingCheck(setting.key)
return
}
} else {
queueSettingValueChange(event, setting)
}
},
onCancel: () => {
// roll-back
if (!c.onNo || !c.onNo(setting, newVal, val)) {
resetSettingCheck(setting.key)
setChatSettingValue(chatId, setting, val)
// refresh setting modal, if open
c.onNo && c.onNo(setting, newVal, val)
refreshSettings()
resetSettingCheck(setting.key)
return
} else {
queueSettingValueChange(event, setting)
}
}
})
} else {
c.passed = true
}
}
// passed all
// passed all?
if (checks.find(c => !c.passed)) return
resetSettingCheck(setting.key)
debounce = setTimeout(doSet, 250)
}

View File

@ -326,6 +326,7 @@
<svelte:window
on:keydown={(event) => {
if (event.key === 'Escape') {
event.stopPropagation()
closeSettings()
}
}}

View File

@ -68,6 +68,7 @@
const keydown = (event:KeyboardEvent) => {
if (event.key === 'Escape') {
event.stopPropagation()
event.preventDefault()
message.content = original
editing = false

View File

@ -0,0 +1,70 @@
<script lang="ts">
import { closeModal } from 'svelte-modals'
export let isOpen:boolean
export let title:string
export let message:string
export let asHtml:boolean = false
export let onConfirm:()=>boolean|void
export let onCancel:()=>boolean|void
export let confirmButton:string = 'Okay'
export let confirmButtonClass:string = 'is-info'
export let cancelButton:string = 'Cancel'
export let cancelButtonClass:string = ''
let classes:string = ''
export { classes as class }
const doCancel = () => {
if (!onCancel || !onCancel()) closeModal()
}
const doConfirm = () => {
onConfirm()
closeModal()
}
</script>
{#if isOpen}
<div class="modal is-active">
<!-- svelte-ignore a11y-click-events-have-key-events -->
<div class="modal-background" on:click={doCancel} />
<div class="modal-content nomax">
<article class="message {classes}">
<div class="message-header">
<p>{title}</p>
<button class="delete" aria-label="close" type="button" on:click={doCancel}></button>
</div>
<div class="message-body">
{#if asHtml}{@html message}{:else}{message}{/if}
</div>
<div class="message-footer">
<div class="level is-mobile">
<div class="level-right">
</div>
<div class="level-right">
<div class="level-item">
<button class="button {confirmButtonClass}" type="button" on:click={doConfirm} >{confirmButton}</button>
</div>
<div class="level-item">
<button class="button {cancelButtonClass}" type="button" on:click={doCancel} >{cancelButton}</button>
</div>
</div>
</div>
</div>
</article>
</div>
</div>
{/if}
<svelte:window
on:keydown={(event) => {
if (event.key === 'Escape') {
event.stopPropagation()
doCancel()
}
}}
/>

View File

@ -100,7 +100,8 @@
<svelte:window
on:keydown={(event) => {
if (event.key === 'Escape') {
closeModal()
event.stopPropagation()
onClose()
}
}}
/>

View File

@ -184,7 +184,9 @@ type SettingBoolean = {
} & (SettingNumber | SettingSelect | SettingBoolean | SettingText | SettingOther);
export type SettingPrompt = {
prompt: string;
title: string;
message: string;
class?: string;
checkPrompt: (setting:ChatSetting, newVal:any, oldVal:any)=>boolean;
onYes?: (setting:ChatSetting, newVal:any, oldVal:any)=>boolean;
onNo?: (setting:ChatSetting, newVal:any, oldVal:any)=>boolean;