package main // This file caches images in memory so we are not loading them from disk every time we need them // It also does the same for images that need to be grabbed from HTTP. import ( "crypto/sha256" "fmt" "github.com/diamondburned/gotk4/pkg/gdk/v4" "github.com/diamondburned/gotk4/pkg/gtk/v4" "github.com/kirsle/configdir" "io" "net/http" "os" "path/filepath" "sync" ) // global or app-level map/cache // var textureCache = make(map[string]gdk.Paintabler) var textureCache sync.Map // Invalid images, if an image/avatar cannot be loaded on the system (e.g: incompatible format) it's put here var invalidImages = make(map[string]bool) func ensureCache() (string, error) { cachePath := configdir.LocalCache("lambda-im") err := configdir.MakePath(cachePath) // Ensure it exists. if err != nil { return "", err } return cachePath, nil } func getTexture(path string) (gdk.Paintabler, error) { tex, exists := textureCache.Load(path) if exists { return tex.(gdk.Paintabler), nil } tex, err := gdk.NewTextureFromFilename(path) // load once if err != nil { return nil, err } textureCache.Store(path, tex) return tex.(gdk.Paintabler), nil } func newPictureFromPath(path string) (*gtk.Picture, error) { tex, err := getTexture(path) if err != nil { return nil, err } img := gtk.NewPictureForPaintable(tex) return img, nil } func newImageFromPath(path string) (*gtk.Image, error) { tex, err := getTexture(path) if err != nil { return nil, err } img := gtk.NewImageFromPaintable(tex) return img, nil } func newPictureFromWeb(url string) (*gtk.Picture, error) { pa, _ := ensureCache() // step 1: get a sha256 sum of the URL sum := fmt.Sprintf("%x", sha256.Sum256([]byte(url))) p, ok := textureCache.Load(sum) if ok { return gtk.NewPictureForPaintable(p.(gdk.Paintabler)), nil } // step 2: download it resp, err := http.Get(url) if err != nil { return nil, err } b, err := io.ReadAll(resp.Body) if err != nil { return nil, err } fullpath := filepath.Join(pa, sum) // step 3: save it err = os.WriteFile(fullpath, b, 0644) if err != nil { return nil, err } return newPictureFromPath(fullpath) } func newImageFromWeb(url string) (*gtk.Image, error) { pa, _ := ensureCache() // step 1: get a sha256 sum of the URL sum := fmt.Sprintf("%x", sha256.Sum256([]byte(url))) p, ok := textureCache.Load(sum) if ok { return gtk.NewImageFromPaintable(p.(gdk.Paintabler)), nil } // step 2: download it resp, err := http.Get(url) if err != nil { return nil, err } b, err := io.ReadAll(resp.Body) if err != nil { return nil, err } fullpath := filepath.Join(pa, sum) // step 3: save it err = os.WriteFile(fullpath, b, 0644) if err != nil { return nil, err } return newImageFromPath(fullpath) }