Begin testing new UI layout

This commit is contained in:
Webifi 2023-05-30 17:35:36 -05:00
parent 6b24d99022
commit df89356dc0
6 changed files with 207 additions and 77 deletions

View File

@ -10,13 +10,6 @@
import NewChat from './lib/NewChat.svelte' import NewChat from './lib/NewChat.svelte'
import { chatsStorage, apiKeyStorage } from './lib/Storage.svelte' import { chatsStorage, apiKeyStorage } from './lib/Storage.svelte'
// Check if the API key is passed in as a "key" query parameter - if so, save it
// Example: https://niek.github.io/chatgpt-web/#/?key=sk-...
const urlParams: URLSearchParams = new URLSearchParams($querystring)
if (urlParams.has('key')) {
apiKeyStorage.set(urlParams.get('key') as string)
}
// The definition of the routes with some conditions // The definition of the routes with some conditions
const routes = { const routes = {
'/': Home, '/': Home,
@ -37,11 +30,11 @@
'*': Home '*': Home
} }
document.body.classList.add('has-navbar-fixed-top') // document.body.classList.add('something')
</script> </script>
<Navbar /> <!-- <Navbar /> -->
<section class="section"> <section class="section">
<div class="container is-fullhd"> <div class="container is-fullhd">
<div class="columns"> <div class="columns">
@ -57,4 +50,4 @@
</div> </div>
</section> </section>
<Footer /> <!-- <Footer /> -->

View File

