Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add account-level font family setting #431

Merged
merged 3 commits into from
Feb 18, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 9 additions & 1 deletion lib/asciinema/accounts.ex
Original file line number Diff line number Diff line change
Expand Up @@ -70,11 +70,19 @@ defmodule Asciinema.Accounts do
import Ecto.Changeset

user
|> cast(params, [:email, :name, :username, :theme_name, :asciicasts_private_by_default])
|> cast(params, [
:email,
:name,
:username,
:theme_name,
:terminal_font_family,
:asciicasts_private_by_default
])
|> validate_format(:email, @valid_email_re)
|> validate_format(:username, @valid_username_re)
|> validate_length(:username, min: 2, max: 16)
|> validate_inclusion(:theme_name, Media.themes())
|> validate_inclusion(:terminal_font_family, Media.terminal_font_families())
|> add_contraints()
end

Expand Down
1 change: 1 addition & 0 deletions lib/asciinema/accounts/user.ex
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ defmodule Asciinema.Accounts.User do
field :name, :string
field :auth_token, :string
field :theme_name, :string
field :terminal_font_family, :string
field :asciicasts_private_by_default, :boolean, default: true
field :last_login_at, :utc_datetime_usec
field :is_admin, :boolean
Expand Down
2 changes: 1 addition & 1 deletion lib/asciinema/recordings.ex
Original file line number Diff line number Diff line change
Expand Up @@ -274,7 +274,7 @@ defmodule Asciinema.Recordings do
Asciicast.update_changeset(
asciicast,
attrs,
Media.custom_terminal_font_families(),
Media.terminal_font_families(),
Media.themes()
)

Expand Down
4 changes: 2 additions & 2 deletions lib/asciinema/recordings/asciicast.ex
Original file line number Diff line number Diff line change
Expand Up @@ -92,7 +92,7 @@ defmodule Asciinema.Recordings.Asciicast do
|> generate_secret_token
end

def update_changeset(struct, attrs, custom_terminal_font_families \\ [], themes \\ []) do
def update_changeset(struct, attrs, terminal_font_families \\ [], themes \\ []) do
struct
|> changeset(attrs)
|> cast(attrs, [
Expand All @@ -114,7 +114,7 @@ defmodule Asciinema.Recordings.Asciicast do
greater_than_or_equal_to: 1.0,
less_than_or_equal_to: 2.0
)
|> validate_inclusion(:terminal_font_family, custom_terminal_font_families)
|> validate_inclusion(:terminal_font_family, terminal_font_families)
|> validate_number(:snapshot_at, greater_than: 0)
|> validate_change(:markers, &validate_markers/2)
end
Expand Down
2 changes: 1 addition & 1 deletion lib/asciinema/streaming.ex
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,7 @@ defmodule Asciinema.Streaming do
greater_than_or_equal_to: 1.0,
less_than_or_equal_to: 2.0
)
|> validate_inclusion(:terminal_font_family, Media.custom_terminal_font_families())
|> validate_inclusion(:terminal_font_family, Media.terminal_font_families())
end

def update_live_stream(stream, attrs) when is_list(attrs) do
Expand Down
4 changes: 2 additions & 2 deletions lib/asciinema_web/controllers/live_stream/edit.html.heex
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@
field={f[:theme_name]}
options={theme_options()}
class="form-control"
prompt={"Default (#{default_theme_name(@changeset.data)})"}
prompt={"Account default (#{default_theme_display_name(@changeset.data)})"}
/>
</div>
</div>
Expand Down Expand Up @@ -92,7 +92,7 @@
field={f[:terminal_font_family]}
options={terminal_font_family_options()}
class="form-control"
prompt="Default (web safe, platform specific)"
prompt={"Account default (#{default_font_display_name(@changeset.data)})"}
/>
<small class="form-text text-muted">
Choose one of Nerd Font variants if icons or other symbols in your recording are not visible.
Expand Down
15 changes: 13 additions & 2 deletions lib/asciinema_web/controllers/live_stream_html.ex
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
defmodule AsciinemaWeb.LiveStreamHTML do
use AsciinemaWeb, :html
alias AsciinemaWeb.{PlayerView, RecordingView}
alias AsciinemaWeb.{PlayerView, RecordingView, UserView}

embed_templates "live_stream/*"

