Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion docs/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ Your web application, titled **"Unity Chat U1 6.6"**, provides an interactive ch
- **Speech Recognition:** Users can dictate messages through voice input, which captures speech and translates it into textual inputs in real-time.

- **Message Handling:**
- **Markdown Support:** AI-generated responses utilize Markdown, enhanced with syntax highlighting (via highlight.js) for clarity in code snippets.
- **Markdown Support:** AI-generated responses utilize Markdown with highlight.js, offering syntax highlighting for over 100 languages and automatically adapting to the active site theme.
- **Image Embedding:** Automatically embeds images generated by Pollinations based on AI conversation content.
- **Editing and Regeneration:** Users can edit their messages or regenerate AI responses conveniently from within the chat interface.

Expand Down
3 changes: 2 additions & 1 deletion index.html
Original file line number Diff line number Diff line change
Expand Up @@ -468,7 +468,8 @@ <h3 class="modal-title">Voice Chat</h3>
</script>
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0-alpha1/dist/js/bootstrap.bundle.min.js" defer></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.9.0/highlight.min.js" defer></script>
<script defer src="js/ui/screensaver.js"></script>
<script defer src="js/ui/highlight.js"></script>
<script defer src="js/ui/screensaver.js"></script>
<script defer src="js/storage/storage.js"></script>
<script defer src="js/storage/memory-api.js"></script>

