Connectifi.DesktopAgent.WPF 0.1.0

dotnet add package Connectifi.DesktopAgent.WPF --version 0.1.0                
NuGet\Install-Package Connectifi.DesktopAgent.WPF -Version 0.1.0                
This command is intended to be used within the Package Manager Console in Visual Studio, as it uses the NuGet module's version of Install-Package.
<PackageReference Include="Connectifi.DesktopAgent.WPF" Version="0.1.0" />                
For projects that support PackageReference, copy this XML node into the project file to reference the package.
paket add Connectifi.DesktopAgent.WPF --version 0.1.0                
#r "nuget: Connectifi.DesktopAgent.WPF, 0.1.0"                
#r directive can be used in F# Interactive and Polyglot Notebooks. Copy this into the interactive tool or source code of the script to reference the package.
// Install Connectifi.DesktopAgent.WPF as a Cake Addin
#addin nuget:?package=Connectifi.DesktopAgent.WPF&version=0.1.0

// Install Connectifi.DesktopAgent.WPF as a Cake Tool
#tool nuget:?package=Connectifi.DesktopAgent.WPF&version=0.1.0                

Connectifi.DesktopAgent.WPF

This project is a WPF wrapper around the Connectifi.DesktopAgent project. Connectifi.DesktopAgent.WPF specifically does the following:

  • creates a WebView2 component and binds Connectifi.DesktopAgent to it
  • exposes the CreateAgent method following the same pattern as the Connectifi Agent Web component, available from NPM

Usage

Add the DesktopAgentWPF control into your application and call the CreateAgent method, passing in the URL for the Connectifi Service and the AppId (applicationName@directoryName). 'CreateAgentwill resolve to aDesktopAgent` that provides the FDC3 .NET API plus extensions for integrating the Agent UI.

Code example of instantiating the Agent:

    using Connectifi.DesktopAgent
    ...
            var desktopAgentWPF = new DesktopAgentWPF();
            (this.Content as Grid).Children.Add(desktopAgentWPF);
            var desktopAgent = await desktopAgentWPF.CreateAgent([INTEROP SERVICE URL HERE], [APPID HERE]);

            desktopAgent.OnHandleIntentResolution += (_, evt) =>
            {
                _resolverDialog = new AppSelectionWPF(this);
                CurrentIntent = _currentIntent;
                CurrentTicker = _currentTicker;
                _resolverDialog.ShowAppSelectionAsync(evt.HandleIntentResolution);
            };
            desktopAgent.OnConnectifiEvent += OnConnectifiEvent;
        

DesktopAgent Status WPF User Control

The DesktopAgentStatusUserControl control displays the current status of the Connectifi Agent

  • Requires a reference to the DesktopAgentWPF object
    <Window
        ...
        xmlns:desktopAgentWPFControls="clr-namespace:Connectifi.DesktopAgent.WPF.Controls;assembly=Connectifi.DesktopAgent.WPF"
        >
        ...
        <StatusBar Name="StatusBar_AgentStatus"
                   Height="30"
                   DockPanel.Dock="Bottom"
                   HorizontalAlignment="Stretch">
            <StatusBarItem HorizontalAlignment="Right">
                <desktopAgentWPFControls:DesktopAgentStatusUserControl 
                    DesktopAgentWPF="{Binding DesktopAgentWPF, RelativeSource={RelativeSource AncestorType={x:Type local:MainWindow}}}" />
            </StatusBarItem>
        </StatusBar>
        ...
    </Window>

DesktopAgent Events

OnConnectifiEvent

This event occurs whenever the web agent received any event from Connectifi. It can be type converted to any of the following possibilities. Please see the Web documentation for further information.

  • HandleOpenConnectifiEvent
    Called after fdc3.open or an intent is resolved. In this case, the service sends a message to the client requesting it to launch a specific app. The message format is as follows:
