Refactoring displayActionMessage signature. Now accepting an options object. This should allow for more options in the future.

This commit is contained in:
David Négrier 2021-08-05 12:02:00 +02:00
parent 87e4367455
commit bc1c6a4986
7 changed files with 84 additions and 36 deletions

View file

@ -93,7 +93,11 @@ WA.ui.registerMenuCommand("test", () => {
### Awaiting User Confirmation (with space bar) ### Awaiting User Confirmation (with space bar)
``` ```
WA.ui.displayActionMessage(message: string, callback: () => void): ActionMessage WA.ui.displayActionMessage({
message: string,
callback: () => void,
type?: "message"|"warning",
}): ActionMessage
``` ```
Displays a message at the bottom of the screen (that will disappear when space bar is pressed). Displays a message at the bottom of the screen (that will disappear when space bar is pressed).
@ -105,8 +109,11 @@ Displays a message at the bottom of the screen (that will disappear when space b
Example: Example:
```javascript ```javascript
const triggerMessage = WA.ui.displayActionMessage("press 'space' to confirm", () => { const triggerMessage = WA.ui.displayActionMessage({
WA.chat.sendChatMessage("confirmed", "trigger message logic") message: "press 'space' to confirm",
callback: () => {
WA.chat.sendChatMessage("confirmed", "trigger message logic")
}
}); });
setTimeout(() => { setTimeout(() => {

View file

@ -1,12 +1,17 @@
import * as tg from 'generic-type-guard'; import * as tg from "generic-type-guard";
export const triggerActionMessage = 'triggerActionMessage'; export const triggerActionMessage = "triggerActionMessage";
export const removeActionMessage = 'removeActionMessage'; export const removeActionMessage = "removeActionMessage";
export const isActionMessageType = tg.isSingletonStringUnion("message", "warning");
export type ActionMessageType = tg.GuardedType<typeof isActionMessageType>;
export const isTriggerActionMessageEvent = new tg.IsInterface() export const isTriggerActionMessageEvent = new tg.IsInterface()
.withProperties({ .withProperties({
message: tg.isString, message: tg.isString,
uuid: tg.isString, uuid: tg.isString,
type: isActionMessageType,
}) })
.get(); .get();

View file

@ -417,6 +417,15 @@ class IframeListener {
}); });
} }
sendActionMessageTriggered(uuid: string): void {
this.postMessage({
type: "messageTriggered",
data: {
uuid,
},
});
}
/** /**
* Sends the message... to all allowed iframes. * Sends the message... to all allowed iframes.
*/ */

View file

@ -1,10 +1,12 @@
import { import {
ActionMessageType,
MessageReferenceEvent, MessageReferenceEvent,
removeActionMessage, removeActionMessage,
triggerActionMessage, triggerActionMessage,
TriggerActionMessageEvent, TriggerActionMessageEvent,
} from "../../Events/ui/TriggerActionMessageEvent"; } from "../../Events/ui/TriggerActionMessageEvent";
import { queryWorkadventure } from "../IframeApiContribution"; import { queryWorkadventure } from "../IframeApiContribution";
import type { ActionMessageOptions } from "../ui";
function uuidv4() { function uuidv4() {
return "xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx".replace(/[xy]/g, (c) => { return "xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx".replace(/[xy]/g, (c) => {
const r = (Math.random() * 16) | 0, const r = (Math.random() * 16) | 0,
@ -13,29 +15,29 @@ function uuidv4() {
}); });
} }
export let triggerMessageInstance: ActionMessage | undefined = undefined;
export class ActionMessage { export class ActionMessage {
uuid: string; public readonly uuid: string;
private readonly type: ActionMessageType;
private readonly message: string;
private readonly callback: () => void;
constructor(private message: string, private callback: () => void) { constructor(actionMessageOptions: ActionMessageOptions, private onRemove: () => void) {
this.uuid = uuidv4(); this.uuid = uuidv4();
if (triggerMessageInstance) { this.message = actionMessageOptions.message;
triggerMessageInstance.remove(); this.type = actionMessageOptions.type ?? "message";
} this.callback = actionMessageOptions.callback;
triggerMessageInstance = this;
this.create(); this.create();
} }
async create() { private async create() {
await queryWorkadventure({ await queryWorkadventure({
type: triggerActionMessage, type: triggerActionMessage,
data: { data: {
message: this.message, message: this.message,
type: this.type,
uuid: this.uuid, uuid: this.uuid,
} as TriggerActionMessageEvent, } as TriggerActionMessageEvent,
}); });
this.callback();
} }
async remove() { async remove() {
@ -45,6 +47,10 @@ export class ActionMessage {
uuid: this.uuid, uuid: this.uuid,
} as MessageReferenceEvent, } as MessageReferenceEvent,
}); });
triggerMessageInstance = undefined; this.onRemove();
}
triggerCallback() {
this.callback();
} }
} }