Expand All @@ -9,8 +9,11 @@ defmodule AsciinemaWeb.LiveStreamHTML do
defdelegate author_profile_path(stream), to: PlayerView
defdelegate theme_name(stream), to: PlayerView
defdelegate theme_options, to: PlayerView
defdelegate theme_display_name(stream), to: PlayerView
defdelegate default_theme_name(stream), to: PlayerView
defdelegate terminal_font_family(stream), to: PlayerView
defdelegate terminal_font_family_options, to: PlayerView
defdelegate terminal_font_family_display_name(asciicast), to: PlayerView

def player_src(stream) do
%{
Expand All @@ -27,7 +30,7 @@ defmodule AsciinemaWeb.LiveStreamHTML do
autoplay: true,
theme: theme_name(stream),
terminalLineHeight: stream.terminal_line_height,
customTerminalFontFamily: stream.terminal_font_family
customTerminalFontFamily: terminal_font_family(stream)
]
|> Keyword.merge(opts)
|> Enum.into(%{})
Expand All @@ -39,6 +42,14 @@ defmodule AsciinemaWeb.LiveStreamHTML do

def title(stream), do: stream.title || "#{author_username(stream)}'s live stream"

def default_theme_display_name(%{user: user}) do
theme_display_name(UserView.theme_name(user) || "asciinema")
end

def default_font_display_name(%{user: user}) do
terminal_font_family_display_name(UserView.terminal_font_family(user) || "default")
end

@http_to_ws %{"http" => "ws", "https" => "wss"}

defp ws_producer_url(live_stream) do
Expand Down
8 changes: 4 additions & 4 deletions lib/asciinema_web/templates/recording/edit.html.eex
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@
<div class="form-group row">
<%= label f, :theme_name, "Terminal theme", class: "col-sm-4 col-md-3 col-lg-3 col-form-label" %>
<div class="col-sm-8 col-md-9 col-lg-9">
<%= select f, :theme_name, theme_options(), class: "form-control", prompt: "Default (#{default_theme_name(@changeset.data)})" %>
<%= select f, :theme_name, theme_options(), class: "form-control", prompt: "Account default (#{default_theme_display_name(@changeset.data)})" %>
</div>
</div>

Expand All @@ -69,15 +69,15 @@
<div class="col-sm-8 col-md-9 col-lg-9">
<%= text_input f, :terminal_line_height, class: "form-control", type: "number", min: 1, max: 2, step: "any", placeholder: "1.33333" %>
<%= error_tag f, :terminal_line_height %>
<small class="form-text text-muted">Relative to font size. Lowering it to ~1.1 helps with alignment of block characters like ▀ ▄ █</small>
<small class="form-text text-muted">Relative to the font size. Lowering it to ~1.1 helps with alignment of block characters such as ▀ ▄ █</small>
</div>
</div>

<div class="form-group row">
<%= label f, :terminal_font_family, "Terminal font family", class: "col-sm-4 col-md-3 col-lg-3 col-form-label" %>
<div class="col-sm-8 col-md-9 col-lg-9">
<%= select f, :terminal_font_family, terminal_font_family_options(), class: "form-control", prompt: "Default (web safe, platform specific)" %>
<small class="form-text text-muted">Choose one of Nerd Font variants if icons or other symbols in your recording are not visible.</small>
<%= select f, :terminal_font_family, terminal_font_family_options(), class: "form-control", prompt: "Account default (#{default_font_display_name(@changeset.data)})" %>
<small class="form-text text-muted">Choose one of the Nerd Font variants if icons or other symbols in your recording are not visible.</small>
</div>
</div>

Expand Down
34 changes: 21 additions & 13 deletions lib/asciinema_web/templates/user/edit.html.eex
Original file line number Diff line number Diff line change
Expand Up @@ -5,40 +5,48 @@
<legend>Account settings</legend>

<div class="form-group row string optional user_username <%= error_class(f, :username) %>">
<%= label f, :username, class: "string optional col-form-label col-sm-3 col-md-3 col-lg-2" %>
<div class="col-sm-9 col-md-9 col-lg-10">
<%= label f, :username, class: "string optional col-form-label col-3" %>
<div class="col-9">
<%= text_input f, :username, class: "string optional form-control" %>
<%= error_tag f, :username %>
</div>
</div>

<div class="form-group row email required user_email <%= error_class(f, :email) %>">
<%= label f, :email, class: "email required col-form-label col-sm-3 col-md-3 col-lg-2" %>
<div class="col-sm-9 col-md-9 col-lg-10">
<%= label f, :email, class: "email required col-form-label col-3" %>
<div class="col-9">
<%= email_input f, :email, class: "string email required form-control" %>
<%= error_tag f, :email %>
</div>
</div>

