83 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 =
33
source_code
34
|> String.split("\n")
35
|> Enum.map(fn line ->
36
line
37
|> String.graphemes()
38
|> Enum.map(fn char ->
39
%{
40
char: char,
41
duration: :rand.uniform(10) + 5,
42
delay: :rand.uniform(5000),
43
direction: if(:rand.uniform() > 0.5, do: 1, else: -1)
44
}
45
end)
46
end)
47
48
{:noreply, assign(socket, lines: characters)}
49
end
50
51
defp fetch_source_code do
52
CodeDecompiler.decompile_to_string(__MODULE__)
53
end
54
55
def render(assigns) do
56
~H"""
57
<div class="min-h-screen bg-gray-900 text-white p-8">
58
<div class="max-w-4xl mx-auto">
59
<h1 class="text-3xl font-bold mb-8">
60
Mirror Mirror on the wall, who's the most meta of them all?
61
</h1>
62
<div class="bg-gray-800 rounded-lg p-6 shadow-lg">
63
<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 %>
64
<% end %><% else %>Loading source code...<% end %></code></pre>
65
</div>
66
</div>
67
</div>
68
69
<style>
70
<%= for duration <- 5..15 do %>
71
@keyframes spin<%= duration %> {
72
from { transform: rotate(0deg); }
73
to { transform: rotate(<%= if rem(duration, 2) == 0, do: "360", else: "-360" %>deg); }
74
}
75
<% end %>
76
</style>
77
"""
78
end
79
80
@doc """
81
Source code available at: #{@source_url}
82
"""
83
end
84