Skip to content

Commit

Permalink
Made circuit events strongly-typed via IMessenger.
Browse files Browse the repository at this point in the history
  • Loading branch information
bitbound committed Aug 4, 2023
1 parent 33d4384 commit c9aa682
Show file tree
Hide file tree
Showing 33 changed files with 699 additions and 356 deletions.
7 changes: 7 additions & 0 deletions .editorconfig
Expand Up @@ -111,6 +111,10 @@ dotnet_style_qualification_for_event = false:silent
dotnet_style_qualification_for_method = false:silent
dotnet_style_qualification_for_property = false:silent
dotnet_style_qualification_for_field = false:silent

# IDE0130: Namespace does not match folder structure
dotnet_diagnostic.IDE0130.severity = error

[*.cs]
csharp_indent_labels = one_less_than_current
csharp_using_directive_placement = outside_namespace:silent
Expand Down Expand Up @@ -167,3 +171,6 @@ dotnet_diagnostic.CS8600.severity = error

# CS8602: Dereference of a possibly null reference.
dotnet_diagnostic.CS8602.severity = error

# CS8631: The type cannot be used as type parameter in the generic type or method. Nullability of type argument doesn't match constraint type.
dotnet_diagnostic.CS8631.severity = error
97 changes: 51 additions & 46 deletions Server/Components/Devices/ChatCard.razor.cs
@@ -1,12 +1,12 @@
using Microsoft.AspNetCore.Components;
using Immense.SimpleMessenger;
using Microsoft.AspNetCore.Components;
using Microsoft.AspNetCore.Components.Web;
using Remotely.Server.Hubs;
using Remotely.Server.Models.Messages;
using Remotely.Server.Services;
using Remotely.Shared.Enums;
using Remotely.Shared.ViewModels;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;

namespace Remotely.Server.Components.Devices;
Expand All @@ -30,10 +30,13 @@ public partial class ChatCard : AuthComponentBase, IDisposable
[Inject]
private IJsInterop JsInterop { get; init; } = null!;

[Inject]
private IMessenger Messenger { get; init; } = null!;

public void Dispose()
{
AppState.PropertyChanged -= AppState_PropertyChanged;
CircuitConnection.MessageReceived -= CircuitConnection_MessageReceived;
Messenger.Unregister<ChatReceivedMessage, string>(this, CircuitConnection.ConnectionId);
GC.SuppressFinalize(this);
}

Expand All @@ -46,59 +49,61 @@ protected override async Task OnInitializedAsync()
{
await base.OnInitializedAsync();
AppState.PropertyChanged += AppState_PropertyChanged;
CircuitConnection.MessageReceived += CircuitConnection_MessageReceived;
await Messenger.Register<ChatReceivedMessage, string>(
this,
CircuitConnection.ConnectionId,
HandleChatMessageReceived);
}

private async void AppState_PropertyChanged(object? sender, System.ComponentModel.PropertyChangedEventArgs e)
private async Task HandleChatMessageReceived(ChatReceivedMessage message)
{
if (e.PropertyName == Session.SessionId)
if (message.DeviceId != Session.DeviceId)
{
await InvokeAsync(StateHasChanged);
return;
}
}

private async void CircuitConnection_MessageReceived(object? sender, Models.CircuitEvent e)
{
if (e.EventName == Models.CircuitEventName.ChatReceived)
var session = AppState.DevicesFrameChatSessions.Find(x => x.DeviceId == message.DeviceId);

if (session is null)
{
var deviceId = (string)e.Params[0];
return;
}

if (deviceId == Session.DeviceId)
if (message.DidDisconnect)
{
session.ChatHistory.Add(new ChatHistoryItem()
{
var deviceName = (string)e.Params[1];
var message = (string)e.Params[2];
var disconnected = (bool)e.Params[3];

var session = AppState.DevicesFrameChatSessions.Find(x => x.DeviceId == deviceId);

if (disconnected)
{
session.ChatHistory.Add(new ChatHistoryItem()
{
Message = $"{Session.DeviceName} disconnected.",
Origin = ChatHistoryItemOrigin.System
});
}
else
{
session.ChatHistory.Add(new ChatHistoryItem()
{
Message = message,
Origin = ChatHistoryItemOrigin.Device
});
}

if (!session.IsExpanded)
{
session.MissedChats++;
}

await InvokeAsync(StateHasChanged);

JsInterop.ScrollToEnd(_chatMessagesWindow);
}
Message = $"{Session.DeviceName} disconnected.",
Origin = ChatHistoryItemOrigin.System
});
}
else
{
session.ChatHistory.Add(new ChatHistoryItem()
{
Message = message.MessageText,
Origin = ChatHistoryItemOrigin.Device
});
}