<div class="form-group row string optional user_name <%= error_class(f, :name) %>">
<%= label f, :name, "Full name", class: "string optional col-form-label col-sm-3 col-md-3 col-lg-2" %>
<div class="col-sm-9 col-md-9 col-lg-10">
<%= label f, :name, "Full name", class: "string optional col-form-label col-3" %>
<div class="col-9">
<%= text_input f, :name, class: "string optional form-control" %>
<%= error_tag f, :name %>
</div>
</div>

<div class="form-group row select optional user_theme_name">
<%= label f, :theme_name, "Terminal theme", class: "select optional col-form-label col-sm-3 col-md-3 col-lg-2" %>
<div class="col-sm-9 col-md-9 col-lg-10">
<%= label f, :theme_name, "Default terminal theme", class: "col-3 select optional col-form-label" %>
<div class="col-9">
<%= select f, :theme_name, theme_options(), class: "select optional form-control", prompt: "Default (asciinema)" %>
<small class="form-text text-muted">Applies to all your recordings unless a custom theme is chosen for a recording</small>
<small class="form-text text-muted">Applies to all your recordings that don't explicitly override this.</small>
</div>
</div>

<div class="form-group row">
<%= label f, :terminal_font_family, "Default terminal font", class: "col-sm-4 col-md-3 col-form-label" %>
<div class="col-sm-8 col-md-9">
<%= select f, :terminal_font_family, terminal_font_family_options(), class: "form-control", prompt: "Default (#{default_font_display_name()})" %>
<small class="form-text text-muted">Applies to all your recordings that don't explicitly override this.</small>
</div>
</div>

<div class="form-group row radio_buttons optional user_asciicasts_private_by_default">
<%= label f, :asciicasts_private_by_default, "Recording visibility", class: "radio_buttons optional col-form-label col-sm-3 col-md-3 col-lg-2" %>
<div class="col-sm-9 col-md-9 col-lg-10">
<%= label f, :asciicasts_private_by_default, "New recording visibility", class: "col-3 radio_buttons optional col-form-label" %>
<div class="col-9">
<div class="form-check">
<%= radio_button f, :asciicasts_private_by_default, false, class: "radio_buttons optional form-check-input" %>
<%= label f, :asciicasts_private_by_default, "public", for: "user_asciicasts_private_by_default_false", class: "form-check-label" %>
Expand All @@ -52,8 +60,8 @@
</div>

<div class="form-group row">
<label class="col-form-label col-sm-3 col-md-3 col-lg-2"></label>
<div class="col-sm-offset-3 col-sm-9 col-md-offset-3 col-md-9 col-lg-offset-2 col-lg-10">
<label class="col-form-label col-3"></label>
<div class="col-offset-3 col-9">
<br>
<%= submit "Save", class: "btn btn-primary" %>
<%= link "Cancel", to: profile_path(@conn), class: "btn" %>
Expand Down
50 changes: 36 additions & 14 deletions lib/asciinema_web/views/player_view.ex
Original file line number Diff line number Diff line change
Expand Up @@ -29,31 +29,53 @@ defmodule AsciinemaWeb.PlayerView do
end

def theme_options do
[
{"asciinema", "asciinema"},
{"Dracula", "dracula"},
{"Monokai", "monokai"},
{"Nord", "nord"},
{"Tango", "tango"},
{"Solarized Dark", "solarized-dark"},
{"Solarized Light", "solarized-light"}
]
for theme <- Media.themes() do
{theme_display_name(theme), theme}
end
end

def theme_name(medium) do
medium.theme_name || default_theme_name(medium)
end

def theme_display_name(theme) do
case theme do
"asciinema" -> "asciinema"
"dracula" -> "Dracula"
"monokai" -> "Monokai"
"nord" -> "Nord"
"tango" -> "Tango"
"solarized-dark" -> "Solarized Dark"
"solarized-light" -> "Solarized Light"
end
end

def default_theme_name(%{user: user}) do
UserView.theme_name(user) || "asciinema"
end

def terminal_font_family_options do
for family <- Media.custom_terminal_font_families() do
case family do
"FiraCode Nerd Font" -> {"Nerd Font - Fira Code", family}
"JetBrainsMono Nerd Font" -> {"Nerd Font - JetBrains Mono", family}
end
for family <- Media.terminal_font_families() do
{terminal_font_family_display_name(family), family}
end
end

