lchat/web/wasm/app.go

299 lines
8.9 KiB
Go
Raw Permalink Normal View History

2024-11-12 19:34:06 +00:00
package main
import (
"bytes"
"encoding/json"
"git.ailur.dev/ailur/jsFetch"
"strconv"
2024-11-12 19:34:06 +00:00
"syscall/js"
"time"
)
var messageDivs = make(map[string]js.Value)
2024-11-12 19:34:06 +00:00
func refreshMessages(localStorage js.Value, messageBox js.Value, userId string) {
jsonBody, err := json.Marshal(map[string]interface{}{
"token": localStorage.Call("getItem", "token").String(),
})
if err != nil {
alert("Failed to encode request: " + err.Error())
return
}
response, err := jsFetch.Post(localStorage.Call("getItem", "server").String()+"/api/messages", "application/json", bytes.NewReader(jsonBody))
if err != nil {
alert("Failed to contact server: " + err.Error())
return
}
if response.StatusCode != 200 {
if response.StatusCode == 500 {
alert("Something went wrong on our end. Please try again later.")
} else {
var body map[string]interface{}
err := json.NewDecoder(response.Body).Decode(&body)
if err != nil {
alert("Failed to decode response: " + err.Error())
} else {
alert(body["error"].(string))
}
}
return
}
var body []map[string]interface{}
2024-11-12 19:34:06 +00:00
err = json.NewDecoder(response.Body).Decode(&body)
if err != nil {
alert("Failed to decode response: " + err.Error())
return
}
if !messageBox.Get("lastChild").IsNull() {
messageBox.Get("lastChild").Get("style").Set("margin-bottom", "15px")
}
ids := make(map[string]struct{})
for _, message := range body {
ids[message["id"].(string)] = struct{}{}
}
if len(messageDivs) > len(body) {
for id := range messageDivs {
_, exists := ids[id]
if !exists {
messageDivs[id].Call("remove")
delete(messageDivs, id)
}
2024-11-12 19:34:06 +00:00
}
}
2024-11-12 19:34:06 +00:00
for _, message := range body {
_, exists := messageDivs[message["id"].(string)]
if !exists {
messageDiv := createMessage(message["message"].(string), message["name"].(string), message["sender"].(string) == userId, message["id"].(string), time.Unix(int64(message["sent"].(float64)), 0))
messageBox.Call("appendChild", messageDiv)
messageDivs[message["id"].(string)] = messageDiv
}
2024-11-12 19:34:06 +00:00
}
if !messageBox.Get("lastChild").IsNull() {
messageBox.Get("lastChild").Get("style").Set("margin-bottom", "22.5px")
}
messageBox.Set("scrollTop", messageBox.Get("scrollHeight").Float())
2024-11-12 19:34:06 +00:00
}
func alert(message string) {
js.Global().Call("alert", message)
}
func createMessage(message string, user string, delete bool, id string, timestamp time.Time) js.Value {
div := js.Global().Get("document").Call("createElement", "div")
author := js.Global().Get("document").Call("createElement", "span")
author.Get("classList").Call("add", "author")
author.Set("innerText", user)
content := js.Global().Get("document").Call("createElement", "span")
content.Get("classList").Call("add", "content")
content.Set("innerText", message)
timestampSpan := js.Global().Get("document").Call("createElement", "span")
timestampSpan.Get("classList").Call("add", "timestamp")
timestampSpan.Set("innerText", timestamp.Format("15:04"))
if delete {
div.Get("style").Set("padding-bottom", "55px")
deleteButton := js.Global().Get("document").Call("createElement", "button")
deleteButton.Set("innerText", "Delete")
deleteButton.Call("addEventListener", "click", js.FuncOf(func(this js.Value, args []js.Value) interface{} {
go func() {
jsonBody, err := json.Marshal(map[string]interface{}{
"id": id,
"token": js.Global().Get("localStorage").Call("getItem", "token").String(),
})
if err != nil {
alert("Failed to encode request: " + err.Error())
return
}
response, err := jsFetch.Post(js.Global().Get("localStorage").Call("getItem", "server").String()+"/api/delete", "application/json", bytes.NewReader(jsonBody))
if err != nil {
alert("Failed to contact server: " + err.Error())
return
}
if response.StatusCode != 200 {
if response.StatusCode == 500 {
alert("Something went wrong on our end. Please try again later.")
} else {
var body map[string]interface{}
err := json.NewDecoder(response.Body).Decode(&body)
if err != nil {
alert("Failed to decode response: " + err.Error())
} else {
alert(body["error"].(string))
}
}
return
}
div.Call("remove")
}()
return nil
}))
div.Call("appendChild", deleteButton)
}
div.Call("appendChild", author)
div.Call("appendChild", content)
return div
}
func handleSend(sendField js.Value, localStorage js.Value) {
jsonBody, err := json.Marshal(map[string]interface{}{
"message": sendField.Get("value").String(),
"token": localStorage.Call("getItem", "token").String(),
})
if err != nil {
alert("Failed to encode request: " + err.Error())
return
}
response, err := jsFetch.Post(localStorage.Call("getItem", "server").String()+"/api/send", "application/json", bytes.NewReader(jsonBody))
if err != nil {
alert("Failed to contact server: " + err.Error())
return
}
if response.StatusCode != 200 {
if response.StatusCode == 500 {
alert("Something went wrong on our end. Please try again later.")
} else {
var body map[string]interface{}
err := json.NewDecoder(response.Body).Decode(&body)
if err != nil {
alert("Failed to decode response: " + err.Error())
} else {
alert(body["error"].(string))
}
}
return
}
sendField.Set("value", "")
}
2024-11-12 19:34:06 +00:00
func main() {
localStorage := js.Global().Get("localStorage")
login := js.Global().Get("document").Call("getElementById", "login")
app := js.Global().Get("document").Call("getElementById", "app")
logout := js.Global().Get("document").Call("getElementById", "logout")
sendField := js.Global().Get("document").Call("getElementById", "sendField")
send := js.Global().Get("document").Call("getElementById", "send")
messageBox := js.Global().Get("document").Call("getElementById", "messageBox")
inviteButton := js.Global().Get("document").Call("getElementById", "invite")
2024-11-12 19:34:06 +00:00
if localStorage.Call("getItem", "server").IsNull() {
localStorage.Call("setItem", "server", "https://chat.ailur.dev:1974")
}
if localStorage.Call("getItem", "token").IsNull() {
return
}
if localStorage.Call("getItem", "admin").String() == "true" {
inviteButton.Get("style").Set("display", "initial")
inviteButton.Call("addEventListener", "click", js.FuncOf(func(this js.Value, args []js.Value) interface{} {
go func() {
uses := js.Global().Get("prompt").Invoke("How many uses should the invite have?")
usesInt, err := strconv.Atoi(uses.String())
if err != nil {
alert("Invalid number of uses.")
return
}
jsonBody, err := json.Marshal(map[string]interface{}{
"token": localStorage.Call("getItem", "token").String(),
"uses": usesInt,
})
if err != nil {
alert("Failed to encode request: " + err.Error())
return
}
response, err := jsFetch.Post(localStorage.Call("getItem", "server").String()+"/api/invite", "application/json", bytes.NewReader(jsonBody))
if err != nil {
alert("Failed to contact server: " + err.Error())
return
}
if response.StatusCode != 200 {
if response.StatusCode == 500 {
alert("Something went wrong on our end. Please try again later.")
} else {
var body map[string]interface{}
err := json.NewDecoder(response.Body).Decode(&body)
if err != nil {
alert("Failed to decode response: " + err.Error())
} else {
alert(body["error"].(string))
}
}
return
}
var body map[string]interface{}
err = json.NewDecoder(response.Body).Decode(&body)
if err != nil {
alert("Failed to decode response: " + err.Error())
return
}
alert("Your invite URL is: " + js.Global().Get("location").Get("origin").String() + "/invite?invite=" + body["code"].(string))
}()
return nil
}))
} else {
logout.Get("style").Set("margin-left", "auto")
}
2024-11-12 19:34:06 +00:00
userId := localStorage.Call("getItem", "userId").String()
login.Get("style").Set("display", "none")
app.Get("style").Set("display", "initial")
logout.Call("addEventListener", "click", js.FuncOf(func(this js.Value, args []js.Value) interface{} {
go func() {
localStorage.Call("removeItem", "token")
localStorage.Call("removeItem", "userId")
localStorage.Call("removeItem", "admin")
2024-11-12 19:34:06 +00:00
js.Global().Get("location").Set("href", "login")
}()
return nil
}))
send.Call("addEventListener", "click", js.FuncOf(func(this js.Value, args []js.Value) interface{} {
go handleSend(sendField, localStorage)
return nil
}))
2024-11-12 19:34:06 +00:00
sendField.Call("addEventListener", "keypress", js.FuncOf(func(this js.Value, args []js.Value) interface{} {
if args[0].Get("key").String() == "Enter" {
go handleSend(sendField, localStorage)
}
2024-11-12 19:34:06 +00:00
return nil
}))
go refreshMessages(localStorage, messageBox, userId)
go func() {
webSocket := js.Global().Get("WebSocket").New(localStorage.Call("getItem", "server").String() + "/api/ping")
webSocket.Set("onmessage", js.FuncOf(func(this js.Value, args []js.Value) interface{} {
go refreshMessages(localStorage, messageBox, userId)
return nil
}))
}()
select {}
}