Use modal for setting field change confirmations
This commit is contained in:
		
							parent
							
								
									f1dbf5d74d
								
							
						
					
					
						commit
						939d69fe46
					
				| 
						 | 
					@ -545,6 +545,7 @@
 | 
				
			||||||
        on:keydown={e => {
 | 
					        on:keydown={e => {
 | 
				
			||||||
          // Only send if Enter is pressed, not Shift+Enter
 | 
					          // Only send if Enter is pressed, not Shift+Enter
 | 
				
			||||||
          if (e.key === 'Enter' && !e.shiftKey) {
 | 
					          if (e.key === 'Enter' && !e.shiftKey) {
 | 
				
			||||||
 | 
					            e.stopPropagation()
 | 
				
			||||||
            submitForm()
 | 
					            submitForm()
 | 
				
			||||||
            e.preventDefault()
 | 
					            e.preventDefault()
 | 
				
			||||||
          }
 | 
					          }
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -143,6 +143,7 @@
 | 
				
			||||||
<svelte:window
 | 
					<svelte:window
 | 
				
			||||||
  on:keydown={(event) => {
 | 
					  on:keydown={(event) => {
 | 
				
			||||||
    if (event.key === 'Escape') {
 | 
					    if (event.key === 'Escape') {
 | 
				
			||||||
 | 
					      event.stopPropagation()
 | 
				
			||||||
      showChatMenu = false
 | 
					      showChatMenu = false
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
  }}
 | 
					  }}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -6,6 +6,8 @@
 | 
				
			||||||
  import { autoGrowInputOnEvent } from './Util.svelte'
 | 
					  import { autoGrowInputOnEvent } from './Util.svelte'
 | 
				
			||||||
  // import { replace } from 'svelte-spa-router'
 | 
					  // import { replace } from 'svelte-spa-router'
 | 
				
			||||||
  import Fa from 'svelte-fa/src/fa.svelte'
 | 
					  import Fa from 'svelte-fa/src/fa.svelte'
 | 
				
			||||||
 | 
					  import { openModal } from 'svelte-modals'
 | 
				
			||||||
 | 
					  import PromptConfirm from './PromptConfirm.svelte'
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  export let setting:ChatSetting
 | 
					  export let setting:ChatSetting
 | 
				
			||||||
  export let chatSettings:ChatSettings
 | 
					  export let chatSettings:ChatSettings
 | 
				
			||||||
| 
						 | 
					@ -32,7 +34,8 @@
 | 
				
			||||||
  const settingChecks:Record<string, SettingPrompt[]> = {
 | 
					  const settingChecks:Record<string, SettingPrompt[]> = {
 | 
				
			||||||
    profile: [
 | 
					    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) => {
 | 
					        checkPrompt: (setting, newVal, oldVal) => {
 | 
				
			||||||
          return !!chatSettings.isDirty && newVal !== oldVal
 | 
					          return !!chatSettings.isDirty && newVal !== oldVal
 | 
				
			||||||
        },
 | 
					        },
 | 
				
			||||||
| 
						 | 
					@ -113,31 +116,37 @@
 | 
				
			||||||
      const c = checks[i]
 | 
					      const c = checks[i]
 | 
				
			||||||
      if (c.passed) continue
 | 
					      if (c.passed) continue
 | 
				
			||||||
      if (c.checkPrompt(setting, newVal, val)) {
 | 
					      if (c.checkPrompt(setting, newVal, val)) {
 | 
				
			||||||
        // eventually this needs to be an async call to a confirmation modal where
 | 
					        openModal(PromptConfirm, {
 | 
				
			||||||
        // "passed", not really being used here, will be reworked to some other
 | 
					          title: c.title,
 | 
				
			||||||
        // state to deal with inevitable issues once a non-blocking modal is used.
 | 
					          message: c.message,
 | 
				
			||||||
        if (window.confirm(c.prompt)) {
 | 
					          class: c.class || 'is-warning',
 | 
				
			||||||
          c.passed = true
 | 
					          onConfirm: () => {
 | 
				
			||||||
          if (c.onYes && c.onYes(setting, newVal, val)) {
 | 
					            c.passed = true
 | 
				
			||||||
            resetSettingCheck(setting.key)
 | 
					            if (c.onYes && c.onYes(setting, newVal, val)) {
 | 
				
			||||||
            return
 | 
					              resetSettingCheck(setting.key)
 | 
				
			||||||
 | 
					            } 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()
 | 
				
			||||||
 | 
					            } else {
 | 
				
			||||||
 | 
					              queueSettingValueChange(event, setting)
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
          }
 | 
					          }
 | 
				
			||||||
        } else {
 | 
					        })
 | 
				
			||||||
          // roll-back
 | 
					 | 
				
			||||||
          if (!c.onNo || !c.onNo(setting, newVal, val)) {
 | 
					 | 
				
			||||||
            setChatSettingValue(chatId, setting, val)
 | 
					 | 
				
			||||||
            // refresh setting modal, if open
 | 
					 | 
				
			||||||
            c.onNo && c.onNo(setting, newVal, val)
 | 
					 | 
				
			||||||
            refreshSettings()
 | 
					 | 
				
			||||||
            resetSettingCheck(setting.key)
 | 
					 | 
				
			||||||
            return
 | 
					 | 
				
			||||||
          }
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
      } else {
 | 
					      } else {
 | 
				
			||||||
        c.passed = true
 | 
					        c.passed = true
 | 
				
			||||||
      }
 | 
					      }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    // passed all
 | 
					    // passed all?
 | 
				
			||||||
 | 
					    if (checks.find(c => !c.passed)) return
 | 
				
			||||||
    resetSettingCheck(setting.key)
 | 
					    resetSettingCheck(setting.key)
 | 
				
			||||||
    debounce = setTimeout(doSet, 250)
 | 
					    debounce = setTimeout(doSet, 250)
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -326,6 +326,7 @@
 | 
				
			||||||
<svelte:window
 | 
					<svelte:window
 | 
				
			||||||
  on:keydown={(event) => {
 | 
					  on:keydown={(event) => {
 | 
				
			||||||
    if (event.key === 'Escape') {
 | 
					    if (event.key === 'Escape') {
 | 
				
			||||||
 | 
					      event.stopPropagation()
 | 
				
			||||||
      closeSettings()
 | 
					      closeSettings()
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
  }}
 | 
					  }}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -68,6 +68,7 @@
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  const keydown = (event:KeyboardEvent) => {
 | 
					  const keydown = (event:KeyboardEvent) => {
 | 
				
			||||||
    if (event.key === 'Escape') {
 | 
					    if (event.key === 'Escape') {
 | 
				
			||||||
 | 
					      event.stopPropagation()
 | 
				
			||||||
      event.preventDefault()
 | 
					      event.preventDefault()
 | 
				
			||||||
      message.content = original
 | 
					      message.content = original
 | 
				
			||||||
      editing = false
 | 
					      editing = false
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -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()
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					  }}
 | 
				
			||||||
 | 
					/>
 | 
				
			||||||
| 
						 | 
					@ -100,7 +100,8 @@
 | 
				
			||||||
<svelte:window
 | 
					<svelte:window
 | 
				
			||||||
  on:keydown={(event) => {
 | 
					  on:keydown={(event) => {
 | 
				
			||||||
    if (event.key === 'Escape') {
 | 
					    if (event.key === 'Escape') {
 | 
				
			||||||
      closeModal()
 | 
					      event.stopPropagation()
 | 
				
			||||||
 | 
					      onClose()
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
  }}
 | 
					  }}
 | 
				
			||||||
/>
 | 
					/>
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -184,7 +184,9 @@ type SettingBoolean = {
 | 
				
			||||||
  } & (SettingNumber | SettingSelect | SettingBoolean | SettingText | SettingOther);
 | 
					  } & (SettingNumber | SettingSelect | SettingBoolean | SettingText | SettingOther);
 | 
				
			||||||
  
 | 
					  
 | 
				
			||||||
  export type SettingPrompt = {
 | 
					  export type SettingPrompt = {
 | 
				
			||||||
    prompt: string;
 | 
					    title: string;
 | 
				
			||||||
 | 
					    message: string;
 | 
				
			||||||
 | 
					    class?: string;
 | 
				
			||||||
    checkPrompt: (setting:ChatSetting, newVal:any, oldVal:any)=>boolean;
 | 
					    checkPrompt: (setting:ChatSetting, newVal:any, oldVal:any)=>boolean;
 | 
				
			||||||
    onYes?: (setting:ChatSetting, newVal:any, oldVal:any)=>boolean;
 | 
					    onYes?: (setting:ChatSetting, newVal:any, oldVal:any)=>boolean;
 | 
				
			||||||
    onNo?: (setting:ChatSetting, newVal:any, oldVal:any)=>boolean;
 | 
					    onNo?: (setting:ChatSetting, newVal:any, oldVal:any)=>boolean;
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
		Reference in New Issue