Blog/Components/Pages/Send.razor 3.4 K · 92 lines · raw · history

1 @page "/Send"
2 @using System.Text.Json
3 @using Blog.Services
4 @using Microsoft.Extensions.Options
5 @inject IOptions<SendOptions> Options
6
7 <PageTitle>Send</PageTitle>
8 <script type="module" src="@Assets["Components/Pages/Send.razor.js"]"></script>
9
10 <main>
11 <h1>Send</h1>
12
13 <p>
14 Send a file, or a few lines of text, to another browser. Open this page in both, pair them
15 with the link or the code, and it goes straight from one to the other.
16 </p>
17
18 @* The ICE servers are configuration, so the page carries them rather than the script
19 hard-coding them. A data attribute rather than a <script type="application/json"> block:
20 Razor HTML-encodes element content, and attribute encoding round-trips through JSON.parse. *@
21 <div id="ice" data-servers="@IceServers" hidden></div>
22
23 <Panel Legend="Connection">
24 <p id="state">Starting…</p>
25
26 @* Put away once the room has its two browsers: the link is no use to a third. *@
27 <div id="pairing">
28 <div class="flex-row">
29 <label for="link">Link</label>
30 <input type="text" id="link" readonly/>
31 <button type="button" id="copy">Copy</button>
32 </div>
33
34 <p>…or read out the code: <strong id="code"></strong></p>
35
36 <div id="qrcode"></div>
37 </div>
38
39 <form id="joinForm" class="flex-row">
40 <label for="joinCode">Been given a code?</label>
41 <input type="text" id="joinCode" placeholder="ABCD-EFGH-JKMN" autocomplete="off"
42 spellcheck="false"/>
43 <button type="submit">Join</button>
44 </form>
45 </Panel>
46
47 <Panel Legend="Sending">
48 <div id="drop" class="dropzone">
49 <input type="file" id="files" multiple disabled/>
50 <p>…or drop files here.</p>
51 </div>
52 <ul id="outgoing" class="transfers"></ul>
53 </Panel>
54
55 <Panel Legend="Received">
56 <ul id="incoming" class="transfers"></ul>
57 <p id="nothingYet">Nothing yet.</p>
58 </Panel>
59
60 <Panel Legend="Messages">
61 <ol id="messages" class="messages"></ol>
62
63 @* Enter sends and shift-Enter is a new line, the way every chat box works; the button is
64 there for a phone keyboard, which has no shift-Enter to speak of. *@
65 <form id="messageForm">
66 <label for="messageText">Text</label>
67 <textarea id="messageText" rows="2" disabled
68 placeholder="A link, a note, a snippet — Enter sends it."></textarea>
69 <button type="submit" id="messageSend" disabled>Send</button>
70 </form>
71 </Panel>
72
73 <Panel Legend="How this works">
74 <p>
75 <a href="https://developer.mozilla.org/en-US/docs/Web/API/WebRTC_API"
76 rel="external noreferrer">WebRTC</a> is the browser's own way of opening a
77 connection straight to another browser. The two ends swap what they know about how
78 to reach each other, settle on a route, and from then on talk directly — on a shared
79 network, over the local one. The file is read off disk in chunks and written down
80 that connection. Messages take the same way, so they are never seen by this site either.
81 </p>
82 </Panel>
83
84 <Log/>
85 </main>
86
87 @code {
88
89 /// <summary>The configured STUN/TURN URLs, as a JSON array for <c>RTCPeerConnection</c>.</summary>
90 private string IceServers => JsonSerializer.Serialize(Options.Value.IceServers);
91
92 }