add signalr support

This commit is contained in:
Ryan Peters 2023-01-25 08:48:50 -05:00
parent 1ee15a8ed3
commit 5a015b379b
9 changed files with 89 additions and 61 deletions

View File

@ -1,36 +0,0 @@
using BinaryDad.Notes.Services;
using Microsoft.AspNetCore.Mvc;
namespace BinaryDad.Notes.Controllers;
[ApiController]
[Route("[controller]")]
public class ApiController : ControllerBase
{
private readonly INoteService noteService;
public ApiController(INoteService noteService)
{
this.noteService = noteService;
}
[HttpGet]
[Route("get")]
public string Get() => noteService.Get();
[HttpPost]
[Route("save")]
public async Task<bool> Save()
{
var content = string.Empty;
using (var reader = new StreamReader(Request.Body))
{
content = await reader.ReadToEndAsync();
}
noteService.Save(content);
return true;
}
}

22
NoteHub.cs Normal file
View File

@ -0,0 +1,22 @@
using BinaryDad.Notes.Services;
using Microsoft.AspNetCore.SignalR;
namespace BinaryDad.Notes
{
public class NoteHub : Hub
{
private readonly INoteService noteService;
public NoteHub(INoteService noteService)
{
this.noteService = noteService;
}
public async Task SaveNote(string content)
{
noteService.Save(content);
await Clients.Others.SendAsync("updateNote", content);
}
}
}

View File

@ -1,9 +1,11 @@
using BinaryDad.Notes;
using BinaryDad.Notes.Services;
var builder = WebApplication.CreateBuilder(args);
// Add services to the container.
builder.Services.AddControllersWithViews();
builder.Services.AddSignalR();
builder.Services.AddSingleton<INoteService, FileNoteService>();
var app = builder.Build();
@ -24,4 +26,6 @@ app.MapControllerRoute(
name: "default",
pattern: "{controller=Home}/{action=Index}/{id?}");
app.MapHub<NoteHub>("/noteHub");
app.Run();

View File

@ -5,4 +5,5 @@
<textarea id="content" name="content" spellcheck="false">@Model</textarea>
<div id="saved-indicator">Saved!</div>
<div class="toast" id="saved-indicator">Saved!</div>
<div class="toast" id="update-indicator">Updated!</div>

View File

@ -12,6 +12,7 @@
@RenderBody()
<script src="~/lib/jquery/dist/jquery.min.js"></script>
<script src="~/lib/signalr/dist/browser/signalr.min.js"></script>
<script src="~/js/site.js" asp-append-version="true"></script>
@await RenderSectionAsync("Scripts", required: false)
</body>

13
libman.json Normal file
View File

@ -0,0 +1,13 @@
{
"version": "1.0",
"defaultProvider": "unpkg",
"libraries": [
{
"library": "@microsoft/signalr@latest",
"destination": "wwwroot/lib/signalr/",
"files": [
"dist/browser/signalr.min.js"
]
}
]
}

View File

@ -28,7 +28,7 @@ textarea {
resize: none;
color: #444;
font-size: 12px;
font-family: Consolas;
font-family: Consolas, 'Courier New';
outline: none;
position: absolute;
box-sizing: border-box;
@ -40,18 +40,25 @@ textarea {
color: #ddd;
}
#saved-indicator {
.toast {
position: fixed;
bottom: -40px;
right: 20px;
font-size: 12px;
background-color: green;
padding: 10px;
border-radius: 10px 10px 0 0;
color: #fff;
transition: bottom 0.2s;
}
#saved-indicator.show {
.toast.show {
bottom: 0;
}
#saved-indicator {
background-color: green;
}
#update-indicator {
background-color: orangered;
}

View File

@ -1,38 +1,53 @@
let saveContent = function ($textarea) {
let connection = new signalR.HubConnectionBuilder().withUrl("/noteHub").build();
connection.start().then(function () {
console.log('Started websocket listener');
}).catch(function (err) {
return console.error(err.toString());
});
let showToast = function (selector) {
const cssClass = 'show';
// show 'saved' indicator
$(selector).addClass(cssClass).delay(800).queue(function (next) {
$(this).removeClass(cssClass);
next();
});
}
let saveContent = function ($textarea) {
$textarea = $textarea || $('textarea');
var content = $textarea.val();
$.ajax('/api/save', {
data: content,
contentType: 'text/plain',
type: 'POST'
}).done(function (data) {
// show 'saved' indicator
$('#saved-indicator').addClass('show').delay(800).queue(function (next) {
$(this).removeClass('show');
next();
});
}).fail(function () {
alert('Could not connect to server. Check your internet connection and try again.');
connection.invoke('SaveNote', content).then(function () {
showToast('#saved-indicator');
});
};
$(function () {
let $textarea = $('textarea');
// update content upon sync save
connection.on('updateNote', function (content) {
$textarea.val(content);
showToast('#update-indicator');
});
// set dark mode
if (window.location.hash == '#dark') {
$('textarea').addClass('dark');
$textarea.addClass('dark');
}
var timer = null;
let ignoredKeyCodes = [17, 18, 20, 27, 37, 38, 39, 40, 91];
// save after a second delay after typing
$('textarea').keyup(function (e) {
$textarea.keyup(function (e) {
clearTimeout(timer);
@ -46,7 +61,7 @@ $(function () {
});
// support tab key in textarea
$('textarea').keydown(function (e) {
$textarea.keydown(function (e) {
if (e.keyCode === 9) { // tab was pressed
// get caret position/selection
var start = this.selectionStart;
@ -66,5 +81,4 @@ $(function () {
return false;
}
});
});

File diff suppressed because one or more lines are too long