add signalr support
This commit is contained in:
parent
1ee15a8ed3
commit
5a015b379b
@ -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
22
NoteHub.cs
Normal 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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -1,9 +1,11 @@
|
|||||||
|
using BinaryDad.Notes;
|
||||||
using BinaryDad.Notes.Services;
|
using BinaryDad.Notes.Services;
|
||||||
|
|
||||||
var builder = WebApplication.CreateBuilder(args);
|
var builder = WebApplication.CreateBuilder(args);
|
||||||
|
|
||||||
// Add services to the container.
|
// Add services to the container.
|
||||||
builder.Services.AddControllersWithViews();
|
builder.Services.AddControllersWithViews();
|
||||||
|
builder.Services.AddSignalR();
|
||||||
builder.Services.AddSingleton<INoteService, FileNoteService>();
|
builder.Services.AddSingleton<INoteService, FileNoteService>();
|
||||||
|
|
||||||
var app = builder.Build();
|
var app = builder.Build();
|
||||||
@ -24,4 +26,6 @@ app.MapControllerRoute(
|
|||||||
name: "default",
|
name: "default",
|
||||||
pattern: "{controller=Home}/{action=Index}/{id?}");
|
pattern: "{controller=Home}/{action=Index}/{id?}");
|
||||||
|
|
||||||
|
app.MapHub<NoteHub>("/noteHub");
|
||||||
|
|
||||||
app.Run();
|
app.Run();
|
||||||
|
@ -5,4 +5,5 @@
|
|||||||
|
|
||||||
<textarea id="content" name="content" spellcheck="false">@Model</textarea>
|
<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>
|
@ -12,6 +12,7 @@
|
|||||||
@RenderBody()
|
@RenderBody()
|
||||||
|
|
||||||
<script src="~/lib/jquery/dist/jquery.min.js"></script>
|
<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>
|
<script src="~/js/site.js" asp-append-version="true"></script>
|
||||||
@await RenderSectionAsync("Scripts", required: false)
|
@await RenderSectionAsync("Scripts", required: false)
|
||||||
</body>
|
</body>
|
||||||
|
13
libman.json
Normal file
13
libman.json
Normal 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"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
@ -28,7 +28,7 @@ textarea {
|
|||||||
resize: none;
|
resize: none;
|
||||||
color: #444;
|
color: #444;
|
||||||
font-size: 12px;
|
font-size: 12px;
|
||||||
font-family: Consolas;
|
font-family: Consolas, 'Courier New';
|
||||||
outline: none;
|
outline: none;
|
||||||
position: absolute;
|
position: absolute;
|
||||||
box-sizing: border-box;
|
box-sizing: border-box;
|
||||||
@ -40,18 +40,25 @@ textarea {
|
|||||||
color: #ddd;
|
color: #ddd;
|
||||||
}
|
}
|
||||||
|
|
||||||
#saved-indicator {
|
.toast {
|
||||||
position: fixed;
|
position: fixed;
|
||||||
bottom: -40px;
|
bottom: -40px;
|
||||||
right: 20px;
|
right: 20px;
|
||||||
font-size: 12px;
|
font-size: 12px;
|
||||||
background-color: green;
|
|
||||||
padding: 10px;
|
padding: 10px;
|
||||||
border-radius: 10px 10px 0 0;
|
border-radius: 10px 10px 0 0;
|
||||||
color: #fff;
|
color: #fff;
|
||||||
transition: bottom 0.2s;
|
transition: bottom 0.2s;
|
||||||
}
|
}
|
||||||
|
|
||||||
#saved-indicator.show {
|
.toast.show {
|
||||||
bottom: 0;
|
bottom: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#saved-indicator {
|
||||||
|
background-color: green;
|
||||||
|
}
|
||||||
|
|
||||||
|
#update-indicator {
|
||||||
|
background-color: orangered;
|
||||||
|
}
|
||||||
|
@ -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');
|
$textarea = $textarea || $('textarea');
|
||||||
|
|
||||||
var content = $textarea.val();
|
var content = $textarea.val();
|
||||||
|
|
||||||
$.ajax('/api/save', {
|
connection.invoke('SaveNote', content).then(function () {
|
||||||
data: content,
|
showToast('#saved-indicator');
|
||||||
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.');
|
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
$(function () {
|
$(function () {
|
||||||
|
|
||||||
|
let $textarea = $('textarea');
|
||||||
|
|
||||||
|
// update content upon sync save
|
||||||
|
connection.on('updateNote', function (content) {
|
||||||
|
$textarea.val(content);
|
||||||
|
showToast('#update-indicator');
|
||||||
|
});
|
||||||
|
|
||||||
// set dark mode
|
// set dark mode
|
||||||
if (window.location.hash == '#dark') {
|
if (window.location.hash == '#dark') {
|
||||||
$('textarea').addClass('dark');
|
$textarea.addClass('dark');
|
||||||
}
|
}
|
||||||
|
|
||||||
var timer = null;
|
var timer = null;
|
||||||
|
|
||||||
let ignoredKeyCodes = [17, 18, 20, 27, 37, 38, 39, 40, 91];
|
let ignoredKeyCodes = [17, 18, 20, 27, 37, 38, 39, 40, 91];
|
||||||
|
|
||||||
// save after a second delay after typing
|
// save after a second delay after typing
|
||||||
$('textarea').keyup(function (e) {
|
$textarea.keyup(function (e) {
|
||||||
|
|
||||||
clearTimeout(timer);
|
clearTimeout(timer);
|
||||||
|
|
||||||
@ -46,7 +61,7 @@ $(function () {
|
|||||||
});
|
});
|
||||||
|
|
||||||
// support tab key in textarea
|
// support tab key in textarea
|
||||||
$('textarea').keydown(function (e) {
|
$textarea.keydown(function (e) {
|
||||||
if (e.keyCode === 9) { // tab was pressed
|
if (e.keyCode === 9) { // tab was pressed
|
||||||
// get caret position/selection
|
// get caret position/selection
|
||||||
var start = this.selectionStart;
|
var start = this.selectionStart;
|
||||||
@ -66,5 +81,4 @@ $(function () {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
});
|
});
|
2
wwwroot/lib/signalr/dist/browser/signalr.min.js
vendored
Normal file
2
wwwroot/lib/signalr/dist/browser/signalr.min.js
vendored
Normal file
File diff suppressed because one or more lines are too long
Loading…
x
Reference in New Issue
Block a user