class ConnectifiOpenMessage
{
    string Name { get; }
    pstring Url { get;  }
}

Where name is the name of the app in the directory, url is the url to launch (for web applications)
By default it opens the default web browser at the provided url.
See more

    • OnSessionAuthRequiredConnectifiEvent
      Called when the user is being authenticated. Passed the directory name as an argument.
    • OnAuthErrorConnectifiEvent
      (Deprecated) See OnSessionAuthRequiredConnectifiEvent.
  • OnSessionErrorConnectifiEvent
    (Deprecated) Called when the user could not connect to the directory because the app was not registered in the directory or the directory could not be found. Passed the directory name as an argument.
  • OnAppIdentityErrorConnectifiEvent
    (Deprecated) Called when the user could not connect to the directory because the app was not registered in the directory or the directory could not be found. Passed the directory name as an argument.
  • OnLoadErrorConnectifiEvent
    Called when the there is a timeout connecting to the service (interop endpoint).
  • OnChannelJoinedConnectifiEvent
    Called when a channel is joined. Argument is the id of the channel joined.
  • OnChannelLeftConnectifiEvent
    Called when leaveCurrentChannel is executed. I.e. the user leaves the current channel but does not join another.
  • OnConnectedConnectifiEvent
    Called when a socket connection is established.
  • OnDisconnectedConnectifiEvent
    Called when the socket connection is dropped. Will be passed the auto-reconnect time (in milliseconds) as an argument.
  • OnWorkingChangedConnectifiEvent
    Called when the agent starts or stops "working" or "being busy". the boolean argument is the current state.
  • OnSignedInConnectifiEvent
    Called after the user has successfully signed into the directory. Will be passed the username / identifier as an argument.
  • OnSignedOutConnectifiEvent
    Called after the user is signed out.
desktopAgent.OnConnectifiEvent += (s, e) =>
{
    if (e.ConnectifiEvent is OnConnectedConnectifiEvent)
    {
        //
    }
};

OnHandleIntentResolution

This event is to trigger showing the user a list of options for handling an intent and then providing back their chosen selection.

desktopAgent.OnHandleIntentResolution += (s, e) =>
{
    // show user the choice of apps from the available list within e.HandleIntentResolution.Message
    // after user selection call
    // e.HandleIntentResolution.Callback(/* selected app */, /* selected intent */);
};
class HandleIntentResolution
{
    IntentResolutionMessage Message { get; }
    Task Callback(ConnectifiApp selected, string intent);
    Task CloseCallback(bool? resolve);
}

The intent resolution message has the following properties:

 class IntentResolutionMessage
{
    ResolutionType ResolutionType { get; }  // �intent-resolver� or �context-resolver� depending on if the resolution is coming from a raiseIntent or raiseIntentsForContext call.
    T? Context<T>() where T : IContext;     // the FDC3 context object associated with the intent - you must specify the generic argument as the type to deserialize to - e.g. Instrument
    AppIntentResult[] Data { get; }         // either a single result (�intent-resolver� type) or a list of results (�context-resolver�). See AppIntentResult below.
}

class AppIntentResult
{
    IntentMetadata Intent { get; }
    ConnectifiApp[] Apps { get; }
}

class ConnectifiApp : AppMetadata
{
    string Type { get; }
    string Id { get; }
    string Url { get; }
    string InstanceTitle { get; }
    DirectoryIntent[] Intents { get; }
    int Proximity { get; }      // Starting with 0 - a number indicating the relative device and application proximity from the app that initiated the resolver. For example, if the target app is on the same device and running in the same application (e.g. Chrome) as the initiator, proximity is 0. The scoring is meant to aid sorting the list in order of apps closest to furthers from where the user is currently working.
    string Useragent { get; }   // the raw user agent string for the app
    string Browser { get; }    // indicator of browser type the app is running in
    string Device { get; }     // indicator of the device the app is running on
    string Os { get; }         // indicator of the OS the app is running on
    long LastUpdate { get; }
}

