summaryrefslogtreecommitdiff
path: root/src/Main.hs
diff options
context:
space:
mode:
authorTom Smeding <tom@tomsmeding.com>2026-04-09 22:14:55 +0200
committerTom Smeding <tom@tomsmeding.com>2026-04-09 22:14:55 +0200
commitb5c5b51792adc4a487554190e730f928574f889b (patch)
treed3e060a64463996c7b79953d84e7d276911f10a4 /src/Main.hs
parent0710fa9b2cac6a3f3d18de6b303c69b2af606fd5 (diff)
Nick colors (only sensible in dark mode so far)nickcolor
Diffstat (limited to 'src/Main.hs')
-rw-r--r--src/Main.hs28
1 files changed, 27 insertions, 1 deletions
diff --git a/src/Main.hs b/src/Main.hs
index cc4ad7e..d315492 100644
--- a/src/Main.hs
+++ b/src/Main.hs
@@ -6,11 +6,12 @@ module Main (main) where
import Control.Exception (mask_)
import Control.Monad (when, forM, guard)
+import Data.Bits (xor, shiftR, (.&.))
import Data.ByteString (ByteString)
import Data.ByteString qualified as BS
import Data.ByteString.Char8 qualified as BS8
import Data.ByteString.Lazy qualified as BSL
-import Data.Char (isDigit, ord)
+import Data.Char (isDigit, chr, ord)
import Data.Function (on, (&))
import Data.IORef
import Data.List.NonEmpty (NonEmpty((:|)), groupBy)
@@ -21,6 +22,9 @@ import Data.Text qualified as T
import Data.Text.Encoding qualified as TE
import Data.Text.IO.Utf8 qualified as T
import Data.Time (Day, toGregorian, fromGregorianValid)
+import Data.Word
+import Graphics.Color.Space
+import Graphics.Color.Space.OKLAB.LCH
import Network.Wai
import Network.HTTP.Types
import Network.Wai.Handler.Warp (runSettings, defaultSettings, setFork, setPort)
@@ -120,6 +124,7 @@ pageLog conf pages index req alias =
,"nickwrap1" ~> nickw1
,"nick" ~> nick
,"nickwrap2" ~> nickw2
+ ,"nickcolor" ~> nickColor nick
,"message" ~> msg]
| ((time, eid, ev), dayidx) <- zip events [0..]
, let (classlist, (nickw1, nick, nickw2), msg) = renderEvent ev]]
@@ -163,6 +168,7 @@ pageCalendarDay conf pages index req alias datestr =
,"nickwrap1" ~> nickw1
,"nick" ~> nick
,"nickwrap2" ~> nickw2
+ ,"nickcolor" ~> nickColor nick
,"message" ~> msg]
| ((time, eid, ev), dayidx) <- zip events [0..]
, let (classlist, (nickw1, nick, nickw2), msg) = renderEvent ev]]
@@ -207,6 +213,26 @@ renderEvent = \case
ParseError -> (j "ev-parseerror", (no, "", no), "<parse error>")
where no = Nothing; j = Just
+-- | Returns a CSS color string, including the @#@
+nickColor :: Text -> Text
+nickColor nick =
+ let -- mix (just some random odd constants)
+ n1 = T.foldl' (\n c -> 0x678731a3 * (fromIntegral (ord c) `xor` n) + 0xbc3c0a93) 0xbb115003 nick :: Word32
+ -- scramble (two steps from splitmix32)
+ n2 = let z1 = (n1 `xor` (n1 `shiftR` 16)) * 0x85ebca6b
+ in (z1 `xor` (z1 `shiftR` 13)) * 0xc2b2ae35
+ in T.pack $ "hsl(" ++ show (floor @Double @Int (fromIntegral n2 / 2**32 * 360)) ++ " 60% 70%)"
+ -- -- construct the OKLCH color
+ -- clr1 = ColorOKLCH @Double 0.8256 0.0859 (fromIntegral n2 / 2**32 * 360)
+ -- -- convert to sRGB
+ -- ColorRGB r g b = convertColor @(SRGB NonLinear) clr1
+ -- -- render as css color
+ -- toHex val = let byte = floor (max 0 (min 1 val) * 255.99)
+ -- toHexDig v | v < 10 = chr (ord '0' + v)
+ -- | otherwise = chr (ord 'a' + v - 10)
+ -- in [toHexDig (byte `shiftR` 4), toHexDig (byte .&. 15)]
+ -- in T.pack $ '#' : toHex r ++ toHex g ++ toHex b
+
pageCalendar :: Config -> Pages -> Index -> Text -> IO Response
pageCalendar conf pages index alias =
case econfAlias2Chan conf Map.!? alias of