defmodule RaxolWeb.Settings.PreferencesComponent do
use RaxolWeb, :live_component
alias Raxol.Core.UserPreferences
def render(assigns) do
~H"""
Terminal Preferences
<.form
for={@preferences_changeset}
id="preferences-form"
phx-submit="update_preferences"
phx-change="validate_preferences"
phx-target={@myself}
class="settings-form"
>
<.form_group
name="font_size"
label="Font Size"
type="number"
value={@preferences["terminal"]["font_size"]}
min="8"
max="24"
/>
<.form_group
name="font_family"
label="Font Family"
type="text"
value={@preferences["terminal"]["font_family"]}
/>
<.form_group
name="scrollback_size"
label="Scrollback Size"
type="number"
value={@preferences["terminal"]["scrollback_size"]}
min="100"
max="10000"
/>
<.button type="submit" class="settings-button">
Update Preferences
"""
end
def handle_event("update_preferences", params, socket) do
preferences = socket.assigns.preferences
# Sanitize and validate input
case sanitize_preferences_params(params) do
{:ok, sanitized_params} ->
updated_preferences =
Map.merge(preferences, %{
"terminal" => %{
"font_size" => sanitized_params["font_size"],
"font_family" => sanitized_params["font_family"],
"scrollback_size" => sanitized_params["scrollback_size"]
}
})
UserPreferences.set_preferences(updated_preferences)
send(self(), {:preferences_updated, updated_preferences})
{:noreply,
socket
|> put_flash(:info, "Preferences updated successfully.")
|> assign(:preferences, updated_preferences)}
{:error, reason} ->
{:noreply,
socket
|> put_flash(:error, "Invalid preferences: #{reason}")
|> assign(:preferences_changeset, %{
errors: [{"preferences", {"Invalid input", []}}]
})}
end
end
def handle_event("validate_preferences", _params, socket) do
{:noreply, socket}
end
defp sanitize_preferences_params(params) do
try do
font_size = String.to_integer(params["font_size"])
scrollback_size = String.to_integer(params["scrollback_size"])
cond do
font_size < 8 or font_size > 24 ->
{:error, "Font size must be between 8 and 24"}
scrollback_size < 100 or scrollback_size > 10_000 ->
{:error, "Scrollback size must be between 100 and 10_000"}
true ->
{:ok,
%{
"font_size" => font_size,
"font_family" => String.trim(params["font_family"]),
"scrollback_size" => scrollback_size
}}
end
rescue
_ -> {:error, "Invalid numeric values"}
end
end
end