Actions menu api (#1862)

* wip

* wip

* random action on click

* removing actions

* register single key per command use

* change removeActionsMenu action name

* fixed actions menu not hiding content properly:

* actions menu fix

* added mock Block Player action

* ActionsMenu buttons styling

* added displaying priority for menu actions

* moved utils actionMenu features to the UI

* import as a type:

* more object oriented style for API

* removed registered actions from RemotePlayer instance

* readme update

* Fixing typos / Improving wording

* added instructions on AlterActionsMenu test map

Co-authored-by: Hanusiak Piotr <piotr@ltmp.co>
Co-authored-by: David Négrier <d.negrier@thecodingmachine.com>
This commit is contained in:
Piotr Hanusiak
2022-03-14 10:15:10 +01:00
committed by GitHub
parent 55db6a9b12
commit d4dcd0d5ce
16 changed files with 565 additions and 41 deletions
+113 -5
View File
@@ -8,6 +8,12 @@ import { ActionMessage } from "./Ui/ActionMessage";
import { isMessageReferenceEvent } from "../Events/ui/TriggerActionMessageEvent";
import { Menu } from "./Ui/Menu";
import type { RequireOnlyOne } from "../types";
import { isRemotePlayerClickedEvent, RemotePlayerClickedEvent } from "../Events/RemotePlayerClickedEvent";
import {
ActionsMenuActionClickedEvent,
isActionsMenuActionClickedEvent,
} from "../Events/ActionsMenuActionClickedEvent";
import { Observable, Subject } from "rxjs";
let popupId = 0;
const popups: Map<number, Popup> = new Map<number, Popup>();
@@ -42,7 +48,77 @@ export interface ActionMessageOptions {
callback: () => void;
}
export interface RemotePlayerInterface {
addAction(key: string, callback: Function): void;
}
export class RemotePlayer implements RemotePlayerInterface {
private id: number;
private actions: Map<string, ActionsMenuAction> = new Map<string, ActionsMenuAction>();
constructor(id: number) {
this.id = id;
}
public addAction(key: string, callback: Function): ActionsMenuAction {
const newAction = new ActionsMenuAction(this, key, callback);
this.actions.set(key, newAction);
sendToWorkadventure({
type: "addActionsMenuKeyToRemotePlayer",
data: { id: this.id, actionKey: key },
});
return newAction;
}
public callAction(key: string): void {
const action = this.actions.get(key);
if (action) {
action.call();
}
}
public removeAction(key: string): void {
this.actions.delete(key);
sendToWorkadventure({
type: "removeActionsMenuKeyFromRemotePlayer",
data: { id: this.id, actionKey: key },
});
}
}
export class ActionsMenuAction {
private remotePlayer: RemotePlayer;
private key: string;
private callback: Function;
constructor(remotePlayer: RemotePlayer, key: string, callback: Function) {
this.remotePlayer = remotePlayer;
this.key = key;
this.callback = callback;
}
public call(): void {
this.callback();
}
public remove(): void {
this.remotePlayer.removeAction(this.key);
}
}
export class WorkAdventureUiCommands extends IframeApiContribution<WorkAdventureUiCommands> {
public readonly _onRemotePlayerClicked: Subject<RemotePlayerInterface>;
public readonly onRemotePlayerClicked: Observable<RemotePlayerInterface>;
private currentlyClickedRemotePlayer?: RemotePlayer;
constructor() {
super();
this._onRemotePlayerClicked = new Subject<RemotePlayerInterface>();
this.onRemotePlayerClicked = this._onRemotePlayerClicked.asObservable();
}
callbacks = [
apiCallback({
type: "buttonClickedEvent",
@@ -82,9 +158,38 @@ export class WorkAdventureUiCommands extends IframeApiContribution<WorkAdventure
}
},
}),
apiCallback({
type: "remotePlayerClickedEvent",
typeChecker: isRemotePlayerClickedEvent,
callback: (payloadData: RemotePlayerClickedEvent) => {
this.currentlyClickedRemotePlayer = new RemotePlayer(payloadData.id);
this._onRemotePlayerClicked.next(this.currentlyClickedRemotePlayer);
},
}),
apiCallback({
type: "actionsMenuActionClickedEvent",
typeChecker: isActionsMenuActionClickedEvent,
callback: (payloadData: ActionsMenuActionClickedEvent) => {
this.currentlyClickedRemotePlayer?.callAction(payloadData.actionName);
},
}),
];
openPopup(targetObject: string, message: string, buttons: ButtonDescriptor[]): Popup {
public addActionsMenuKeyToRemotePlayer(id: number, actionKey: string): void {
sendToWorkadventure({
type: "addActionsMenuKeyToRemotePlayer",
data: { id, actionKey },
});
}
public removeActionsMenuKeyFromRemotePlayer(id: number, actionKey: string): void {
sendToWorkadventure({
type: "removeActionsMenuKeyFromRemotePlayer",
data: { id, actionKey },
});
}
public openPopup(targetObject: string, message: string, buttons: ButtonDescriptor[]): Popup {
popupId++;
const popup = new Popup(popupId);
const btnMap = new Map<number, () => void>();
@@ -119,7 +224,10 @@ export class WorkAdventureUiCommands extends IframeApiContribution<WorkAdventure
return popup;
}
registerMenuCommand(commandDescriptor: string, options: MenuOptions | ((commandDescriptor: string) => void)): Menu {
public registerMenuCommand(
commandDescriptor: string,
options: MenuOptions | ((commandDescriptor: string) => void)
): Menu {
const menu = new Menu(commandDescriptor);
if (typeof options === "function") {
@@ -168,15 +276,15 @@ export class WorkAdventureUiCommands extends IframeApiContribution<WorkAdventure
return menu;
}
displayBubble(): void {
public displayBubble(): void {
sendToWorkadventure({ type: "displayBubble", data: null });
}
removeBubble(): void {
public removeBubble(): void {
sendToWorkadventure({ type: "removeBubble", data: null });
}
displayActionMessage(actionMessageOptions: ActionMessageOptions): ActionMessage {
public displayActionMessage(actionMessageOptions: ActionMessageOptions): ActionMessage {
const actionMessage = new ActionMessage(actionMessageOptions, () => {
actionMessages.delete(actionMessage.uuid);
});