Packages
Terminal emulation and driver infrastructure for Raxol. ANSI parsing, screen buffers, command processing, cursor management, input handling, session management, and termbox2 NIF integration.
Current section
Files
Jump to
Current section
Files
lib/raxol/terminal/config/animation_cache.ex
defmodule Raxol.Terminal.Config.AnimationCache do
@moduledoc """
Manages caching for terminal animations using the unified caching system.
"""
alias Raxol.Core.Runtime.Log
# Module attributes for preload dir
@preload_dir "priv/animations"
@doc """
Initializes the animation cache.
"""
def init_animation_cache do
# The unified cache system is already initialized by the application
:ok
end
@doc """
Gets a cached animation.
## Parameters
* `animation_path` - Path to the animation file
"""
def get_cached_animation(animation_path) do
case animation_path do
nil -> {:error, :invalid_path}
path -> Raxol.Terminal.Cache.System.get(path, namespace: :animation)
end
end
@doc """
Caches animation data directly (for testing and in-memory usage).
## Parameters
* `animation_key` - Key to store the animation under
* `animation_data` - Animation data to cache
"""
def cache_animation_data(animation_key, animation_data) do
case Raxol.Terminal.Cache.System.put(animation_key, animation_data,
namespace: :animation,
metadata: %{
type: :data,
size: byte_size(:erlang.term_to_binary(animation_data)),
original_size: byte_size(:erlang.term_to_binary(animation_data)),
compressed: false
}
) do
:ok ->
Log.info("Animation data cached: #{animation_key}")
:ok
error ->
Log.info("Failed to cache animation data: #{inspect(error)}")
error
end
end
@doc """
Caches an animation from a file.
## Parameters
* `animation_path` - Path to the animation file
* `animation_type` - Type of animation (:gif, :video, :shader, :particle)
"""
def cache_animation(animation_path, animation_type) do
case File.read(animation_path) do
{:ok, animation_data} ->
compressed_data = compress_animation(animation_data, animation_type)
compressed_size = byte_size(compressed_data)
original_size = byte_size(animation_data)
metadata = %{
type: animation_type,
size: compressed_size,
original_size: original_size,
compressed: true
}
case Raxol.Terminal.Cache.System.put(animation_path, compressed_data,
namespace: :animation,
metadata: metadata
) do
:ok ->
handle_cache_success(animation_path, compressed_size, original_size)
error ->
handle_cache_error(error)
end
{:error, reason} ->
handle_file_error(reason)
end
end
@doc """
Decompresses an animation.
## Parameters
* `compressed_data` - Compressed animation data
"""
def decompress_animation(compressed_data) do
:zlib.uncompress(compressed_data)
end
@doc """
Gets the current cache size.
"""
def get_cache_size do
case Raxol.Terminal.Cache.System.stats(namespace: :animation) do
{:ok, stats} -> stats.size
_ -> 0
end
end
@doc """
Preloads animations from the preload directory.
"""
def preload_animations do
preload_path = Path.expand(@preload_dir)
case File.mkdir_p(preload_path) do
:ok ->
animation_files = find_animation_files(preload_path)
Enum.each(animation_files, fn {path, type} ->
# Ignore result for preload
cache_animation(path, type)
end)
Log.info("Preloaded #{length(animation_files)} animations")
:ok
{:error, reason} ->
IO.warn("Could not create preload directory #{preload_path}: #{inspect(reason)}")
:ok
end
end
@doc """
Clears the animation cache.
"""
def clear_animation_cache do
Raxol.Terminal.Cache.System.clear(namespace: :animation)
Log.info("Animation cache cleared")
:ok
end
@doc """
Gets animation cache statistics.
"""
def get_animation_cache_stats do
case Raxol.Terminal.Cache.System.stats(namespace: :animation) do
{:ok, stats} ->
{:ok,
%{
count: stats.size,
total_size: stats.size,
# We don't track original size in unified cache
total_original_size: stats.size,
average_size:
case stats.size > 0 do
true -> div(stats.size, stats.size)
false -> 0
end,
# We don't track compression ratio in unified cache
compression_ratio: 0,
max_size: stats.max_size,
used_percent:
case stats.max_size > 0 do
true -> round(stats.size / stats.max_size * 100)
false -> 0
end,
hit_count: Map.get(stats, :hit_count, 0),
miss_count: Map.get(stats, :miss_count, 0),
hit_ratio: Map.get(stats, :hit_ratio, 0.0)
}}
_ ->
{:ok,
%{
count: 0,
total_size: 0,
total_original_size: 0,
average_size: 0,
compression_ratio: 0,
max_size: 0,
used_percent: 0,
hit_count: 0,
miss_count: 0,
hit_ratio: 0.0
}}
end
end
@doc """
Preloads a single animation.
## Parameters
* `animation_path` - Path to the animation file
"""
def preload_animation(animation_path) do
preload_animation_with_validation(
animation_path,
File.exists?(animation_path)
)
end
defp preload_animation_with_validation(_animation_path, false) do
{:error, :file_not_found}
end
defp preload_animation_with_validation(animation_path, true) do
case determine_animation_type(animation_path) do
nil ->
{:error, :unsupported_animation_type}
animation_type ->
case cache_animation(animation_path, animation_type) do
:ok -> {:ok, animation_type}
error -> error
end
end
end
# Private Functions
defp handle_cache_success(animation_path, compressed_size, original_size) do
case original_size > 0 do
true ->
compression_ratio = round((1 - compressed_size / original_size) * 100)
Log.info(
"Animation cached: #{animation_path} (#{compressed_size} bytes, #{compression_ratio}% compression)"
)
false ->
Log.info(
"Animation cached: #{animation_path} (#{compressed_size} bytes, empty original file)"
)
end
:ok
end
defp handle_cache_error(error) do
Log.info("Failed to cache animation: #{inspect(error)}")
error
end
defp handle_file_error(reason) do
Log.info("Failed to cache animation: #{inspect(reason)}")
{:error, reason}
end
defp compress_animation(animation_data, _animation_type) do
:zlib.compress(animation_data)
end
defp find_animation_files(directory) do
case File.ls(directory) do
{:ok, files} ->
Enum.flat_map(files, &process_animation_file(&1, directory))
_ ->
[]
end
end
defp process_animation_file(file, directory) do
path = Path.join(directory, file)
case File.regular?(path) do
true ->
case determine_animation_type(path) do
nil -> []
type -> [{path, type}]
end
false ->
[]
end
end
defp determine_animation_type(path) do
ext = Path.extname(path) |> String.downcase()
case ext do
".gif" -> :gif
".mp4" -> :video
".webm" -> :video
".glsl" -> :shader
".frag" -> :shader
".vert" -> :shader
".particle" -> :particle
_ -> nil
end
end
end