75 lines
2.7 kB
1
defmodule BlogWeb.MirrorLive do
2
use BlogWeb, :live_view
3
require Logger
4
5
@source_url "https://raw.githubusercontent.com/notactuallytreyanastasio/blog/main/lib/blog_web/live/mirror_live.ex"
6
7
def mount(_params, _session, socket) do
8
if connected?(socket) do
9
# Fetch source code asynchronously when client connects
10
Task.async(fn -> fetch_source_code() end)
11
end
12
13
{:ok,
14
assign(socket,
15
source_code: "Loading source code...",
16
page_title: "I am looking at myself",
17
meta_attrs: [
18
%{name: "title", content: "Mirror Mirror on the wall"},
19
%{name: "description", content: "A page that shows its own source code"},
20
%{property: "og:title", content: "Mirror Mirror on the wall"},
21
%{property: "og:description", content: "A page that shows its own source code"},
22
%{property: "og:type", content: "website"}
23
]
24
)}
25
end
26
27
def handle_info({ref, source_code}, socket) when is_reference(ref) do
28
# Flush the DOWN message
29
Process.demonitor(ref, [:flush])
30
31
# Split into lines first, then characters
32
characters = source_code
33
|> String.split("\n")
34
|> Enum.map(fn line ->
35
line
36
|> String.graphemes()
37
|> Enum.map(fn char ->
38
%{
39
char: char,
40
duration: :rand.uniform(10) + 5,
41
delay: :rand.uniform(5000),
42
direction: if(:rand.uniform() > 0.5, do: 1, else: -1)
43
}
44
end)
45
end)
46
{:noreply, assign(socket, lines: characters)}
47
end
48
49
defp fetch_source_code do
50
Req.get!("https://raw.githubusercontent.com/notactuallytreyanastasio/blog/main/lib/blog_web/live/mirror_live.ex") |> Map.get(:body)
51
end
52
53
def render(assigns) do
54
~H"""
55
<div class="min-h-screen bg-gray-900 text-white p-8">
56
<div class="max-w-4xl mx-auto">
57
<h1 class="text-3xl font-bold mb-8">Mirror Mirror on the wall, who's the most meta of them all?</h1>
58
<div class="bg-gray-800 rounded-lg p-6 shadow-lg">
59
<pre class="text-sm font-mono" style="tab-size: 2;"><code class="language-elixir"><%= if assigns[:lines] do %><%= for line <- @lines do %><%= for char <- line do %><span style={"display: inline-block; animation: spin#{char.duration} #{char.duration}s linear #{char.delay}ms infinite;"}><%= char.char %></span><% end %>
60
<% end %><% else %>Loading source code...<% end %></code></pre>
61
</div>
62
</div>
63
</div>
64
65
<style>
66
<%= for duration <- 5..15 do %>
67
@keyframes spin<%= duration %> {
68
from { transform: rotate(0deg); }
69
to { transform: rotate(<%= if rem(duration, 2) == 0, do: "360", else: "-360" %>deg); }
70
}
71
<% end %>
72
</style>
73
"""
74
end
75
end
76