if (!session.IsExpanded)
{
session.MissedChats++;
}

await InvokeAsync(StateHasChanged);

JsInterop.ScrollToEnd(_chatMessagesWindow);
}

private async void AppState_PropertyChanged(object? sender, System.ComponentModel.PropertyChangedEventArgs e)
{
if (e.PropertyName == Session.SessionId)
{
await InvokeAsync(StateHasChanged);
}
}

private void CloseChatCard()
{
AppState.DevicesFrameChatSessions.RemoveAll(x => x.DeviceId == Session.DeviceId);
Expand Down
62 changes: 30 additions & 32 deletions Server/Components/Devices/ChatFrame.razor.cs
@@ -1,7 +1,10 @@
using Microsoft.AspNetCore.Components;
using Immense.SimpleMessenger;
using Microsoft.AspNetCore.Components;
using Microsoft.AspNetCore.Components.Web;
using Remotely.Server.Hubs;
using Remotely.Server.Models.Messages;
using Remotely.Server.Services;
using Remotely.Shared.Entities;
using Remotely.Shared.Enums;
using Remotely.Shared.ViewModels;
using System;
Expand All @@ -20,55 +23,50 @@ public partial class ChatFrame : AuthComponentBase, IDisposable
[Inject]
private ICircuitConnection CircuitConnection { get; init; } = null!;

[Inject]
private IMessenger Messenger { get; init; } = null!;

public void Dispose()
{
AppState.PropertyChanged -= AppState_PropertyChanged;
CircuitConnection.MessageReceived -= CircuitConnection_MessageReceived;
Messenger.Unregister<ChatReceivedMessage, string>(this, CircuitConnection.ConnectionId);
GC.SuppressFinalize(this);
}

protected override async Task OnInitializedAsync()
{
await base.OnInitializedAsync();
AppState.PropertyChanged += AppState_PropertyChanged;
CircuitConnection.MessageReceived += CircuitConnection_MessageReceived;
await Messenger.Register<ChatReceivedMessage, string>(
this,
CircuitConnection.ConnectionId,
HandleChatMessageReceived);
}

private void CircuitConnection_MessageReceived(object? sender, Models.CircuitEvent e)
private async Task HandleChatMessageReceived(ChatReceivedMessage message)
{
if (e.EventName == Models.CircuitEventName.ChatReceived)
if (AppState.DevicesFrameChatSessions.Exists(x => x.DeviceId == message.DeviceId) ||
message.DidDisconnect)
{
var deviceId = (string)e.Params[0];

if (!AppState.DevicesFrameChatSessions.Exists(x => x.DeviceId == deviceId))
{
var deviceName = (string)e.Params[1];
var message = (string)e.Params[2];
var disconnected = (bool)e.Params[3];

if (disconnected)
{
return;
}
return;
}

var newChat = new ChatSession()
{
DeviceId = deviceId,
DeviceName = deviceName,
IsExpanded = true
};
var newChat = new ChatSession()
{
DeviceId = message.DeviceId,
DeviceName = message.DeviceName,
IsExpanded = true
};

newChat.ChatHistory.Add(new ChatHistoryItem()
{
Message = message,
Origin = ChatHistoryItemOrigin.Device
});
newChat.ChatHistory.Add(new ChatHistoryItem()
{
Message = message.MessageText,
Origin = ChatHistoryItemOrigin.Device
});

AppState.DevicesFrameChatSessions.Add(newChat);
AppState.DevicesFrameChatSessions.Add(newChat);

InvokeAsync(StateHasChanged);
}
}
await InvokeAsync(StateHasChanged);
}

