Code/InteractiveComputer/UI/ComputerAppHost.razor
@namespace PaneOS.InteractiveComputer
@using System
@using PaneOS.InteractiveComputer
@using Microsoft.AspNetCore.Components
@using Sandbox
@using Sandbox.UI
@inherits Panel
@code
{
[Parameter] public ComputerRunningApp? Instance { get; set; }
private string? mountedInstanceId;
private ComputerAppSession? mirrorSession;
protected override int BuildHash()
{
unchecked
{
var hash = 17;
hash = hash * 31 + (Instance?.State.InstanceId?.GetHashCode() ?? 0);
hash = hash * 31 + (Instance?.State.Data.Count ?? 0);
hash = hash * 31 + (Instance?.Session?.GetHashCode() ?? 0);
hash = hash * 31 + (mirrorSession?.GetHashCode() ?? 0);
return hash;
}
}
protected override void OnAfterTreeRender( bool firstTime )
{
try
{
base.OnAfterTreeRender( firstTime );
AddClass( "app-host" );
if ( Instance?.State is null )
return;
var content = ResolveMountedContent();
if ( !content.IsValid() )
return;
if ( ReferenceEquals( content, this ) || WouldCreateParentCycle( content ) )
return;
if ( mountedInstanceId == Instance.State.InstanceId && ReferenceEquals( content.Parent, this ) )
return;
if ( !ReferenceEquals( content.Parent, this ) )
content.Parent = this;
mountedInstanceId = Instance.State.InstanceId;
}
catch ( NullReferenceException )
{
return;
}
catch ( Exception ex ) when ( ex.Message.Contains( "Removed Child but didn't have child!", StringComparison.OrdinalIgnoreCase ) )
{
return;
}
catch ( Exception ex )
{
Log.Warning( $"PaneOS app host mount skipped: {ex.Message}" );
}
}
public override void OnDeleted()
{
try
{
if ( Instance?.Session.Content is { } content && ReferenceEquals( content.Parent, this ) )
content.Parent = null;
if ( mirrorSession?.Content is { } mirrorContent && ReferenceEquals( mirrorContent.Parent, this ) )
mirrorContent.Parent = null;
}
catch ( Exception )
{
}
base.OnDeleted();
}
private bool WouldCreateParentCycle( Panel content )
{
for ( Panel? ancestor = this; ancestor is not null; ancestor = ancestor.Parent )
{
if ( ReferenceEquals( ancestor, content ) )
return true;
}
return false;
}
private Panel ResolveMountedContent()
{
if ( Instance?.Session.Content is null )
return new Panel();
var content = Instance.Session.Content;
if ( content.IsValid() && (content.Parent is null || ReferenceEquals( content.Parent, this )) )
{
mirrorSession = null;
return content;
}
if ( mirrorSession is null || mountedInstanceId != Instance.State.InstanceId || !mirrorSession.Content.IsValid() )
mirrorSession = Instance.Runtime.CreateMirrorSession( Instance );
return mirrorSession.Content;
}
}