diff options
Diffstat (limited to 'g4f/gui/client')
-rw-r--r-- | g4f/gui/client/index.html | 51 | ||||
-rw-r--r-- | g4f/gui/client/static/css/style.css | 5 | ||||
-rw-r--r-- | g4f/gui/client/static/js/chat.v1.js | 52 | ||||
-rw-r--r-- | g4f/gui/client/static/js/highlightjs-copy.min.js | 55 |
4 files changed, 127 insertions, 36 deletions
diff --git a/g4f/gui/client/index.html b/g4f/gui/client/index.html index 1a660062..7e8ef09c 100644 --- a/g4f/gui/client/index.html +++ b/g4f/gui/client/index.html @@ -224,28 +224,35 @@ </div> </div> <div class="buttons"> - <div class="field"> - <select name="model" id="model"> - <option value="">Model: Default</option> - <option value="gpt-4">gpt-4</option> - <option value="gpt-3.5-turbo">gpt-3.5-turbo</option> - <option value="llama-3-70b-chat">llama-3-70b-chat</option> - <option value="llama-3.1-70b">llama-3.1-70b</option> - <option value="gemini-pro">gemini-pro</option> - <option value="">----</option> - </select> - <select name="model2" id="model2" class="hidden"></select> - </div> - <div class="field"> - <select name="provider" id="provider"> - <option value="">Provider: Auto</option> - <option value="Bing">Bing</option> - <option value="OpenaiChat">OpenAI ChatGPT</option> - <option value="Gemini">Gemini</option> - <option value="Liaobots">Liaobots</option> - <option value="MetaAI">Meta AI</option> - <option value="You">You</option> - <option value="">----</option> + <div class="field"> + <select name="model" id="model"> + <option value="">Model: Default</option> + <option value="gpt-4">gpt-4</option> + <option value="gpt-4o">gpt-4o</option> + <option value="gpt-4o-mini">gpt-4o-mini</option> + <option value="llama-3.1-70b">llama-3.1-70b</option> + <option value="llama-3.1-70b">llama-3.1-405b</option> + <option value="llama-3.1-70b">mixtral-8x7b</option> + <option value="gemini-pro">gemini-pro</option> + <option value="gemini-flash">gemini-flash</option> + <option value="claude-3-haiku">claude-3-haiku</option> + <option value="claude-3.5-sonnet">claude-3.5-sonnet</option> + <option value="">----</option> + </select> + <select name="model2" id="model2" class="hidden"></select> + </div> + <div class="field"> + <select name="provider" id="provider"> + <option value="">Provider: Auto</option> + <option value="OpenaiChat">OpenAI ChatGPT</option> + <option value="Gemini">Gemini</option> + <option value="MetaAI">Meta AI</option> + <option value="DeepInfraChat">DeepInfraChat</option> + <option value="Blackbox">Blackbox</option> + <option value="HuggingChat">HuggingChat</option> + <option value="DDG">DDG</option> + <option value="Pizzagpt">Pizzagpt</option> + <option value="">----</option> </select> </div> </div> diff --git a/g4f/gui/client/static/css/style.css b/g4f/gui/client/static/css/style.css index f3a4708d..441e2042 100644 --- a/g4f/gui/client/static/css/style.css +++ b/g4f/gui/client/static/css/style.css @@ -87,12 +87,9 @@ body { } body { - padding: 10px; background: var(--colour-1); color: var(--colour-3); height: 100vh; - max-width: 1600px; - margin: auto; } .row { @@ -1146,4 +1143,4 @@ a:-webkit-any-link { .message.regenerate { opacity: 1; } -}
\ No newline at end of file +} diff --git a/g4f/gui/client/static/js/chat.v1.js b/g4f/gui/client/static/js/chat.v1.js index 9790b261..42ddb129 100644 --- a/g4f/gui/client/static/js/chat.v1.js +++ b/g4f/gui/client/static/js/chat.v1.js @@ -57,6 +57,25 @@ function filter_message(text) { ) } +function fallback_clipboard (text) { + var textBox = document.createElement("textarea"); + textBox.value = text; + textBox.style.top = "0"; + textBox.style.left = "0"; + textBox.style.position = "fixed"; + document.body.appendChild(textBox); + textBox.focus(); + textBox.select(); + try { + var success = document.execCommand('copy'); + var msg = success ? 'succeeded' : 'failed'; + console.log('Clipboard Fallback: Copying text command ' + msg); + } catch (e) { + console.error('Clipboard Fallback: Unable to copy', e); + } + document.body.removeChild(textBox); +} + hljs.addPlugin(new CopyButtonPlugin()); let typesetPromise = Promise.resolve(); const highlight = (container) => { @@ -88,18 +107,31 @@ const register_message_buttons = async () => { }) } }); + document.querySelectorAll(".message .fa-clipboard").forEach(async (el) => { if (!("click" in el.dataset)) { el.dataset.click = "true"; el.addEventListener("click", async () => { const message_el = el.parentElement.parentElement.parentElement; const copyText = await get_message(window.conversation_id, message_el.dataset.index); - navigator.clipboard.writeText(copyText); + + try { + if (!navigator.clipboard) { + throw new Error("navigator.clipboard: Clipboard API unavailable."); + } + await navigator.clipboard.writeText(copyText); + } catch (e) { + console.error(e); + console.error("Clipboard API writeText() failed! Fallback to document.exec(\"copy\")..."); + fallback_clipboard(copyText); + } + el.classList.add("clicked"); setTimeout(() => el.classList.remove("clicked"), 1000); }) } }); + document.querySelectorAll(".message .fa-volume-high").forEach(async (el) => { if (!("click" in el.dataset)) { el.dataset.click = "true"; @@ -306,6 +338,14 @@ const prepare_messages = (messages, message_index = -1) => { messages = messages.filter((_, index) => message_index >= index); } + let new_messages = []; + if (systemPrompt?.value) { + new_messages.push({ + "role": "system", + "content": systemPrompt.value + }); + } + // Remove history, if it's selected if (document.getElementById('history')?.checked) { if (message_index == null) { @@ -315,13 +355,6 @@ const prepare_messages = (messages, message_index = -1) => { } } - let new_messages = []; - if (systemPrompt?.value) { - new_messages.push({ - "role": "system", - "content": systemPrompt.value - }); - } messages.forEach((new_message) => { // Include only not regenerated messages if (new_message && !new_message.regenerate) { @@ -334,6 +367,7 @@ const prepare_messages = (messages, message_index = -1) => { return new_messages; } + async function add_message_chunk(message) { if (message.type == "conversation") { console.info("Conversation used:", message.conversation) @@ -1424,4 +1458,4 @@ if (SpeechRecognition) { recognition.start(); } }); -}
\ No newline at end of file +} diff --git a/g4f/gui/client/static/js/highlightjs-copy.min.js b/g4f/gui/client/static/js/highlightjs-copy.min.js index ac11d33e..cd8ae957 100644 --- a/g4f/gui/client/static/js/highlightjs-copy.min.js +++ b/g4f/gui/client/static/js/highlightjs-copy.min.js @@ -1 +1,54 @@ -class CopyButtonPlugin{constructor(options={}){self.hook=options.hook;self.callback=options.callback}"after:highlightElement"({el,text}){let button=Object.assign(document.createElement("button"),{innerHTML:"Copy",className:"hljs-copy-button"});button.dataset.copied=false;el.parentElement.classList.add("hljs-copy-wrapper");el.parentElement.appendChild(button);el.parentElement.style.setProperty("--hljs-theme-background",window.getComputedStyle(el).backgroundColor);button.onclick=function(){if(!navigator.clipboard)return;let newText=text;if(hook&&typeof hook==="function"){newText=hook(text,el)||text}navigator.clipboard.writeText(newText).then(function(){button.innerHTML="Copied!";button.dataset.copied=true;let alert=Object.assign(document.createElement("div"),{role:"status",className:"hljs-copy-alert",innerHTML:"Copied to clipboard"});el.parentElement.appendChild(alert);setTimeout(()=>{button.innerHTML="Copy";button.dataset.copied=false;el.parentElement.removeChild(alert);alert=null},2e3)}).then(function(){if(typeof callback==="function")return callback(newText,el)})}}}
\ No newline at end of file +class CopyButtonPlugin { + constructor(options = {}) { + self.hook = options.hook; + self.callback = options.callback + } + "after:highlightElement"({ + el, + text + }) { + let button = Object.assign(document.createElement("button"), { + innerHTML: "Copy", + className: "hljs-copy-button" + }); + button.dataset.copied = false; + el.parentElement.classList.add("hljs-copy-wrapper"); + el.parentElement.appendChild(button); + el.parentElement.style.setProperty("--hljs-theme-background", window.getComputedStyle(el).backgroundColor); + button.onclick = async () => { + let newText = text; + if (hook && typeof hook === "function") { + newText = hook(text, el) || text + } + try { + if (!navigator.clipboard) { + throw new Error("navigator.clipboard: Clipboard API unavailable."); + } + await navigator.clipboard.writeText(newText); + } catch (e) { + console.error(e); + console.error("Clipboard API writeText() failed! Fallback to document.exec(\"copy\")..."); + fallback_clipboard(newText); + } + button.innerHTML = "Copied!"; + button.dataset.copied = true; + let alert = Object.assign(document.createElement("div"), { + role: "status", + className: "hljs-copy-alert", + innerHTML: "Copied to clipboard" + }); + el.parentElement.appendChild(alert); + setTimeout(() => { + button.innerHTML = "Copy"; + button.dataset.copied = false; + el.parentElement.removeChild(alert); + alert = null + }, 2e3) + } + + + if (typeof callback === "function") return callback(newText, el); + + } + +} |