private void AppState_PropertyChanged(object? sender, System.ComponentModel.PropertyChangedEventArgs e)
Expand Down
77 changes: 49 additions & 28 deletions Server/Components/Devices/DeviceCard.razor.cs
@@ -1,21 +1,17 @@
using Immense.RemoteControl.Server.Abstractions;
using Immense.SimpleMessenger;
using Microsoft.AspNetCore.Components;
using Microsoft.AspNetCore.Components.Forms;
using Microsoft.AspNetCore.Components.Web;
using Microsoft.AspNetCore.SignalR;
using Microsoft.Extensions.Logging;
using Remotely.Server.Auth;
using Remotely.Server.Enums;
using Remotely.Server.Hubs;
using Remotely.Server.Models;
using Remotely.Server.Models.Messages;
using Remotely.Server.Services;
using Remotely.Shared.Entities;
using Remotely.Shared.Enums;
using Remotely.Shared.Utilities;
using Remotely.Shared.ViewModels;
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Linq;
using System.Text.Json;
using System.Threading.Tasks;
Expand Down Expand Up @@ -69,10 +65,13 @@ public partial class DeviceCard : AuthComponentBase, IDisposable
[Inject]
private IUpgradeService UpgradeService { get; init; } = null!;

[Inject]
private IMessenger Messenger { get; init; } = null!;

public void Dispose()
{
AppState.PropertyChanged -= AppState_PropertyChanged;
CircuitConnection.MessageReceived -= CircuitConnection_MessageReceived;
Messenger.Unregister<DeviceStateChangedMessage, string>(this, CircuitConnection.ConnectionId);
GC.SuppressFinalize(this);
}

Expand All @@ -84,7 +83,48 @@ protected override async Task OnInitializedAsync()
_currentVersion = UpgradeService.GetCurrentVersion();
_deviceGroups = DataService.GetDeviceGroups(UserName);
AppState.PropertyChanged += AppState_PropertyChanged;
CircuitConnection.MessageReceived += CircuitConnection_MessageReceived;
await Messenger.Register<DeviceStateChangedMessage, string>(
this,
CircuitConnection.ConnectionId,
HandleDeviceStateChanged);
}

private async Task HandleDeviceStateChanged(DeviceStateChangedMessage message)
{
if (message.Device.ID != Device.ID)
{
return;
}

// TODO: It would be cool to decorate user-editable properties
// with a "UserEditable" attribute, then use a source generator
// to create/update a method that copies property values for
// those that do not have the attribute. We could do the same
// with reflection, but this method is called too frequently,
// and the performance hit would likely be significant.

// If the card is expanded, only update the immutable UI
// elements, so any changes to the form fields aren't lost.
if (IsExpanded)
{
Device.CurrentUser = message.Device.CurrentUser;
Device.Platform = message.Device.Platform;
Device.TotalStorage = message.Device.TotalStorage;
Device.UsedStorage = message.Device.UsedStorage;
Device.Drives = message.Device.Drives;
Device.CpuUtilization = message.Device.CpuUtilization;
Device.TotalMemory = message.Device.TotalMemory;
Device.UsedMemory = message.Device.UsedMemory;
Device.AgentVersion = message.Device.AgentVersion;
Device.LastOnline = message.Device.LastOnline;
Device.PublicIP = message.Device.PublicIP;
Device.MacAddresses = message.Device.MacAddresses;
}
else
{
Device = message.Device;
}
await InvokeAsync(StateHasChanged);
}

private void AppState_PropertyChanged(object? sender, System.ComponentModel.PropertyChangedEventArgs e)
Expand All @@ -97,25 +137,6 @@ private void AppState_PropertyChanged(object? sender, System.ComponentModel.Prop
}
}

private async void CircuitConnection_MessageReceived(object? sender, CircuitEvent e)
{
switch (e.EventName)
{
case CircuitEventName.DeviceUpdate:
case CircuitEventName.DeviceWentOffline:
{
if (e.Params?.FirstOrDefault() is Device device &&
device.ID == Device?.ID)
{
Device = device;
await InvokeAsync(StateHasChanged);
}
break;
}
default:
break;
}
}
private void ContextMenuOpening(MouseEventArgs args)
{
if (GetCardState() == DeviceCardState.Normal)
Expand Down Expand Up @@ -331,7 +352,7 @@ private async Task UninstallAgent()
await CircuitConnection.UninstallAgents(new[] { Device.ID });
AppState.DevicesFrameFocusedDevice = null;
AppState.DevicesFrameFocusedCardState = DeviceCardState.Normal;
ParentFrame.Refresh();
await ParentFrame.Refresh();
}
}

Expand Down

0 comments on commit c9aa682

Please sign in to comment.