Skip to content

Commit

Permalink
Implement identicon-based avatars, make it default
Browse files Browse the repository at this point in the history
  • Loading branch information
ku1ik committed May 2, 2024
1 parent 1bb7fdc commit ef35bf1
Show file tree
Hide file tree
Showing 11 changed files with 55 additions and 4 deletions.
2 changes: 1 addition & 1 deletion assets/css/_recording_card.scss
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,7 @@ div.asciicast-card {
width: 20px;
height: 20px;

img {
img, svg {
width: 100%;
height: 100%;
border-radius: 2px;
Expand Down
2 changes: 2 additions & 0 deletions config/config.exs
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,8 @@ config :asciinema, Asciinema.FileCache, path: "cache/"

config :asciinema, Asciinema.Emails.Mailer, adapter: Bamboo.LocalAdapter

config :asciinema, :avatar_provider, :identicon

config :asciinema, :png_generator, Asciinema.PngGenerator.Rsvg

config :asciinema, Asciinema.PngGenerator.Rsvg,
Expand Down
6 changes: 6 additions & 0 deletions config/runtime.exs
Original file line number Diff line number Diff line change
Expand Up @@ -212,6 +212,12 @@ if config_env() in [:prod, :dev] do
config :asciinema, :sign_up_enabled?, false
end

provider = env.("AVATAR_PROVIDER")

if provider in ["gravatar", "identicon"] do
config :asciinema, :avatar_provider, String.to_existing_atom(provider)
end

if dsn = env.("SENTRY_DSN") do
config :sentry, dsn: dsn
else
Expand Down
14 changes: 14 additions & 0 deletions lib/asciinema_web/controllers/avatar_controller.ex
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
defmodule AsciinemaWeb.AvatarController do
use AsciinemaWeb, :new_controller
alias Asciinema.Accounts

@one_day 24 * 60 * 60

def show(conn, %{"id" => id}) do
with {:ok, user} <- Accounts.fetch_user(id) do
conn
|> put_resp_header("cache-control", "public, max-age=#{@one_day}")
|> render("show.svg", user: user)
end
end
end
7 changes: 7 additions & 0 deletions lib/asciinema_web/controllers/avatar_svg.ex
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
defmodule AsciinemaWeb.AvatarSVG do
def show(%{user: user}) do
email = user.email || "#{user.id}@asciinema"

{:safe, IdenticonSvg.generate(email, 6, :basic)}
end
end
2 changes: 1 addition & 1 deletion lib/asciinema_web/controllers/recording/card.html.heex
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@

<span class="author-avatar">
<.link href={author_profile_path(@asciicast)} title={author_username(@asciicast)}>
<img src={author_avatar_url(@asciicast)} class="avatar" />
<img src={author_avatar_url(@asciicast)} />
</.link>
</span>

Expand Down
10 changes: 8 additions & 2 deletions lib/asciinema_web/controllers/user_html.ex
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,14 @@ defmodule AsciinemaWeb.UserHTML do
defdelegate default_font_display_name, to: Fonts

def avatar_url(user) do
username = username(user)
email = user.email || "#{username}+#{user.id}@asciinema.org"
avatar_url(user, Application.fetch_env!(:asciinema, :avatar_provider))
end

def avatar_url(user, :identicon), do: ~p"/u/#{user}/avatar"

def avatar_url(user, :gravatar) do
email = user.email || "#{user.id}@asciinema"

Gravatar.gravatar_url(email)
end

Expand Down
1 change: 1 addition & 0 deletions lib/asciinema_web/router.ex
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,7 @@ defmodule AsciinemaWeb.Router do
resources "/users", UserController, as: :users, only: [:new, :create]
get "/u/:id", UserController, :show
get "/~:username", UserController, :show
get "/u/:id/avatar", AvatarController, :show

resources "/username", UsernameController, only: [:new, :create], singleton: true
get "/username/skip", UsernameController, :skip, as: :username
Expand Down
1 change: 1 addition & 0 deletions mix.exs
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,7 @@ defmodule Asciinema.MixProject do
{:hackney, "~> 1.18"},
{:horde, "~> 0.8.7"},
{:html_sanitize_ex, "~> 1.4"},
{:identicon_svg, "~> 0.8.0"},
{:inflex, "~> 2.0"},
{:jason, "~> 1.2"},
{:libcluster, "~> 3.3"},
Expand Down
1 change: 1 addition & 0 deletions mix.lock
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@
"horde": {:hex, :horde, "0.8.7", "e51ab8e0e5bc7dcd0caa85d84b144cccfde97994bd865d822c7e489746b87e7f", [:mix], [{:delta_crdt, "~> 0.6.2", [hex: :delta_crdt, repo: "hexpm", optional: false]}, {:libring, "~> 1.4", [hex: :libring, repo: "hexpm", optional: false]}, {:telemetry, "~> 0.4.0 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}, {:telemetry_poller, "~> 0.5.0 or ~> 1.0", [hex: :telemetry_poller, repo: "hexpm", optional: false]}], "hexpm", "835aede887d777542f85e0a88293c18113abcc1356006050ec216da16aa5e0e3"},
"html_entities": {:hex, :html_entities, "0.5.2", "9e47e70598da7de2a9ff6af8758399251db6dbb7eebe2b013f2bbd2515895c3c", [:mix], [], "hexpm", "c53ba390403485615623b9531e97696f076ed415e8d8058b1dbaa28181f4fdcc"},
"html_sanitize_ex": {:hex, :html_sanitize_ex, "1.4.2", "c479398b6de798c03eb5d04a0a9a9159d73508f83f6590a00b8eacba3619cf4c", [:mix], [{:mochiweb, "~> 2.15", [hex: :mochiweb, repo: "hexpm", optional: false]}], "hexpm", "aef6c28585d06a9109ad591507e508854c5559561f950bbaea773900dd369b0e"},
"identicon_svg": {:hex, :identicon_svg, "0.8.0", "a3368175bffff7c18a28bc7f2aec065787f16caee8a86560c7219141413cf15c", [:mix], [], "hexpm", "26ff8ce55c0674b0c9031c7f51038e31d0e939cb95b6dd038a287bc89d8711d2"},
"idna": {:hex, :idna, "6.1.1", "8a63070e9f7d0c62eb9d9fcb360a7de382448200fbbd1b106cc96d3d8099df8d", [:rebar3], [{:unicode_util_compat, "~> 0.7.0", [hex: :unicode_util_compat, repo: "hexpm", optional: false]}], "hexpm", "92376eb7894412ed19ac475e4a86f7b413c1b9fbb5bd16dccd57934157944cea"},
"inflex": {:hex, :inflex, "2.1.0", "a365cf0821a9dacb65067abd95008ca1b0bb7dcdd85ae59965deef2aa062924c", [:mix], [], "hexpm", "14c17d05db4ee9b6d319b0bff1bdf22aa389a25398d1952c7a0b5f3d93162dd8"},
"jason": {:hex, :jason, "1.4.1", "af1504e35f629ddcdd6addb3513c3853991f694921b1b9368b0bd32beb9f1b63", [:mix], [{:decimal, "~> 1.0 or ~> 2.0", [hex: :decimal, repo: "hexpm", optional: true]}], "hexpm", "fbb01ecdfd565b56261302f7e1fcc27c4fb8f32d56eab74db621fc154604a7a1"},
Expand Down
13 changes: 13 additions & 0 deletions test/controllers/avatar_controller_test.exs
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
defmodule Asciinema.AvatarControllerTest do
use AsciinemaWeb.ConnCase
import Asciinema.Factory

test "image response", %{conn: conn} do
user = insert(:user)

conn = get(conn, ~p"/u/#{user}/avatar")

assert response(conn, 200)
assert List.first(get_resp_header(conn, "content-type")) =~ ~r|image/.+|
end
end

0 comments on commit ef35bf1

Please sign in to comment.