Provide commands and searches to Home

OpenFin Home helps users find content they want to open and information provided by applications or platforms registered with OpenFin Home. To do this, OpenFin Home provides a command line interface (CLI) that allows the user to search by using one of the registered providers.

Any application or platform can integrate with OpenFin Home by registering a HomeProvider. When multiple providers are registered with OpenFin Home, the user may choose which provider they want to perform their search by selecting the appropriate entry in the Home toolbar.

The HomeProvider interface extends the CLIProvider interface. In OpenFin Workspace version 4.0, these interfaces are identical. In later releases, HomeProvider may have additional properties or methods.

A HomeProvider can do the following:

  • Integrate with OpenFin Home.
  • Return customizable search results to Home, which can include suggested searches and filtering options.
  • Give the user control over searches by carrying out searches with the selected provider.
  • Set a logo icon to be displayed when the provider is selected.

Overview

At a high level, there are two steps to implementing a HomeProvider:

  1. Implement the HomeProvider interface to create your CLI provider.
  2. Register your CLI provider with HomeApi.

How to create a CLI Provider

At a finer-grain level, here are the steps to creating a CLI Provider:

  1. Install node.

  2. Install npm.

  3. Install the Workspace npm package, which enables your code to import the Home namespace:

npm i -E @openfin/workspace
  1. In your code, import OpenFin Workspace:
import {
    Home,
    CLIProvider,
    CLISearchListenerRequest,
    CLISearchResult,
    CLISearchListenerResponse,
    CLISearchResponse,
    CLIDispatchedSearchResult,
    App
} from "@openfin/workspace";
  1. Define and register your CLIProvider object:
const cliProvider: CLIProvider = {
    title: "My title,
    name: "My Provider name,
    icon: "url to icon",
    onUserInput: onUserInput,
    onResultDispatch: onResultDispatch,
};

await Home.register(cliProvider);

The onUserInput and onResultDispatch properties point to functions that are called when the user triggers a search and when the user selects a search result (respectively).

  1. Create the onUserInput function:
const onUserInput = async (
    request: CLISearchListenerRequest,
    response: CLISearchListenerResponse
): Promise<CLISearchResponse> => {
    const query = request.query.toLowerCase();
    if (query.indexOf("/") === 0) {
        return { results: [] };
    }
    
    // integrators list of Apps
    const apps: App[] = await getApps();
    
    const results: CLISearchResult<any>[] = apps
        .map((app) => {
            return {
                key: app.appId,
                title: app.title,
                actions: [{ name: "launch-app", hotkey: "enter" }],
                data: app,
                template: "Plain",
            };
        })
        .filter((entry) => {
            return entry.title.includes(query);
        });
    
    const result: CLISearchResponse = {
        results,
    };
    
    return result;
};
  1. Create the onResultDispatch function:
const onResultDispstch = async (result: CLIDispatchedSearchResult) => {
    if (result.data !== undefined) {
        await launchApp(result.data);
    } else {
        console.warn("Unable to execute result without data being passed");
    }
};

The full source code

Here is a complete file for creating and registering a CLI provider:

import { Home, CLIProvider, CLISearchListenerRequest, CLIFilter, CLISearchResult, CLISearchListenerResponse, CLISearchResponse, CLIDispatchedSearchResult, launchApp  } from "@openfin/workspace";
import { getApps } from "./apps";

const providerName = "register-with-home-basic";

async function getResults(query?: string) : Promise<CLISearchResponse> {
   
    let apps = await getApps();

    if(Array.isArray(apps)){
        
        let initialResults: CLISearchResult<any>[] = [];

        for(let i = 0; i < apps.length; i++) {
            if(apps[i].description !== undefined) {
                let entry: any = {
                    key: apps[i].appId,
                    title: apps[i].title,
                    actions: [{ name: "launch-app", hotkey: 'enter' }],
                    data: apps[i],
                    description: apps[i].description,
                    shortDescription: apps[i].description,
                    template: "SimpleText",
                    templateContent: apps[i].description,
                };
                initialResults.push(entry);
            } else {
                let entry: any = {
                    key: apps[i].appId,
                    title: apps[i].title,
                    actions: [{ name: "launch-app", hotkey: 'enter' }],
                    data: apps[i],
                    template: "Plain"
                };
                initialResults.push(entry);
            }
        }

        let finalResults;

        if(query === undefined || query === null || query.length === 0) {
            finalResults = initialResults;
        } else {
            finalResults = initialResults.filter(entry => {
              let targetValue = entry.title;
                        
              if(targetValue !== undefined && targetValue !== null && typeof targetValue === "string") {
                  return targetValue.toLowerCase().indexOf(query) > -1;
              }
              return false;
            });
        }

        let response: CLISearchResponse = {
            results: finalResults
        };

        return response;
    } else {
        return {
            results:[]
        };
    }
}

export async function register(): Promise<void> {
    console.log("Initialising home.");

    const queryMinLength = 3;

    const onUserInput = async (request: CLISearchListenerRequest, response: CLISearchListenerResponse): Promise<CLISearchResponse> => {
        let query = request.query.toLowerCase();
        if(query.indexOf("/") === 0) {
            return {results: [] };
        }

        if(query.length < queryMinLength) {
            return getResults();
        }

        return getResults(query);
    };

    const onSelection = async (result:CLIDispatchedSearchResult) => {
        if (result.data !== undefined) {
            await launchApp(result.data);
        }  else {
            console.warn("Unable to execute result without data being passed");
        }
    };

    const cliProvider:CLIProvider = {
        title: "Basic Workspace Platform",
        name: providerName,
        icon: "http://localhost:8080/favicon.ico",
        onUserInput: onUserInput,
        onResultDispatch: onSelection,
     };

     console.log("Home configured.");

    return Home.register(cliProvider);
}

export async function deregister() {
  return Home.deregister(providerName);
}

export async function show() {
    return Home.show();
}

export async function hide() {
    return Home.hide();
}

Did this page help you?