Clean up UI for settings modal, better for mobile.
This commit is contained in:
		
							parent
							
								
									43f52e1fd1
								
							
						
					
					
						commit
						a38ce6d702
					
				
							
								
								
									
										27
									
								
								src/app.scss
								
								
								
								
							
							
						
						
									
										27
									
								
								src/app.scss
								
								
								
								
							| 
						 | 
					@ -157,9 +157,9 @@ html {
 | 
				
			||||||
  resize: vertical;
 | 
					  resize: vertical;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
$footer-padding: 1.5rem 1.5rem;
 | 
					// $footer-padding: 1.5rem 1.5rem;
 | 
				
			||||||
$fullhd: 2000px;
 | 
					// $fullhd: 2000px;
 | 
				
			||||||
$modal-content-width: 1000px;
 | 
					// $modal-content-width: 1000px;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@import "/node_modules/bulma/bulma.sass";
 | 
					@import "/node_modules/bulma/bulma.sass";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -277,6 +277,12 @@ $modal-background-background-color-dark: rgba($dark, 0.86) !default; // remove t
 | 
				
			||||||
  max-height: calc(100vh - 60px);
 | 
					  max-height: calc(100vh - 60px);
 | 
				
			||||||
  overflow-y: auto;
 | 
					  overflow-y: auto;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					.modal-card .dropdown-menu .dropdown-content {
 | 
				
			||||||
 | 
					  max-height: calc(100vh - 80px);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					.modal-card {
 | 
				
			||||||
 | 
					  overflow: visible;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@media only screen and (max-width: 768px) {
 | 
					@media only screen and (max-width: 768px) {
 | 
				
			||||||
  .main-menu .dropdown-menu .dropdown-content {
 | 
					  .main-menu .dropdown-menu .dropdown-content {
 | 
				
			||||||
| 
						 | 
					@ -594,3 +600,18 @@ aside.menu.main-menu .menu-expanse {
 | 
				
			||||||
  border-top-left-radius: 0px !important;
 | 
					  border-top-left-radius: 0px !important;
 | 
				
			||||||
  border-bottom-left-radius: 0px !important;
 | 
					  border-bottom-left-radius: 0px !important;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					.modal-card footer {
 | 
				
			||||||
 | 
					  justify-content: space-between;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					.modal-card footer .level {
 | 
				
			||||||
 | 
					  width: 100%;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					.modal-card header, .modal-card footer, .modal-card .notification {
 | 
				
			||||||
 | 
					  padding: .8em;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					.modal-card .notification {
 | 
				
			||||||
 | 
					  margin-left: -.5em;
 | 
				
			||||||
 | 
					  margin-right: -.5em;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
| 
						 | 
					@ -24,13 +24,13 @@
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
  
 | 
					  
 | 
				
			||||||
  const settingChecks:Record<string, SettingPrompt[]> = {
 | 
					  const settingChecks:Record<string, SettingPrompt[]> = {
 | 
				
			||||||
    'profile': [
 | 
					    profile: [
 | 
				
			||||||
      {
 | 
					      {
 | 
				
			||||||
        prompt: 'Unsaved changes to the current profile will be lost.\n Continue?',
 | 
					        prompt: 'Unsaved changes to the current profile will be lost.\n Continue?',
 | 
				
			||||||
        fn: (setting, newVal, oldVal) => {
 | 
					        fn: (setting, newVal, oldVal) => {
 | 
				
			||||||
          return !!chatSettings.isDirty && newVal !== oldVal
 | 
					          return !!chatSettings.isDirty && newVal !== oldVal
 | 
				
			||||||
        },
 | 
					        },
 | 
				
			||||||
        passed: false,
 | 
					        passed: false
 | 
				
			||||||
      },
 | 
					      },
 | 
				
			||||||
      {
 | 
					      {
 | 
				
			||||||
        prompt: 'Personality change will not correctly apply to existing chat session.\n Continue?',
 | 
					        prompt: 'Personality change will not correctly apply to existing chat session.\n Continue?',
 | 
				
			||||||
| 
						 | 
					@ -38,8 +38,8 @@
 | 
				
			||||||
          return chat.sessionStarted && newVal !== originalProfile &&
 | 
					          return chat.sessionStarted && newVal !== originalProfile &&
 | 
				
			||||||
            (getProfile(newVal).characterName !== chatSettings.characterName)
 | 
					            (getProfile(newVal).characterName !== chatSettings.characterName)
 | 
				
			||||||
        },
 | 
					        },
 | 
				
			||||||
        passed: false,
 | 
					        passed: false
 | 
				
			||||||
      },
 | 
					      }
 | 
				
			||||||
    ]
 | 
					    ]
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -77,7 +77,6 @@
 | 
				
			||||||
          console.log('Refreshed from setting', setting.key, chatSettings[setting.key], val)
 | 
					          console.log('Refreshed from setting', setting.key, chatSettings[setting.key], val)
 | 
				
			||||||
          refreshSettings()
 | 
					          refreshSettings()
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
          
 | 
					 | 
				
			||||||
      } catch (e) {
 | 
					      } catch (e) {
 | 
				
			||||||
        setChatSettingValue(chatId, setting, val)
 | 
					        setChatSettingValue(chatId, setting, val)
 | 
				
			||||||
        window.alert('Unable to change:\n' + e.message)
 | 
					        window.alert('Unable to change:\n' + e.message)
 | 
				
			||||||
| 
						 | 
					@ -87,7 +86,7 @@
 | 
				
			||||||
    const checks = settingChecks[setting.key] || []
 | 
					    const checks = settingChecks[setting.key] || []
 | 
				
			||||||
    const newVal = cleanSettingValue(setting.type, el.checked || el.value)
 | 
					    const newVal = cleanSettingValue(setting.type, el.checked || el.value)
 | 
				
			||||||
    for (let i = 0, l = checks.length; i < l; i++) {
 | 
					    for (let i = 0, l = checks.length; i < l; i++) {
 | 
				
			||||||
      let c = checks[i]
 | 
					      const c = checks[i]
 | 
				
			||||||
      if (c.passed) continue
 | 
					      if (c.passed) continue
 | 
				
			||||||
      if (c.fn(setting, newVal, val)) {
 | 
					      if (c.fn(setting, newVal, val)) {
 | 
				
			||||||
        // eventually this needs to be an async call to a confirmation modal where
 | 
					        // eventually this needs to be an async call to a confirmation modal where
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -18,7 +18,7 @@
 | 
				
			||||||
  import {
 | 
					  import {
 | 
				
			||||||
    faTrash,
 | 
					    faTrash,
 | 
				
			||||||
    faClone,
 | 
					    faClone,
 | 
				
			||||||
    faEllipsisVertical,
 | 
					    faEllipsis,
 | 
				
			||||||
    faFloppyDisk,
 | 
					    faFloppyDisk,
 | 
				
			||||||
    faThumbtack,
 | 
					    faThumbtack,
 | 
				
			||||||
    faDownload,
 | 
					    faDownload,
 | 
				
			||||||
| 
						 | 
					@ -27,7 +27,7 @@
 | 
				
			||||||
  import { exportProfileAsJSON } from './Export.svelte'
 | 
					  import { exportProfileAsJSON } from './Export.svelte'
 | 
				
			||||||
  import { afterUpdate } from 'svelte'
 | 
					  import { afterUpdate } from 'svelte'
 | 
				
			||||||
  import ChatSettingField from './ChatSettingField.svelte'
 | 
					  import ChatSettingField from './ChatSettingField.svelte'
 | 
				
			||||||
    import { getModelMaxTokens } from './Stats.svelte';
 | 
					  import { getModelMaxTokens } from './Stats.svelte'
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  export let chatId:number
 | 
					  export let chatId:number
 | 
				
			||||||
  export const show = () => { showSettings() }
 | 
					  export const show = () => { showSettings() }
 | 
				
			||||||
| 
						 | 
					@ -50,7 +50,7 @@
 | 
				
			||||||
  $: chatSettings = chat.settings
 | 
					  $: chatSettings = chat.settings
 | 
				
			||||||
  $: globalStore = $globalStorage
 | 
					  $: globalStore = $globalStorage
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  let originalProfile = chatSettings && chatSettings.profile
 | 
					  const originalProfile = chatSettings && chatSettings.profile
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  afterUpdate(() => {
 | 
					  afterUpdate(() => {
 | 
				
			||||||
    sizeTextElements()
 | 
					    sizeTextElements()
 | 
				
			||||||
| 
						 | 
					@ -64,7 +64,7 @@
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  const clearSettings = () => {
 | 
					  const clearSettings = () => {
 | 
				
			||||||
    resetChatSettings(chatId)
 | 
					    resetChatSettings(chatId)
 | 
				
			||||||
    showSettingsModal++ // Make sure the dialog updates
 | 
					    refreshSettings()
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  const refreshSettings = async () => {
 | 
					  const refreshSettings = async () => {
 | 
				
			||||||
| 
						 | 
					@ -204,10 +204,12 @@
 | 
				
			||||||
  // excludeFromProfile
 | 
					  // excludeFromProfile
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  const deepEqual = (x:any, y:any) => {
 | 
					  const deepEqual = (x:any, y:any) => {
 | 
				
			||||||
    const ok = Object.keys, tx = typeof x, ty = typeof y
 | 
					    const ok = Object.keys; const tx = typeof x; const ty = typeof y
 | 
				
			||||||
    return x && y && tx === 'object' && tx === ty ? (
 | 
					    return x && y && tx === 'object' && tx === ty
 | 
				
			||||||
 | 
					      ? (
 | 
				
			||||||
          ok(x).every(key => excludeFromProfile[key] || deepEqual(x[key], y[key]))
 | 
					          ok(x).every(key => excludeFromProfile[key] || deepEqual(x[key], y[key]))
 | 
				
			||||||
    ) : (x === y || ((x===undefined||x===null||x===false) && (y===undefined||y===null||y===false)))
 | 
					        )
 | 
				
			||||||
 | 
					      : (x === y || ((x === undefined || x === null || x === false) && (y === undefined || y === null || y === false)))
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  const setDirty = (e:CustomEvent|undefined = undefined) => {
 | 
					  const setDirty = (e:CustomEvent|undefined = undefined) => {
 | 
				
			||||||
| 
						 | 
					@ -228,10 +230,28 @@
 | 
				
			||||||
  <div class="modal-card" on:click={() => { showProfileMenu = false }}>
 | 
					  <div class="modal-card" on:click={() => { showProfileMenu = false }}>
 | 
				
			||||||
    <header class="modal-card-head">
 | 
					    <header class="modal-card-head">
 | 
				
			||||||
      <p class="modal-card-title">Chat Settings</p>
 | 
					      <p class="modal-card-title">Chat Settings</p>
 | 
				
			||||||
      <div class="dropdown is-right" class:is-active={showProfileMenu}>
 | 
					      <button class="delete" aria-label="close" on:click={closeSettings}></button>
 | 
				
			||||||
 | 
					    </header>
 | 
				
			||||||
 | 
					    <section class="modal-card-body">
 | 
				
			||||||
 | 
					      {#key showSettingsModal}
 | 
				
			||||||
 | 
					      {#each settingsList as setting}
 | 
				
			||||||
 | 
					        <ChatSettingField on:refresh={refreshSettings} on:change={setDirty} chat={chat} chatDefaults={chatDefaults} chatSettings={chatSettings} setting={setting} originalProfile={originalProfile} />
 | 
				
			||||||
 | 
					      {/each}
 | 
				
			||||||
 | 
					      {/key}
 | 
				
			||||||
 | 
					    </section>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    <footer class="modal-card-foot">
 | 
				
			||||||
 | 
					      <div class="level is-mobile">
 | 
				
			||||||
 | 
					        <div class="level-left">
 | 
				
			||||||
 | 
					          <!-- <button class="button is-info" on:click={closeSettings}>Close</button> -->
 | 
				
			||||||
 | 
					          <button class="button" class:is-disabled={!chatSettings.isDirty} on:click={saveProfile}>Save Changes</button>    
 | 
				
			||||||
 | 
					          <button class="button is-warning" class:is-disabled={!chatSettings.isDirty} on:click={clearSettings}>Reset</button>
 | 
				
			||||||
 | 
					        </div>
 | 
				
			||||||
 | 
					        <div class="level-right">
 | 
				
			||||||
 | 
					          <div class="dropdown is-right is-up" class:is-active={showProfileMenu}>
 | 
				
			||||||
            <div class="dropdown-trigger">
 | 
					            <div class="dropdown-trigger">
 | 
				
			||||||
              <button class="button" aria-haspopup="true" aria-controls="dropdown-menu3" on:click|preventDefault|stopPropagation={() => { showProfileMenu = !showProfileMenu }}>
 | 
					              <button class="button" aria-haspopup="true" aria-controls="dropdown-menu3" on:click|preventDefault|stopPropagation={() => { showProfileMenu = !showProfileMenu }}>
 | 
				
			||||||
            <span><Fa icon={faEllipsisVertical}/></span>
 | 
					                <span class="icon"><Fa icon={faEllipsis}/></span>
 | 
				
			||||||
              </button>
 | 
					              </button>
 | 
				
			||||||
            </div>
 | 
					            </div>
 | 
				
			||||||
            <div class="dropdown-menu" id="dropdown-menu3" role="menu">
 | 
					            <div class="dropdown-menu" id="dropdown-menu3" role="menu">
 | 
				
			||||||
| 
						 | 
					@ -263,19 +283,8 @@
 | 
				
			||||||
              </div>
 | 
					              </div>
 | 
				
			||||||
            </div>
 | 
					            </div>
 | 
				
			||||||
          </div>
 | 
					          </div>
 | 
				
			||||||
    </header>
 | 
					        </div>
 | 
				
			||||||
    <section class="modal-card-body">
 | 
					      </div>  
 | 
				
			||||||
      {#key showSettingsModal}
 | 
					 | 
				
			||||||
      {#each settingsList as setting}
 | 
					 | 
				
			||||||
        <ChatSettingField on:refresh={refreshSettings} on:change={setDirty} chat={chat} chatDefaults={chatDefaults} chatSettings={chatSettings} setting={setting} originalProfile={originalProfile} />
 | 
					 | 
				
			||||||
      {/each}
 | 
					 | 
				
			||||||
      {/key}
 | 
					 | 
				
			||||||
    </section>
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    <footer class="modal-card-foot">
 | 
					 | 
				
			||||||
      <button class="button is-info" on:click={closeSettings}>Close</button>
 | 
					 | 
				
			||||||
      <button class="button is-warning" on:click={clearSettings}>Reset</button>
 | 
					 | 
				
			||||||
      <button class="button" class:is-disabled={!chatSettings.isDirty} on:click={saveProfile}>Save Changes</button>
 | 
					 | 
				
			||||||
    </footer>
 | 
					    </footer>
 | 
				
			||||||
  </div>
 | 
					  </div>
 | 
				
			||||||
</div>
 | 
					</div>
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -100,8 +100,6 @@ export const restartProfile = (chatId:number, noApply:boolean=false) => {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// Apply currently selected profile
 | 
					// Apply currently selected profile
 | 
				
			||||||
export const applyProfile = (chatId:number, key:string = '', resetChat:boolean = false) => {
 | 
					export const applyProfile = (chatId:number, key:string = '', resetChat:boolean = false) => {
 | 
				
			||||||
  const settings = getChatSettings(chatId)
 | 
					 | 
				
			||||||
  const profile = getProfile(key || settings.profile)
 | 
					 | 
				
			||||||
  resetChatSettings(chatId, resetChat) // Fully reset
 | 
					  resetChatSettings(chatId, resetChat) // Fully reset
 | 
				
			||||||
  if (!resetChat) return
 | 
					  if (!resetChat) return
 | 
				
			||||||
  return restartProfile(chatId, true)
 | 
					  return restartProfile(chatId, true)
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1,6 +1,6 @@
 | 
				
			||||||
<script context="module" lang="ts">
 | 
					<script context="module" lang="ts">
 | 
				
			||||||
    import { applyProfile } from './Profiles.svelte'
 | 
					    import { applyProfile } from './Profiles.svelte'
 | 
				
			||||||
    import { getChat, getChatSettings } from './Storage.svelte'
 | 
					    import { getChatSettings } from './Storage.svelte'
 | 
				
			||||||
    import { encode } from 'gpt-tokenizer'
 | 
					    import { encode } from 'gpt-tokenizer'
 | 
				
			||||||
// Setting definitions
 | 
					// Setting definitions
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -62,7 +62,7 @@ const gptDefaults = {
 | 
				
			||||||
  presence_penalty: 0,
 | 
					  presence_penalty: 0,
 | 
				
			||||||
  frequency_penalty: 0,
 | 
					  frequency_penalty: 0,
 | 
				
			||||||
  logit_bias: null,
 | 
					  logit_bias: null,
 | 
				
			||||||
  user: undefined,
 | 
					  user: undefined
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// Core set of defaults
 | 
					// Core set of defaults
 | 
				
			||||||
| 
						 | 
					@ -82,13 +82,13 @@ const defaults:ChatSettings = {
 | 
				
			||||||
  systemPrompt: '',
 | 
					  systemPrompt: '',
 | 
				
			||||||
  autoStartSession: false,
 | 
					  autoStartSession: false,
 | 
				
			||||||
  trainingPrompts: [],
 | 
					  trainingPrompts: [],
 | 
				
			||||||
  isDirty: false,
 | 
					  isDirty: false
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
const excludeFromProfile = {
 | 
					const excludeFromProfile = {
 | 
				
			||||||
  messages: true,
 | 
					  messages: true,
 | 
				
			||||||
  user: true,
 | 
					  user: true,
 | 
				
			||||||
  isDirty: true,
 | 
					  isDirty: true
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
const profileSetting: ChatSetting & SettingSelect = {
 | 
					const profileSetting: ChatSetting & SettingSelect = {
 | 
				
			||||||
| 
						 | 
					@ -103,7 +103,7 @@ const profileSetting: ChatSetting & SettingSelect = {
 | 
				
			||||||
        applyProfile(chatId)
 | 
					        applyProfile(chatId)
 | 
				
			||||||
        return true // Signal we should refresh the setting modal
 | 
					        return true // Signal we should refresh the setting modal
 | 
				
			||||||
      },
 | 
					      },
 | 
				
			||||||
      setDefault: (chatId, setting, value) => {},
 | 
					      setDefault: (chatId, setting, value) => {}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// Settings that will not be part of the API request
 | 
					// Settings that will not be part of the API request
 | 
				
			||||||
| 
						 | 
					@ -229,7 +229,7 @@ const modelSetting: ChatSetting & SettingSelect = {
 | 
				
			||||||
      options: [],
 | 
					      options: [],
 | 
				
			||||||
      type: 'select',
 | 
					      type: 'select',
 | 
				
			||||||
      forceApi: true, // Need to make sure we send this
 | 
					      forceApi: true, // Need to make sure we send this
 | 
				
			||||||
      afterChange: (chatId, setting) => true, // refresh settings
 | 
					      afterChange: (chatId, setting) => true // refresh settings
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
const chatSettingsList: ChatSetting[] = [
 | 
					const chatSettingsList: ChatSetting[] = [
 | 
				
			||||||
| 
						 | 
					@ -276,7 +276,7 @@ const chatSettingsList: ChatSetting[] = [
 | 
				
			||||||
        max: 32768,
 | 
					        max: 32768,
 | 
				
			||||||
        step: 1,
 | 
					        step: 1,
 | 
				
			||||||
        type: 'number',
 | 
					        type: 'number',
 | 
				
			||||||
        forceApi: true, // Since default here is different than gpt default, will make sure we always send it
 | 
					        forceApi: true // Since default here is different than gpt default, will make sure we always send it
 | 
				
			||||||
      },
 | 
					      },
 | 
				
			||||||
      {
 | 
					      {
 | 
				
			||||||
        key: 'presence_penalty',
 | 
					        key: 'presence_penalty',
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
		Reference in New Issue