View file

@ -5,6 +5,7 @@ import { apiCallback } from "./registeredCallbacks";
import type { ButtonClickedCallback, ButtonDescriptor } from "./Ui/ButtonDescriptor"; import type { ButtonClickedCallback, ButtonDescriptor } from "./Ui/ButtonDescriptor";
import { Popup } from "./Ui/Popup"; import { Popup } from "./Ui/Popup";
import { ActionMessage } from "./Ui/ActionMessage"; import { ActionMessage } from "./Ui/ActionMessage";
import { isMessageReferenceEvent } from "../Events/ui/TriggerActionMessageEvent";
let popupId = 0; let popupId = 0;
const popups: Map<number, Popup> = new Map<number, Popup>(); const popups: Map<number, Popup> = new Map<number, Popup>();
@ -14,6 +15,7 @@ const popupCallbacks: Map<number, Map<number, ButtonClickedCallback>> = new Map<
>(); >();
const menuCallbacks: Map<string, (command: string) => void> = new Map(); const menuCallbacks: Map<string, (command: string) => void> = new Map();
const actionMessages = new Map<string, ActionMessage>();
interface ZonedPopupOptions { interface ZonedPopupOptions {
zone: string; zone: string;
@ -23,6 +25,12 @@ interface ZonedPopupOptions {
popupOptions: Array<ButtonDescriptor>; popupOptions: Array<ButtonDescriptor>;
} }
export interface ActionMessageOptions {
message: string;
type?: "message" | "warning";
callback: () => void;
}
export class WorkAdventureUiCommands extends IframeApiContribution<WorkAdventureUiCommands> { export class WorkAdventureUiCommands extends IframeApiContribution<WorkAdventureUiCommands> {
callbacks = [ callbacks = [
apiCallback({ apiCallback({
@ -49,6 +57,16 @@ export class WorkAdventureUiCommands extends IframeApiContribution<WorkAdventure
} }
}, },
}), }),
apiCallback({
type: "messageTriggered",
typeChecker: isMessageReferenceEvent,
callback: (event) => {
const actionMessage = actionMessages.get(event.uuid);
if (actionMessage) {
actionMessage.triggerCallback();
}
},
}),
]; ];
openPopup(targetObject: string, message: string, buttons: ButtonDescriptor[]): Popup { openPopup(targetObject: string, message: string, buttons: ButtonDescriptor[]): Popup {
@ -104,8 +122,12 @@ export class WorkAdventureUiCommands extends IframeApiContribution<WorkAdventure
sendToWorkadventure({ type: "removeBubble", data: null }); sendToWorkadventure({ type: "removeBubble", data: null });
} }
displayActionMessage(message: string, callback: () => void): ActionMessage { displayActionMessage(actionMessageOptions: ActionMessageOptions): ActionMessage {
return new ActionMessage(message, callback); const actionMessage = new ActionMessage(actionMessageOptions, () => {
actionMessages.delete(actionMessage.uuid);
});
actionMessages.set(actionMessage.uuid, actionMessage);
return actionMessage;
} }
} }

View file

@ -1150,21 +1150,17 @@ ${escapedMessage}
}); });
}); });
iframeListener.registerAnswerer( iframeListener.registerAnswerer("triggerActionMessage", (message) =>
"triggerActionMessage", layoutManagerActionStore.addAction({
(message) => uuid: message.uuid,
new Promise((resolver) => { type: "message",
layoutManagerActionStore.addAction({ message: message.message,
uuid: message.uuid, callback: () => {
type: "message", layoutManagerActionStore.removeAction(message.uuid);
message: message.message, iframeListener.sendActionMessageTriggered(message.uuid);
callback: () => { },
layoutManagerActionStore.removeAction(message.uuid); userInputManager: this.userInputManager,
resolver(); })
},
userInputManager: this.userInputManager,
});
})
); );
iframeListener.registerAnswerer("removeActionMessage", (message) => { iframeListener.registerAnswerer("removeActionMessage", (message) => {

View file

@ -2,8 +2,11 @@ WA.onInit().then(() => {
let message; let message;
WA.room.onEnterZone("carpet", () => { WA.room.onEnterZone("carpet", () => {
message = WA.ui.displayActionMessage("This is a test message. Press space to display a chat message. Walk out to hide the message.", () => { message = WA.ui.displayActionMessage({
WA.chat.sendChatMessage("Hello world!", "The bot"); message: "This is a test message. Press space to display a chat message. Walk out to hide the message.",
callback: () => {
WA.chat.sendChatMessage("Hello world!", "The bot");
}
}); });
}); });