diff --git a/controllers/emoji.go b/controllers/emoji.go new file mode 100644 index 000000000..3c2f64af1 --- /dev/null +++ b/controllers/emoji.go @@ -0,0 +1,42 @@ +package controllers + +import ( + "encoding/json" + "io/ioutil" + "net/http" + "path" + "path/filepath" + "strings" + + "github.com/gabek/owncast/models" + log "github.com/sirupsen/logrus" +) + +// Make this path configurable if somebody has a valid reason +// to need it to be. The config is getting a bit bloated. +const emojiPath = "/img/emoji" // Relative to webroot + +//GetCustomEmoji returns a list of custom emoji via the API +func GetCustomEmoji(w http.ResponseWriter, r *http.Request) { + emojiList := make([]models.CustomEmoji, 0) + + fullPath := filepath.Join("webroot", emojiPath) + files, err := ioutil.ReadDir(fullPath) + if err != nil { + log.Errorln(err) + // Throw HTTP 500 + return + } + + // Memoize this result somewhere? Right now it iterates through the + // filesystem every time the API is hit. Should you need to restart + // the server to add emoji? + for _, f := range files { + name := strings.TrimSuffix(f.Name(), path.Ext(f.Name())) + path := filepath.Join(emojiPath, f.Name()) + singleEmoji := models.CustomEmoji{name, path} + emojiList = append(emojiList, singleEmoji) + } + + json.NewEncoder(w).Encode(emojiList) +} diff --git a/models/emoji.go b/models/emoji.go new file mode 100644 index 000000000..e63e7725d --- /dev/null +++ b/models/emoji.go @@ -0,0 +1,7 @@ +package models + +//CustomEmoji represents an image that can be used in chat as a custom emoji +type CustomEmoji struct { + Name string `json:"name"` + Emoji string `json:"emoji"` +} diff --git a/router/router.go b/router/router.go index 9cdc6f4e2..13633552f 100644 --- a/router/router.go +++ b/router/router.go @@ -23,6 +23,9 @@ func Start() error { // status of the system http.HandleFunc("/status", controllers.GetStatus) + // custom emoji supported in the chat + http.HandleFunc("/emoji", controllers.GetCustomEmoji) + if !config.Config.DisableWebFeatures { // websocket chat server go chat.Start() diff --git a/webroot/img/emoji/Reaper-gg.png b/webroot/img/emoji/Reaper-gg.png new file mode 100644 index 000000000..e07b557fe Binary files /dev/null and b/webroot/img/emoji/Reaper-gg.png differ diff --git a/webroot/img/emoji/Reaper-hi.png b/webroot/img/emoji/Reaper-hi.png new file mode 100644 index 000000000..9ef837752 Binary files /dev/null and b/webroot/img/emoji/Reaper-hi.png differ diff --git a/webroot/img/emoji/Reaper-hype.png b/webroot/img/emoji/Reaper-hype.png new file mode 100644 index 000000000..1a14e337d Binary files /dev/null and b/webroot/img/emoji/Reaper-hype.png differ diff --git a/webroot/img/emoji/Reaper-lol.png b/webroot/img/emoji/Reaper-lol.png new file mode 100644 index 000000000..453bf0c23 Binary files /dev/null and b/webroot/img/emoji/Reaper-lol.png differ diff --git a/webroot/img/emoji/Reaper-love.png b/webroot/img/emoji/Reaper-love.png new file mode 100644 index 000000000..63ad349c8 Binary files /dev/null and b/webroot/img/emoji/Reaper-love.png differ diff --git a/webroot/img/emoji/Reaper-rage.png b/webroot/img/emoji/Reaper-rage.png new file mode 100644 index 000000000..b05520018 Binary files /dev/null and b/webroot/img/emoji/Reaper-rage.png differ diff --git a/webroot/img/emoji/Reaper-rip.png b/webroot/img/emoji/Reaper-rip.png new file mode 100644 index 000000000..2e8cd2540 Binary files /dev/null and b/webroot/img/emoji/Reaper-rip.png differ diff --git a/webroot/img/emoji/Reaper-wtf.png b/webroot/img/emoji/Reaper-wtf.png new file mode 100644 index 000000000..bb58e68e5 Binary files /dev/null and b/webroot/img/emoji/Reaper-wtf.png differ diff --git a/webroot/img/emoji/ac-box.png b/webroot/img/emoji/ac-box.png new file mode 100644 index 000000000..368cc4bef Binary files /dev/null and b/webroot/img/emoji/ac-box.png differ diff --git a/webroot/img/emoji/ac-construction.png b/webroot/img/emoji/ac-construction.png new file mode 100644 index 000000000..8a683b440 Binary files /dev/null and b/webroot/img/emoji/ac-construction.png differ diff --git a/webroot/img/emoji/ac-fossil.png b/webroot/img/emoji/ac-fossil.png new file mode 100644 index 000000000..96b22540a Binary files /dev/null and b/webroot/img/emoji/ac-fossil.png differ diff --git a/webroot/img/emoji/ac-item-leaf.png b/webroot/img/emoji/ac-item-leaf.png new file mode 100644 index 000000000..27c5be89f Binary files /dev/null and b/webroot/img/emoji/ac-item-leaf.png differ diff --git a/webroot/img/emoji/ac-kkslider.png b/webroot/img/emoji/ac-kkslider.png new file mode 100644 index 000000000..c4b86a2ff Binary files /dev/null and b/webroot/img/emoji/ac-kkslider.png differ diff --git a/webroot/img/emoji/ac-moneytree.png b/webroot/img/emoji/ac-moneytree.png new file mode 100644 index 000000000..6dd27dfd0 Binary files /dev/null and b/webroot/img/emoji/ac-moneytree.png differ diff --git a/webroot/img/emoji/ac-mosquito.png b/webroot/img/emoji/ac-mosquito.png new file mode 100644 index 000000000..22538769e Binary files /dev/null and b/webroot/img/emoji/ac-mosquito.png differ diff --git a/webroot/img/emoji/ac-shirt.png b/webroot/img/emoji/ac-shirt.png new file mode 100644 index 000000000..166cbf88f Binary files /dev/null and b/webroot/img/emoji/ac-shirt.png differ diff --git a/webroot/img/emoji/ac-song.png b/webroot/img/emoji/ac-song.png new file mode 100644 index 000000000..73eb177af Binary files /dev/null and b/webroot/img/emoji/ac-song.png differ diff --git a/webroot/img/emoji/ac-tree.png b/webroot/img/emoji/ac-tree.png new file mode 100644 index 000000000..2cb0f496f Binary files /dev/null and b/webroot/img/emoji/ac-tree.png differ diff --git a/webroot/img/emoji/ac-turnip.png b/webroot/img/emoji/ac-turnip.png new file mode 100644 index 000000000..f0c2f7f70 Binary files /dev/null and b/webroot/img/emoji/ac-turnip.png differ diff --git a/webroot/img/emoji/ac-weeds.png b/webroot/img/emoji/ac-weeds.png new file mode 100644 index 000000000..58a6db19c Binary files /dev/null and b/webroot/img/emoji/ac-weeds.png differ diff --git a/webroot/img/emoji/alert.gif b/webroot/img/emoji/alert.gif new file mode 100644 index 000000000..82b7840a2 Binary files /dev/null and b/webroot/img/emoji/alert.gif differ diff --git a/webroot/img/emoji/bananadance.gif b/webroot/img/emoji/bananadance.gif new file mode 100644 index 000000000..aac532b00 Binary files /dev/null and b/webroot/img/emoji/bananadance.gif differ diff --git a/webroot/img/emoji/bb8.png b/webroot/img/emoji/bb8.png new file mode 100644 index 000000000..9e05109ae Binary files /dev/null and b/webroot/img/emoji/bb8.png differ diff --git a/webroot/img/emoji/beerparrot.gif b/webroot/img/emoji/beerparrot.gif new file mode 100644 index 000000000..d2a6d25fa Binary files /dev/null and b/webroot/img/emoji/beerparrot.gif differ diff --git a/webroot/img/emoji/bells.png b/webroot/img/emoji/bells.png new file mode 100644 index 000000000..9b55f45f5 Binary files /dev/null and b/webroot/img/emoji/bells.png differ diff --git a/webroot/img/emoji/birthdaypartyparrot.gif b/webroot/img/emoji/birthdaypartyparrot.gif new file mode 100644 index 000000000..827c90891 Binary files /dev/null and b/webroot/img/emoji/birthdaypartyparrot.gif differ diff --git a/webroot/img/emoji/blacklightsaber.png b/webroot/img/emoji/blacklightsaber.png new file mode 100644 index 000000000..db8d68dbc Binary files /dev/null and b/webroot/img/emoji/blacklightsaber.png differ diff --git a/webroot/img/emoji/bluelightsaber.png b/webroot/img/emoji/bluelightsaber.png new file mode 100644 index 000000000..77b8fd35e Binary files /dev/null and b/webroot/img/emoji/bluelightsaber.png differ diff --git a/webroot/img/emoji/bluntparrot.gif b/webroot/img/emoji/bluntparrot.gif new file mode 100644 index 000000000..4f7e59e4d Binary files /dev/null and b/webroot/img/emoji/bluntparrot.gif differ diff --git a/webroot/img/emoji/bobaparrot.gif b/webroot/img/emoji/bobaparrot.gif new file mode 100644 index 000000000..171f5ddc0 Binary files /dev/null and b/webroot/img/emoji/bobaparrot.gif differ diff --git a/webroot/img/emoji/cakeparrot.gif b/webroot/img/emoji/cakeparrot.gif new file mode 100644 index 000000000..dd3f200be Binary files /dev/null and b/webroot/img/emoji/cakeparrot.gif differ diff --git a/webroot/img/emoji/chewbacca.png b/webroot/img/emoji/chewbacca.png new file mode 100644 index 000000000..956f735c4 Binary files /dev/null and b/webroot/img/emoji/chewbacca.png differ diff --git a/webroot/img/emoji/chillparrot.gif b/webroot/img/emoji/chillparrot.gif new file mode 100644 index 000000000..6fbe4c2f1 Binary files /dev/null and b/webroot/img/emoji/chillparrot.gif differ diff --git a/webroot/img/emoji/christmasparrot.gif b/webroot/img/emoji/christmasparrot.gif new file mode 100644 index 000000000..6ab963589 Binary files /dev/null and b/webroot/img/emoji/christmasparrot.gif differ diff --git a/webroot/img/emoji/coffeeparrot.gif b/webroot/img/emoji/coffeeparrot.gif new file mode 100644 index 000000000..33a959727 Binary files /dev/null and b/webroot/img/emoji/coffeeparrot.gif differ diff --git a/webroot/img/emoji/confusedparrot.gif b/webroot/img/emoji/confusedparrot.gif new file mode 100644 index 000000000..e641f4393 Binary files /dev/null and b/webroot/img/emoji/confusedparrot.gif differ diff --git a/webroot/img/emoji/copparrot.gif b/webroot/img/emoji/copparrot.gif new file mode 100644 index 000000000..31904cc9d Binary files /dev/null and b/webroot/img/emoji/copparrot.gif differ diff --git a/webroot/img/emoji/coronavirus.png b/webroot/img/emoji/coronavirus.png new file mode 100644 index 000000000..9865ba318 Binary files /dev/null and b/webroot/img/emoji/coronavirus.png differ diff --git a/webroot/img/emoji/covid19parrot.gif b/webroot/img/emoji/covid19parrot.gif new file mode 100644 index 000000000..ca9f0a99d Binary files /dev/null and b/webroot/img/emoji/covid19parrot.gif differ diff --git a/webroot/img/emoji/cryptoparrot.gif b/webroot/img/emoji/cryptoparrot.gif new file mode 100644 index 000000000..81d00917c Binary files /dev/null and b/webroot/img/emoji/cryptoparrot.gif differ diff --git a/webroot/img/emoji/dabparrot.gif b/webroot/img/emoji/dabparrot.gif new file mode 100644 index 000000000..d7d0981de Binary files /dev/null and b/webroot/img/emoji/dabparrot.gif differ diff --git a/webroot/img/emoji/dadparrot.gif b/webroot/img/emoji/dadparrot.gif new file mode 100644 index 000000000..9f129d90e Binary files /dev/null and b/webroot/img/emoji/dadparrot.gif differ diff --git a/webroot/img/emoji/daftpunkparrot.gif b/webroot/img/emoji/daftpunkparrot.gif new file mode 100644 index 000000000..9d1adef74 Binary files /dev/null and b/webroot/img/emoji/daftpunkparrot.gif differ diff --git a/webroot/img/emoji/darkbeerparrot.gif b/webroot/img/emoji/darkbeerparrot.gif new file mode 100644 index 000000000..8562d7b7a Binary files /dev/null and b/webroot/img/emoji/darkbeerparrot.gif differ diff --git a/webroot/img/emoji/darkmodeparrot.gif b/webroot/img/emoji/darkmodeparrot.gif new file mode 100644 index 000000000..78b7f83ab Binary files /dev/null and b/webroot/img/emoji/darkmodeparrot.gif differ diff --git a/webroot/img/emoji/darth_vader.png b/webroot/img/emoji/darth_vader.png new file mode 100644 index 000000000..040363bc6 Binary files /dev/null and b/webroot/img/emoji/darth_vader.png differ diff --git a/webroot/img/emoji/dealwithitparrot.gif b/webroot/img/emoji/dealwithitparrot.gif new file mode 100644 index 000000000..f5f149ed3 Binary files /dev/null and b/webroot/img/emoji/dealwithitparrot.gif differ diff --git a/webroot/img/emoji/death_star.png b/webroot/img/emoji/death_star.png new file mode 100644 index 000000000..a587ec8b1 Binary files /dev/null and b/webroot/img/emoji/death_star.png differ diff --git a/webroot/img/emoji/discoparrot.gif b/webroot/img/emoji/discoparrot.gif new file mode 100644 index 000000000..752f84379 Binary files /dev/null and b/webroot/img/emoji/discoparrot.gif differ diff --git a/webroot/img/emoji/division-gg.png b/webroot/img/emoji/division-gg.png new file mode 100644 index 000000000..58c2cadaf Binary files /dev/null and b/webroot/img/emoji/division-gg.png differ diff --git a/webroot/img/emoji/division-hi.png b/webroot/img/emoji/division-hi.png new file mode 100644 index 000000000..b9c6d626a Binary files /dev/null and b/webroot/img/emoji/division-hi.png differ diff --git a/webroot/img/emoji/division-hype.png b/webroot/img/emoji/division-hype.png new file mode 100644 index 000000000..4639b6660 Binary files /dev/null and b/webroot/img/emoji/division-hype.png differ diff --git a/webroot/img/emoji/division-lol.png b/webroot/img/emoji/division-lol.png new file mode 100644 index 000000000..c15f358c6 Binary files /dev/null and b/webroot/img/emoji/division-lol.png differ diff --git a/webroot/img/emoji/division-omg.png b/webroot/img/emoji/division-omg.png new file mode 100644 index 000000000..4e3b6d2a5 Binary files /dev/null and b/webroot/img/emoji/division-omg.png differ diff --git a/webroot/img/emoji/division-rage.png b/webroot/img/emoji/division-rage.png new file mode 100644 index 000000000..2f89c4621 Binary files /dev/null and b/webroot/img/emoji/division-rage.png differ diff --git a/webroot/img/emoji/division-rip.png b/webroot/img/emoji/division-rip.png new file mode 100644 index 000000000..0ba84c2ef Binary files /dev/null and b/webroot/img/emoji/division-rip.png differ diff --git a/webroot/img/emoji/division-wtf.png b/webroot/img/emoji/division-wtf.png new file mode 100644 index 000000000..6d1e07900 Binary files /dev/null and b/webroot/img/emoji/division-wtf.png differ diff --git a/webroot/img/emoji/docparrot.gif b/webroot/img/emoji/docparrot.gif new file mode 100644 index 000000000..04aedd160 Binary files /dev/null and b/webroot/img/emoji/docparrot.gif differ diff --git a/webroot/img/emoji/donutparrot.gif b/webroot/img/emoji/donutparrot.gif new file mode 100644 index 000000000..3905bf7b4 Binary files /dev/null and b/webroot/img/emoji/donutparrot.gif differ diff --git a/webroot/img/emoji/doom_mad.gif b/webroot/img/emoji/doom_mad.gif new file mode 100644 index 000000000..e699fe8d7 Binary files /dev/null and b/webroot/img/emoji/doom_mad.gif differ diff --git a/webroot/img/emoji/empire.png b/webroot/img/emoji/empire.png new file mode 100644 index 000000000..bae0017bb Binary files /dev/null and b/webroot/img/emoji/empire.png differ diff --git a/webroot/img/emoji/everythingsfineparrot.gif b/webroot/img/emoji/everythingsfineparrot.gif new file mode 100644 index 000000000..e25bd7166 Binary files /dev/null and b/webroot/img/emoji/everythingsfineparrot.gif differ diff --git a/webroot/img/emoji/evilparrot.gif b/webroot/img/emoji/evilparrot.gif new file mode 100644 index 000000000..b1767a3bd Binary files /dev/null and b/webroot/img/emoji/evilparrot.gif differ diff --git a/webroot/img/emoji/explodyparrot.gif b/webroot/img/emoji/explodyparrot.gif new file mode 100644 index 000000000..54358e1ff Binary files /dev/null and b/webroot/img/emoji/explodyparrot.gif differ diff --git a/webroot/img/emoji/fixparrot.gif b/webroot/img/emoji/fixparrot.gif new file mode 100644 index 000000000..72c4b63b4 Binary files /dev/null and b/webroot/img/emoji/fixparrot.gif differ diff --git a/webroot/img/emoji/flyingmoneyparrot.gif b/webroot/img/emoji/flyingmoneyparrot.gif new file mode 100644 index 000000000..fd4146aa8 Binary files /dev/null and b/webroot/img/emoji/flyingmoneyparrot.gif differ diff --git a/webroot/img/emoji/footballparrot.gif b/webroot/img/emoji/footballparrot.gif new file mode 100644 index 000000000..dd4080834 Binary files /dev/null and b/webroot/img/emoji/footballparrot.gif differ diff --git a/webroot/img/emoji/gabe1.png b/webroot/img/emoji/gabe1.png new file mode 100644 index 000000000..3cf942f9f Binary files /dev/null and b/webroot/img/emoji/gabe1.png differ diff --git a/webroot/img/emoji/gabe2.png b/webroot/img/emoji/gabe2.png new file mode 100644 index 000000000..987d91cf3 Binary files /dev/null and b/webroot/img/emoji/gabe2.png differ diff --git a/webroot/img/emoji/gentlemanparrot.gif b/webroot/img/emoji/gentlemanparrot.gif new file mode 100644 index 000000000..2996b37d5 Binary files /dev/null and b/webroot/img/emoji/gentlemanparrot.gif differ diff --git a/webroot/img/emoji/githubparrot.gif b/webroot/img/emoji/githubparrot.gif new file mode 100644 index 000000000..042350254 Binary files /dev/null and b/webroot/img/emoji/githubparrot.gif differ diff --git a/webroot/img/emoji/goomba.gif b/webroot/img/emoji/goomba.gif new file mode 100644 index 000000000..c6bb719e7 Binary files /dev/null and b/webroot/img/emoji/goomba.gif differ diff --git a/webroot/img/emoji/gothparrot.gif b/webroot/img/emoji/gothparrot.gif new file mode 100644 index 000000000..eca455ec9 Binary files /dev/null and b/webroot/img/emoji/gothparrot.gif differ diff --git a/webroot/img/emoji/hamburgerparrot.gif b/webroot/img/emoji/hamburgerparrot.gif new file mode 100644 index 000000000..56ba9ec34 Binary files /dev/null and b/webroot/img/emoji/hamburgerparrot.gif differ diff --git a/webroot/img/emoji/harrypotterparrot.gif b/webroot/img/emoji/harrypotterparrot.gif new file mode 100644 index 000000000..f5c43c9f9 Binary files /dev/null and b/webroot/img/emoji/harrypotterparrot.gif differ diff --git a/webroot/img/emoji/headbangingparrot.gif b/webroot/img/emoji/headbangingparrot.gif new file mode 100644 index 000000000..dcc8df990 Binary files /dev/null and b/webroot/img/emoji/headbangingparrot.gif differ diff --git a/webroot/img/emoji/headingparrot.gif b/webroot/img/emoji/headingparrot.gif new file mode 100644 index 000000000..a6ee2da69 Binary files /dev/null and b/webroot/img/emoji/headingparrot.gif differ diff --git a/webroot/img/emoji/headsetparrot.gif b/webroot/img/emoji/headsetparrot.gif new file mode 100644 index 000000000..49687070b Binary files /dev/null and b/webroot/img/emoji/headsetparrot.gif differ diff --git a/webroot/img/emoji/hmmparrot.gif b/webroot/img/emoji/hmmparrot.gif new file mode 100644 index 000000000..d3d5ffe9e Binary files /dev/null and b/webroot/img/emoji/hmmparrot.gif differ diff --git a/webroot/img/emoji/hypnoparrot.gif b/webroot/img/emoji/hypnoparrot.gif new file mode 100644 index 000000000..2ccb8fed7 Binary files /dev/null and b/webroot/img/emoji/hypnoparrot.gif differ diff --git a/webroot/img/emoji/icecreamparrot.gif b/webroot/img/emoji/icecreamparrot.gif new file mode 100644 index 000000000..3903121b7 Binary files /dev/null and b/webroot/img/emoji/icecreamparrot.gif differ diff --git a/webroot/img/emoji/illuminatiparrot.gif b/webroot/img/emoji/illuminatiparrot.gif new file mode 100644 index 000000000..991eb3109 Binary files /dev/null and b/webroot/img/emoji/illuminatiparrot.gif differ diff --git a/webroot/img/emoji/jediparrot.gif b/webroot/img/emoji/jediparrot.gif new file mode 100644 index 000000000..c0be46124 Binary files /dev/null and b/webroot/img/emoji/jediparrot.gif differ diff --git a/webroot/img/emoji/keanu_thanks.gif b/webroot/img/emoji/keanu_thanks.gif new file mode 100644 index 000000000..989b9b759 Binary files /dev/null and b/webroot/img/emoji/keanu_thanks.gif differ diff --git a/webroot/img/emoji/laptop_parrot.gif b/webroot/img/emoji/laptop_parrot.gif new file mode 100644 index 000000000..183129324 Binary files /dev/null and b/webroot/img/emoji/laptop_parrot.gif differ diff --git a/webroot/img/emoji/loveparrot.gif b/webroot/img/emoji/loveparrot.gif new file mode 100644 index 000000000..b1dbc41b1 Binary files /dev/null and b/webroot/img/emoji/loveparrot.gif differ diff --git a/webroot/img/emoji/mandalorian.png b/webroot/img/emoji/mandalorian.png new file mode 100644 index 000000000..30ac1bea4 Binary files /dev/null and b/webroot/img/emoji/mandalorian.png differ diff --git a/webroot/img/emoji/margaritaparrot.gif b/webroot/img/emoji/margaritaparrot.gif new file mode 100644 index 000000000..1d6ce4c90 Binary files /dev/null and b/webroot/img/emoji/margaritaparrot.gif differ diff --git a/webroot/img/emoji/mario.gif b/webroot/img/emoji/mario.gif new file mode 100644 index 000000000..87f113333 Binary files /dev/null and b/webroot/img/emoji/mario.gif differ diff --git a/webroot/img/emoji/matrixparrot.gif b/webroot/img/emoji/matrixparrot.gif new file mode 100644 index 000000000..a7a68a004 Binary files /dev/null and b/webroot/img/emoji/matrixparrot.gif differ diff --git a/webroot/img/emoji/meldparrot.gif b/webroot/img/emoji/meldparrot.gif new file mode 100644 index 000000000..dd91bbd29 Binary files /dev/null and b/webroot/img/emoji/meldparrot.gif differ diff --git a/webroot/img/emoji/metalparrot.gif b/webroot/img/emoji/metalparrot.gif new file mode 100644 index 000000000..c4209b01c Binary files /dev/null and b/webroot/img/emoji/metalparrot.gif differ diff --git a/webroot/img/emoji/michaeljacksonparrot.gif b/webroot/img/emoji/michaeljacksonparrot.gif new file mode 100644 index 000000000..4217ca4e1 Binary files /dev/null and b/webroot/img/emoji/michaeljacksonparrot.gif differ diff --git a/webroot/img/emoji/moonparrot.gif b/webroot/img/emoji/moonparrot.gif new file mode 100644 index 000000000..ab8241d38 Binary files /dev/null and b/webroot/img/emoji/moonparrot.gif differ diff --git a/webroot/img/emoji/moonwalkingparrot.gif b/webroot/img/emoji/moonwalkingparrot.gif new file mode 100644 index 000000000..52c5dcf43 Binary files /dev/null and b/webroot/img/emoji/moonwalkingparrot.gif differ diff --git a/webroot/img/emoji/mustacheparrot.gif b/webroot/img/emoji/mustacheparrot.gif new file mode 100644 index 000000000..39b43f231 Binary files /dev/null and b/webroot/img/emoji/mustacheparrot.gif differ diff --git a/webroot/img/emoji/nicolas_cage_party.gif b/webroot/img/emoji/nicolas_cage_party.gif new file mode 100644 index 000000000..4f523c138 Binary files /dev/null and b/webroot/img/emoji/nicolas_cage_party.gif differ diff --git a/webroot/img/emoji/nodeparrot.gif b/webroot/img/emoji/nodeparrot.gif new file mode 100644 index 000000000..0a05f5924 Binary files /dev/null and b/webroot/img/emoji/nodeparrot.gif differ diff --git a/webroot/img/emoji/norwegianblueparrot.gif b/webroot/img/emoji/norwegianblueparrot.gif new file mode 100644 index 000000000..0aa9583ec Binary files /dev/null and b/webroot/img/emoji/norwegianblueparrot.gif differ diff --git a/webroot/img/emoji/opensourceparrot.gif b/webroot/img/emoji/opensourceparrot.gif new file mode 100644 index 000000000..3904b389e Binary files /dev/null and b/webroot/img/emoji/opensourceparrot.gif differ diff --git a/webroot/img/emoji/originalparrot.gif b/webroot/img/emoji/originalparrot.gif new file mode 100644 index 000000000..907b554b8 Binary files /dev/null and b/webroot/img/emoji/originalparrot.gif differ diff --git a/webroot/img/emoji/owncast.png b/webroot/img/emoji/owncast.png new file mode 100644 index 000000000..10be70a89 Binary files /dev/null and b/webroot/img/emoji/owncast.png differ diff --git a/webroot/img/emoji/palpatine.png b/webroot/img/emoji/palpatine.png new file mode 100644 index 000000000..2053ec3e7 Binary files /dev/null and b/webroot/img/emoji/palpatine.png differ diff --git a/webroot/img/emoji/papalparrot.gif b/webroot/img/emoji/papalparrot.gif new file mode 100644 index 000000000..6fb981cca Binary files /dev/null and b/webroot/img/emoji/papalparrot.gif differ diff --git a/webroot/img/emoji/parrot.gif b/webroot/img/emoji/parrot.gif new file mode 100644 index 000000000..458ad859d Binary files /dev/null and b/webroot/img/emoji/parrot.gif differ diff --git a/webroot/img/emoji/parrotnotfound.gif b/webroot/img/emoji/parrotnotfound.gif new file mode 100644 index 000000000..2a9bfc16c Binary files /dev/null and b/webroot/img/emoji/parrotnotfound.gif differ diff --git a/webroot/img/emoji/partyparrot.gif b/webroot/img/emoji/partyparrot.gif new file mode 100644 index 000000000..3cecb6860 Binary files /dev/null and b/webroot/img/emoji/partyparrot.gif differ diff --git a/webroot/img/emoji/phparrot.gif b/webroot/img/emoji/phparrot.gif new file mode 100644 index 000000000..449e17238 Binary files /dev/null and b/webroot/img/emoji/phparrot.gif differ diff --git a/webroot/img/emoji/pirateparrot.gif b/webroot/img/emoji/pirateparrot.gif new file mode 100644 index 000000000..76fdda463 Binary files /dev/null and b/webroot/img/emoji/pirateparrot.gif differ diff --git a/webroot/img/emoji/pizzaparrot.gif b/webroot/img/emoji/pizzaparrot.gif new file mode 100644 index 000000000..ce9e21ace Binary files /dev/null and b/webroot/img/emoji/pizzaparrot.gif differ diff --git a/webroot/img/emoji/pokeparrot.gif b/webroot/img/emoji/pokeparrot.gif new file mode 100644 index 000000000..1159e2a5e Binary files /dev/null and b/webroot/img/emoji/pokeparrot.gif differ diff --git a/webroot/img/emoji/popcornparrot.gif b/webroot/img/emoji/popcornparrot.gif new file mode 100644 index 000000000..e67329eca Binary files /dev/null and b/webroot/img/emoji/popcornparrot.gif differ diff --git a/webroot/img/emoji/porg.png b/webroot/img/emoji/porg.png new file mode 100644 index 000000000..aaedcfdf4 Binary files /dev/null and b/webroot/img/emoji/porg.png differ diff --git a/webroot/img/emoji/portalparrot.gif b/webroot/img/emoji/portalparrot.gif new file mode 100644 index 000000000..5971fbd2a Binary files /dev/null and b/webroot/img/emoji/portalparrot.gif differ diff --git a/webroot/img/emoji/pumpkinparrot.gif b/webroot/img/emoji/pumpkinparrot.gif new file mode 100644 index 000000000..6f9c9b2d0 Binary files /dev/null and b/webroot/img/emoji/pumpkinparrot.gif differ diff --git a/webroot/img/emoji/quadparrot.gif b/webroot/img/emoji/quadparrot.gif new file mode 100644 index 000000000..0449973a5 Binary files /dev/null and b/webroot/img/emoji/quadparrot.gif differ diff --git a/webroot/img/emoji/r2d2.png b/webroot/img/emoji/r2d2.png new file mode 100644 index 000000000..8f1ad871c Binary files /dev/null and b/webroot/img/emoji/r2d2.png differ diff --git a/webroot/img/emoji/redenvelopeparrot.gif b/webroot/img/emoji/redenvelopeparrot.gif new file mode 100644 index 000000000..75dc001ac Binary files /dev/null and b/webroot/img/emoji/redenvelopeparrot.gif differ diff --git a/webroot/img/emoji/ripparrot.gif b/webroot/img/emoji/ripparrot.gif new file mode 100644 index 000000000..99ae28845 Binary files /dev/null and b/webroot/img/emoji/ripparrot.gif differ diff --git a/webroot/img/emoji/rotatingparrot.gif b/webroot/img/emoji/rotatingparrot.gif new file mode 100644 index 000000000..1ec84cf4a Binary files /dev/null and b/webroot/img/emoji/rotatingparrot.gif differ diff --git a/webroot/img/emoji/ryangoslingparrot.gif b/webroot/img/emoji/ryangoslingparrot.gif new file mode 100644 index 000000000..2b84749ee Binary files /dev/null and b/webroot/img/emoji/ryangoslingparrot.gif differ diff --git a/webroot/img/emoji/rythmicalparrot.gif b/webroot/img/emoji/rythmicalparrot.gif new file mode 100644 index 000000000..33241619d Binary files /dev/null and b/webroot/img/emoji/rythmicalparrot.gif differ diff --git a/webroot/img/emoji/sadparrot.gif b/webroot/img/emoji/sadparrot.gif new file mode 100644 index 000000000..0ca87e56b Binary files /dev/null and b/webroot/img/emoji/sadparrot.gif differ diff --git a/webroot/img/emoji/schnitzelparrot.gif b/webroot/img/emoji/schnitzelparrot.gif new file mode 100644 index 000000000..cb7d81648 Binary files /dev/null and b/webroot/img/emoji/schnitzelparrot.gif differ diff --git a/webroot/img/emoji/scienceparrot.gif b/webroot/img/emoji/scienceparrot.gif new file mode 100644 index 000000000..f7c8a6952 Binary files /dev/null and b/webroot/img/emoji/scienceparrot.gif differ diff --git a/webroot/img/emoji/shipitparrot.gif b/webroot/img/emoji/shipitparrot.gif new file mode 100644 index 000000000..072227de8 Binary files /dev/null and b/webroot/img/emoji/shipitparrot.gif differ diff --git a/webroot/img/emoji/shufflepartyparrot.gif b/webroot/img/emoji/shufflepartyparrot.gif new file mode 100644 index 000000000..159986a86 Binary files /dev/null and b/webroot/img/emoji/shufflepartyparrot.gif differ diff --git a/webroot/img/emoji/sintparrot.gif b/webroot/img/emoji/sintparrot.gif new file mode 100644 index 000000000..8138e5430 Binary files /dev/null and b/webroot/img/emoji/sintparrot.gif differ diff --git a/webroot/img/emoji/sithparrot.gif b/webroot/img/emoji/sithparrot.gif new file mode 100644 index 000000000..1f349cb8a Binary files /dev/null and b/webroot/img/emoji/sithparrot.gif differ diff --git a/webroot/img/emoji/skiparrot.gif b/webroot/img/emoji/skiparrot.gif new file mode 100644 index 000000000..668014e55 Binary files /dev/null and b/webroot/img/emoji/skiparrot.gif differ diff --git a/webroot/img/emoji/sleepingparrot.gif b/webroot/img/emoji/sleepingparrot.gif new file mode 100644 index 000000000..882baf290 Binary files /dev/null and b/webroot/img/emoji/sleepingparrot.gif differ diff --git a/webroot/img/emoji/sonic.gif b/webroot/img/emoji/sonic.gif new file mode 100644 index 000000000..fb918e88f Binary files /dev/null and b/webroot/img/emoji/sonic.gif differ diff --git a/webroot/img/emoji/spyparrot.gif b/webroot/img/emoji/spyparrot.gif new file mode 100644 index 000000000..d3fa88dd3 Binary files /dev/null and b/webroot/img/emoji/spyparrot.gif differ diff --git a/webroot/img/emoji/stalkerparrot.gif b/webroot/img/emoji/stalkerparrot.gif new file mode 100644 index 000000000..349d6494b Binary files /dev/null and b/webroot/img/emoji/stalkerparrot.gif differ diff --git a/webroot/img/emoji/starwars.png b/webroot/img/emoji/starwars.png new file mode 100644 index 000000000..ddbede438 Binary files /dev/null and b/webroot/img/emoji/starwars.png differ diff --git a/webroot/img/emoji/stayhomeparrot.gif b/webroot/img/emoji/stayhomeparrot.gif new file mode 100644 index 000000000..fc0882828 Binary files /dev/null and b/webroot/img/emoji/stayhomeparrot.gif differ diff --git a/webroot/img/emoji/storm_trooper.gif b/webroot/img/emoji/storm_trooper.gif new file mode 100644 index 000000000..3f5af01a7 Binary files /dev/null and b/webroot/img/emoji/storm_trooper.gif differ diff --git a/webroot/img/emoji/stormtrooper.png b/webroot/img/emoji/stormtrooper.png new file mode 100644 index 000000000..1dec38b09 Binary files /dev/null and b/webroot/img/emoji/stormtrooper.png differ diff --git a/webroot/img/emoji/sushiparrot.gif b/webroot/img/emoji/sushiparrot.gif new file mode 100644 index 000000000..a22122c47 Binary files /dev/null and b/webroot/img/emoji/sushiparrot.gif differ diff --git a/webroot/img/emoji/tacoparrot.gif b/webroot/img/emoji/tacoparrot.gif new file mode 100644 index 000000000..dcef11dc1 Binary files /dev/null and b/webroot/img/emoji/tacoparrot.gif differ diff --git a/webroot/img/emoji/tennisparrot.gif b/webroot/img/emoji/tennisparrot.gif new file mode 100644 index 000000000..fe6f9be69 Binary files /dev/null and b/webroot/img/emoji/tennisparrot.gif differ diff --git a/webroot/img/emoji/thanks.png b/webroot/img/emoji/thanks.png new file mode 100644 index 000000000..2a9d0ce29 Binary files /dev/null and b/webroot/img/emoji/thanks.png differ diff --git a/webroot/img/emoji/thumbsupparrot.gif b/webroot/img/emoji/thumbsupparrot.gif new file mode 100644 index 000000000..9c6e45f66 Binary files /dev/null and b/webroot/img/emoji/thumbsupparrot.gif differ diff --git a/webroot/img/emoji/tiedyeparrot.gif b/webroot/img/emoji/tiedyeparrot.gif new file mode 100644 index 000000000..24ab30984 Binary files /dev/null and b/webroot/img/emoji/tiedyeparrot.gif differ diff --git a/webroot/img/emoji/tpparrot.gif b/webroot/img/emoji/tpparrot.gif new file mode 100644 index 000000000..7456ff262 Binary files /dev/null and b/webroot/img/emoji/tpparrot.gif differ diff --git a/webroot/img/emoji/transparront.gif b/webroot/img/emoji/transparront.gif new file mode 100644 index 000000000..1efb20346 Binary files /dev/null and b/webroot/img/emoji/transparront.gif differ diff --git a/webroot/img/emoji/twinsparrot.gif b/webroot/img/emoji/twinsparrot.gif new file mode 100644 index 000000000..ba25a64d9 Binary files /dev/null and b/webroot/img/emoji/twinsparrot.gif differ diff --git a/webroot/img/emoji/upvoteparrot.gif b/webroot/img/emoji/upvoteparrot.gif new file mode 100644 index 000000000..5d2137a81 Binary files /dev/null and b/webroot/img/emoji/upvoteparrot.gif differ diff --git a/webroot/img/emoji/vikingparrot.gif b/webroot/img/emoji/vikingparrot.gif new file mode 100644 index 000000000..5d6fcb690 Binary files /dev/null and b/webroot/img/emoji/vikingparrot.gif differ diff --git a/webroot/img/emoji/wesmart.png b/webroot/img/emoji/wesmart.png new file mode 100644 index 000000000..eb9f865f4 Binary files /dev/null and b/webroot/img/emoji/wesmart.png differ diff --git a/webroot/img/emoji/wfhparrot.gif b/webroot/img/emoji/wfhparrot.gif new file mode 100644 index 000000000..69029c408 Binary files /dev/null and b/webroot/img/emoji/wfhparrot.gif differ diff --git a/webroot/img/emoji/wineparrot.gif b/webroot/img/emoji/wineparrot.gif new file mode 100644 index 000000000..19b57d6f0 Binary files /dev/null and b/webroot/img/emoji/wineparrot.gif differ diff --git a/webroot/img/emoji/yoda.gif b/webroot/img/emoji/yoda.gif new file mode 100644 index 000000000..117958c7f Binary files /dev/null and b/webroot/img/emoji/yoda.gif differ diff --git a/webroot/index.html b/webroot/index.html index b9e112ee8..b4fb2b46b 100644 --- a/webroot/index.html +++ b/webroot/index.html @@ -28,7 +28,6 @@ - @@ -156,14 +155,11 @@
- - - +
+
😏
+
+ + - \ No newline at end of file + diff --git a/webroot/js/app.js b/webroot/js/app.js index e4582adf9..1c5a8d9b5 100644 --- a/webroot/js/app.js +++ b/webroot/js/app.js @@ -8,12 +8,9 @@ const MESSAGE_ONLINE = 'Stream is online'; const TEMP_IMAGE = 'data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7'; -const LOCAL_TEST = window.location.href.indexOf('localhost:') >= 0; - -const URL_PREFIX = LOCAL_TEST ? 'http://localhost:8080' : ''; -const URL_CONFIG = `${URL_PREFIX}/config`; -const URL_STATUS = `${URL_PREFIX}/status`; -const URL_CHAT_HISTORY = `${URL_PREFIX}/chat`; +const URL_CONFIG = `/config`; +const URL_STATUS = `/status`; +const URL_CHAT_HISTORY = `/chat`; const TIMER_STATUS_UPDATE = 5000; // ms const TIMER_DISABLE_CHAT_AFTER_OFFLINE = 5 * 60 * 1000; // 5 mins @@ -120,7 +117,7 @@ class Owncast { window.document.title = data.title; - this.getExtraUserContent(`${URL_PREFIX}${data.extraUserInfoFileName}`); + this.getExtraUserContent(`${data.extraUserInfoFileName}`); this.configData = data; } diff --git a/webroot/js/emoji.js b/webroot/js/emoji.js new file mode 100644 index 000000000..33ef36b48 --- /dev/null +++ b/webroot/js/emoji.js @@ -0,0 +1,41 @@ +import { EmojiButton } from 'https://cdn.skypack.dev/@joeattardi/emoji-button' + +fetch('/emoji') + .then(response => { + if (!response.ok) { + throw new Error(`Network response was not ok ${response.ok}`); + } + return response.json(); + }) + .then(json => { + setupEmojiPickerWithCustomEmoji(json); + }) + .catch(error => { + this.handleNetworkingError(`Emoji Fetch: ${error}`); + }); + +function setupEmojiPickerWithCustomEmoji(customEmoji) { + const picker = new EmojiButton({ + zIndex: 100, + theme: 'dark', + custom: customEmoji, + initialCategory: 'custom', + showPreview: false, + position: { + top: '50%', + right: '100' + } + }); + const trigger = document.querySelector('#emoji-button'); + + trigger.addEventListener('click', () => picker.togglePicker(picker)); + picker.on('emoji', emoji => { + if (emoji.url) { + const url = location.protocol + "//" + location.host + "/" + emoji.url; + const name = url.split('\\').pop().split('/').pop(); + document.querySelector('#message-body-form').innerHTML += "\"""; + } else { + document.querySelector('#message-body-form').innerHTML += emoji.emoji; + } + }); +} diff --git a/webroot/js/message.js b/webroot/js/message.js index e000c992c..f3ca460b0 100644 --- a/webroot/js/message.js +++ b/webroot/js/message.js @@ -19,7 +19,7 @@ class Message { formatText() { showdown.setFlavor('github'); - var markdownToHTML = new showdown.Converter({ + let formattedText = new showdown.Converter({ emoji: true, openLinksInNewWindow: true, tables: false, @@ -28,16 +28,73 @@ class Message { strikethrough: true, ghMentions: false, }).makeHtml(this.body); - const linked = autoLink(markdownToHTML, { - embed: true, - removeHTTP: true, - linkAttr: { - target: '_blank' - } - }); - const highlighted = this.highlightUsername(linked); - return addNewlines(highlighted); + + formattedText = this.linkify(formattedText, this.body); + formattedText = this.highlightUsername(formattedText); + + return addNewlines(formattedText); } + + // TODO: Move this into a util function once we can organize code + // and split things up. + linkify(text, rawText) { + const urls = getURLs(stripTags(rawText)); + if (urls) { + urls.forEach(function (url) { + let linkURL = url; + + // Add http prefix if none exist in the URL so it actually + // will work in an anchor tag. + if (linkURL.indexOf('http') === -1) { + linkURL = 'http://' + linkURL; + } + + // Remove the protocol prefix in the display URLs just to make + // things look a little nicer. + const displayURL = url.replace(/(^\w+:|^)\/\//, ''); + const link = `${displayURL}`; + text = text.replace(url, link); + + if (getYoutubeIdFromURL(url)) { + if (this.isTextJustURLs(text, [url, displayURL])) { + text = ''; + } else { + text += '
'; + } + + const youtubeID = getYoutubeIdFromURL(url); + text += getYoutubeEmbedFromID(youtubeID); + } else if (url.indexOf('instagram.com/p/') > -1) { + if (this.isTextJustURLs(text, [url, displayURL])) { + text = ''; + } else { + text += `
`; + } + text += getInstagramEmbedFromURL(url); + } else if (isImage(url)) { + if (this.isTextJustURLs(text, [url, displayURL])) { + text = ''; + } else { + text += `
`; + } + text += getImageForURL(url); + } + }.bind(this)); + } + return text; + } + + isTextJustURLs(text, urls) { + for (var i = 0; i < urls.length; i++) { + const url = urls[i]; + if (stripTags(text) === url) { + return true; + } + } + + return false; + } + userColor() { return messageBubbleColorForString(this.author); } @@ -73,7 +130,7 @@ class MessagingInterface { this.tagMessageFormWarning = document.getElementById('message-form-warning'); this.inputMessageAuthor = document.getElementById('self-message-author'); - this.inputChangeUserName = document.getElementById('username-change-input'); + this.inputChangeUserName = document.getElementById('username-change-input'); this.btnUpdateUserName = document.getElementById('button-update-username'); this.btnCancelUpdateUsername = document.getElementById('button-cancel-change'); @@ -204,8 +261,8 @@ class MessagingInterface { } tryToComplete() { - const rawValue = this.formMessageInput.value; - const position = this.formMessageInput.selectionStart; + const rawValue = this.formMessageInput.innerHTML; + const position = getCaretPosition(this.formMessageInput); const at = rawValue.lastIndexOf('@', position - 1); if (at === -1) { @@ -231,9 +288,9 @@ class MessagingInterface { if (possibilities.length > 0) { this.suggestion = possibilities[this.completionIndex]; - this.formMessageInput.value = rawValue.substring(0, at + 1) + this.suggestion + ' ' + rawValue.substring(position); - this.formMessageInput.selectionStart = at + this.suggestion.length + 2; - this.formMessageInput.selectionEnd = this.formMessageInput.selectionStart; + // TODO: Fix the space not working. I'm guessing because the DOM ignores spaces and it requires a nbsp or something? + this.formMessageInput.innerHTML = rawValue.substring(0, at + 1) + this.suggestion + ' ' + rawValue.substring(position); + setCaretPosition(this.formMessageInput, at + this.suggestion.length + 2); } return true; @@ -241,7 +298,7 @@ class MessagingInterface { handleMessageInputKeydown(event) { var okCodes = [37,38,39,40,16,91,18,46,8]; - var value = this.formMessageInput.value.trim(); + var value = this.formMessageInput.innerHTML.trim(); var numCharsLeft = this.maxMessageLength - value.length; if (event.keyCode === 13) { // enter if (!this.prepNewLine) { @@ -260,7 +317,7 @@ class MessagingInterface { event.preventDefault(); // value could have been changed, update variables - value = this.formMessageInput.value.trim(); + value = this.formMessageInput.innerHTML.trim(); numCharsLeft = this.maxMessageLength - value.length; } } @@ -287,7 +344,7 @@ class MessagingInterface { } handleSubmitChatButton(event) { - var value = this.formMessageInput.value.trim(); + var value = this.formMessageInput.innerHTML.trim(); if (value) { this.submitChat(value); event.preventDefault(); @@ -310,7 +367,7 @@ class MessagingInterface { this.send(message); // clear out things. - this.formMessageInput.value = ''; + this.formMessageInput.innerHTML = ''; this.tagMessageFormWarning.innerText = ''; const hasSentFirstChatMessage = getLocalStorage(KEY_CHAT_FIRST_MESSAGE_SENT); @@ -322,20 +379,25 @@ class MessagingInterface { disableChat() { if (this.formMessageInput) { - this.formMessageInput.disabled = true; - this.formMessageInput.placeholder = CHAT_PLACEHOLDER_OFFLINE; + this.formMessageInput.contentEditable = false; + this.formMessageInput.innerHTML = ''; + this.formMessageInput.setAttribute("placeholder", CHAT_PLACEHOLDER_OFFLINE); } } + enableChat() { if (this.formMessageInput) { - this.formMessageInput.disabled = false; + this.formMessageInput.contentEditable = true; this.setChatPlaceholderText(); } } setChatPlaceholderText() { + // NOTE: This is a fake placeholder that is being styled via CSS. + // You can't just set the .placeholder property because it's not a form element. const hasSentFirstChatMessage = getLocalStorage(KEY_CHAT_FIRST_MESSAGE_SENT); - this.formMessageInput.placeholder = hasSentFirstChatMessage ? CHAT_PLACEHOLDER_TEXT : CHAT_INITIAL_PLACEHOLDER_TEXT + const placeholderText = hasSentFirstChatMessage ? CHAT_PLACEHOLDER_TEXT : CHAT_INITIAL_PLACEHOLDER_TEXT; + this.formMessageInput.setAttribute("placeholder", placeholderText); } // handle Vue.js message display @@ -373,4 +435,88 @@ class MessagingInterface { } } -export { Message, MessagingInterface } \ No newline at end of file +export { Message, MessagingInterface } + +function stripTags(str) { + return str.replace(/<\/?[^>]+(>|$)/g, ""); +} + +function getURLs(str) { + var exp = /((\w+:\/\/\S+)|(\w+[\.:]\w+\S+))[^\s,\.]/ig; + return str.match(exp); +} + +function getYoutubeIdFromURL(url) { + try { + var regExp = /^.*(youtu.be\/|v\/|u\/\w\/|embed\/|watch\?v=|\&v=)([^#\&\?]*).*/; + var match = url.match(regExp); + + if (match && match[2].length == 11) { + return match[2]; + } else { + return null; + } + } catch (e) { + console.log(e); + return null; + } +} + +function getYoutubeEmbedFromID(id) { + return ``; +} + +function getInstagramEmbedFromURL(url) { + const urlObject = new URL(url.replace(/\/$/, "")); + urlObject.pathname += "/embed"; + return ``; +} + +function isImage(url) { + const re = /\.(jpe?g|png|gif)$/; + const isImage = re.test(url); + return isImage; +} + +function getImageForURL(url) { + return ``; +} + + +// Taken from https://stackoverflow.com/questions/3972014/get-contenteditable-caret-index-position +function getCaretPosition(editableDiv) { + var caretPos = 0, + sel, range; + if (window.getSelection) { + sel = window.getSelection(); + if (sel.rangeCount) { + range = sel.getRangeAt(0); + if (range.commonAncestorContainer.parentNode == editableDiv) { + caretPos = range.endOffset; + } + } + } else if (document.selection && document.selection.createRange) { + range = document.selection.createRange(); + if (range.parentElement() == editableDiv) { + var tempEl = document.createElement("span"); + editableDiv.insertBefore(tempEl, editableDiv.firstChild); + var tempRange = range.duplicate(); + tempRange.moveToElementText(tempEl); + tempRange.setEndPoint("EndToEnd", range); + caretPos = tempRange.text.length; + } + } + return caretPos; +} + +// Pieced together from parts of https://stackoverflow.com/questions/6249095/how-to-set-caretcursor-position-in-contenteditable-element-div +function setCaretPosition(editableDiv, position) { + var range = document.createRange(); + var sel = window.getSelection(); + range.selectNode(editableDiv); + range.setStart(editableDiv.childNodes[0], position); + range.collapse(true); + + sel.removeAllRanges(); + sel.addRange(range); +} \ No newline at end of file diff --git a/webroot/js/player.js b/webroot/js/player.js index 890bc2833..986e3566d 100644 --- a/webroot/js/player.js +++ b/webroot/js/player.js @@ -1,9 +1,8 @@ // https://docs.videojs.com/player const VIDEO_ID = 'video'; -const LOCAL_TEST = window.location.href.indexOf('localhost:') >= 0; -const URL_PREFIX = LOCAL_TEST ? 'http://localhost:8080' : ''; -const URL_STREAM = `${URL_PREFIX}/hls/stream.m3u8`; +// TODO: This directory is customizable in the config. So we should expose this via the config API. +const URL_STREAM = `/hls/stream.m3u8`; // Video setup const VIDEO_SRC = { diff --git a/webroot/js/utils.js b/webroot/js/utils.js index 632beb573..ef388da94 100644 --- a/webroot/js/utils.js +++ b/webroot/js/utils.js @@ -1,9 +1,12 @@ -export const LOCAL_TEST = window.location.href.indexOf('localhost:') >= 0; -export const URL_PREFIX = LOCAL_TEST ? 'http://localhost:8080' : ''; +const URL_STATUS = `/status`; +const URL_CHAT_HISTORY = `/chat`; +// TODO: This directory is customizable in the config. So we should expose this via the config API. +const URL_STREAM = `/hls/stream.m3u8`; +const URL_WEBSOCKET = `${location.protocol === 'https:' ? 'wss' : 'ws'}://${location.host}/entry`; -export const POSTER_DEFAULT = `${URL_PREFIX}/img/logo.png`; -export const POSTER_THUMB = `${URL_PREFIX}/thumbnail.jpg`; +const POSTER_DEFAULT = `/img/logo.png`; +const POSTER_THUMB = `/thumbnail.jpg`; export const URL_OWNCAST = 'https://github.com/gabek/owncast'; // used in footer diff --git a/webroot/js/websocket.js b/webroot/js/websocket.js index bc4efd1d9..6c628d6e5 100644 --- a/webroot/js/websocket.js +++ b/webroot/js/websocket.js @@ -1,9 +1,6 @@ import SOCKET_MESSAGE_TYPES from './chat/socketMessageTypes.js'; -const LOCAL_TEST = window.location.href.indexOf('localhost:') >= 0; -const URL_WEBSOCKET = LOCAL_TEST - ? 'wss://goth.land/entry' - : `${location.protocol === 'https:' ? 'wss' : 'ws'}://${location.host}/entry`; +const URL_WEBSOCKET = `${location.protocol === 'https:' ? 'wss' : 'ws'}://${location.host}/entry`; const TIMER_WEBSOCKET_RECONNECT = 5000; // ms diff --git a/webroot/styles/layout.css b/webroot/styles/layout.css index 81de24302..b179dfef1 100644 --- a/webroot/styles/layout.css +++ b/webroot/styles/layout.css @@ -376,10 +376,21 @@ h2 { } #message-body-form { font-size: 1em; + height: 60px; } #message-body-form:disabled{ opacity: .5; } +#message-body-form img { + display: inline; + padding-left: 5px; + padding-right: 5px; +} + +#message-body-form .emoji { + width: 40px; +} + #message-form-actions { flex-direction: row; justify-content: space-between; @@ -387,6 +398,15 @@ h2 { width: 100%; } +.message-text img { + display: inline; + padding-left: 5px; + padding-right: 5px; +} + +.message-text .emoji { + width: 60px; +} /* ************************************************8 */ @@ -618,18 +638,86 @@ h2 { border-radius: 15px; } +.message-text .instagram-embed { + height: 314px; +} + +.message-text code { + background-color:darkslategrey; + padding: 3px; +} +/* Emoji picker */ +#emoji-button { + position: relative; + top: -65px; + right: 10px; + cursor: pointer; +} + .message-text .embedded-image { width: 100%; height: 170px; border-radius: 15px; } -.message-text .highlighted { - color: orange; - font-weight: bold; +.message-text code { + background-color:darkslategrey; + padding: 3px; +} + +/* Emoji picker */ +#emoji-button { + position: relative; + top: -65px; + right: 10px; + cursor: pointer; +} +.message-text .embedded-image { + width: 100%; + height: 170px; + border-radius: 15px; } .message-text code { background-color:darkslategrey; padding: 3px; -} \ No newline at end of file +} +.message-text .highlighted { + color: orange; + font-weight: 400; + font-size: 14px; + +} + +.message-text code { + background-color:darkslategrey; + padding: 3px; +} + +/* +The chat input has a fake placeholder that is styled below. +It pulls the placeholder text from the div's placeholder attribute. +But really it's just the innerHTML content. +*/ + +/* If the div is empty then show the placeholder */ +#message-body-form:empty:before{ + content: attr(placeholder); + pointer-events: none; + display: block; /* For Firefox */ + + /* Style the div's placeholder text color */ + color: rgba(0, 0, 0, 0.5); +} + +/* When chat is enabled (contenteditable=true) */ +#message-body-form[contenteditable=true]:before { + opacity: 1.0; +} + + +/* When chat is disabled (contenteditable=false) chat input div should appear disabled. */ +#message-body-form[contenteditable=false] { + opacity: 0.6; +} + diff --git a/webroot/vendor/autolink.js b/webroot/vendor/autolink.js deleted file mode 100644 index 4bbfba284..000000000 --- a/webroot/vendor/autolink.js +++ /dev/null @@ -1,238 +0,0 @@ -const re = { - http: /.*?:\/\//g, - url: /(\s|^)((https?|ftp):\/\/)?[\da-z\d:%._\+~#=-]{2,256}\.[a-z]{2,6}\b([\da-z:%_\+.~#?&//=-]*)/gi, - image: /\.(jpe?g|png|gif)$/, - email: /(([^<>()\[\]\\.,;:\s@"]+(\.[^<>()\[\]\\.,;:\s@"]+)*)|(".+"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))/gi, - cloudmusic: /http:\/\/music\.163\.com\/#\/song\?id=(\d+)/i, - kickstarter: /(https?:\/\/www\.kickstarter\.com\/projects\/\d+\/[a-zA-Z0-9_-]+)(\?\w+\=\w+)?/i, - youtube: /https?:\/\/www\.youtube\.com\/watch\?v=([a-zA-Z0-9_-]+)(\?\w+\=\w+)?/i, - vimeo: /https?:\/\/(?:www\.|player\.)?vimeo.com\/(?:channels\/(?:\w+\/)?|groups\/[^\/]*\/videos\/|album\/\d+\/video\/|video\/|)(\d+)(?:$|\/|\?)/i, - youku: /https?:\/\/v\.youku\.com\/v_show\/id_([a-zA-Z0-9_\=-]+).html(\?\w+\=\w+)?(\#\w+)?/i -} -/** - * AutoLink constructor function - * - * @param {String} text - * @param {Object} options - * @constructor - */ -function AutoLink(string, options = {}) { - this.string = options.safe ? safe_tags_replace(string) : string - this.options = options - this.attrs = '' - this.linkAttr = '' - this.imageAttr = '' - if (this.options.sharedAttr) { - this.attrs = getAttr(this.options.sharedAttr) - } - if (this.options.linkAttr) { - this.linkAttr = getAttr(this.options.linkAttr) - } - if (this.options.imageAttr) { - this.imageAttr = getAttr(this.options.imageAttr) - } -} - -AutoLink.prototype = { - constructor: AutoLink, - /** - * call relative functions to parse url/email/image - * - * @returns {String} - */ - parse: function() { - var shouldReplaceImage = defaultTrue(this.options.image) - var shouldRelaceEmail = defaultTrue(this.options.email) - var shouldRelaceBr = defaultTrue(this.options.br) - - var result = '' - if (!shouldReplaceImage) { - result = this.string.replace(re.url, this.formatURLMatch.bind(this)) - } else { - result = this.string.replace(re.url, this.formatIMGMatch.bind(this)) - } - if (shouldRelaceEmail) { - result = this.formatEmailMatch.call(this, result) - } - if (shouldRelaceBr) { - result = result.replace(/\r?\n/g, '
') - } - return result - }, - /** - * @param {String} match - * @returns {String} Offset 1 - */ - formatURLMatch: function(match, p1) { - match = prepHTTP(match.trim()) - if (this.options.cloudmusic || this.options.embed) { - if (match.indexOf('music.163.com/#/song?id=') > -1) { - return match.replace( - re.cloudmusic, - p1 + - '' - ) - } - } - if (this.options.kickstarter || this.options.embed) { - if (re.kickstarter.test(match)) { - return match.replace( - re.kickstarter, - p1 + - '' - ) - } - } - if (this.options.vimeo || this.options.embed) { - if (re.vimeo.test(match)) { - return match.replace( - re.vimeo, - p1 + - '' - ) - } - } - if (this.options.youtube || this.options.embed) { - if (re.youtube.test(match)) { - return match.replace( - re.youtube, - p1 + - '' - ) - } - } - if (this.options.youku || this.options.embed) { - if (re.youku.test(match)) { - return match.replace( - re.youku, - p1 + - '' - ) - } - } - var text = this.options.removeHTTP ? removeHTTP(match) : match - return ( - p1 + - '' + - text + - '' - ) - }, - /** - * @param {String} match - * @param {String} Offset 1 - */ - formatIMGMatch: function(match, p1) { - match = match.trim() - var isIMG = re.image.test(match) - if (isIMG) { - return ( - p1 + - '' - ) - } - return this.formatURLMatch(match, p1) - }, - /** - * @param {String} text - */ - formatEmailMatch: function(text) { - return text.replace( - re.email, - '$&' - ) - } -} - -/** - * return true if undefined - * else return itself - * - * @param {Boolean} val - * @returns {Boolean} - */ -function defaultTrue(val) { - return typeof val === 'undefined' ? true : val -} - -/** - * parse attrs from object - * - * @param {Object} obj - * @returns {Stirng} - */ -function getAttr(obj) { - var attr = '' - for (var key in obj) { - if (key) { - attr += ' ' + key + '="' + obj[key] + '"' - } - } - return attr -} - -/** - * @param {String} url - * @returns {String} - */ -function prepHTTP(url) { - if (url.substring(0, 4) !== 'http' && url.substring(0, 2) !== '//') { - return 'http://' + url - } - return url -} - -/** - * @param {String} url - * @returns {String} - */ -function removeHTTP(url) { - return url.replace(re.http, '') -} - -var tagsToReplace = { - '&': '&', - '<': '<', - '>': '>' -} - -/** - * Replace tag if should be replace - * - * @param {String} tag - * @returns {String} - */ -function replaceTag(tag) { - return tagsToReplace[tag] || tag -} - -/** - * Make string safe by replacing html tag - * - * @param {String} str - * @returns {String} - */ -function safe_tags_replace(str) { - return str.replace(/[&<>]/g, replaceTag) -} - -/** - * return an instance of AutoLink - * - * @param {String} string - * @param {Object} options - * @returns {Object} - */ -function autoLink(string, options) { - return new AutoLink(string, options).parse() -}