def terminal_font_family(medium) do
case medium.terminal_font_family || default_terminal_font_family(medium) do
"default" -> nil
family -> family
end
end

def terminal_font_family_display_name(family) do
case family do
"default" -> "System monospace, web safe"
"FiraCode Nerd Font" -> "Nerd Font - Fira Code"
"JetBrainsMono Nerd Font" -> "Nerd Font - JetBrains Mono"
end
end

def default_terminal_font_family(%{user: user}) do
UserView.terminal_font_family(user)
end
end
16 changes: 14 additions & 2 deletions lib/asciinema_web/views/recording_view.ex
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
defmodule AsciinemaWeb.RecordingView do
alias AsciinemaWeb.PlayerView
use AsciinemaWeb, :view
import Scrivener.HTML
alias Asciinema.Recordings.Asciicast
alias AsciinemaWeb.Endpoint
alias AsciinemaWeb.PlayerView
alias AsciinemaWeb.Router.Helpers.Extra, as: RoutesX
alias AsciinemaWeb.{PlayerView, UserView}

Expand All @@ -12,8 +12,12 @@ defmodule AsciinemaWeb.RecordingView do
defdelegate author_profile_path(stream), to: PlayerView
defdelegate theme_name(stream), to: PlayerView
defdelegate theme_options, to: PlayerView
defdelegate theme_display_name(asciicast), to: PlayerView
defdelegate default_theme_name(stream), to: PlayerView
defdelegate terminal_font_family(asciicast), to: PlayerView
defdelegate terminal_font_family_options, to: PlayerView
defdelegate terminal_font_family_display_name(asciicast), to: PlayerView
defdelegate default_terminal_font_family(asciicast), to: PlayerView
defdelegate username(user), to: UserView

def player_src(asciicast), do: file_url(asciicast)
Expand All @@ -24,7 +28,7 @@ defmodule AsciinemaWeb.RecordingView do
rows: rows(asciicast),
theme: theme_name(asciicast),
terminalLineHeight: asciicast.terminal_line_height,
customTerminalFontFamily: asciicast.terminal_font_family,
customTerminalFontFamily: terminal_font_family(asciicast),
poster: poster(asciicast.snapshot),
markers: markers(asciicast.markers),
idleTimeLimit: asciicast.idle_time_limit,
Expand Down Expand Up @@ -58,6 +62,14 @@ defmodule AsciinemaWeb.RecordingView do
)
end

def default_theme_display_name(%{user: user}) do
theme_display_name(UserView.theme_name(user) || "asciinema")
end

def default_font_display_name(%{user: user}) do
terminal_font_family_display_name(UserView.terminal_font_family(user) || "default")
end

defp short_text_description(asciicast) do
if asciicast.description do
asciicast.description
Expand Down
13 changes: 12 additions & 1 deletion lib/asciinema_web/views/user_view.ex
Original file line number Diff line number Diff line change
@@ -1,9 +1,12 @@
defmodule AsciinemaWeb.UserView do
use AsciinemaWeb, :view
import Scrivener.HTML
alias AsciinemaWeb.PlayerView
alias Asciinema.Gravatar

defdelegate theme_options, to: AsciinemaWeb.PlayerView
defdelegate theme_options, to: PlayerView
defdelegate terminal_font_family_options, to: PlayerView
defdelegate terminal_font_family_display_name(asciicast), to: PlayerView

def avatar_url(user) do
username = username(user)
Expand All @@ -29,6 +32,14 @@ defmodule AsciinemaWeb.UserView do
user.theme_name
end

def terminal_font_family(user) do
user.terminal_font_family
end

def default_font_display_name do
terminal_font_family_display_name("default")
end

def active_tokens(api_tokens) do
api_tokens
|> Enum.reject(& &1.revoked_at)
Expand Down
5 changes: 3 additions & 2 deletions lib/media.ex
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
defmodule Asciinema.Media do
@custom_terminal_font_families [
@terminal_font_families [
"default",
"FiraCode Nerd Font",
"JetBrainsMono Nerd Font"
]
Expand All @@ -14,7 +15,7 @@ defmodule Asciinema.Media do
"tango"
]

def custom_terminal_font_families, do: @custom_terminal_font_families
def terminal_font_families, do: @terminal_font_families

def themes, do: @themes
end
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
defmodule Asciinema.Repo.Migrations.AddTerminalFontFamilyToUsers do
use Ecto.Migration

def change do
alter table(:users) do
add :terminal_font_family, :string
end
end
end
Loading