App.razor 3.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126
  1. @inject HttpClient http
  2. @code {
  3. private string nickName;
  4. private string nickNameClass => string.IsNullOrWhiteSpace(nickName) ? "is-invalid form-control" : "form-control";
  5. private string message;
  6. private string messageClass => string.IsNullOrWhiteSpace(message) ? "is-invalid form-control" : "form-control";
  7. private int connState = 0;
  8. private const int maxDisplayMessage = 1000;
  9. private List<string> displayingMessages = new List<string>(maxDisplayMessage);
  10. }
  11. <div class="container">
  12. <h2>Simple Web Chat</h2>
  13. @if (connState == 0)
  14. {
  15. <div class="input-group mb-3">
  16. <div class="form-floating">
  17. <InputText class="@nickNameClass" placeholder="Nick name" type="search" onsearch="@Connect" @oninput="NickNameChanged" ValueExpression="()=>nickName"></InputText>
  18. @if (string.IsNullOrEmpty(nickName))
  19. {
  20. <label>Please enter nick name</label>
  21. }
  22. else
  23. {
  24. <label>Nick name</label>
  25. }
  26. </div>
  27. <button @onclick="@Connect" class="btn btn-outline-primary" type="button">Connect</button>
  28. </div>
  29. }
  30. else if (connState == 1)
  31. {
  32. <span>Conecting...</span>
  33. }
  34. else if (connState == 2)
  35. {
  36. <div class="input-group mb-3">
  37. <div class="form-floating">
  38. <InputText class="@messageClass" placeholder="Message to send" type="search" onsearch="@Send" @oninput="MessageChanged" Value="@message" ValueExpression="()=>message"></InputText>
  39. @if (string.IsNullOrEmpty(message))
  40. {
  41. <label>Please enter message</label>
  42. }
  43. else
  44. {
  45. <label>Message to send</label>
  46. }
  47. </div>
  48. <button @onclick="@Send" class="btn btn-outline-secondary" type="button">Send</button>
  49. </div>
  50. @foreach (var item in displayingMessages)
  51. {
  52. <pre class="font-monospace" style="white-space:pre-wrap">@item</pre>
  53. }
  54. }
  55. else
  56. {
  57. <span>Error</span>
  58. }
  59. </div>
  60. @code {
  61. private System.Net.WebSockets.ClientWebSocket sck;
  62. private void NickNameChanged(ChangeEventArgs e)
  63. {
  64. nickName = e.Value.ToString().Trim();
  65. StateHasChanged();
  66. }
  67. private void MessageChanged(ChangeEventArgs e)
  68. {
  69. message = e.Value.ToString().Trim();
  70. StateHasChanged();
  71. }
  72. private async Task Connect()
  73. {
  74. if (string.IsNullOrEmpty(nickName)) return;
  75. connState = 1;
  76. StateHasChanged();
  77. try
  78. {
  79. sck = new System.Net.WebSockets.ClientWebSocket();
  80. sck.Options.AddSubProtocol("swcp");
  81. var b = http.BaseAddress;
  82. await sck.ConnectAsync(new Uri($"{(b.Scheme == "https" ? "wss" : "ws")}://{b.Host}:{b.Port}/connect"), default);
  83. connState = 2;
  84. StateHasChanged();
  85. var buf = System.Text.Encoding.UTF8.GetBytes(nickName);
  86. await sck.SendAsync(buf, System.Net.WebSockets.WebSocketMessageType.Text, true, default);
  87. while (true)
  88. {
  89. buf = new Byte[1024];
  90. var r = await sck.ReceiveAsync(buf, default);
  91. displayingMessages.Insert(0, System.Text.Encoding.UTF8.GetString(buf, 0, r.Count));
  92. while (displayingMessages.Count >= maxDisplayMessage) displayingMessages.RemoveAt(maxDisplayMessage - 1);
  93. StateHasChanged();
  94. }
  95. }
  96. catch (Exception)
  97. {
  98. connState = -1;
  99. }
  100. }
  101. private async Task Send()
  102. {
  103. if (string.IsNullOrEmpty(message)) return;
  104. var msg = $"{nickName}: {message}";
  105. await sck.SendAsync(System.Text.Encoding.UTF8.GetBytes(msg), System.Net.WebSockets.WebSocketMessageType.Text, true, default);
  106. message = "";
  107. StateHasChanged();
  108. }
  109. }