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 ``;
- }
- 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() {
- ${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 ``;
+ }
+ 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 {