The AppIntentResult joins up the standard FDC3 IntentMetadata type with an Array of ConnectifiApp types. (i.e. an intent and the app results matching it). The ConnectifiApp type is an extension of the standard FDC3 AppMetadata type that provides some additional properties that be used to help the user disambiguate between applications.

OnAuthRequired

DesktopAgent will send an OnAuthRequired event to inform the container that authorization is required, in which case the App should show the necessary web view. The DesktopAgentWPF class will handle the web view display itself.

desktopAgent.OnAuthRequired += (s, e) =>
{
    jsWebview.Visibility = e.IsAuthRequired ? Visibility.Visible : Visibility.Collapsed;
};

Configuration

The DesktopAgent can be configured to disable default behaviors through the Configuration property.

desktopAgent.Configuration.DefaultHandleOpen = false;      // disable opening default web browser at app url when HandleOpenConnectifiEvent is received
desktopAgent.Configuration.DefaultHandleAuthError = false; // disable navigating to login screen within WebView2 for manual user authentication when OnAuthErrorConnectifiEvent is received

Auth options

Hosting the Login Panel in a specific panel

For the DesktopAgentOptions object creation used with CreateAgent, you can specify a panel to host the WebView in other than the current window.

  • In the example below, TargetWebPanel is a Panel object you want to show the login page
var options = new DesktopAgentOptions(TargetWebPanel);
var desktopAgent = await desktopAgentWPF.CreateAgent([INTEROP SERVICE URL HERE], [APPID HERE], options);

Faster auth display time

Additionally, you can pass the LoginPagePath (based on your actual auth process's page), and the auth display will show upon navigation to that page. This fires earlier than depending on the default OnAuthRequired event behavior.

  • Below suggests a setting useful for AWS Cognito, whose login url path starts with "/login?"
var options = new DesktopAgentOptions(TargetWebPanel)
            {
                LoginPagePath = "/login?"
            };
var desktopAgent = await desktopAgentWPF.CreateAgent([INTEROP SERVICE URL HERE], [APPID HERE], options);

Hosting the Login Panel in a popup

If you want to use a modal dialog for Auth, a few additional options exist

When the dialog is opened, you can tell DesktopAgentWPF to put that auth panel into the Dialog's own panel. this.Content below refers to a panel on the modal dialog

DesktopAgentWPF?.PushWebViewPanel((this.Content as Panel)!);

Subsequently be sure to pop the webview panel back its earlier location on your dialog's closing event, as the Panel always needs to be active.

DesktopAgentWPF?.PopWebViewPanel();

License

Copyright 2024 Connectifi

Distributed under the Apache License, Version 2.0.

SPDX-License-Identifier: Apache-2.0

Product Compatible and additional computed target framework versions.
.NET net7.0-windows7.0 is compatible.  net8.0-windows was computed.  net8.0-windows7.0 is compatible. 
.NET Framework net462 is compatible.  net463 was computed.  net47 was computed.  net471 was computed.  net472 was computed.  net48 was computed.  net481 was computed. 
Compatible target framework(s)
Included target framework(s) (in package)
Learn more about Target Frameworks and .NET Standard.

NuGet packages

This package is not used by any NuGet packages.

GitHub repositories

This package is not used by any popular GitHub repositories.

Version Downloads Last updated
0.1.0 144 4/16/2024
0.1.0-beta.2 64 4/16/2024
0.1.0-beta.1 63 4/16/2024
0.0.5 180 4/1/2024
0.0.5-beta.1 68 4/1/2024
0.0.5-alpha.2 60 4/1/2024
0.0.5-alpha.1 55 3/29/2024
0.0.4-beta.1 67 3/20/2024
0.0.4-alpha.3 73 3/16/2024
0.0.4-alpha.2 57 3/16/2024
0.0.4-alpha.1 58 3/14/2024