@ -17,25 +17,6 @@
section.section { section.section {
flex-grow: 1; flex-grow: 1;
} }
.chat-option-menu.navbar-item {
margin-left: auto;
}
/* temp. fix to keep navbar from getting huge on small screen devices
if the right menu is put in the proper navbar-end container */
.navbar-brand {
/* margin-right: 0; */
width: 100%;
}
.dropdown-item .menu-icon {
padding-right: .5em;
}
.dropdown-menu .dropdown-content {
max-height: calc(100vh - 60px);
overflow-y: auto;
}
} }
.is-disabled { .is-disabled {
@ -180,6 +161,27 @@ $modal-background-background-color-dark: rgba($dark, 0.86) !default; // remove t
} }
} }
/* Bulma layout hacks */
.chat-option-menu.navbar-item {
margin-left: auto;
}
/* temp. fix to keep navbar from getting huge on small screen devices
if the right menu is put in the proper navbar-end container */
.navbar-brand {
/* margin-right: 0; */
width: 100%;
}
.dropdown-item .menu-icon {
padding-right: .5em;
}
.dropdown-menu .dropdown-content {
max-height: calc(100vh - 60px);
overflow-y: auto;
}
.chat-menu-item { .chat-menu-item {
position: relative; position: relative;
} }
@ -195,3 +197,125 @@ $modal-background-background-color-dark: rgba($dark, 0.86) !default; // remove t
right: .4em; right: .4em;
z-index: 200; z-index: 200;
} }
/* Overrides for main layout */
section.section {
padding: 0px;
}
aside.menu.main-menu {
position: fixed;
width: 20%;
padding-right: 20px;
top: 0px;
bottom:0px;
}
aside.menu.main-menu .menu-expanse {
display: flex;
flex-flow: column;
height: 100%;
background-color: hsla(0, 0%, 60%, 0.208);
box-shadow: 5px 0px 1px hsla(0, 0%, 60%, 0.208);
}
.menu-expanse
.menu-label, .menu-expanse
.menu-list {
flex: 0 1 auto;
}
.menu-expanse
.menu-expansion-list {
flex: 1 1 auto;
overflow-y: auto;
}
.default-text {
color: hsl(0, 0%, 21%) !important;
}
html {
--scrollbarBG: $body-background-color;
--thumbBG: #999999;
}
.lower-mask {
display: block;
position: fixed;
bottom: 0px;
height: 100px;
width: 100%;
background-image: linear-gradient(180deg,hsla(0,0%,100%,0) 13.94%,#fff 54.73%);
}
@media (prefers-color-scheme: dark) {
html {
--thumbBG: #3f3f3f;
}
.default-text {
color: rgb(181, 181, 181) !important;
}
.lower-mask {
background-image: linear-gradient(180deg,hsla(0,0%,100%,0) 13.94%,#17181c 54.73%);
}
aside.menu.main-menu .menu-expanse {
background-color: hsla(0, 0%, 19%, 0.371);
box-shadow: 5px 0px 1px hsla(0, 0%, 19%, 0.371);
}
}
*::-webkit-scrollbar {
width: 11px;
}
*::-webkit-scrollbar-track {
background: var(--scrollbarBG);
}
*::-webkit-scrollbar-thumb {
background-color: var(--thumbBG) ;
border-radius: 6px;
border: 3px solid var(--scrollbarBG);
}
* {
scrollbar-width: thin;
scrollbar-color: var(--thumbBG) var(--scrollbarBG);
}
.chat-content {
padding-left: 20px;
padding-top: 40px;
padding-right: 40px;
padding-bottom: 120px;
}
.chat-focus-point {
width:100%;
height: 1px;
margin-bottom: -.75rem;;
}
.prompt-input-container {
position: fixed;
bottom: 0px;
width: 80%;
padding: 0px 40px 10px 40px;
}
.running-total-container {
min-height:2em;
// padding-bottom:.6em;
// /* padding-left: 1.9em; */
// margin-bottom:- 1em
}
.side-actions {
margin: 5px;
}
.main-menu .gpt-logo .icon {
display: inline-block;
margin-top: 8px;
margin-left: 8px;
}

View File

@ -481,6 +481,7 @@
</script> </script>
<div class="chat-content">
<nav class="level chat-header"> <nav class="level chat-header">
<div class="level-left"> <div class="level-left">
<div class="level-item"> <div class="level-item">
@ -515,7 +516,10 @@
{#if chat.messages.length === 0 || (chat.messages.length === 1 && chat.messages[0].role === 'system')} {#if chat.messages.length === 0 || (chat.messages.length === 1 && chat.messages[0].role === 'system')}
<Prompts bind:input /> <Prompts bind:input />
{/if} {/if}
</div>
<div class="lower-mask"/>
<div class="chat-focus-point"></div>
<div class="prompt-input-container">
<form class="field has-addons has-addons-right is-align-items-flex-end" on:submit|preventDefault={() => submitForm()}> <form class="field has-addons has-addons-right is-align-items-flex-end" on:submit|preventDefault={() => submitForm()}>
<p class="control is-expanded"> <p class="control is-expanded">
<textarea <textarea
@ -549,7 +553,7 @@
</p> </p>
</form> </form>
<!-- a target to scroll to --> <!-- a target to scroll to -->
<div class="chat-focus-point running-total-container"> <div class="running-total-container">
{#each Object.entries(chat.usage || {}) as [model, usage]} {#each Object.entries(chat.usage || {}) as [model, usage]}
<p class="is-size-7 running-totals"> <p class="is-size-7 running-totals">
<em>{model}</em> total <span class="has-text-weight-bold">{usage.total_tokens}</span> <em>{model}</em> total <span class="has-text-weight-bold">{usage.total_tokens}</span>
@ -557,6 +561,7 @@
</p> </p>
{/each} {/each}
</div> </div>
</div>
<ChatSettingsModal chatId={chatId} bind:show={showSettingsModal} /> <ChatSettingsModal chatId={chatId} bind:show={showSettingsModal} />
@ -600,12 +605,3 @@
} }
}} }}
/> />
<style>
.running-total-container {
min-height:2em;
padding-bottom:.6em;
/* padding-left: 1.9em; */
margin-bottom:-2.6em
}
</style>

View File

@ -4,7 +4,8 @@
faGear, faGear,
faTrash, faTrash,
faClone, faClone,
faEllipsisVertical, // faEllipsisVertical,
faEllipsis,
faDownload, faDownload,
faUpload, faUpload,
faEraser, faEraser,
@ -23,9 +24,10 @@
import { clickOutside } from 'svelte-use-click-outside' import { clickOutside } from 'svelte-use-click-outside'
export let chatId export let chatId
export const show = () => { export const show = (showHide:boolean = true) => {
showChatMenu = true showChatMenu = showHide
} }
export let style: string = 'is-right'
let showChatMenu = false let showChatMenu = false
let chatFileInput let chatFileInput
@ -74,13 +76,13 @@
</script> </script>
<div class="dropdown is-right" class:is-active={showChatMenu} use:clickOutside={() => { showChatMenu = false }}> <div class="dropdown {style}" class:is-active={showChatMenu} use:clickOutside={() => { showChatMenu = false }}>
<div class="dropdown-trigger"> <div class="dropdown-trigger">
<button class="button" aria-haspopup="true" <button class="button is-ghost default-text" aria-haspopup="true"
aria-controls="dropdown-menu3" aria-controls="dropdown-menu3"
on:click|preventDefault|stopPropagation={() => { showChatMenu = !showChatMenu }} on:click|preventDefault|stopPropagation={() => { showChatMenu = !showChatMenu }}
> >
<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">

