154 lines
4.9 kB
1
tags: programming,elixir,fun
2
3
# How a fun idea came about
4
I just had a bunch of fun the other night, and we had to enjoy the scene in a very old school way.
5
6
We were not allowed to use our phones, so it was everyone enjoying the show like the old days.
7
8
Much like the old days, you also had to wait in line in person to get a ticket.
9
1 ticket per person.
10
$50.
11
12
Not a bad deal to see [Paul McCartney](https://en.wikipedia.org/wiki/Paul_McCartney).
13
14
Anyways, this all planted the seed of thinking about doing things the "old" way.
15
16
I wanted to make a simple app, and I thought well maybe I should make it so that as you type random letters, you will see some kind of art display as they render.
17
Maybe they fade in dramatically sometimes, and other times slide in, etc.
18
Well, I never got that far.
19
But I did start making something that was right along those lines.
20
21
I decided that since recently I had been thinking about using constraints as a feature, I would make a constrained page:
22
23
Make art by only knowing what key someone just typed, or all the keys they have typed since starting to visit.
24
25
## Well, let's write some code for a Keypress Viewer page
26
This was remarkably easy.
27
28
We can see the entire LiveView at once to get an idea of how simple it really can be for this piece.
29
30
This specific piece of this exercise makes me wonder how much harder this would be in JavaScript
31
32
```elixir
33
# in router.ex
34
live "/keylogger", KeyloggerLive
35
```
36
37
And then
38
39
```elixir
40
# keylogger_live.ex
41
defmodule BlogWeb.KeyloggerLive do
42
use BlogWeb, :live_view
43
import BlogWeb.CoreComponents
44
require Logger
45
46
def mount(_params, _session, socket) do
47
{:ok,
48
assign(socket,
49
pressed_key: "",
50
show_modal: true,
51
page_title: "Experiment - what key are you pressing"
52
)}
53
end
54
55
def handle_event("keydown", %{"key" => key}, socket) do
56
{:noreply, assign(socket, pressed_key: key)}
57
end
58
59
def render(assigns) do
60
~H"""
61
<div phx-window-keydown="keydown">
62
<h1 class="text-[75px]">
63
Pressing: <%= @pressed_key %>
64
</h1>
65
</div>
66
"""
67
end
68
end
69
```
70
71
So this is pretty simple right?
72
73
The entirety of what it gets us, honestly, is pretty impressive.
74
75
We simply hook together when someone presses anything on the keyboard with supported bindings for events on keypress, and then we take the state of the page and in the tempate say hey, render the key that was just coming over the wire.
76
77
Sometimes I love Elixir.
78
79
### What came next?
80
Well, once I had one letter, I thought, "what if I stored every letter someone typed".
81
82
That brought about a deeper process of thought.
83
84
Some people really do just type letters and want them in specific orders, and then to share those letters in specific orders with other people.
85
86
I figured that I could offer a service doing this by writing some simple software.
87
88
So, I started off by figuring out a way to store the state of more than just one letter.
89
90
Let's take a look at what we change here
91
92
```
93
defmodule BlogWeb.KeyloggerLive do
94
# snip ...
95
96
def mount(_params, _session, socket) do
97
{:ok,
98
assign(socket,
99
pressed_key: "",
100
show_modal: true,
101
pressed_keys: "",
102
page_title: "Experiment - what key are you pressing"
103
)}
104
end
105
106
def handle_event("keydown", %{"key" => key}, socket) do
107
{:noreply,
108
socket
109
|> assign(pressed_key: key)
110
|> assign(pressed_keys: socket.assigns.pressed_keys <> key)
111
}
112
end
113
114
def render(assigns) do
115
~H"""
116
<div phx-window-keydown="keydown">
117
<h1 class="text-[75px]">
118
Pressing: <%= @pressed_key %>
119
</h1>
120
<div id="history">
121
<%= @pressed_keys %>
122
</div>
123
</div>
124
"""
125
end
126
end
127
```
128
129
So we did a couple things:
130
131
1. set `pressed_keys` to `""` on mount
132
2. track pressed keys in state as we go
133
3. render that pressed key state in a div on the page
134
135
Now we can remember the order of the keys someone pressed, and then show that they have pressed them.
136
137
**I think we have reached MVP status**
138
139
# A product person enters the room
140
I was telling someone about this brilliant idea and someone alerted me quickly that I shouldn't bet too big on this.
141
142
What was their problem with my master plan?
143
144
They told me I had just reinvented writing down letters to people, and that you can do this digitally trivially.
145
146
But we met at a middle ground: what if I offered a way to send letters like they were written on a typewriter?
147
148
This would mean that everything the user typed must be very deliberate and meaningful, much like my usecase of wanting to type letters in a specific order and have that be a tracked state.
149
150
So, I decided we could set off with this as an idea.
151
152
# Let's write letters to our friends as if we had a typewriter
153
I'll finish this part in the morning, I wanted to get the inspirational layout for the post done tonight.
154
155