diff --git a/config.json b/config.json index 6b612ec..503e709 100644 --- a/config.json +++ b/config.json @@ -1,8 +1,7 @@ { "server": { "ipAddress": "192.168.1.222", - "port": 8080, - "messageMaxAge": 259200 + "port": 8080 }, "paths": { "databasePath": "/home/radon/Documents/chattest.db", @@ -10,5 +9,9 @@ "indexCssPath": "./content/root.css", "indexHtmlPath": "./content/root.html", "messagesHtmlPath": "./content/messages.html" + }, + "options": { + "messageMaxAge": 259200, + "nameMaxLength": 32 } } diff --git a/content/root.css b/content/root.css index ef70451..59e0667 100644 --- a/content/root.css +++ b/content/root.css @@ -255,14 +255,14 @@ body { gap: 10px; } -.youtube-embed { +.video-embed { position: inline; padding-top: 10px; width: 100%; max-width: 560px; /* Standard YouTube width */ } -.youtube-embed iframe { +.video-embed iframe { border-radius: 4px; } diff --git a/content/root.js b/content/root.js index fae05d3..bfb0cf0 100644 --- a/content/root.js +++ b/content/root.js @@ -39,9 +39,7 @@ async function deleteMessage(messageId) { }); if (response.ok) { - // Refresh messages - console.log("Message deleted successfully"); - location.reload(); + updateMessagesInPlace(); } else { console.error("Failed to delete message"); } @@ -51,6 +49,22 @@ async function deleteMessage(messageId) { } } +async function updateMessagesInPlace() { + const currenteScrollLocation = getScrollLocation(); + await loadMessages(true); + setScrollLocation(currenteScrollLocation); +} + +function getScrollLocation() { + const messagesDiv = document.getElementById("messages"); + return messagesDiv.scrollTop; +} + +function setScrollLocation(height) { + const messagesDiv = document.getElementById("messages"); + messagesDiv.scrollTop = height; +} + document.addEventListener("click", function (event) { const settingsPanel = document.getElementById("settings-panel"); const settingsButton = document.querySelector(".settings-button"); @@ -117,7 +131,7 @@ async function loadUsers() { } let lastMessageCount = 0; -async function loadMessages() { +async function loadMessages(forceUpdate = false) { try { let messagesDiv = document.getElementById("messages"); const response = await fetch("/messages"); @@ -152,10 +166,10 @@ async function loadMessages() { const newMessageCount = messages.length; - if ( - newMessageCount > lastMessageCount || - lastMessageCount === 0 - ) { + const update = newMessageCount != lastMessageCount || + lastMessageCount === 0 || forceUpdate; + + if (update) { messagesDiv.innerHTML = ""; Array.from(messages).forEach((msg) => { const messageDiv = document.createElement( @@ -172,49 +186,16 @@ async function loadMessages() { "
", ); - const linkedContent = content.replace( - /(?![^<]*>)(https?:\/\/[^\s<]+)/g, - function (url) { - console.log( - "Processing URL:", - url, - ); // Debug log - - const videoId = getYouTubeID( - url, - ); - if (videoId) { - return `
`; - } else if (isImageUrl(url)) { - console.log( - "Attempting to embed image:", - url, - ); - return `
Embedded image
`; - } - return `${url}`; - }, - ); - - let deleteHtml = ""; - const usernameDiv = document.createElement( "div", ); usernameDiv.innerHTML = username; compareUsername = usernameDiv.textContent; + let deleteHtml = ""; + + const embeddedContent = contentEmbedding( + content, + ); if ( compareUsername === @@ -229,7 +210,7 @@ async function loadMessages() {
${username} ${timestamp} ${deleteHtml}
-
${linkedContent}
`; +
${embeddedContent}
`; messagesDiv.appendChild(messageDiv); }); @@ -241,6 +222,36 @@ async function loadMessages() { } } +function contentEmbedding(content) { + return content.replace( + /(?![^<]*>)(https?:\/\/[^\s<]+)/g, + function (url) { + const videoId = getYouTubeID( + url, + ); + if (videoId) { + return `
`; + } else if (isImageUrl(url)) { + return `
Embedded image
`; + } + return `${url}`; + }, + ); +} + function isImageUrl(url) { return url.match(/\.(jpeg|jpg|gif|png|webp|bmp)($|\?)/i) != null; } @@ -327,8 +338,8 @@ async function setUsername() { setTimeout(() => { document.getElementById("settings-panel").style .display = "none"; - }, 500); - location.reload(); + }, 750); + updateMessagesInPlace(); } else { showUsernameStatus( data.error || "Failed to set username", @@ -363,7 +374,7 @@ async function sendMessage() { if (response.ok) { messageInput.value = ""; messageInput.style.height = "auto"; - loadMessages(); + loadMessages(true); } else { showStatus( data.error || "Failed to send message", @@ -470,7 +481,7 @@ async function initialize() { setInterval(loadMessages, 1000); setInterval(loadUsers, 1000); setInterval(pingCheck, 3000); - await loadMessages(); + await loadMessages(true); scrollToBottom(); } diff --git a/main.go b/main.go index 8d9c534..8e78d42 100644 --- a/main.go +++ b/main.go @@ -438,8 +438,8 @@ func (s *Server) handleUsername(w http.ResponseWriter, r *http.Request) { s.mu.Lock() - if len(req.Username) > 64 { - http.Error(w, fmt.Sprintf(`{"error": "Username too long (must be less than 64 characters)"}`), http.StatusRequestEntityTooLarge) + if len(req.Username) > s.Config.Options.NameMaxLength { + http.Error(w, fmt.Sprintf(`{"error": "Username too long (%v out of %v characters maximum)"}`, len(req.Username), s.Config.Options.NameMaxLength), http.StatusRequestEntityTooLarge) s.mu.Unlock() return } @@ -451,8 +451,8 @@ func (s *Server) handleUsername(w http.ResponseWriter, r *http.Request) { } if s.Database.UserNameExists(req.Username) { - s.mu.Unlock() http.Error(w, fmt.Sprintf(`{"error": "Username already exists"}`), http.StatusConflict) + s.mu.Unlock() return } @@ -659,7 +659,7 @@ func (s *Server) handleCss(w http.ResponseWriter, r *http.Request) { func (s *Server) Run() { s.Database.DbCreateTableMessages() s.Database.DbCreateTableUsers() - s.Database.DeleteOldMessages(s.Config.Server.MessageMaxAge) + s.Database.DeleteOldMessages(s.Config.Options.MessageMaxAge) handler := http.NewServeMux() handler.HandleFunc("/ping", s.handlePing) handler.HandleFunc("/username", s.handleUsername) @@ -699,9 +699,8 @@ func main() { type Config struct { Server struct { - IpAddress string `json:"ipAddress"` - Port int `json:"port"` - MessageMaxAge int `json:"messageMaxAge"` + IpAddress string `json:"ipAddress"` + Port int `json:"port"` } `json:"server"` Paths struct { DatabasePath string `json:"databasePath"` @@ -710,6 +709,10 @@ type Config struct { IndexHtmlPath string `json:"indexHtmlPath"` MessagesHtmlPath string `json:"messagesHtmlPath"` } `json:"paths"` + Options struct { + MessageMaxAge int `json:"messageMaxAge"` + NameMaxLength int `json:"nameMaxLength"` + } `json:"options"` } func LoadConfig(filepath string) Config {