Merge pull request #1227 from jonnytest1/trigger-message-refv3
trigger message api refactorv3
This commit is contained in:
commit
a09f27b448
@ -86,4 +86,51 @@ WA.ui.registerMenuCommand("test", () => {
|
|||||||
|
|
||||||
<div class="col">
|
<div class="col">
|
||||||
<img src="https://workadventu.re/img/docs/menu-command.png" class="figure-img img-fluid rounded" alt="" />
|
<img src="https://workadventu.re/img/docs/menu-command.png" class="figure-img img-fluid rounded" alt="" />
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
### Awaiting User Confirmation (with space bar)
|
||||||
|
|
||||||
|
```
|
||||||
|
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).
|
||||||
|
|
||||||
|
<div class="col">
|
||||||
|
<img src="https://workadventu.re/img/docs/trigger_message.png" class="figure-img img-fluid rounded" alt="" />
|
||||||
|
</div>
|
||||||
|
|
||||||
|
Example:
|
||||||
|
|
||||||
|
```javascript
|
||||||
|
const triggerMessage = WA.ui.displayActionMessage({
|
||||||
|
message: "press 'space' to confirm",
|
||||||
|
callback: () => {
|
||||||
|
WA.chat.sendChatMessage("confirmed", "trigger message logic")
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
setTimeout(() => {
|
||||||
|
// later
|
||||||
|
triggerMessage.remove();
|
||||||
|
}, 1000)
|
||||||
|
```
|
||||||
|
|
||||||
|
Please note that `displayActionMessage` returns an object of the `ActionMessage` class.
|
||||||
|
|
||||||
|
The `ActionMessage` class contains a single method: `remove(): Promise<void>`. This will obviously remove the message when called.
|
||||||
|
|
||||||
|
```javascript
|
||||||
|
class ActionMessage {
|
||||||
|
/**
|
||||||
|
* Hides the message
|
||||||
|
*/
|
||||||
|
remove() {};
|
||||||
|
}
|
||||||
|
```
|
||||||
|
@ -26,7 +26,6 @@
|
|||||||
"rules": {
|
"rules": {
|
||||||
"no-unused-vars": "off",
|
"no-unused-vars": "off",
|
||||||
"@typescript-eslint/no-explicit-any": "error",
|
"@typescript-eslint/no-explicit-any": "error",
|
||||||
|
|
||||||
// TODO: remove those ignored rules and write a stronger code!
|
// TODO: remove those ignored rules and write a stronger code!
|
||||||
"@typescript-eslint/no-floating-promises": "off",
|
"@typescript-eslint/no-floating-promises": "off",
|
||||||
"@typescript-eslint/no-unsafe-call": "off",
|
"@typescript-eslint/no-unsafe-call": "off",
|
||||||
|
@ -9,6 +9,7 @@ import type { OpenCoWebSiteEvent } from "./OpenCoWebSiteEvent";
|
|||||||
import type { OpenPopupEvent } from "./OpenPopupEvent";
|
import type { OpenPopupEvent } from "./OpenPopupEvent";
|
||||||
import type { OpenTabEvent } from "./OpenTabEvent";
|
import type { OpenTabEvent } from "./OpenTabEvent";
|
||||||
import type { UserInputChatEvent } from "./UserInputChatEvent";
|
import type { UserInputChatEvent } from "./UserInputChatEvent";
|
||||||
|
import type { MapDataEvent } from "./MapDataEvent";
|
||||||
import type { LayerEvent } from "./LayerEvent";
|
import type { LayerEvent } from "./LayerEvent";
|
||||||
import type { SetPropertyEvent } from "./setPropertyEvent";
|
import type { SetPropertyEvent } from "./setPropertyEvent";
|
||||||
import type { LoadSoundEvent } from "./LoadSoundEvent";
|
import type { LoadSoundEvent } from "./LoadSoundEvent";
|
||||||
@ -23,6 +24,13 @@ import { isMapDataEvent } from "./MapDataEvent";
|
|||||||
import { isSetVariableEvent } from "./SetVariableEvent";
|
import { isSetVariableEvent } from "./SetVariableEvent";
|
||||||
import type { LoadTilesetEvent } from "./LoadTilesetEvent";
|
import type { LoadTilesetEvent } from "./LoadTilesetEvent";
|
||||||
import { isLoadTilesetEvent } from "./LoadTilesetEvent";
|
import { isLoadTilesetEvent } from "./LoadTilesetEvent";
|
||||||
|
import type {
|
||||||
|
MessageReferenceEvent,
|
||||||
|
removeActionMessage,
|
||||||
|
triggerActionMessage,
|
||||||
|
TriggerActionMessageEvent,
|
||||||
|
} from "./ui/TriggerActionMessageEvent";
|
||||||
|
import { isMessageReferenceEvent, isTriggerActionMessageEvent } from "./ui/TriggerActionMessageEvent";
|
||||||
|
|
||||||
export interface TypedMessageEvent<T> extends MessageEvent {
|
export interface TypedMessageEvent<T> extends MessageEvent {
|
||||||
data: T;
|
data: T;
|
||||||
@ -73,6 +81,7 @@ export interface IframeResponseEventMap {
|
|||||||
hasPlayerMoved: HasPlayerMovedEvent;
|
hasPlayerMoved: HasPlayerMovedEvent;
|
||||||
menuItemClicked: MenuItemClickedEvent;
|
menuItemClicked: MenuItemClickedEvent;
|
||||||
setVariable: SetVariableEvent;
|
setVariable: SetVariableEvent;
|
||||||
|
messageTriggered: MessageReferenceEvent;
|
||||||
}
|
}
|
||||||
export interface IframeResponseEvent<T extends keyof IframeResponseEventMap> {
|
export interface IframeResponseEvent<T extends keyof IframeResponseEventMap> {
|
||||||
type: T;
|
type: T;
|
||||||
@ -105,6 +114,14 @@ export const iframeQueryMapTypeGuards = {
|
|||||||
query: isLoadTilesetEvent,
|
query: isLoadTilesetEvent,
|
||||||
answer: tg.isNumber,
|
answer: tg.isNumber,
|
||||||
},
|
},
|
||||||
|
triggerActionMessage: {
|
||||||
|
query: isTriggerActionMessageEvent,
|
||||||
|
answer: tg.isUndefined,
|
||||||
|
},
|
||||||
|
removeActionMessage: {
|
||||||
|
query: isMessageReferenceEvent,
|
||||||
|
answer: tg.isUndefined,
|
||||||
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
type GuardedType<T> = T extends (x: unknown) => x is infer T ? T : never;
|
type GuardedType<T> = T extends (x: unknown) => x is infer T ? T : never;
|
||||||
|
26
front/src/Api/Events/ui/TriggerActionMessageEvent.ts
Normal file
26
front/src/Api/Events/ui/TriggerActionMessageEvent.ts
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
import * as tg from "generic-type-guard";
|
||||||
|
|
||||||
|
export const triggerActionMessage = "triggerActionMessage";
|
||||||
|
export const removeActionMessage = "removeActionMessage";
|
||||||
|
|
||||||
|
export const isActionMessageType = tg.isSingletonStringUnion("message", "warning");
|
||||||
|
|
||||||
|
export type ActionMessageType = tg.GuardedType<typeof isActionMessageType>;
|
||||||
|
|
||||||
|
export const isTriggerActionMessageEvent = new tg.IsInterface()
|
||||||
|
.withProperties({
|
||||||
|
message: tg.isString,
|
||||||
|
uuid: tg.isString,
|
||||||
|
type: isActionMessageType,
|
||||||
|
})
|
||||||
|
.get();
|
||||||
|
|
||||||
|
export type TriggerActionMessageEvent = tg.GuardedType<typeof isTriggerActionMessageEvent>;
|
||||||
|
|
||||||
|
export const isMessageReferenceEvent = new tg.IsInterface()
|
||||||
|
.withProperties({
|
||||||
|
uuid: tg.isString,
|
||||||
|
})
|
||||||
|
.get();
|
||||||
|
|
||||||
|
export type MessageReferenceEvent = tg.GuardedType<typeof isMessageReferenceEvent>;
|
24
front/src/Api/Events/ui/TriggerMessageEventHandler.ts
Normal file
24
front/src/Api/Events/ui/TriggerMessageEventHandler.ts
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
import {
|
||||||
|
isMessageReferenceEvent,
|
||||||
|
isTriggerActionMessageEvent,
|
||||||
|
removeActionMessage,
|
||||||
|
triggerActionMessage,
|
||||||
|
} from './TriggerActionMessageEvent';
|
||||||
|
|
||||||
|
import * as tg from 'generic-type-guard';
|
||||||
|
|
||||||
|
const isTriggerMessageEventObject = new tg.IsInterface()
|
||||||
|
.withProperties({
|
||||||
|
type: tg.isSingletonString(triggerActionMessage),
|
||||||
|
data: isTriggerActionMessageEvent,
|
||||||
|
})
|
||||||
|
.get();
|
||||||
|
|
||||||
|
const isTriggerMessageRemoveEventObject = new tg.IsInterface()
|
||||||
|
.withProperties({
|
||||||
|
type: tg.isSingletonString(removeActionMessage),
|
||||||
|
data: isMessageReferenceEvent,
|
||||||
|
})
|
||||||
|
.get();
|
||||||
|
|
||||||
|
export const isTriggerMessageHandlerEvent = tg.isUnion(isTriggerMessageEventObject, isTriggerMessageRemoveEventObject);
|
@ -1,4 +1,5 @@
|
|||||||
import { Subject } from "rxjs";
|
import { Subject } from "rxjs";
|
||||||
|
import type * as tg from "generic-type-guard";
|
||||||
import { ChatEvent, isChatEvent } from "./Events/ChatEvent";
|
import { ChatEvent, isChatEvent } from "./Events/ChatEvent";
|
||||||
import { HtmlUtils } from "../WebRtc/HtmlUtils";
|
import { HtmlUtils } from "../WebRtc/HtmlUtils";
|
||||||
import type { EnterLeaveEvent } from "./Events/EnterLeaveEvent";
|
import type { EnterLeaveEvent } from "./Events/EnterLeaveEvent";
|
||||||
@ -121,7 +122,7 @@ class IframeListener {
|
|||||||
init() {
|
init() {
|
||||||
window.addEventListener(
|
window.addEventListener(
|
||||||
"message",
|
"message",
|
||||||
(message: TypedMessageEvent<IframeEvent<keyof IframeEventMap>>) => {
|
(message: MessageEvent<unknown>) => {
|
||||||
// Do we trust the sender of this message?
|
// Do we trust the sender of this message?
|
||||||
// Let's only accept messages from the iframe that are allowed.
|
// Let's only accept messages from the iframe that are allowed.
|
||||||
// Note: maybe we could restrict on the domain too for additional security (in case the iframe goes to another domain).
|
// Note: maybe we could restrict on the domain too for additional security (in case the iframe goes to another domain).
|
||||||
@ -416,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.
|
||||||
*/
|
*/
|
||||||
|
@ -1,51 +1,66 @@
|
|||||||
import type * as tg from "generic-type-guard";
|
import type * as tg from "generic-type-guard";
|
||||||
import type {
|
import type {
|
||||||
IframeEvent,
|
IframeEvent,
|
||||||
IframeEventMap, IframeQuery,
|
IframeEventMap,
|
||||||
|
IframeQuery,
|
||||||
IframeQueryMap,
|
IframeQueryMap,
|
||||||
IframeResponseEventMap
|
IframeResponseEventMap,
|
||||||
} from '../Events/IframeEvent';
|
} from "../Events/IframeEvent";
|
||||||
import type {IframeQueryWrapper} from "../Events/IframeEvent";
|
import type { IframeQueryWrapper } from "../Events/IframeEvent";
|
||||||
|
|
||||||
export function sendToWorkadventure(content: IframeEvent<keyof IframeEventMap>) {
|
export function sendToWorkadventure(content: IframeEvent<keyof IframeEventMap>) {
|
||||||
window.parent.postMessage(content, "*")
|
window.parent.postMessage(content, "*");
|
||||||
}
|
}
|
||||||
|
|
||||||
let queryNumber = 0;
|
let queryNumber = 0;
|
||||||
|
|
||||||
export const answerPromises = new Map<number, {
|
export const answerPromises = new Map<
|
||||||
resolve: (value: (IframeQueryMap[keyof IframeQueryMap]['answer'] | PromiseLike<IframeQueryMap[keyof IframeQueryMap]['answer']>)) => void,
|
number,
|
||||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
{
|
||||||
reject: (reason?: any) => void
|
resolve: (
|
||||||
}>();
|
value:
|
||||||
|
| IframeQueryMap[keyof IframeQueryMap]["answer"]
|
||||||
|
| PromiseLike<IframeQueryMap[keyof IframeQueryMap]["answer"]>
|
||||||
|
) => void;
|
||||||
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||||
|
reject: (reason?: any) => void;
|
||||||
|
}
|
||||||
|
>();
|
||||||
|
|
||||||
export function queryWorkadventure<T extends keyof IframeQueryMap>(content: IframeQuery<T>): Promise<IframeQueryMap[T]['answer']> {
|
export function queryWorkadventure<T extends keyof IframeQueryMap>(
|
||||||
return new Promise<IframeQueryMap[T]['answer']>((resolve, reject) => {
|
content: IframeQuery<T>
|
||||||
window.parent.postMessage({
|
): Promise<IframeQueryMap[T]["answer"]> {
|
||||||
id: queryNumber,
|
return new Promise<IframeQueryMap[T]["answer"]>((resolve, reject) => {
|
||||||
query: content
|
window.parent.postMessage(
|
||||||
} as IframeQueryWrapper<T>, "*");
|
{
|
||||||
|
id: queryNumber,
|
||||||
|
query: content,
|
||||||
|
} as IframeQueryWrapper<T>,
|
||||||
|
"*"
|
||||||
|
);
|
||||||
|
|
||||||
answerPromises.set(queryNumber, {
|
answerPromises.set(queryNumber, {
|
||||||
resolve,
|
resolve,
|
||||||
reject
|
reject,
|
||||||
});
|
});
|
||||||
|
|
||||||
queryNumber++;
|
queryNumber++;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
type GuardedType<Guard extends tg.TypeGuard<unknown>> = Guard extends tg.TypeGuard<infer T> ? T : never
|
type GuardedType<Guard extends tg.TypeGuard<unknown>> = Guard extends tg.TypeGuard<infer T> ? T : never;
|
||||||
|
|
||||||
export interface IframeCallback<Key extends keyof IframeResponseEventMap, T = IframeResponseEventMap[Key], Guard = tg.TypeGuard<T>> {
|
export interface IframeCallback<
|
||||||
|
Key extends keyof IframeResponseEventMap,
|
||||||
typeChecker: Guard,
|
T = IframeResponseEventMap[Key],
|
||||||
callback: (payloadData: T) => void
|
Guard = tg.TypeGuard<T>
|
||||||
|
> {
|
||||||
|
typeChecker: Guard;
|
||||||
|
callback: (payloadData: T) => void;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface IframeCallbackContribution<Key extends keyof IframeResponseEventMap> extends IframeCallback<Key> {
|
export interface IframeCallbackContribution<Key extends keyof IframeResponseEventMap> extends IframeCallback<Key> {
|
||||||
|
type: Key;
|
||||||
type: Key
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -54,9 +69,10 @@ export interface IframeCallbackContribution<Key extends keyof IframeResponseEven
|
|||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
export abstract class IframeApiContribution<T extends {
|
export abstract class IframeApiContribution<
|
||||||
callbacks: Array<IframeCallbackContribution<keyof IframeResponseEventMap>>,
|
T extends {
|
||||||
}> {
|
callbacks: Array<IframeCallbackContribution<keyof IframeResponseEventMap>>;
|
||||||
|
}
|
||||||
abstract callbacks: T["callbacks"]
|
> {
|
||||||
|
abstract callbacks: T["callbacks"];
|
||||||
}
|
}
|
||||||
|
56
front/src/Api/iframe/Ui/ActionMessage.ts
Normal file
56
front/src/Api/iframe/Ui/ActionMessage.ts
Normal file
@ -0,0 +1,56 @@
|
|||||||
|
import {
|
||||||
|
ActionMessageType,
|
||||||
|
MessageReferenceEvent,
|
||||||
|
removeActionMessage,
|
||||||
|
triggerActionMessage,
|
||||||
|
TriggerActionMessageEvent,
|
||||||
|
} from "../../Events/ui/TriggerActionMessageEvent";
|
||||||
|
import { queryWorkadventure } from "../IframeApiContribution";
|
||||||
|
import type { ActionMessageOptions } from "../ui";
|
||||||
|
function uuidv4() {
|
||||||
|
return "xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx".replace(/[xy]/g, (c) => {
|
||||||
|
const r = (Math.random() * 16) | 0,
|
||||||
|
v = c === "x" ? r : (r & 0x3) | 0x8;
|
||||||
|
return v.toString(16);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
export class ActionMessage {
|
||||||
|
public readonly uuid: string;
|
||||||
|
private readonly type: ActionMessageType;
|
||||||
|
private readonly message: string;
|
||||||
|
private readonly callback: () => void;
|
||||||
|
|
||||||
|
constructor(actionMessageOptions: ActionMessageOptions, private onRemove: () => void) {
|
||||||
|
this.uuid = uuidv4();
|
||||||
|
this.message = actionMessageOptions.message;
|
||||||
|
this.type = actionMessageOptions.type ?? "message";
|
||||||
|
this.callback = actionMessageOptions.callback;
|
||||||
|
this.create();
|
||||||
|
}
|
||||||
|
|
||||||
|
private async create() {
|
||||||
|
await queryWorkadventure({
|
||||||
|
type: triggerActionMessage,
|
||||||
|
data: {
|
||||||
|
message: this.message,
|
||||||
|
type: this.type,
|
||||||
|
uuid: this.uuid,
|
||||||
|
} as TriggerActionMessageEvent,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
async remove() {
|
||||||
|
await queryWorkadventure({
|
||||||
|
type: removeActionMessage,
|
||||||
|
data: {
|
||||||
|
uuid: this.uuid,
|
||||||
|
} as MessageReferenceEvent,
|
||||||
|
});
|
||||||
|
this.onRemove();
|
||||||
|
}
|
||||||
|
|
||||||
|
triggerCallback() {
|
||||||
|
this.callback();
|
||||||
|
}
|
||||||
|
}
|
@ -1,10 +1,11 @@
|
|||||||
import { isButtonClickedEvent } from "../Events/ButtonClickedEvent";
|
import { isButtonClickedEvent } from "../Events/ButtonClickedEvent";
|
||||||
import { isMenuItemClickedEvent } from "../Events/ui/MenuItemClickedEvent";
|
import { isMenuItemClickedEvent } from "../Events/ui/MenuItemClickedEvent";
|
||||||
import type { MenuItemRegisterEvent } from "../Events/ui/MenuItemRegisterEvent";
|
|
||||||
import { IframeApiContribution, sendToWorkadventure } from "./IframeApiContribution";
|
import { IframeApiContribution, sendToWorkadventure } from "./IframeApiContribution";
|
||||||
import { apiCallback } from "./registeredCallbacks";
|
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 { 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 {
|
||||||
@ -103,6 +121,14 @@ export class WorkAdventureUiCommands extends IframeApiContribution<WorkAdventure
|
|||||||
removeBubble(): void {
|
removeBubble(): void {
|
||||||
sendToWorkadventure({ type: "removeBubble", data: null });
|
sendToWorkadventure({ type: "removeBubble", data: null });
|
||||||
}
|
}
|
||||||
|
|
||||||
|
displayActionMessage(actionMessageOptions: ActionMessageOptions): ActionMessage {
|
||||||
|
const actionMessage = new ActionMessage(actionMessageOptions, () => {
|
||||||
|
actionMessages.delete(actionMessage.uuid);
|
||||||
|
});
|
||||||
|
actionMessages.set(actionMessage.uuid, actionMessage);
|
||||||
|
return actionMessage;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export default new WorkAdventureUiCommands();
|
export default new WorkAdventureUiCommands();
|
||||||
|
@ -1,26 +1,5 @@
|
|||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import { layoutManagerActionStore } from "../../Stores/LayoutManagerStore";
|
import { layoutManagerActionStore } from "../../Stores/LayoutManagerStore";
|
||||||
import { onDestroy, onMount } from "svelte";
|
|
||||||
import { get } from "svelte/store";
|
|
||||||
|
|
||||||
onMount(() => {
|
|
||||||
for (const action of get(layoutManagerActionStore)) {
|
|
||||||
action.userInputManager?.addSpaceEventListner(action.callback);
|
|
||||||
if ( action.type === 'warning') {
|
|
||||||
//remove it after 10 sec
|
|
||||||
setTimeout(() => {
|
|
||||||
layoutManagerActionStore.removeAction(action);
|
|
||||||
}, 10000)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
onDestroy(() => {
|
|
||||||
for (const action of get(layoutManagerActionStore)) {
|
|
||||||
action.userInputManager?.removeSpaceEventListner(action.callback);
|
|
||||||
}
|
|
||||||
layoutManagerActionStore.clearActions();
|
|
||||||
})
|
|
||||||
|
|
||||||
function onClick(callback: () => void) {
|
function onClick(callback: () => void) {
|
||||||
callback();
|
callback();
|
||||||
@ -75,4 +54,4 @@
|
|||||||
50% {bottom: 30px;}
|
50% {bottom: 30px;}
|
||||||
100% {bottom: 40px;}
|
100% {bottom: 40px;}
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
@ -86,7 +86,7 @@ import { playersStore } from "../../Stores/PlayersStore";
|
|||||||
import { chatVisibilityStore } from "../../Stores/ChatStore";
|
import { chatVisibilityStore } from "../../Stores/ChatStore";
|
||||||
import Tileset = Phaser.Tilemaps.Tileset;
|
import Tileset = Phaser.Tilemaps.Tileset;
|
||||||
import { userIsAdminStore } from "../../Stores/GameStore";
|
import { userIsAdminStore } from "../../Stores/GameStore";
|
||||||
import { layoutManagerActionStore, layoutManagerVisibilityStore } from "../../Stores/LayoutManagerStore";
|
import { layoutManagerActionStore } from "../../Stores/LayoutManagerStore";
|
||||||
import { get } from "svelte/store";
|
import { get } from "svelte/store";
|
||||||
|
|
||||||
export interface GameSceneInitInterface {
|
export interface GameSceneInitInterface {
|
||||||
@ -792,7 +792,7 @@ export class GameScene extends DirtyScene {
|
|||||||
});
|
});
|
||||||
this.gameMap.onPropertyChange("openWebsite", (newValue, oldValue, allProps) => {
|
this.gameMap.onPropertyChange("openWebsite", (newValue, oldValue, allProps) => {
|
||||||
if (newValue === undefined) {
|
if (newValue === undefined) {
|
||||||
layoutManagerVisibilityStore.set(false);
|
layoutManagerActionStore.removeAction("openWebsite");
|
||||||
coWebsiteManager.closeCoWebsite();
|
coWebsiteManager.closeCoWebsite();
|
||||||
} else {
|
} else {
|
||||||
const openWebsiteFunction = () => {
|
const openWebsiteFunction = () => {
|
||||||
@ -802,7 +802,7 @@ export class GameScene extends DirtyScene {
|
|||||||
allProps.get("openWebsiteAllowApi") as boolean | undefined,
|
allProps.get("openWebsiteAllowApi") as boolean | undefined,
|
||||||
allProps.get("openWebsitePolicy") as string | undefined
|
allProps.get("openWebsitePolicy") as string | undefined
|
||||||
);
|
);
|
||||||
layoutManagerVisibilityStore.set(false);
|
layoutManagerActionStore.removeAction("openWebsite");
|
||||||
};
|
};
|
||||||
|
|
||||||
const openWebsiteTriggerValue = allProps.get(TRIGGER_WEBSITE_PROPERTIES);
|
const openWebsiteTriggerValue = allProps.get(TRIGGER_WEBSITE_PROPERTIES);
|
||||||
@ -812,12 +812,12 @@ export class GameScene extends DirtyScene {
|
|||||||
message = "Press SPACE or touch here to open web site";
|
message = "Press SPACE or touch here to open web site";
|
||||||
}
|
}
|
||||||
layoutManagerActionStore.addAction({
|
layoutManagerActionStore.addAction({
|
||||||
type: "openWebsite",
|
uuid: "openWebsite",
|
||||||
|
type: "message",
|
||||||
message: message,
|
message: message,
|
||||||
callback: () => openWebsiteFunction(),
|
callback: () => openWebsiteFunction(),
|
||||||
userInputManager: this.userInputManager,
|
userInputManager: this.userInputManager,
|
||||||
});
|
});
|
||||||
layoutManagerVisibilityStore.set(true);
|
|
||||||
} else {
|
} else {
|
||||||
openWebsiteFunction();
|
openWebsiteFunction();
|
||||||
}
|
}
|
||||||
@ -825,7 +825,7 @@ export class GameScene extends DirtyScene {
|
|||||||
});
|
});
|
||||||
this.gameMap.onPropertyChange("jitsiRoom", (newValue, oldValue, allProps) => {
|
this.gameMap.onPropertyChange("jitsiRoom", (newValue, oldValue, allProps) => {
|
||||||
if (newValue === undefined) {
|
if (newValue === undefined) {
|
||||||
layoutManagerVisibilityStore.set(false);
|
layoutManagerActionStore.removeAction("jitsi");
|
||||||
this.stopJitsi();
|
this.stopJitsi();
|
||||||
} else {
|
} else {
|
||||||
const openJitsiRoomFunction = () => {
|
const openJitsiRoomFunction = () => {
|
||||||
@ -838,7 +838,7 @@ export class GameScene extends DirtyScene {
|
|||||||
} else {
|
} else {
|
||||||
this.startJitsi(roomName, undefined);
|
this.startJitsi(roomName, undefined);
|
||||||
}
|
}
|
||||||
layoutManagerVisibilityStore.set(false);
|
layoutManagerActionStore.removeAction("jitsi");
|
||||||
};
|
};
|
||||||
|
|
||||||
const jitsiTriggerValue = allProps.get(TRIGGER_JITSI_PROPERTIES);
|
const jitsiTriggerValue = allProps.get(TRIGGER_JITSI_PROPERTIES);
|
||||||
@ -848,12 +848,12 @@ export class GameScene extends DirtyScene {
|
|||||||
message = "Press SPACE or touch here to enter Jitsi Meet room";
|
message = "Press SPACE or touch here to enter Jitsi Meet room";
|
||||||
}
|
}
|
||||||
layoutManagerActionStore.addAction({
|
layoutManagerActionStore.addAction({
|
||||||
type: "jitsiRoom",
|
uuid: "jitsi",
|
||||||
|
type: "message",
|
||||||
message: message,
|
message: message,
|
||||||
callback: () => openJitsiRoomFunction(),
|
callback: () => openJitsiRoomFunction(),
|
||||||
userInputManager: this.userInputManager,
|
userInputManager: this.userInputManager,
|
||||||
});
|
});
|
||||||
layoutManagerVisibilityStore.set(true);
|
|
||||||
} else {
|
} else {
|
||||||
openJitsiRoomFunction();
|
openJitsiRoomFunction();
|
||||||
}
|
}
|
||||||
@ -909,7 +909,7 @@ export class GameScene extends DirtyScene {
|
|||||||
let html = `<div id="container" hidden><div class="nes-container with-title is-centered">
|
let html = `<div id="container" hidden><div class="nes-container with-title is-centered">
|
||||||
${escapedMessage}
|
${escapedMessage}
|
||||||
</div> `;
|
</div> `;
|
||||||
const buttonContainer = `<div class="buttonContainer"</div>`;
|
const buttonContainer = '<div class="buttonContainer"</div>';
|
||||||
html += buttonContainer;
|
html += buttonContainer;
|
||||||
let id = 0;
|
let id = 0;
|
||||||
for (const button of openPopupEvent.buttons) {
|
for (const button of openPopupEvent.buttons) {
|
||||||
@ -1149,6 +1149,23 @@ ${escapedMessage}
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
iframeListener.registerAnswerer("triggerActionMessage", (message) =>
|
||||||
|
layoutManagerActionStore.addAction({
|
||||||
|
uuid: message.uuid,
|
||||||
|
type: "message",
|
||||||
|
message: message.message,
|
||||||
|
callback: () => {
|
||||||
|
layoutManagerActionStore.removeAction(message.uuid);
|
||||||
|
iframeListener.sendActionMessageTriggered(message.uuid);
|
||||||
|
},
|
||||||
|
userInputManager: this.userInputManager,
|
||||||
|
})
|
||||||
|
);
|
||||||
|
|
||||||
|
iframeListener.registerAnswerer("removeActionMessage", (message) => {
|
||||||
|
layoutManagerActionStore.removeAction(message.uuid);
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
private setPropertyLayer(
|
private setPropertyLayer(
|
||||||
@ -1271,6 +1288,10 @@ ${escapedMessage}
|
|||||||
this.biggestAvailableAreaStoreUnsubscribe();
|
this.biggestAvailableAreaStoreUnsubscribe();
|
||||||
iframeListener.unregisterAnswerer("getState");
|
iframeListener.unregisterAnswerer("getState");
|
||||||
iframeListener.unregisterAnswerer("loadTileset");
|
iframeListener.unregisterAnswerer("loadTileset");
|
||||||
|
iframeListener.unregisterAnswerer("getMapData");
|
||||||
|
iframeListener.unregisterAnswerer("getState");
|
||||||
|
iframeListener.unregisterAnswerer("triggerActionMessage");
|
||||||
|
iframeListener.unregisterAnswerer("removeActionMessage");
|
||||||
this.sharedVariablesManager?.close();
|
this.sharedVariablesManager?.close();
|
||||||
|
|
||||||
mediaManager.hideGameOverlay();
|
mediaManager.hideGameOverlay();
|
||||||
|
@ -1,15 +1,14 @@
|
|||||||
import { writable } from "svelte/store";
|
import { derived, writable } from "svelte/store";
|
||||||
import type { UserInputManager } from "../Phaser/UserInput/UserInputManager";
|
import type { UserInputManager } from "../Phaser/UserInput/UserInputManager";
|
||||||
|
|
||||||
export interface LayoutManagerAction {
|
export interface LayoutManagerAction {
|
||||||
type: string;
|
uuid: string;
|
||||||
|
type: "warning" | "message";
|
||||||
message: string | number | boolean | undefined;
|
message: string | number | boolean | undefined;
|
||||||
callback: () => void;
|
callback: () => void;
|
||||||
userInputManager: UserInputManager | undefined;
|
userInputManager: UserInputManager | undefined;
|
||||||
}
|
}
|
||||||
|
|
||||||
export const layoutManagerVisibilityStore = writable(false);
|
|
||||||
|
|
||||||
function createLayoutManagerAction() {
|
function createLayoutManagerAction() {
|
||||||
const { subscribe, set, update } = writable<LayoutManagerAction[]>([]);
|
const { subscribe, set, update } = writable<LayoutManagerAction[]>([]);
|
||||||
|
|
||||||
@ -18,26 +17,26 @@ function createLayoutManagerAction() {
|
|||||||
addAction: (newAction: LayoutManagerAction): void => {
|
addAction: (newAction: LayoutManagerAction): void => {
|
||||||
update((list: LayoutManagerAction[]) => {
|
update((list: LayoutManagerAction[]) => {
|
||||||
let found = false;
|
let found = false;
|
||||||
for (const actions of list) {
|
for (const action of list) {
|
||||||
if (actions.type === newAction.type && actions.message === newAction.message) {
|
if (action.uuid === newAction.uuid) {
|
||||||
found = true;
|
found = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!found) {
|
if (!found) {
|
||||||
list.push(newAction);
|
list.push(newAction);
|
||||||
|
newAction.userInputManager?.addSpaceEventListner(newAction.callback);
|
||||||
}
|
}
|
||||||
|
|
||||||
return list;
|
return list;
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
removeAction: (oldAction: LayoutManagerAction): void => {
|
removeAction: (uuid: string): void => {
|
||||||
update((list: LayoutManagerAction[]) => {
|
update((list: LayoutManagerAction[]) => {
|
||||||
const index = list.findIndex(
|
const index = list.findIndex((action) => action.uuid === uuid);
|
||||||
(actions) => actions.type === oldAction.type && actions.message === oldAction.message
|
|
||||||
);
|
|
||||||
|
|
||||||
if (index !== -1) {
|
if (index !== -1) {
|
||||||
|
list[index].userInputManager?.removeSpaceEventListner(list[index].callback);
|
||||||
list.splice(index, 1);
|
list.splice(index, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -51,3 +50,7 @@ function createLayoutManagerAction() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export const layoutManagerActionStore = createLayoutManagerAction();
|
export const layoutManagerActionStore = createLayoutManagerAction();
|
||||||
|
|
||||||
|
export const layoutManagerVisibilityStore = derived(layoutManagerActionStore, ($layoutManagerActionStore) => {
|
||||||
|
return !!$layoutManagerActionStore.length;
|
||||||
|
});
|
||||||
|
@ -25,15 +25,18 @@ export class MediaManager {
|
|||||||
if (result.type === "error") {
|
if (result.type === "error") {
|
||||||
console.error(result.error);
|
console.error(result.error);
|
||||||
layoutManagerActionStore.addAction({
|
layoutManagerActionStore.addAction({
|
||||||
|
uuid: "cameraAccessDenied",
|
||||||
type: "warning",
|
type: "warning",
|
||||||
message: "Camera access denied. Click here and check your browser permissions.",
|
message: "Camera access denied. Click here and check your browser permissions.",
|
||||||
callback: () => {
|
callback: () => {
|
||||||
helpCameraSettingsVisibleStore.set(true);
|
helpCameraSettingsVisibleStore.set(true);
|
||||||
layoutManagerVisibilityStore.set(false);
|
|
||||||
},
|
},
|
||||||
userInputManager: this.userInputManager,
|
userInputManager: this.userInputManager,
|
||||||
});
|
});
|
||||||
layoutManagerVisibilityStore.set(true);
|
//remove it after 10 sec
|
||||||
|
setTimeout(() => {
|
||||||
|
layoutManagerActionStore.removeAction("cameraAccessDenied");
|
||||||
|
}, 10000);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@ -42,15 +45,18 @@ export class MediaManager {
|
|||||||
if (result.type === "error") {
|
if (result.type === "error") {
|
||||||
console.error(result.error);
|
console.error(result.error);
|
||||||
layoutManagerActionStore.addAction({
|
layoutManagerActionStore.addAction({
|
||||||
|
uuid: "screenSharingAccessDenied",
|
||||||
type: "warning",
|
type: "warning",
|
||||||
message: "Screen sharing denied. Click here and check your browser permissions.",
|
message: "Screen sharing denied. Click here and check your browser permissions.",
|
||||||
callback: () => {
|
callback: () => {
|
||||||
helpCameraSettingsVisibleStore.set(true);
|
helpCameraSettingsVisibleStore.set(true);
|
||||||
layoutManagerVisibilityStore.set(false);
|
|
||||||
},
|
},
|
||||||
userInputManager: this.userInputManager,
|
userInputManager: this.userInputManager,
|
||||||
});
|
});
|
||||||
layoutManagerVisibilityStore.set(true);
|
//remove it after 10 sec
|
||||||
|
setTimeout(() => {
|
||||||
|
layoutManagerActionStore.removeAction("screenSharingAccessDenied");
|
||||||
|
}, 10000);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
16
maps/tests/TriggerMessageApi/script.js
Normal file
16
maps/tests/TriggerMessageApi/script.js
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
WA.onInit().then(() => {
|
||||||
|
let message;
|
||||||
|
|
||||||
|
WA.room.onEnterZone("carpet", () => {
|
||||||
|
message = WA.ui.displayActionMessage({
|
||||||
|
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");
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
WA.room.onLeaveZone("carpet", () => {
|
||||||
|
message && message.remove();
|
||||||
|
});
|
||||||
|
});
|
106
maps/tests/TriggerMessageApi/triggerMessage.json
Normal file
106
maps/tests/TriggerMessageApi/triggerMessage.json
Normal file
@ -0,0 +1,106 @@
|
|||||||
|
{ "compressionlevel":-1,
|
||||||
|
"height":10,
|
||||||
|
"infinite":false,
|
||||||
|
"layers":[
|
||||||
|
{
|
||||||
|
"data":[1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1],
|
||||||
|
"height":10,
|
||||||
|
"id":1,
|
||||||
|
"name":"floor",
|
||||||
|
"opacity":1,
|
||||||
|
"type":"tilelayer",
|
||||||
|
"visible":true,
|
||||||
|
"width":10,
|
||||||
|
"x":0,
|
||||||
|
"y":0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"data":[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 12, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
|
||||||
|
"height":10,
|
||||||
|
"id":2,
|
||||||
|
"name":"start",
|
||||||
|
"opacity":1,
|
||||||
|
"type":"tilelayer",
|
||||||
|
"visible":true,
|
||||||
|
"width":10,
|
||||||
|
"x":0,
|
||||||
|
"y":0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"data":[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 34, 34, 0, 0, 0, 0, 0, 0, 0, 0, 34, 34, 0, 0, 0, 0, 0, 0, 0, 0, 34, 34, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
|
||||||
|
"height":10,
|
||||||
|
"id":8,
|
||||||
|
"name":"carpet",
|
||||||
|
"opacity":1,
|
||||||
|
"properties":[
|
||||||
|
{
|
||||||
|
"name":"zone",
|
||||||
|
"type":"string",
|
||||||
|
"value":"carpet"
|
||||||
|
}],
|
||||||
|
"type":"tilelayer",
|
||||||
|
"visible":true,
|
||||||
|
"width":10,
|
||||||
|
"x":0,
|
||||||
|
"y":0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"draworder":"topdown",
|
||||||
|
"id":3,
|
||||||
|
"name":"floorLayer",
|
||||||
|
"objects":[
|
||||||
|
{
|
||||||
|
"height":304.037037037037,
|
||||||
|
"id":3,
|
||||||
|
"name":"",
|
||||||
|
"rotation":0,
|
||||||
|
"text":
|
||||||
|
{
|
||||||
|
"fontfamily":"Sans Serif",
|
||||||
|
"pixelsize":11,
|
||||||
|
"text":"Test:\nWalk on the carpet\n\nResult:\nA message is displayed at the bottom of the screen\n\nTest:\nPress space\n\nResult:\nA chat message is displayed\n\n\nTest:\nWalk out of the carpet\n\nResult:\nThe message is hidden\n",
|
||||||
|
"wrap":true
|
||||||
|
},
|
||||||
|
"type":"",
|
||||||
|
"visible":true,
|
||||||
|
"width":252.4375,
|
||||||
|
"x":2.78125,
|
||||||
|
"y":2.5
|
||||||
|
}],
|
||||||
|
"opacity":1,
|
||||||
|
"type":"objectgroup",
|
||||||
|
"visible":true,
|
||||||
|
"x":0,
|
||||||
|
"y":0
|
||||||
|
}],
|
||||||
|
"nextlayerid":9,
|
||||||
|
"nextobjectid":11,
|
||||||
|
"orientation":"orthogonal",
|
||||||
|
"properties":[
|
||||||
|
{
|
||||||
|
"name":"script",
|
||||||
|
"type":"string",
|
||||||
|
"value":"script.js"
|
||||||
|
}],
|
||||||
|
"renderorder":"right-down",
|
||||||
|
"tiledversion":"2021.03.23",
|
||||||
|
"tileheight":32,
|
||||||
|
"tilesets":[
|
||||||
|
{
|
||||||
|
"columns":11,
|
||||||
|
"firstgid":1,
|
||||||
|
"image":"..\/tileset1.png",
|
||||||
|
"imageheight":352,
|
||||||
|
"imagewidth":352,
|
||||||
|
"margin":0,
|
||||||
|
"name":"tileset1",
|
||||||
|
"spacing":0,
|
||||||
|
"tilecount":121,
|
||||||
|
"tileheight":32,
|
||||||
|
"tilewidth":32
|
||||||
|
}],
|
||||||
|
"tilewidth":32,
|
||||||
|
"type":"map",
|
||||||
|
"version":1.5,
|
||||||
|
"width":10
|
||||||
|
}
|
@ -202,6 +202,14 @@
|
|||||||
<a href="#" class="testLink" data-testmap="Variables/shared_variables.json" target="_blank">Testing shared scripting variables</a>
|
<a href="#" class="testLink" data-testmap="Variables/shared_variables.json" target="_blank">Testing shared scripting variables</a>
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>
|
||||||
|
<input type="radio" name="test-trigger-message-api"> Success <input type="radio" name="test-trigger-message-api"> Failure <input type="radio" name="test-trigger-message-api" checked> Pending
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<a href="#" class="testLink" data-testmap="TriggerMessageApi/triggerMessage.json" target="_blank">Testing trigger message API</a>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
</table>
|
</table>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
|
@ -1,40 +1,41 @@
|
|||||||
|
///<reference path="../../front/src/iframe_api.ts" />
|
||||||
console.log('SCRIPT LAUNCHED');
|
console.log('SCRIPT LAUNCHED');
|
||||||
//WA.sendChatMessage('Hi, my name is Poly and I repeat what you say!', 'Poly Parrot');
|
//WA.sendChatMessage('Hi, my name is Poly and I repeat what you say!', 'Poly Parrot');
|
||||||
var isFirstTimeTuto = false;
|
var isFirstTimeTuto = false;
|
||||||
var textFirstPopup = 'Hey ! This is how to open start a discussion with someone ! You can be 4 max in a booble';
|
var textFirstPopup = 'Hey ! This is how to open start a discussion with someone ! You can be 4 max in a booble';
|
||||||
var textSecondPopup = 'You can also use the chat to communicate ! ';
|
var textSecondPopup = 'You can also use the chat to communicate ! ';
|
||||||
var targetObjectTutoBubble ='myPopup1';
|
var targetObjectTutoBubble = 'myPopup1';
|
||||||
var targetObjectTutoChat ='myPopup2';
|
var targetObjectTutoChat = 'myPopup2';
|
||||||
var popUpExplanation = undefined;
|
var popUpExplanation = undefined;
|
||||||
function launchTuto (){
|
function launchTuto() {
|
||||||
WA.ui.openPopup(targetObjectTutoBubble, textFirstPopup, [
|
WA.ui.openPopup(targetObjectTutoBubble, textFirstPopup, [
|
||||||
{
|
{
|
||||||
label: "Next",
|
label: "Next",
|
||||||
className: "popUpElement",
|
className: "popUpElement",
|
||||||
callback: (popup) => {
|
callback: (popup) => {
|
||||||
popup.close();
|
popup.close();
|
||||||
|
|
||||||
WA.ui.openPopup(targetObjectTutoChat, textSecondPopup, [
|
WA.ui.openPopup(targetObjectTutoChat, textSecondPopup, [
|
||||||
{
|
{
|
||||||
label: "Open Chat",
|
label: "Open Chat",
|
||||||
className: "popUpElement",
|
className: "popUpElement",
|
||||||
callback: (popup1) => {
|
callback: (popup1) => {
|
||||||
WA.chat.sendChatMessage("Hey you can talk here too ! ", 'WA Guide');
|
WA.chat.sendChatMessage("Hey you can talk here too ! ", 'WA Guide');
|
||||||
popup1.close();
|
popup1.close();
|
||||||
WA.controls.restorePlayerControls();
|
WA.controls.restorePlayerControls();
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
])
|
])
|
||||||
}
|
|
||||||
}
|
}
|
||||||
]);
|
}
|
||||||
WA.controls.disablePlayerControls();
|
]);
|
||||||
|
WA.controls.disablePlayerControls();
|
||||||
|
|
||||||
}
|
}
|
||||||
WA.chat.onChatMessage((message => {
|
WA.chat.onChatMessage((message => {
|
||||||
console.log('CHAT MESSAGE RECEIVED BY SCRIPT');
|
console.log('CHAT MESSAGE RECEIVED BY SCRIPT');
|
||||||
WA.chat.sendChatMessage('Poly Parrot says: "'+message+'"', 'Poly Parrot');
|
WA.chat.sendChatMessage('Poly Parrot says: "' + message + '"', 'Poly Parrot');
|
||||||
}));
|
}));
|
||||||
|
|
||||||
WA.room.onEnterZone('myTrigger', () => {
|
WA.room.onEnterZone('myTrigger', () => {
|
||||||
@ -50,11 +51,11 @@ WA.room.onEnterZone('notExist', () => {
|
|||||||
|
|
||||||
WA.room.onEnterZone('popupZone', () => {
|
WA.room.onEnterZone('popupZone', () => {
|
||||||
WA.ui.displayBubble();
|
WA.ui.displayBubble();
|
||||||
if (!isFirstTimeTuto) {
|
if(!isFirstTimeTuto) {
|
||||||
isFirstTimeTuto = true;
|
isFirstTimeTuto = true;
|
||||||
launchTuto();
|
launchTuto();
|
||||||
}
|
}
|
||||||
else popUpExplanation = WA.ui.openPopup(targetObjectTutoChat,'Do you want to review the explanation ? ', [
|
else popUpExplanation = WA.ui.openPopup(targetObjectTutoChat, 'Do you want to review the explanation ? ', [
|
||||||
{
|
{
|
||||||
label: "No",
|
label: "No",
|
||||||
className: "popUpElementReviewexplanation",
|
className: "popUpElementReviewexplanation",
|
||||||
@ -74,6 +75,13 @@ WA.room.onEnterZone('popupZone', () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
WA.room.onLeaveZone('popupZone', () => {
|
WA.room.onLeaveZone('popupZone', () => {
|
||||||
if (popUpExplanation !== undefined) popUpExplanation.close();
|
if(popUpExplanation !== undefined) popUpExplanation.close();
|
||||||
WA.ui.removeBubble();
|
WA.ui.removeBubble();
|
||||||
})
|
})
|
||||||
|
|
||||||
|
const message = WA.ui.displayActionMessage("testMessage", () => {
|
||||||
|
WA.chat.sendChatMessage("triggered", "triggerbot");
|
||||||
|
})
|
||||||
|
setTimeout(() => {
|
||||||
|
message.remove();
|
||||||
|
}, 5000)
|
||||||
|
12
package-lock.json
generated
Normal file
12
package-lock.json
generated
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
{
|
||||||
|
"requires": true,
|
||||||
|
"lockfileVersion": 1,
|
||||||
|
"dependencies": {
|
||||||
|
"husky": {
|
||||||
|
"version": "6.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/husky/-/husky-6.0.0.tgz",
|
||||||
|
"integrity": "sha512-SQS2gDTB7tBN486QSoKPKQItZw97BMOd+Kdb6ghfpBc0yXyzrddI0oDV5MkDAbuB4X2mO3/nj60TRMcYxwzZeQ==",
|
||||||
|
"dev": true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user