View File

@ -4,6 +4,8 @@
import { apiKeyStorage, chatsStorage } from './Storage.svelte' import { apiKeyStorage, chatsStorage } from './Storage.svelte'
import Fa from 'svelte-fa/src/fa.svelte' import Fa from 'svelte-fa/src/fa.svelte'
import { faSquarePlus, faKey } from '@fortawesome/free-solid-svg-icons/index' import { faSquarePlus, faKey } from '@fortawesome/free-solid-svg-icons/index'
import ChatOptionMenu from './ChatOptionMenu.svelte';
import logo from '../assets/logo.svg'
$: sortedChats = $chatsStorage.sort((a, b) => b.id - a.id) $: sortedChats = $chatsStorage.sort((a, b) => b.id - a.id)
@ -11,9 +13,15 @@
</script> </script>
<aside class="menu"> <aside class="menu main-menu">
<p class="menu-label">Chats</p> <div class="menu-expanse">
<ul class="menu-list"> <div class="menu-label gpt-logo navbar-brand">
<a class="navbar-item" href={'#/'}>
<img src={logo} alt="ChatGPT-web" width="28" height="28" />
<p class="ml-2 is-size-4 has-text-weight-bold">ChatGPT-web</p>
</a>
</div>
<ul class="menu-list menu-expansion-list">
{#if sortedChats.length === 0} {#if sortedChats.length === 0}
<li><a href={'#'} class="is-disabled">No chats yet...</a></li> <li><a href={'#'} class="is-disabled">No chats yet...</a></li>
{:else} {:else}
@ -22,20 +30,27 @@
{/each} {/each}
{/if} {/if}
</ul> </ul>
<p class="menu-label">Actions</p> <!-- <p class="menu-label">Actions</p> -->
<ul class="menu-list"> <ul class="menu-list">
{#if !$apiKeyStorage} {#if !$apiKeyStorage}
<li> <li>
<a href={'#/'} class="panel-block" class:is-disabled={!$apiKeyStorage} class:is-active={!activeChatId} <a href={'#/'} class="panel-block" class:is-disabled={!$apiKeyStorage} class:is-active={!activeChatId}
><span class="greyscale mr-2"><Fa icon={faKey} /></span> API key</a ><span class="icon"><Fa icon={faKey} /></span> API key</a
> >
</li> </li>
{:else} {:else}
<li> <li>
<div class="level-right side-actions">
<div class="level-item">
<a href={'#/chat/new'} class="panel-block" class:is-disabled={!$apiKeyStorage} <a href={'#/chat/new'} class="panel-block" class:is-disabled={!$apiKeyStorage}
><span class="greyscale mr-2"><Fa icon={faSquarePlus} /></span> New chat</a ><span class="greyscale mr-2"><Fa icon={faSquarePlus} /></span> New chat</a
> ></div>
<div class="level-item">
<ChatOptionMenu bind:chatId={activeChatId} style="is-right is-up" />
</div>
</div>
</li> </li>
{/if} {/if}
</ul> </ul>
</div>
</aside> </aside>

View File

@ -5,9 +5,9 @@
// Reference: https://openai.com/pricing#language-models // Reference: https://openai.com/pricing#language-models
// TODO: Move to settings of some type // TODO: Move to settings of some type
const modelDetails : Record<string, [number, number, number]> = { const modelDetails : Record<string, [number, number, number]> = {
'gpt-4-32k': [0.00006, 0.00012, 32768], // $0.06 per 1000 tokens prompt, $0.12 per 1000 tokens completion, max tokens 'gpt-4-32k': [0.00006, 0.00012, 32768], // $0.06 per 1000 tokens prompt, $0.12 per 1000 tokens completion, max 32k
'gpt-4': [0.00003, 0.00006, 8192], // $0.03 per 1000 tokens prompt, $0.06 per 1000 tokens completion 'gpt-4': [0.00003, 0.00006, 8192], // $0.03 per 1000 tokens prompt, $0.06 per 1000 tokens completion, max 8k
'gpt-3.5': [0.000002, 0.000002, 4096] // $0.002 per 1000 tokens (both prompt and completion) 'gpt-3.5': [0.000002, 0.000002, 4096] // $0.002 per 1000 tokens (both prompt and completion), max 4k
} }
const tpCache = {} const tpCache = {}