import gleam/bit_array import gleam/dict.{type Dict} import gleam/int import gleam/list import gleam/result import gleam/string import image import simplifile import wisp pub type CachedImage { CachedImage(base64: String, info: image.ImageInformation) } pub type ThemeCache = Dict(String, Dict(Int, CachedImage)) pub fn load_themes() { let themes = case simplifile.read_directory("./themes") { Ok(files) -> files Error(_) -> { wisp.log_error("Error reading themes directory") [] } } themes |> list.map(fn(theme) { #(theme, load_theme(theme)) }) |> dict.from_list } fn load_theme(theme) -> Dict(Int, CachedImage) { let theme_directory = "./themes/" <> theme let files = case simplifile.read_directory(theme_directory) { Ok(files) -> files Error(_) -> { wisp.log_error("Error reading theme directory " <> theme_directory) [] } } files |> list.filter_map(fn(file) { use digit <- result.try(parse_digit_filename(file)) use cached_image <- result.try(load_cached_image( theme_directory <> "/" <> file, )) Ok(#(digit, cached_image)) }) |> dict.from_list } fn parse_digit_filename(file) { case string.split(file, ".") { [digit, _extension] -> int.parse(digit) _ -> Error(Nil) } } fn load_cached_image(path) { case simplifile.read_bits(from: path) { Ok(image_data) -> case image.get_image_information(image_data) { Ok(info) -> Ok(CachedImage( base64: bit_array.base64_encode(image_data, False), info: info, )) Error(_) -> { wisp.log_error("Error getting image information for " <> path) Error(Nil) } } Error(_) -> { wisp.log_error("Error reading image file " <> path) Error(Nil) } } } pub fn get_image(cache, theme, digit) -> Result(CachedImage, Nil) { dict.get(cache, theme) |> result.then(fn(theme_images) { dict.get(theme_images, digit) }) }