changes
This commit is contained in:
parent
9e931243ef
commit
c6b6021fa9
@ -224,6 +224,21 @@ body {
|
||||
transition: opacity 0.3s;
|
||||
}
|
||||
|
||||
.edit-button {
|
||||
background: none;
|
||||
border: none;
|
||||
cursor: pointer;
|
||||
color: var(--timestamp-color);
|
||||
padding: 2px 6px;
|
||||
font-size: 12px;
|
||||
opacity: 0;
|
||||
transition: opacity 0.3s;
|
||||
}
|
||||
|
||||
.message:hover .edit-button {
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
.message:hover .delete-button {
|
||||
opacity: 1;
|
||||
}
|
||||
@ -232,6 +247,10 @@ body {
|
||||
background: var(--timestamp-color);
|
||||
}
|
||||
|
||||
.edit-button:hover {
|
||||
background: var(--timestamp-color);
|
||||
}
|
||||
|
||||
.settings-icon, .users-icon, .theme-icon{
|
||||
width: 24px;
|
||||
height: 24px;
|
||||
@ -537,6 +556,11 @@ button.scroll:hover {
|
||||
opacity: 1; /* Always visible on mobile */
|
||||
}
|
||||
|
||||
.edit-button {
|
||||
padding: 8px 12px;
|
||||
opacity: 1; /* Always visible on mobile */
|
||||
}
|
||||
|
||||
@media (orientation: landscape) {
|
||||
.messages-section {
|
||||
margin-top: 45px;
|
||||
|
@ -27,6 +27,41 @@ function toggleTheme() {
|
||||
localStorage.setItem("theme", newTheme);
|
||||
}
|
||||
|
||||
async function editMessage(messageId, content) {
|
||||
const newContent = prompt("Edit message:", content);
|
||||
if (newContent === null) {
|
||||
return;
|
||||
}
|
||||
if (newContent === "") {
|
||||
deleteMessage(messageId);
|
||||
return;
|
||||
}
|
||||
if (newContent === content) {
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
const response = await fetch("/messages", {
|
||||
method: "PATCH",
|
||||
headers: {
|
||||
"Content-Type": "application/json",
|
||||
},
|
||||
body: JSON.stringify({
|
||||
messageId: messageId,
|
||||
messageContent: newContent,
|
||||
}),
|
||||
});
|
||||
|
||||
if (response.ok) {
|
||||
updateMessagesInPlace();
|
||||
} else {
|
||||
console.error("Failed to edit message");
|
||||
}
|
||||
} catch (error) {
|
||||
console.error("Error editing message:", error);
|
||||
}
|
||||
}
|
||||
|
||||
async function deleteMessage(messageId) {
|
||||
if (confirm("Delete this message?")) {
|
||||
try {
|
||||
@ -201,12 +236,24 @@ async function loadMessages(forceUpdate = false, scrollLocation) {
|
||||
);
|
||||
usernameDiv.innerHTML = username;
|
||||
compareUsername = usernameDiv.textContent;
|
||||
let deleteHtml = "";
|
||||
|
||||
const embeddedContent = contentEmbedding(
|
||||
content,
|
||||
);
|
||||
|
||||
let deleteHtml = "";
|
||||
let editHtml = "";
|
||||
|
||||
const parser = new DOMParser();
|
||||
const contentHtmlString = content;
|
||||
const doc = parser.parseFromString(
|
||||
contentHtmlString,
|
||||
"text/html",
|
||||
);
|
||||
const contentString =
|
||||
doc.querySelector("span").textContent;
|
||||
console.log(contentString);
|
||||
|
||||
if (
|
||||
compareUsername ===
|
||||
document.getElementById(
|
||||
@ -215,10 +262,12 @@ async function loadMessages(forceUpdate = false, scrollLocation) {
|
||||
) {
|
||||
deleteHtml =
|
||||
`<button class="delete-button" title="Delete message" onclick="deleteMessage('${messageId}')" style="display: inline;">🗑️</button>`;
|
||||
editHtml =
|
||||
`<button class="edit-button" title="Edit message" onclick="editMessage('${messageId}', '${contentString}')" style="display: inline;">📝</button>`;
|
||||
}
|
||||
messageDiv.innerHTML = `
|
||||
<div class="message-header">
|
||||
<div class="username">${username} ${timestamp} ${deleteHtml}</div>
|
||||
<div class="username">${username} ${timestamp} ${deleteHtml} ${editHtml}</div>
|
||||
</div>
|
||||
<div class="content">${embeddedContent}</div>`;
|
||||
|
||||
|
36
main.go
36
main.go
@ -281,6 +281,18 @@ func (db *Database) MessageDeleteIfOwner(id string, ip string) (int, error) {
|
||||
|
||||
}
|
||||
|
||||
func (db *Database) MessageEditIfOwner(id string, content string, ip string) (int, error) {
|
||||
res, err := db.db.Exec("UPDATE messages SET content = ? WHERE id = ? AND ip_address = ?", content, id, ip)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
affected, err := res.RowsAffected()
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
return int(affected), nil
|
||||
}
|
||||
|
||||
func (db *Database) DeleteOldMessages(ageMinutes int) {
|
||||
if ageMinutes <= 0 {
|
||||
return
|
||||
@ -474,6 +486,30 @@ func getMessageTemplate(filepath string, body string) string {
|
||||
|
||||
func (s *Server) handleMessages(w http.ResponseWriter, r *http.Request) {
|
||||
switch r.Method {
|
||||
case http.MethodPatch:
|
||||
w.Header().Set("Content-Type", "application/json")
|
||||
var req struct {
|
||||
MessageId string `json:"messageId"`
|
||||
MessageContent string `json:"messageContent"`
|
||||
}
|
||||
if err := json.NewDecoder(r.Body).Decode(&req); err != nil {
|
||||
http.Error(w, `{"error": "Invalid JSON"}`, http.StatusBadRequest)
|
||||
return
|
||||
}
|
||||
|
||||
clientIP := getClientIP(r)
|
||||
if affected, err := s.Database.MessageEditIfOwner(req.MessageId, req.MessageContent, clientIP); err != nil {
|
||||
http.Error(w, `{"error": "Unauthorized"}`, http.StatusNotFound)
|
||||
return
|
||||
} else if affected == 0 {
|
||||
http.Error(w, `{"error": "Message not found"}`, http.StatusNotFound)
|
||||
return
|
||||
}
|
||||
|
||||
json.NewEncoder(w).Encode(map[string]string{
|
||||
"status": "Message edited successfully",
|
||||
})
|
||||
|
||||
case http.MethodGet:
|
||||
w.Header().Set("Content-Type", "text/html")
|
||||
|
||||
|
@ -7,11 +7,10 @@
|
||||
### Low Priority
|
||||
- Reposition the search button
|
||||
- Fix mobile views instead of hiding elements that you don't want to position properly
|
||||
- Ability to edit messages
|
||||
## Backend
|
||||
### High Priority
|
||||
- Lazy load with pagination (frontend and backend)
|
||||
### Mid Priority
|
||||
- Nothing yet
|
||||
### Low Priority
|
||||
- Ability to edit messages
|
||||
- Nothing yet
|
||||
|
Loading…
x
Reference in New Issue
Block a user