diff --git a/CHANGELOG.md b/CHANGELOG.md index 664aae5..701963d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,18 +1,5 @@ [Unreleased] -## v1.1.0 - 2025-09-07 - -### Added - -- feat(chat): use websocket to update messages -- feat(chat): add css animation - -## v1.0.1 - 2025-08-31 - -### Fixed - -- fix: fix path of assets - ## v1.0.0 - 2025-08-29 First release! 🎉 diff --git a/README.md b/README.md index 2b834c6..fe591c7 100644 --- a/README.md +++ b/README.md @@ -6,12 +6,6 @@ It implements the webhook triggered when a new message is posted in the chat. It ## Installation -### Pre-compiled package - -Go to [releases](https://gitnet.fr/deblan/owncast-webhook/releases) and download the [latest version](https://gitnet.fr/deblan/owncast-webhook/releases/download/latest/owncast-webhook). - -### From source - Requirements: nodejs (tested with >=22), golang (tested with >=1.24) ``` @@ -39,8 +33,6 @@ Add a webhook (Integration > Webhooks): You can embed the chat using this URL: `{server.base_url}/chat/messages` -If you use a reverse proxy, configure `{server.base_url}/ws.*` as weboscket. - ## Usage ``` diff --git a/assets/src/js/lib/chat.js b/assets/src/js/lib/chat.js index 38a6666..60217f3 100644 --- a/assets/src/js/lib/chat.js +++ b/assets/src/js/lib/chat.js @@ -1,51 +1,40 @@ const isChat = () => { - return getChat() !== null + return document.querySelector('#chat') !== null } const getChat = () => { return document.querySelector('#chat') } -const createWebSocketConnection = () => { - const protocol = location.protocol === 'https:' ? 'wss' : 'ws' +const updateChat = () => { + fetch(document.location.href) + .then((response) => response.text()) + .then((html) => { + const parser = new DOMParser() + const doc = parser.parseFromString(html, 'text/html') + const nextMessages = doc.querySelectorAll('.message') - return new WebSocket(`${protocol}://${window.location.hostname}:${window.location.port}/ws/chat/messages`) -} + const currentMessages = getChat().querySelectorAll('.message') + const messagesContainer = getChat().querySelector('.messages') -const isInViewport = (element) => { - const rect = element.getBoundingClientRect() + nextMessages.forEach((nextMessage) => { + let add = true - return (rect.top - 90) > 0 -} + currentMessages.forEach((currentMessage) => { + if (currentMessage.id === nextMessage.id) { + add = false + } + }) -const runChat = () => { - const ws = createWebSocketConnection() + if (add) { + messagesContainer.appendChild(nextMessage) + } + }) - ws.addEventListener('close', runChat) + messagesContainer.scrollTo(0, messagesContainer.scrollHeight) - ws.addEventListener('message', (event) => { - const items = JSON.parse(event.data) - - if (items == null || !items.length) { - return - } - - const container = getChat().querySelector('.messages') - - items.forEach((item) => { - const message = document.createElement('div') - message.innerHTML = item - - container.appendChild(message) + window.setTimeout(updateChat, 500) }) - - getChat().querySelectorAll('.message').forEach((message) => { - if (!isInViewport(message)) { - message.classList.toggle('animate__fadeInUp', false) - message.classList.toggle('animate__fadeOutUp', true) - } - }) - }) } -export {isChat, runChat} +export {isChat, updateChat} diff --git a/assets/src/js/main.js b/assets/src/js/main.js index 393d4ec..8d75a5c 100644 --- a/assets/src/js/main.js +++ b/assets/src/js/main.js @@ -1,6 +1,6 @@ import '../scss/main.scss' -import {isChat, runChat} from './lib/chat.js' +import {isChat, updateChat} from './lib/chat.js' if (isChat()) { - runChat() + updateChat() } diff --git a/assets/src/scss/main.scss b/assets/src/scss/main.scss index 7110344..37ce62e 100644 --- a/assets/src/scss/main.scss +++ b/assets/src/scss/main.scss @@ -1,5 +1,3 @@ -@import "~animate.css/animate.css"; - :root { --color-owncast-user-0: #ff717b; --color-owncast-user-1: #f4e413; @@ -18,24 +16,19 @@ --theme-color-users-5: var(--color-owncast-user-5); --theme-color-users-6: var(--color-owncast-user-6); --theme-color-users-7: var(--color-owncast-user-7); - - --animate-duration: 500ms; } #chat { background: transparent; margin: 0; font-family: monospace; + height: calc(100vh - 10px); + /* border: 5px solid #254779; */ .messages { + max-height: calc(100vh - 20px); overflow: hidden; font-size: 13px; - display: flex; - align-self: end; - flex-direction: column; - position: fixed; - bottom: 10px; - width: 100%; .message { background: #000000cc; diff --git a/assets/view.go b/assets/view.go index fe222b3..bfa9b75 100644 --- a/assets/view.go +++ b/assets/view.go @@ -4,6 +4,8 @@ import ( "embed" "encoding/json" + "github.com/a-h/templ" + "github.com/labstack/echo/v4" . "maragu.dev/gomponents" . "maragu.dev/gomponents/html" ) @@ -15,9 +17,35 @@ var ( entrypoints map[string]map[string]map[string][]string ) +func Render(ctx echo.Context, statusCode int, t templ.Component) error { + buf := templ.GetBuffer() + defer templ.ReleaseBuffer(buf) + + if err := t.Render(ctx.Request().Context(), buf); err != nil { + return err + } + + return ctx.HTML(statusCode, buf.String()) +} + +func Asset(name string) string { + if manifest == nil { + value, _ := statics.ReadFile("static/manifest.json") + json.Unmarshal(value, &manifest) + } + + path, ok := manifest[name] + + if !ok { + return "" + } + + return path +} + func entrypointFiles(app, category string) []string { if entrypoints == nil { - value, _ := statics.ReadFile("dist/entrypoints.json") + value, _ := statics.ReadFile("static/entrypoints.json") json.Unmarshal(value, &entrypoints) } @@ -36,21 +64,6 @@ func entrypointFiles(app, category string) []string { return files } -func Asset(name string) string { - if manifest == nil { - value, _ := statics.ReadFile("dist/manifest.json") - json.Unmarshal(value, &manifest) - } - - path, ok := manifest[name] - - if !ok { - return "" - } - - return path -} - func EntrypointJs(app string) []Node { files := entrypointFiles(app, "js") var results []Node diff --git a/bin/watch.sh b/bin/watch.sh index 1aa23bc..f4ddf7a 100755 --- a/bin/watch.sh +++ b/bin/watch.sh @@ -6,7 +6,6 @@ sn=owncastwh st="Owncast Webhook" while true; do - screen -X -S "$sn" quit rm -f cmd/server/rice-box.go ./node_modules/.bin/webpack screen -S "$sn" -d -m go run ./cmd/server/ diff --git a/cmd/server/server.go b/cmd/server/server.go index 9e16d5c..e771a99 100644 --- a/cmd/server/server.go +++ b/cmd/server/server.go @@ -14,7 +14,6 @@ import ( "github.com/labstack/echo/v4/middleware" "gitnet.fr/deblan/owncast-webhook/internal/client/twitch" "gitnet.fr/deblan/owncast-webhook/internal/config" - "gitnet.fr/deblan/owncast-webhook/internal/test" "gitnet.fr/deblan/owncast-webhook/internal/web/router" ) @@ -37,17 +36,13 @@ func main() { e := echo.New() e.Validator = &AppValidator{validator: validator.New()} - e.Static("/dist", "dist") + e.Static("/static", "static") assetHandler := http.FileServer(rice.MustFindBox("../../assets/dist").HTTPBox()) - e.GET("/dist/*", echo.WrapHandler(http.StripPrefix("/dist/", assetHandler))) + e.GET("/static/*", echo.WrapHandler(http.StripPrefix("/static/", assetHandler))) e.Use(middleware.Logger()) router.RegisterControllers(e) - if conf.Test.Enable { - test.GenerateFakeMessages() - } - if conf.Twitch.Enable { twitch.IrcClient() } diff --git a/config.ini.example b/config.ini.example index 7885e57..9be2b6d 100644 --- a/config.ini.example +++ b/config.ini.example @@ -10,7 +10,3 @@ base_url = "https://live.example.com" [twitch] enable = false channel = "username" - -; Add fake messages to test -[test] -enable = false diff --git a/go.mod b/go.mod index 12784d9..5aefb9e 100644 --- a/go.mod +++ b/go.mod @@ -4,9 +4,9 @@ go 1.23.0 require ( github.com/GeertJohan/go.rice v1.0.3 + github.com/a-h/templ v0.2.778 github.com/gempir/go-twitch-irc/v4 v4.2.0 github.com/go-playground/validator v9.31.0+incompatible - github.com/gorilla/websocket v1.5.3 github.com/labstack/echo/v4 v4.12.0 gopkg.in/ini.v1 v1.67.0 maragu.dev/gomponents v1.2.0 @@ -14,7 +14,6 @@ require ( require ( github.com/daaku/go.zipexe v1.0.2 // indirect - github.com/go-faker/faker/v4 v4.6.1 // indirect github.com/go-playground/locales v0.14.1 // indirect github.com/go-playground/universal-translator v0.18.1 // indirect github.com/golang-jwt/jwt v3.2.2+incompatible // indirect @@ -25,10 +24,11 @@ require ( github.com/stretchr/testify v1.9.0 // indirect github.com/valyala/bytebufferpool v1.0.0 // indirect github.com/valyala/fasttemplate v1.2.2 // indirect + github.com/yassinebenaid/godump v0.11.1 // indirect golang.org/x/crypto v0.27.0 // indirect golang.org/x/net v0.28.0 // indirect golang.org/x/sys v0.25.0 // indirect - golang.org/x/text v0.28.0 // indirect + golang.org/x/text v0.18.0 // indirect golang.org/x/time v0.5.0 // indirect gopkg.in/go-playground/assert.v1 v1.2.1 // indirect ) diff --git a/go.sum b/go.sum index bdbad59..da1c362 100644 --- a/go.sum +++ b/go.sum @@ -1,6 +1,8 @@ github.com/GeertJohan/go.incremental v1.0.0/go.mod h1:6fAjUhbVuX1KcMD3c8TEgVUqmo4seqhv0i0kdATSkM0= github.com/GeertJohan/go.rice v1.0.3 h1:k5viR+xGtIhF61125vCE1cmJ5957RQGXG6dmbaWZSmI= github.com/GeertJohan/go.rice v1.0.3/go.mod h1:XVdrU4pW00M4ikZed5q56tPf1v2KwnIKeIdc9CBYNt4= +github.com/a-h/templ v0.2.778 h1:VzhOuvWECrwOec4790lcLlZpP4Iptt5Q4K9aFxQmtaM= +github.com/a-h/templ v0.2.778/go.mod h1:lq48JXoUvuQrU0VThrK31yFwdRjTCnIE5bcPCM9IP1w= github.com/akavel/rsrc v0.8.0/go.mod h1:uLoCtb9J+EyAqh+26kdrTgmzRBFPGOolLWKpdxkKq+c= github.com/daaku/go.zipexe v1.0.2 h1:Zg55YLYTr7M9wjKn8SY/WcpuuEi+kR2u4E8RhvpyXmk= github.com/daaku/go.zipexe v1.0.2/go.mod h1:5xWogtqlYnfBXkSB1o9xysukNP9GTvaNkqzUZbt3Bw8= @@ -8,8 +10,6 @@ github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/gempir/go-twitch-irc/v4 v4.2.0 h1:OCeff+1aH4CZIOxgKOJ8dQjh+1ppC6sLWrXOcpGZyq4= github.com/gempir/go-twitch-irc/v4 v4.2.0/go.mod h1:QsOMMAk470uxQ7EYD9GJBGAVqM/jDrXBNbuePfTauzg= -github.com/go-faker/faker/v4 v4.6.1 h1:xUyVpAjEtB04l6XFY0V/29oR332rOSPWV4lU8RwDt4k= -github.com/go-faker/faker/v4 v4.6.1/go.mod h1:arSdxNCSt7mOhdk8tEolvHeIJ7eX4OX80wXjKKvkKBY= github.com/go-playground/locales v0.14.1 h1:EWaQ/wswjilfKLTECiXz7Rh+3BjFhfDFKv/oXslEjJA= github.com/go-playground/locales v0.14.1/go.mod h1:hxrqLVvrK65+Rwrd5Fc6F2O76J/NuW9t0sjnWqG1slY= github.com/go-playground/universal-translator v0.18.1 h1:Bcnm0ZwsGyWbCzImXv+pAJnYK9S473LQFuzCbDbfSFY= @@ -18,8 +18,8 @@ github.com/go-playground/validator v9.31.0+incompatible h1:UA72EPEogEnq76ehGdEDp github.com/go-playground/validator v9.31.0+incompatible/go.mod h1:yrEkQXlcI+PugkyDjY2bRrL/UBU4f3rvrgkN3V8JEig= github.com/golang-jwt/jwt v3.2.2+incompatible h1:IfV12K8xAKAnZqdXVzCZ+TOjboZ2keLg81eXfW3O+oY= github.com/golang-jwt/jwt v3.2.2+incompatible/go.mod h1:8pz2t5EyA70fFQQSrl6XZXzqecmYZeUEB8OUGHkxJ+I= -github.com/gorilla/websocket v1.5.3 h1:saDtZ6Pbx/0u+bgYQ3q96pZgCzfhKXGPqt7kZ72aNNg= -github.com/gorilla/websocket v1.5.3/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= +github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI= +github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= github.com/jessevdk/go-flags v1.4.0/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI= github.com/labstack/echo/v4 v4.12.0 h1:IKpw49IMryVB2p1a4dzwlhP1O2Tf2E0Ir/450lH+kI0= github.com/labstack/echo/v4 v4.12.0/go.mod h1:UP9Cr2DJXbOK3Kr9ONYzNowSh7HP0aG0ShAyycHSJvM= @@ -42,6 +42,8 @@ github.com/valyala/bytebufferpool v1.0.0/go.mod h1:6bBcMArwyJ5K/AmCkWv1jt77kVWyC github.com/valyala/fasttemplate v1.0.1/go.mod h1:UQGH1tvbgY+Nz5t2n7tXsz52dQxojPUpymEIMZ47gx8= github.com/valyala/fasttemplate v1.2.2 h1:lxLXG0uE3Qnshl9QyaK6XJxMXlQZELvChBOCmQD0Loo= github.com/valyala/fasttemplate v1.2.2/go.mod h1:KHLXt3tVN2HBp8eijSv/kGJopbvo7S+qRAEEKiv+SiQ= +github.com/yassinebenaid/godump v0.11.1 h1:SPujx/XaYqGDfmNh7JI3dOyCUVrG0bG2duhO3Eh2EhI= +github.com/yassinebenaid/godump v0.11.1/go.mod h1:dc/0w8wmg6kVIvNGAzbKH1Oa54dXQx8SNKh4dPRyW44= golang.org/x/crypto v0.27.0 h1:GXm2NjJrPaiv/h1tb2UH8QfgC/hOf/+z0p6PT8o1w7A= golang.org/x/crypto v0.27.0/go.mod h1:1Xngt8kV6Dvbssa53Ziq6Eqn0HqbZi5Z6R0ZpwQzt70= golang.org/x/net v0.28.0 h1:a9JDOJc5GMUJ0+UDqmLT86WiEy7iWyIhz8gz8E4e5hE= @@ -50,8 +52,8 @@ golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBc golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.25.0 h1:r+8e+loiHxRqhXVl6ML1nO3l1+oFoWbnlu2Ehimmi34= golang.org/x/sys v0.25.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= -golang.org/x/text v0.28.0 h1:rhazDwis8INMIwQ4tpjLDzUhx6RlXqZNPEM0huQojng= -golang.org/x/text v0.28.0/go.mod h1:U8nCwOR8jO/marOQ0QbDiOngZVEBB7MAiitBuMjXiNU= +golang.org/x/text v0.18.0 h1:XvMDiNzPAl0jr17s6W9lcaIhGUfUORdGCNsuLmPG224= +golang.org/x/text v0.18.0/go.mod h1:BuEKDfySbSR4drPmRPG/7iBdf8hvFMuRexcpahXilzY= golang.org/x/time v0.5.0 h1:o7cqy6amK/52YcAKIPlM3a+Fpj35zvRj2TP+e1xFSfk= golang.org/x/time v0.5.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM= gopkg.in/go-playground/assert.v1 v1.2.1 h1:xoYuJVE7KT85PYWrN730RguIQO0ePzVRfFMXadIrXTM= diff --git a/internal/config/config.go b/internal/config/config.go index e3d07c3..9b020a2 100644 --- a/internal/config/config.go +++ b/internal/config/config.go @@ -16,9 +16,6 @@ type Config struct { Owncast struct { BaseUrl string } - Test struct { - Enable bool - } Twitch struct { Enable bool Channel string @@ -48,7 +45,6 @@ func (c *Config) Load(file string) { config.Server.WebhookSecret = cfg.Section("server").Key("webhook_secret").String() config.Owncast.BaseUrl = cfg.Section("owncast").Key("base_url").String() - config.Test.Enable = cfg.Section("test").Key("enable").MustBool(false) config.Twitch.Enable = cfg.Section("twitch").Key("enable").MustBool(false) config.Twitch.Channel = cfg.Section("twitch").Key("channel").String() diff --git a/internal/store/message.go b/internal/store/message.go index a8b106d..385a8c1 100644 --- a/internal/store/message.go +++ b/internal/store/message.go @@ -7,7 +7,6 @@ var messageStore *MessageStore const ( MessageOriginOwncast MessageOrigin = iota MessageOriginTwitch - MessageOriginTest ) type MessageStore struct { @@ -22,10 +21,6 @@ func (s *MessageStore) All() []MessageInterface { return s.messages } -func (s *MessageStore) Clear() { - s.messages = []MessageInterface{} -} - func GetMessageStore() *MessageStore { if messageStore == nil { messageStore = new(MessageStore) diff --git a/internal/store/test_message.go b/internal/store/test_message.go deleted file mode 100644 index 1cdfe12..0000000 --- a/internal/store/test_message.go +++ /dev/null @@ -1,30 +0,0 @@ -package store - -import ( - "github.com/gempir/go-twitch-irc/v4" - "github.com/go-faker/faker/v4" -) - -type TestMessage struct { - Message twitch.PrivateMessage -} - -func (o TestMessage) ID() string { - return faker.Sentence() -} - -func (o TestMessage) Visible() bool { - return true -} - -func (o TestMessage) Origin() MessageOrigin { - return MessageOriginTest -} - -func (o TestMessage) Author() string { - return faker.Username() -} - -func (o TestMessage) Content() string { - return faker.Sentence() -} diff --git a/internal/test/fake.go b/internal/test/fake.go deleted file mode 100644 index 90fbd12..0000000 --- a/internal/test/fake.go +++ /dev/null @@ -1,17 +0,0 @@ -package test - -import ( - "math/rand" - "time" - - "gitnet.fr/deblan/owncast-webhook/internal/store" -) - -func GenerateFakeMessages() { - go func() { - for { - store.GetMessageStore().Add(store.TestMessage{}) - time.Sleep(time.Duration(rand.Intn(3000-100)+100) * time.Millisecond) - } - }() -} diff --git a/internal/web/controller/chat/controller.go b/internal/web/controller/chat/controller.go index 7bc963f..a5f654c 100644 --- a/internal/web/controller/chat/controller.go +++ b/internal/web/controller/chat/controller.go @@ -1,10 +1,8 @@ package chat import ( - "bytes" - "encoding/json" + "fmt" - "github.com/gorilla/websocket" "github.com/labstack/echo/v4" "gitnet.fr/deblan/owncast-webhook/assets" "gitnet.fr/deblan/owncast-webhook/internal/store" @@ -13,10 +11,6 @@ import ( . "maragu.dev/gomponents/html" ) -var ( - upgrader = websocket.Upgrader{} -) - type Controller struct { } @@ -24,60 +18,64 @@ func New(e *echo.Echo) *Controller { c := Controller{} e.GET("/chat/messages", c.Messages) - e.GET("/ws/chat/messages", c.WebsocketMessages) return &c } -func (ctrl *Controller) WebsocketMessages(c echo.Context) error { - ws, err := upgrader.Upgrade(c.Response(), c.Request(), nil) - - if err != nil { - return err - } - - defer ws.Close() - - storage := store.GetMessageStore() - - for { - messages := storage.All() - - if len(messages) == 0 { - continue - } - - storage.Clear() - - var items []string - - for _, message := range messages { - var buff bytes.Buffer - msg := CreateMessageView(message) - msg.Render(&buff) - - items = append(items, buff.String()) - } - - j, _ := json.Marshal(items) - - ws.WriteMessage(websocket.TextMessage, j) - } - - return nil -} - func (ctrl *Controller) Messages(c echo.Context) error { + createMessage := func(message store.MessageInterface) Node { + var containerStyle Node + var userStyle Node + var originIcon Node + + switch message.Origin() { + case store.MessageOriginOwncast: + msg := message.(store.OwncastMessage) + + containerStyle = StyleAttr(fmt.Sprintf( + "border-color: var(--theme-color-users-%d)", + msg.WebhookMessage.User.DisplayColor, + )) + + userStyle = StyleAttr(fmt.Sprintf( + "color: var(--theme-color-users-%d)", + msg.WebhookMessage.User.DisplayColor, + )) + + originIcon = Img(Src(assets.Asset("static/img/owncast.png")), Class("message-origin")) + case store.MessageOriginTwitch: + originIcon = Img(Src(assets.Asset("static/img/twitch.png")), Class("message-origin")) + } + + return Div( + Class("message"), + ID(message.ID()), + containerStyle, + Div( + Class("message-user"), + userStyle, + Group([]Node{originIcon, Text(message.Author())}), + ), + Div( + Class("message-body"), + Raw(message.Content()), + ), + ) + } + page := HTML5(HTML5Props{ Title: "Chat", Language: "fr", Head: []Node{ Group(assets.EntrypointCss("main")), - Link(Rel("icon"), Type("image/x-icon"), Href(assets.Asset("dist/img/favicon.png"))), + Link(Rel("icon"), Type("image/x-icon"), Href(assets.Asset("static/img/favicon.png"))), }, Body: []Node{ ID("chat"), - Div(Class("messages")), + Div( + Class("messages"), + Map(store.GetMessageStore().All(), createMessage), + ), Group(assets.EntrypointJs("main")), }, }) diff --git a/internal/web/controller/chat/utils.go b/internal/web/controller/chat/utils.go deleted file mode 100644 index 7b6ef4a..0000000 --- a/internal/web/controller/chat/utils.go +++ /dev/null @@ -1,50 +0,0 @@ -package chat - -import ( - "fmt" - - "gitnet.fr/deblan/owncast-webhook/assets" - "gitnet.fr/deblan/owncast-webhook/internal/store" - . "maragu.dev/gomponents" - . "maragu.dev/gomponents/html" -) - -func CreateMessageView(message store.MessageInterface) Node { - var containerStyle Node - var userStyle Node - var originIcon Node - - switch message.Origin() { - case store.MessageOriginOwncast: - msg := message.(store.OwncastMessage) - - containerStyle = StyleAttr(fmt.Sprintf( - "border-color: var(--theme-color-users-%d)", - msg.WebhookMessage.User.DisplayColor, - )) - - userStyle = StyleAttr(fmt.Sprintf( - "color: var(--theme-color-users-%d)", - msg.WebhookMessage.User.DisplayColor, - )) - - originIcon = Img(Src(assets.Asset("dist/img/owncast.png")), Class("message-origin")) - case store.MessageOriginTwitch: - originIcon = Img(Src(assets.Asset("dist/img/twitch.png")), Class("message-origin")) - } - - return Div( - Class("message animate__animated animate__fadeInUp"), - ID(message.ID()), - containerStyle, - Div( - Class("message-user"), - userStyle, - Group([]Node{originIcon, Text(message.Author())}), - ), - Div( - Class("message-body"), - Raw(message.Content()), - ), - ) -} diff --git a/package-lock.json b/package-lock.json index 9037682..21e542c 100644 --- a/package-lock.json +++ b/package-lock.json @@ -6,7 +6,6 @@ "": { "dependencies": { "@symfony/webpack-encore": "github:symfony/webpack-encore", - "animate.css": "^4.1.1", "raw-loader": "^4.0.2" }, "devDependencies": { @@ -2735,12 +2734,6 @@ "ajv": "^6.9.1" } }, - "node_modules/animate.css": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/animate.css/-/animate.css-4.1.1.tgz", - "integrity": "sha512-+mRmCTv6SbCmtYJCN4faJMNFVNN5EuCTTprDTAo7YzIGji2KADmakjVA3+8mVDkZ2Bf09vayB35lSQIex2+QaQ==", - "license": "MIT" - }, "node_modules/ansi-regex": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", diff --git a/package.json b/package.json index ed07c0d..5a26d4e 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,6 @@ { "dependencies": { "@symfony/webpack-encore": "github:symfony/webpack-encore", - "animate.css": "^4.1.1", "raw-loader": "^4.0.2" }, "devDependencies": {