Expand Down
16 changes: 6 additions & 10 deletions js/chat/chat-init.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,10 +13,6 @@ document.addEventListener("DOMContentLoaded", () => {
if (newTitle && newTitle !== currentSession.name) Storage.renameSession(currentSession.id, newTitle);
}
};
const highlightAllCodeBlocks = () => {
if (!window.hljs) return;
chatBox.querySelectorAll("pre code").forEach(block => hljs.highlightElement(block));
};
const appendMessage = ({ role, content, index, imageUrls = [], audioUrls = [] }) => {
const container = document.createElement("div");
container.classList.add("message");
Expand Down Expand Up @@ -116,8 +112,8 @@ document.addEventListener("DOMContentLoaded", () => {
block.parentNode.insertAdjacentElement("afterend", buttonContainer);
});
chatBox.appendChild(container);
chatBox.scrollTop = chatBox.scrollHeight;
highlightAllCodeBlocks();
chatBox.scrollTop = chatBox.scrollHeight;
window.highlightUtils?.highlightAllCodeBlocks(chatBox);
};
const downloadCodeAsTxt = (codeContent, language) => {
const blob = new Blob([codeContent], { type: "text/plain" });
Expand Down Expand Up @@ -394,7 +390,7 @@ document.addEventListener("DOMContentLoaded", () => {
}
}
});
highlightAllCodeBlocks();
window.highlightUtils?.highlightAllCodeBlocks(chatBox);
};
window.addNewMessage = ({ role, content, imageUrls = [], audioUrls = [] }) => {
const currentSession = Storage.getCurrentSession();
Expand Down Expand Up @@ -439,14 +435,14 @@ document.addEventListener("DOMContentLoaded", () => {
chatBox.scrollTop = chatBox.scrollHeight;
sendToPolliLib(() => {
loadingDiv.remove();
highlightAllCodeBlocks();
window.highlightUtils?.highlightAllCodeBlocks(chatBox);
}, newContent);
showToast("User message updated and new response generated");
} else {
currentSession.messages[msgIndex].content = newContent;
Storage.updateSessionMessages(currentSession.id, currentSession.messages);
renderStoredMessages(currentSession.messages);
highlightAllCodeBlocks();
window.highlightUtils?.highlightAllCodeBlocks(chatBox);
showToast("AI message updated");
}
};
Expand Down Expand Up @@ -484,7 +480,7 @@ document.addEventListener("DOMContentLoaded", () => {
console.log(`Sending re-generate request for user message: ${userMessage} (with unique suffix: ${uniqueUserMessage})`);
window.sendToPolliLib(() => {
loadingDiv.remove();
highlightAllCodeBlocks();
window.highlightUtils?.highlightAllCodeBlocks(chatBox);
checkAndUpdateSessionTitle();
showToast("Response regenerated successfully");
}, uniqueUserMessage);
Expand Down
41 changes: 16 additions & 25 deletions js/chat/chat-storage.js
Original file line number Diff line number Diff line change
Expand Up @@ -25,15 +25,6 @@ document.addEventListener("DOMContentLoaded", () => {
}
}
}
function highlightAllCodeBlocks() {
if (!window.hljs) {
return;
}
const codeBlocks = chatBox.querySelectorAll("pre code");
codeBlocks.forEach((block) => {
hljs.highlightElement(block);
});
}
function appendMessage({ role, content, index, imageUrls = [], audioUrls = [] }) {
const container = document.createElement("div");
container.classList.add("message");
Expand Down Expand Up @@ -147,9 +138,9 @@ document.addEventListener("DOMContentLoaded", () => {
buttonContainer.appendChild(downloadCodeBtn);
block.parentNode.insertAdjacentElement("afterend", buttonContainer);
});
chatBox.appendChild(container);
chatBox.scrollTop = chatBox.scrollHeight;
highlightAllCodeBlocks();
chatBox.appendChild(container);
chatBox.scrollTop = chatBox.scrollHeight;
window.highlightUtils?.highlightAllCodeBlocks(chatBox);
}
function downloadCodeAsTxt(codeContent, language) {
const blob = new Blob([codeContent], { type: "text/plain" });
Expand Down Expand Up @@ -400,7 +391,7 @@ document.addEventListener("DOMContentLoaded", () => {
audioUrls: storedAudio
});
});
highlightAllCodeBlocks();
window.highlightUtils?.highlightAllCodeBlocks(chatBox);
chatInput.disabled = false;
chatInput.focus();
}
Expand Down Expand Up @@ -450,18 +441,18 @@ document.addEventListener("DOMContentLoaded", () => {
chatBox.scrollTop = chatBox.scrollHeight;
window.sendToPolliLib(() => {
loadingDiv.remove();
highlightAllCodeBlocks();
window.highlightUtils?.highlightAllCodeBlocks(chatBox);
}, newContent);
showToast("User message updated and new response generated");
} else {
currentSession.messages[msgIndex].content = newContent;
Storage.updateSessionMessages(currentSession.id, currentSession.messages);
renderStoredMessages(currentSession.messages);
highlightAllCodeBlocks();
showToast("AI message updated");
}
}
function reGenerateAIResponse(aiIndex) {
window.highlightUtils?.highlightAllCodeBlocks(chatBox);
showToast("AI message updated");
}
}
function reGenerateAIResponse(aiIndex) {
console.log(`Re-generating AI response for index: ${aiIndex}`);
const currentSession = Storage.getCurrentSession();
if (aiIndex < 0 || aiIndex >= currentSession.messages.length || currentSession.messages[aiIndex].role !== "ai") {
Expand Down Expand Up @@ -496,12 +487,12 @@ document.addEventListener("DOMContentLoaded", () => {
chatBox.scrollTop = chatBox.scrollHeight;
const uniqueUserMessage = `${userMessage} [regen-${Date.now()}-${Math.random().toString(36).substring(2)}]`;
console.log(`Sending re-generate request for user message: ${userMessage} (with unique suffix: ${uniqueUserMessage})`);
window.sendToPolliLib(() => {
loadingDiv.remove();
highlightAllCodeBlocks();
showToast("Response regenerated successfully");
}, uniqueUserMessage);
}
window.sendToPolliLib(() => {
loadingDiv.remove();
window.highlightUtils?.highlightAllCodeBlocks(chatBox);
showToast("Response regenerated successfully");
}, uniqueUserMessage);
}

if (voiceToggleBtn) {
voiceToggleBtn.addEventListener("click", window._chatInternals.toggleAutoSpeak);
Expand Down
49 changes: 49 additions & 0 deletions js/ui/highlight.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
(function() {
const HLJS_BASE = "https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.9.0/styles/";

const hljsThemeMap = {
light: "github",
dark: "github-dark",
hacker: "a11y-dark",
oled: "atom-one-dark",
"subtle-light": "atom-one-light",
burple: "atom-one-dark",
"pretty-pink": "github",
nord: "nord",
"solarized-light": "solarized-light",
"solarized-dark": "solarized-dark",
"gruvbox-light": "gruvbox-light",
"gruvbox-dark": "gruvbox-dark",
cyberpunk: "atom-one-dark",
dracula: "dracula",
monokai: "monokai",
"material-dark": "atom-one-dark",
"material-light": "atom-one-light",
"pastel-dream": "github",
"ocean-breeze": "github",
"vintage-paper": "github",
honeycomb: "github",
"rainbow-throwup": "github",
serenity: "atom-one-light"
};

let hljsThemeLink = document.getElementById("hljs-theme-link");
if (!hljsThemeLink) {
hljsThemeLink = document.createElement("link");
hljsThemeLink.id = "hljs-theme-link";
hljsThemeLink.rel = "stylesheet";
document.head.appendChild(hljsThemeLink);
}

function updateHighlightTheme(themeValue) {
const hlTheme = hljsThemeMap[themeValue] || "github-dark";
hljsThemeLink.href = `${HLJS_BASE}${hlTheme}.min.css`;
}

function highlightAllCodeBlocks(container = document) {
if (!window.hljs) return;
container.querySelectorAll("pre code").forEach(block => hljs.highlightElement(block));
}

window.highlightUtils = { updateHighlightTheme, highlightAllCodeBlocks };
})();
43 changes: 2 additions & 41 deletions js/ui/ui.js
Original file line number Diff line number Diff line change
Expand Up @@ -38,13 +38,6 @@ document.addEventListener("DOMContentLoaded", () => {
themeLinkElement.rel = "stylesheet";
document.head.appendChild(themeLinkElement);
}
let hljsThemeLink = document.getElementById("hljs-theme-link");
if (!hljsThemeLink) {
hljsThemeLink = document.createElement("link");
hljsThemeLink.id = "hljs-theme-link";
hljsThemeLink.rel = "stylesheet";
document.head.appendChild(hljsThemeLink);
}

const allThemes = [
{ value: "light", label: "Light", file: "themes/light.css" },
Expand Down Expand Up @@ -72,38 +65,6 @@ document.addEventListener("DOMContentLoaded", () => {
{ value: "serenity", label: "Serenity", file: "themes/serenity.css" }
];

const hljsThemeMap = {
light: "github",
dark: "github-dark",
hacker: "a11y-dark",
oled: "atom-one-dark",
"subtle-light": "atom-one-light",
burple: "atom-one-dark",
"pretty-pink": "github",
nord: "nord",
"solarized-light": "solarized-light",
"solarized-dark": "solarized-dark",
"gruvbox-light": "gruvbox-light",
"gruvbox-dark": "gruvbox-dark",
cyberpunk: "atom-one-dark",
dracula: "dracula",
monokai: "monokai",
"material-dark": "atom-one-dark",
"material-light": "atom-one-light",
"pastel-dream": "github",
"ocean-breeze": "github",
"vintage-paper": "github",
honeycomb: "github",
"rainbow-throwup": "github",
serenity: "atom-one-light"
};

const HLJS_BASE = "https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.9.0/styles/";

function updateHighlightTheme(themeValue) {
const hlTheme = hljsThemeMap[themeValue] || "github-dark";
hljsThemeLink.href = `${HLJS_BASE}${hlTheme}.min.css`;
}

function populateThemeDropdowns() {
themeSelect.innerHTML = "";
Expand All @@ -130,7 +91,7 @@ document.addEventListener("DOMContentLoaded", () => {
themeSelectSettings.value = savedTheme;
const found = allThemes.find(t => t.value === savedTheme);
themeLinkElement.href = found ? found.file : "themes/dark.css";
updateHighlightTheme(savedTheme);
window.highlightUtils?.updateHighlightTheme(savedTheme);
}
loadUserTheme();

Expand All @@ -140,7 +101,7 @@ document.addEventListener("DOMContentLoaded", () => {
themeSelectSettings.value = newThemeValue;
const found = allThemes.find(t => t.value === newThemeValue);
themeLinkElement.href = found ? found.file : "";
updateHighlightTheme(newThemeValue);
window.highlightUtils?.updateHighlightTheme(newThemeValue);
}

themeSelect.addEventListener("change", () => {
Expand Down